History

tccrun.c: standalone backtraces with -bt[N] or -b

This makes it possible to get backtraces with executables (including DLLs/SOs) like we had it already with -g -run. Option -b includes -bt, and -bt includes -g. - new file lib/bt-exe.c: used to link rt_printline and the exception handler from tccrun.c into executables/DLLs. - new file lib/bt-log.c: provides a function that may be called from user code to print out a backtrace with a message (currently for i386/x86_64 only): int (*tcc_backtrace)(const char *fmt, ...); As an extra hack, if 'fmt' is prefixed like "^file.c^..." then the backtrace will skip calls from within 'file.c'. - new file lib/bt-dll.c: used on win32 to link the backtrace and bcheck functions with the main module at runtime - bcheck.c: now uses the tcc_backtrace function from above - tccgen.c: minor cleanups - tccelf.c: stab sections get SHF_ALLOC for easy access. Also in relocate_section(): 64bit relocations for stabs in DLLs cannot work. To find DLL addresses, the DLL base is added manually in tccrun.c via rc.prog_base instead. - tccpe.c: there are some changes to allow merging sections, used to merge .finit_array into .data in the first place. - tccpp.c: tcc -run now #defines __TCC_RUN__ also: refactor a line in tal_realloc that was incompatible with bcheck - tcctest.c: fixed a problem with r12 which tcc cannot preserve as well as gcc does. - tests2/112_backtrace.c: test the feature and the bcheck test18 that previously was in boundtest.c

gr committed 6 years ago

Commit ef422951 parent 4092b0527 files · +1211 −850Browse files

Unified · Split

27 files
  1. Makefile +3 −2
  2. arm-gen.c +1 −1
  3. lib/Makefile +13 −9
  4. lib/bcheck.c +72 −89
  5. lib/bt-dll.c +67 −0
  6. lib/bt-exe.c +43 −0
  7. lib/bt-log.c +36 −0
  8. libtcc.c +4 −4
  9. tcc-doc.texi +6 −3
  10. tcc.c +1 −1
  11. tcc.h +11 −15
  12. tccelf.c +151 −106
  13. tccgen.c +34 −52
  14. tccpe.c +176 −146
  15. tccpp.c +9 −8
  16. tccrun.c +188 −149
  17. tests/Makefile +23 −23
  18. tests/boundtest.c +3 −214
  19. tests/libtcc_test_mt.c +12 −9
  20. tests/tcctest.c +15 −9
  21. tests/tests2/112_backtrace.c +165 −0
  22. tests/tests2/112_backtrace.expect +164 −0
  23. tests/tests2/60_errors_and_warnings.expect +1 −0
  24. tests/tests2/Makefile +5 −5
  25. win32/build-tcc.bat +6 −4
  26. win32/lib/crt1.c +1 −1
  27. x86_64-link.c +1 −0
Makefile+3−2
@@ -281,11 +281,12 @@ IBw = $(call IB,$(wildcard $1),$2) · 280 unmodified lines
281IF = $(if $1,mkdir -p $2 && $(INSTALL) $1 $2)281IF = $(if $1,mkdir -p $2 && $(INSTALL) $1 $2)
282IFw = $(call IF,$(wildcard $1),$2)282IFw = $(call IF,$(wildcard $1),$2)
283IR = mkdir -p $2 && cp -r $1/. $2283IR = mkdir -p $2 && cp -r $1/. $2
284B_O = bcheck.o bt-exe.o bt-log.o bt-dll.o
284 285
285# install progs & libs286# install progs & libs
286install-unx:287install-unx:
287 $(call IBw,$(PROGS) $(PROGS_CROSS),"$(bindir)")288 $(call IBw,$(PROGS) $(PROGS_CROSS),"$(bindir)")
288 $(call IFw,$(LIBTCC1) bcheck.o $(LIBTCC1_U),"$(tccdir)")289 $(call IFw,$(LIBTCC1) $(B_O) $(LIBTCC1_U),"$(tccdir)")
289 $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")290 $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
290 $(call $(if $(findstring .so,$(LIBTCC)),IBw,IFw),$(LIBTCC),"$(libdir)")291 $(call $(if $(findstring .so,$(LIBTCC)),IBw,IFw),$(LIBTCC),"$(libdir)")
291 $(call IF,$(TOPSRC)/libtcc.h,"$(includedir)")292 $(call IF,$(TOPSRC)/libtcc.h,"$(includedir)")
@@ -310,7 +311,7 @@ uninstall-unx: · 18 unmodified lines
310install-win:311install-win:
311 $(call IBw,$(PROGS) $(PROGS_CROSS) $(subst libtcc.a,,$(LIBTCC)),"$(bindir)")312 $(call IBw,$(PROGS) $(PROGS_CROSS) $(subst libtcc.a,,$(LIBTCC)),"$(bindir)")
312 $(call IF,$(TOPSRC)/win32/lib/*.def,"$(tccdir)/lib")313 $(call IF,$(TOPSRC)/win32/lib/*.def,"$(tccdir)/lib")
313 $(call IFw,libtcc1.a bcheck.o $(LIBTCC1_W),"$(tccdir)/lib")314 $(call IFw,libtcc1.a $(B_O) $(LIBTCC1_W),"$(tccdir)/lib")
314 $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")315 $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
315 $(call IR,$(TOPSRC)/win32/include,"$(tccdir)/include")316 $(call IR,$(TOPSRC)/win32/include,"$(tccdir)/include")
316 $(call IR,$(TOPSRC)/win32/examples,"$(tccdir)/examples")317 $(call IR,$(TOPSRC)/win32/examples,"$(tccdir)/examples")
arm-gen.c+1−1
@@ -171,7 +171,7 @@ ST_FUNC void arm_init(struct TCCState *s) · 170 unmodified lines
171 171
172 float_abi = s->float_abi;172 float_abi = s->float_abi;
173#ifndef TCC_ARM_HARDFLOAT173#ifndef TCC_ARM_HARDFLOAT
174 tcc_warning("soft float ABI currently not supported: default to softfp");174# warning "soft float ABI currently not supported: default to softfp"
175#endif175#endif
176}176}
177#else177#else
lib/Makefile+13−9
@@ -13,7 +13,7 @@ XCC = $(XTCC) · 12 unmodified lines
13XAR = $(XTCC) -ar13XAR = $(XTCC) -ar
14XFLAGS-unx = -B$(TOPSRC)14XFLAGS-unx = -B$(TOPSRC)
15XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include15XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include
16XFLAGS = $(XFLAGS$(XCFG))16XFLAGS = $(XFLAGS$(XCFG)) -I$(TOP)
17XCFG = $(or $(findstring -win,$T),-unx)17XCFG = $(or $(findstring -win,$T),-unx)
18 18
19# in order to use gcc, tyoe: make <target>-libtcc1-usegcc=yes19# in order to use gcc, tyoe: make <target>-libtcc1-usegcc=yes
@@ -27,6 +27,8 @@ endif · 7 unmodified lines
27 27
28# only for native compiler28# only for native compiler
29$(X)BCHECK_O = bcheck.o29$(X)BCHECK_O = bcheck.o
30$(X)BT_O = bt-exe.o bt-log.o
31$(X)B_O = bcheck.o bt-exe.o bt-log.o bt-dll.o
30 32
31ifeq ($(CONFIG_musl)$(CONFIG_uClibc),yes)33ifeq ($(CONFIG_musl)$(CONFIG_uClibc),yes)
32 BCHECK_O =34 BCHECK_O =
@@ -38,18 +40,18 @@ ifdef CONFIG_OSX · 5 unmodified lines
38 XFLAGS += -D_ANSI_SOURCE40 XFLAGS += -D_ANSI_SOURCE
39endif41endif
40 42
41I386_O = libtcc1.o alloca86.o alloca86-bt.o43I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O)
42X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o44X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BT_O)
43ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o45ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o $(BT_O)
44ARM64_O = lib-arm64.o46ARM64_O = lib-arm64.o $(BT_O)
45RISCV64_O = lib-arm64.o47RISCV64_O = lib-arm64.o $(BT_O)
46WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o48WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
47 49
48OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O)50OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O)
49OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) $(DSO_O)51OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) $(DSO_O)
50OBJ-x86_64-osx = $(X86_64_O) va_list.o52OBJ-x86_64-osx = $(X86_64_O) va_list.o
51OBJ-i386-win32 = $(I386_O) chkstk.o bcheck.o $(WIN_O)53OBJ-i386-win32 = $(I386_O) chkstk.o $(B_O) $(WIN_O)
52OBJ-x86_64-win32 = $(X86_64_O) chkstk.o bcheck.o $(WIN_O)54OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(B_O) $(WIN_O)
53OBJ-arm64 = $(ARM64_O) $(DSO_O)55OBJ-arm64 = $(ARM64_O) $(DSO_O)
54OBJ-arm = $(ARM_O) $(DSO_O)56OBJ-arm = $(ARM_O) $(DSO_O)
55OBJ-arm-fpa = $(ARM_O) $(DSO_O)57OBJ-arm-fpa = $(ARM_O) $(DSO_O)
@@ -60,7 +62,7 @@ OBJ-arm-eabihf = $(ARM_O) $(DSO_O) · 4 unmodified lines
60OBJ-arm-wince = $(ARM_O) $(WIN_O)62OBJ-arm-wince = $(ARM_O) $(WIN_O)
61OBJ-riscv64 = $(RISCV64_O) $(DSO_O)63OBJ-riscv64 = $(RISCV64_O) $(DSO_O)
62 64
63OBJ-extra = $(filter bcheck.o,$(OBJ-$T))65OBJ-extra = $(filter $(B_O),$(OBJ-$T))
64OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))66OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))
65 67
66ALL = $(addprefix $(TOP)/,$(X)libtcc1.a $(OBJ-extra))68ALL = $(addprefix $(TOP)/,$(X)libtcc1.a $(OBJ-extra))
@@ -80,8 +82,10 @@ $(TOP)/%.o : %.c · 13 unmodified lines
80 $(XCC) -c $< -o $@ $(XFLAGS)82 $(XCC) -c $< -o $@ $(XFLAGS)
81 83
82$(TOP)/bcheck.o : XFLAGS += -g84$(TOP)/bcheck.o : XFLAGS += -g
85$(TOP)/bt-exe.o : $(TOP)/tccrun.c
83 86
84$(X)crt1w.o : crt1.c87$(X)crt1w.o : crt1.c
85$(X)wincrt1w.o : wincrt1.c88$(X)wincrt1w.o : wincrt1.c
89
86clean :90clean :
87 rm -f *.a *.o $(ALL)91 rm -f *.a *.o $(ALL)
lib/bcheck.c+72−89
@@ -49,6 +49,12 @@ · 48 unmodified lines
49#endif49#endif
50#define FASTCALL __attribute__((regparm(3)))50#define FASTCALL __attribute__((regparm(3)))
51 51
52#ifdef _WIN32
53# define DLL_EXPORT __declspec(dllexport)
54#else
55# define DLL_EXPORT
56#endif
57
52#if defined(__FreeBSD__) \58#if defined(__FreeBSD__) \
53 || defined(__FreeBSD_kernel__) \59 || defined(__FreeBSD_kernel__) \
54 || defined(__DragonFly__) \60 || defined(__DragonFly__) \
@@ -162,16 +168,16 @@ void splay_printtree(Tree * t, int d); · 107 unmodified lines
162/* external interface */168/* external interface */
163void __bound_checking (int no_check);169void __bound_checking (int no_check);
164void __bound_never_fatal (int no_check);170void __bound_never_fatal (int no_check);
165void * __bound_ptr_add(void *p, size_t offset);171DLL_EXPORT void * __bound_ptr_add(void *p, size_t offset);
166void * __bound_ptr_indir1(void *p, size_t offset);172DLL_EXPORT void * __bound_ptr_indir1(void *p, size_t offset);
167void * __bound_ptr_indir2(void *p, size_t offset);173DLL_EXPORT void * __bound_ptr_indir2(void *p, size_t offset);
168void * __bound_ptr_indir4(void *p, size_t offset);174DLL_EXPORT void * __bound_ptr_indir4(void *p, size_t offset);
169void * __bound_ptr_indir8(void *p, size_t offset);175DLL_EXPORT void * __bound_ptr_indir8(void *p, size_t offset);
170void * __bound_ptr_indir12(void *p, size_t offset);176DLL_EXPORT void * __bound_ptr_indir12(void *p, size_t offset);
171void * __bound_ptr_indir16(void *p, size_t offset);177DLL_EXPORT void * __bound_ptr_indir16(void *p, size_t offset);
172void FASTCALL __bound_local_new(void *p1);178DLL_EXPORT void FASTCALL __bound_local_new(void *p1);
173void FASTCALL __bound_local_delete(void *p1);179DLL_EXPORT void FASTCALL __bound_local_delete(void *p1);
174void __bound_init(void);180void __bound_init(size_t *);
175void __bound_main_arg(char **p);181void __bound_main_arg(char **p);
176void __bound_exit(void);182void __bound_exit(void);
177#if !defined(_WIN32)183#if !defined(_WIN32)
@@ -179,35 +185,32 @@ void *__bound_mmap (void *start, size_t size, int prot, int flags, int fd, · 1 unmodified line
179 off_t offset);185 off_t offset);
180int __bound_munmap (void *start, size_t size);186int __bound_munmap (void *start, size_t size);
181#endif187#endif
182void __bound_new_region(void *p, size_t size);188DLL_EXPORT void __bound_new_region(void *p, size_t size);
183void *__bound_memcpy(void *dst, const void *src, size_t size);189DLL_EXPORT void *__bound_memcpy(void *dst, const void *src, size_t size);
184int __bound_memcmp(const void *s1, const void *s2, size_t size);190DLL_EXPORT int __bound_memcmp(const void *s1, const void *s2, size_t size);
185void *__bound_memmove(void *dst, const void *src, size_t size);191DLL_EXPORT void *__bound_memmove(void *dst, const void *src, size_t size);
186void *__bound_memset(void *dst, int c, size_t size);192DLL_EXPORT void *__bound_memset(void *dst, int c, size_t size);
187int __bound_strlen(const char *s);193DLL_EXPORT int __bound_strlen(const char *s);
188char *__bound_strcpy(char *dst, const char *src);194DLL_EXPORT char *__bound_strcpy(char *dst, const char *src);
189char *__bound_strncpy(char *dst, const char *src, size_t n);195DLL_EXPORT char *__bound_strncpy(char *dst, const char *src, size_t n);
190int __bound_strcmp(const char *s1, const char *s2);196DLL_EXPORT int __bound_strcmp(const char *s1, const char *s2);
191int __bound_strncmp(const char *s1, const char *s2, size_t n);197DLL_EXPORT int __bound_strncmp(const char *s1, const char *s2, size_t n);
192char *__bound_strcat(char *dest, const char *src);198DLL_EXPORT char *__bound_strcat(char *dest, const char *src);
193char *__bound_strchr(const char *string, int ch);199DLL_EXPORT char *__bound_strchr(const char *string, int ch);
194char *__bound_strdup(const char *s);200DLL_EXPORT char *__bound_strdup(const char *s);
195 201
196#if !MALLOC_REDIR202#if !MALLOC_REDIR
197void *__bound_malloc(size_t size, const void *caller);203DLL_EXPORT void *__bound_malloc(size_t size, const void *caller);
198void *__bound_memalign(size_t size, size_t align, const void *caller);204DLL_EXPORT void *__bound_memalign(size_t size, size_t align, const void *caller);
199void __bound_free(void *ptr, const void *caller);205DLL_EXPORT void __bound_free(void *ptr, const void *caller);
200void *__bound_realloc(void *ptr, size_t size, const void *caller);206DLL_EXPORT void *__bound_realloc(void *ptr, size_t size, const void *caller);
201void *__bound_calloc(size_t nmemb, size_t size);207DLL_EXPORT void *__bound_calloc(size_t nmemb, size_t size);
202#endif208#endif
203 209
204#define FREE_REUSE_SIZE (100)210#define FREE_REUSE_SIZE (100)
205static unsigned int free_reuse_index;211static unsigned int free_reuse_index;
206static void *free_reuse_list[FREE_REUSE_SIZE];212static void *free_reuse_list[FREE_REUSE_SIZE];
207 213
208/* error message, just for TCC */
209const char *__bound_error_msg;
210
211static Tree *tree = NULL;214static Tree *tree = NULL;
212#define TREE_REUSE (1)215#define TREE_REUSE (1)
213#if TREE_REUSE216#if TREE_REUSE
@@ -296,14 +299,18 @@ void __bound_never_fatal (int neverfatal) · 82 unmodified lines
296 fetch_and_add (&never_fatal, neverfatal);299 fetch_and_add (&never_fatal, neverfatal);
297}300}
298 301
302int tcc_backtrace(const char *fmt, ...);
303
299/* print a bound error message */304/* print a bound error message */
300static void bound_error(const char *error)305#define bound_warning(...) \
301{306 tcc_backtrace("^bcheck.c^BCHECK: " __VA_ARGS__)
302 __bound_error_msg = error;307
303 fprintf(stderr,"%s%s %s: %s\n", exec, __FILE__, __FUNCTION__, error);308#define bound_error(...) \
304 if (never_fatal == 0)309 do { \
305 *(void **)0 = 0; /* force a runtime error */310 bound_warning(__VA_ARGS__); \
306}311 if (never_fatal == 0) \
312 exit(255); \
313 } while (0)
307 314
308static void bound_alloc_error(const char *s)315static void bound_alloc_error(const char *s)
309{316{
@@ -317,20 +324,6 @@ static void bound_not_found_warning(const char *file, const char *function, · 7 unmodified lines
317 dprintf(stderr, "%s%s, %s(): Not found %p\n", exec, file, function, ptr);324 dprintf(stderr, "%s%s, %s(): Not found %p\n", exec, file, function, ptr);
318}325}
319 326
320static void bound_ptr_add_warning(const char *file, const char *function,
321 void *ptr)
322{
323 fprintf(stderr,"%s%s %s(): %p is outside of the region\n",
324 exec, file, function, ptr);
325}
326
327static void bound_ptr_indir_error(const char *file, const char *function,
328 void *ptr)
329{
330 fprintf(stderr,"%s%s %s(): %p is outside of the region\n",
331 exec, file, function, ptr);
332}
333
334/* return '(p + offset)' for pointer arithmetic (a pointer can reach327/* return '(p + offset)' for pointer arithmetic (a pointer can reach
335 the end of a region in this case */328 the end of a region in this case */
336void * __bound_ptr_add(void *p, size_t offset)329void * __bound_ptr_add(void *p, size_t offset)
@@ -360,8 +353,7 @@ void * __bound_ptr_add(void *p, size_t offset) · 23 unmodified lines
360 if (addr <= tree->size) {353 if (addr <= tree->size) {
361 if (tree->is_invalid || addr + offset > tree->size) {354 if (tree->is_invalid || addr + offset > tree->size) {
362 POST_SEM ();355 POST_SEM ();
363 if (print_warn_ptr_add)356 bound_warning("%p is outside of the region", p + offset);
364 bound_ptr_add_warning (__FILE__, __FUNCTION__, p + offset);
365 if (never_fatal <= 0)357 if (never_fatal <= 0)
366 return INVALID_POINTER; /* return an invalid pointer */358 return INVALID_POINTER; /* return an invalid pointer */
367 return p + offset;359 return p + offset;
@@ -407,8 +399,7 @@ void * __bound_ptr_indir ## dsize (void *p, size_t offset) \ · 39 unmodified lines
407 if (addr <= tree->size) { \399 if (addr <= tree->size) { \
408 if (tree->is_invalid || addr + offset + dsize > tree->size) { \400 if (tree->is_invalid || addr + offset + dsize > tree->size) { \
409 POST_SEM (); \401 POST_SEM (); \
410 bound_ptr_indir_error (__FILE__, __FUNCTION__, \402 bound_warning("%p is outside of the region", p + offset); \
411 p + offset); \
412 if (never_fatal <= 0) \403 if (never_fatal <= 0) \
413 return INVALID_POINTER; /* return an invalid pointer */ \404 return INVALID_POINTER; /* return an invalid pointer */ \
414 return p + offset; \405 return p + offset; \
@@ -460,8 +451,7 @@ void FASTCALL __bound_local_new(void *p1) · 45 unmodified lines
460 WAIT_SEM ();451 WAIT_SEM ();
461 while ((addr = p[0])) {452 while ((addr = p[0])) {
462 INCR_COUNT(bound_local_new_count);453 INCR_COUNT(bound_local_new_count);
463 if (addr != 1)454 tree = splay_insert(addr + fp, p[1], tree);
464 tree = splay_insert(addr + fp, p[1], tree);
465 p += 2;455 p += 2;
466 }456 }
467 POST_SEM ();457 POST_SEM ();
@@ -498,7 +488,10 @@ void FASTCALL __bound_local_delete(void *p1) · 30 unmodified lines
498 WAIT_SEM ();488 WAIT_SEM ();
499 while ((addr = p[0])) {489 while ((addr = p[0])) {
500 INCR_COUNT(bound_local_delete_count);490 INCR_COUNT(bound_local_delete_count);
501 if (addr == 1) {491 tree = splay_delete(addr + fp, tree);
492 p += 2;
493 }
494 {
502 alloca_list_type *last = NULL;495 alloca_list_type *last = NULL;
503 alloca_list_type *cur = alloca_list;496 alloca_list_type *cur = alloca_list;
504 497
@@ -518,11 +511,8 @@ void FASTCALL __bound_local_delete(void *p1) · 13 unmodified lines
518 cur = cur->next;511 cur = cur->next;
519 }512 }
520 }513 }
521 }
522 else
523 tree = splay_delete(addr + fp, tree);
524 p += 2;
525 }514 }
515
526 POST_SEM ();516 POST_SEM ();
527 while (free_list) {517 while (free_list) {
528 alloca_list_type *next = free_list->next;518 alloca_list_type *next = free_list->next;
@@ -607,14 +597,14 @@ void __bound_new_region(void *p, size_t size) · 78 unmodified lines
607#pragma GCC diagnostic pop597#pragma GCC diagnostic pop
608#endif598#endif
609 599
610void __attribute__((constructor)) __bound_init(void)600void __bound_init(size_t *p)
611{601{
612 extern size_t __bounds_start[];602 dprintf(stderr, "%s, %s(): start\n", __FILE__, __FUNCTION__);
613 size_t *p;
614
615 if (inited)
616 return;
617 603
604 if (inited) {
605 WAIT_SEM();
606 goto add_bounds;
607 }
618 inited = 1;608 inited = 1;
619 609
620 print_warn_ptr_add = getenv ("TCC_BOUNDS_WARN_POINTER_ADD") != NULL;610 print_warn_ptr_add = getenv ("TCC_BOUNDS_WARN_POINTER_ADD") != NULL;
@@ -623,8 +613,6 @@ void __attribute__((constructor)) __bound_init(void) · 2 unmodified lines
623 print_statistic = getenv ("TCC_BOUNDS_PRINT_STATISTIC") != NULL;613 print_statistic = getenv ("TCC_BOUNDS_PRINT_STATISTIC") != NULL;
624 never_fatal = getenv ("TCC_BOUNDS_NEVER_FATAL") != NULL;614 never_fatal = getenv ("TCC_BOUNDS_NEVER_FATAL") != NULL;
625 615
626 dprintf(stderr, "%s, %s(): start\n", __FILE__, __FUNCTION__);
627
628 INIT_SEM ();616 INIT_SEM ();
629 617
630#if MALLOC_REDIR618#if MALLOC_REDIR
@@ -724,27 +712,26 @@ void __attribute__((constructor)) __bound_init(void) · 93 unmodified lines
724 tree = splay_insert((size_t) (&errno), sizeof (int), tree);712 tree = splay_insert((size_t) (&errno), sizeof (int), tree);
725#endif713#endif
726 714
715add_bounds:
716 if (!p)
717 goto no_bounds;
718
727 /* add all static bound check values */719 /* add all static bound check values */
728 p = __bounds_start;
729 while (p[0] != 0) {720 while (p[0] != 0) {
730 tree = splay_insert(p[0], p[1], tree);721 tree = splay_insert(p[0], p[1], tree);
731 p += 2;
732 }
733 POST_SEM ();
734#if BOUND_DEBUG722#if BOUND_DEBUG
735 if (print_calls) {723 if (print_calls) {
736 p = __bounds_start;
737 while (p[0] != 0) {
738 dprintf(stderr, "%s, %s(): static var %p 0x%lx\n",724 dprintf(stderr, "%s, %s(): static var %p 0x%lx\n",
739 __FILE__, __FUNCTION__,725 __FILE__, __FUNCTION__,
740 (void *) p[0], (unsigned long) p[1]);726 (void *) p[0], (unsigned long) p[1]);
741 p += 2;
742 }727 }
743 }
744#endif728#endif
729 p += 2;
730 }
731no_bounds:
745 732
733 POST_SEM ();
746 no_checking = 0;734 no_checking = 0;
747
748 dprintf(stderr, "%s, %s(): end\n\n", __FILE__, __FUNCTION__);735 dprintf(stderr, "%s, %s(): end\n\n", __FILE__, __FUNCTION__);
749}736}
750 737
@@ -931,7 +918,7 @@ void *__bound_malloc(size_t size, const void *caller) · 180 unmodified lines
931#if MALLOC_REDIR918#if MALLOC_REDIR
932 /* This will catch the first dlsym call from __bound_init */919 /* This will catch the first dlsym call from __bound_init */
933 if (malloc_redir == NULL) {920 if (malloc_redir == NULL) {
934 __bound_init ();921 __bound_init (0);
935 if (malloc_redir == NULL) {922 if (malloc_redir == NULL) {
936 ptr = &initial_pool[pool_index];923 ptr = &initial_pool[pool_index];
937 pool_index = (pool_index + size + 15) & ~15;924 pool_index = (pool_index + size + 15) & ~15;
@@ -1113,7 +1100,7 @@ void *__bound_calloc(size_t nmemb, size_t size) · 175 unmodified lines
1113#if MALLOC_REDIR1100#if MALLOC_REDIR
1114 /* This will catch the first dlsym call from __bound_init */1101 /* This will catch the first dlsym call from __bound_init */
1115 if (malloc_redir == NULL) {1102 if (malloc_redir == NULL) {
1116 __bound_init ();1103 __bound_init (0);
1117 if (malloc_redir == NULL) {1104 if (malloc_redir == NULL) {
1118 ptr = &initial_pool[pool_index];1105 ptr = &initial_pool[pool_index];
1119 pool_index = (pool_index + size + 15) & ~15;1106 pool_index = (pool_index + size + 15) & ~15;
@@ -1190,10 +1177,8 @@ static void __bound_check(const void *p, size_t size, const char *function) · 70 unmodified lines
1190{1177{
1191 if (no_checking == 0 && size != 0 &&1178 if (no_checking == 0 && size != 0 &&
1192 __bound_ptr_add((void *)p, size) == INVALID_POINTER) {1179 __bound_ptr_add((void *)p, size) == INVALID_POINTER) {
1193 static char line[100];1180 bound_error("invalid pointer %p, size 0x%lx in %s",
1194 sprintf(line, "invalid pointer %p, size 0x%lx in %s",
1195 p, (unsigned long)size, function);1181 p, (unsigned long)size, function);
1196 bound_error(line);
1197 }1182 }
1198}1183}
1199 1184
@@ -1207,10 +1192,8 @@ static int check_overlap (const void *p1, size_t n1, · 7 unmodified lines
1207 if (no_checking == 0 && n1 != 0 && n2 !=0 &&1192 if (no_checking == 0 && n1 != 0 && n2 !=0 &&
1208 ((p1 <= p2 && p1e > p2) || /* p1----p2====p1e----p2e */1193 ((p1 <= p2 && p1e > p2) || /* p1----p2====p1e----p2e */
1209 (p2 <= p1 && p2e > p1))) { /* p2----p1====p2e----p1e */1194 (p2 <= p1 && p2e > p1))) { /* p2----p1====p2e----p1e */
1210 static char line[100];1195 bound_error("overlapping regions %p(0x%lx), %p(0x%lx) in %s",
1211 sprintf(line, "overlapping regions %p(0x%lx), %p(0x%lx) in %s",
1212 p1, (unsigned long)n1, p2, (unsigned long)n2, function);1196 p1, (unsigned long)n1, p2, (unsigned long)n2, function);
1213 bound_error(line);
1214 return never_fatal < 0;1197 return never_fatal < 0;
1215 }1198 }
1216 return 0;1199 return 0;
lib/bt-dll.c+67−0
@@ -0,0 +1,67 @@
1/* ------------------------------------------------------------- */
2/* stubs for calling bcheck functions from a dll. */
3
4#include <windows.h>
5#include <stdio.h>
6
7#define REDIR_ALL \
8 REDIR(__bt_init) \
9 REDIR(tcc_backtrace) \
10 \
11 REDIR(__bound_ptr_add) \
12 REDIR(__bound_ptr_indir1) \
13 REDIR(__bound_ptr_indir2) \
14 REDIR(__bound_ptr_indir4) \
15 REDIR(__bound_ptr_indir8) \
16 REDIR(__bound_ptr_indir12) \
17 REDIR(__bound_ptr_indir16) \
18 REDIR(__bound_local_new) \
19 REDIR(__bound_local_delete) \
20 REDIR(__bound_new_region) \
21 \
22 REDIR(__bound_free) \
23 REDIR(__bound_malloc) \
24 REDIR(__bound_realloc) \
25 REDIR(__bound_memcpy) \
26 REDIR(__bound_memcmp) \
27 REDIR(__bound_memmove) \
28 REDIR(__bound_memset) \
29 REDIR(__bound_strlen) \
30 REDIR(__bound_strcpy) \
31 REDIR(__bound_strncpy) \
32 REDIR(__bound_strcmp) \
33 REDIR(__bound_strncmp) \
34 REDIR(__bound_strcat) \
35 REDIR(__bound_strchr) \
36 REDIR(__bound_strdup)
37
38#define REDIR(s) void *s;
39static struct { REDIR_ALL } all_ptrs;
40#undef REDIR
41#define REDIR(s) #s"\0"
42static const char all_names[] = REDIR_ALL;
43#undef REDIR
44#define REDIR(s) __asm__(".global "#s";"#s": jmp *%0" : : "m" (all_ptrs.s) );
45static void all_jmps() { REDIR_ALL }
46#undef REDIR
47
48void __bt_init_dll(int bcheck)
49{
50 const char *s = all_names;
51 void **p = (void**)&all_ptrs;
52 do {
53 *p = (void*)GetProcAddress(GetModuleHandle(NULL), (char*)s);
54 if (NULL == *p) {
55 char buf[100];
56 sprintf(buf,
57 "Error: function '%s()' not found in executable. "
58 "(Need -bt or -b for linking the exe.)", s);
59 if (GetStdHandle(STD_ERROR_HANDLE))
60 fprintf(stderr, "TCC/BCHECK: %s\n", buf), fflush(stderr);
61 else
62 MessageBox(NULL, buf, "TCC/BCHECK", MB_ICONERROR);
63 ExitProcess(1);
64 }
65 s = strchr(s,'\0') + 1, ++p;
66 } while (*s && (bcheck || p < &all_ptrs.__bound_ptr_add));
67}
lib/bt-exe.c+43−0
@@ -0,0 +1,43 @@
1/* ------------------------------------------------------------- */
2/* for linking rt_printline and the signal/exception handler
3 from tccrun.c into executables. */
4
5#define CONFIG_TCC_BACKTRACE_ONLY
6#include "../tccrun.c"
7
8int (*__rt_error)(void*, void*, const char *, va_list);
9
10#ifndef _WIN32
11# define __declspec(n)
12#endif
13
14__declspec(dllexport)
15void __bt_init(rt_context *p, int num_callers)
16{
17 __attribute__((weak)) int main();
18 __attribute__((weak)) void __bound_init(void*);
19 struct rt_context *rc = &g_rtctxt;
20 //fprintf(stderr, "__bt_init %d %p %p\n", num_callers, p->stab_sym, p->bounds_start), fflush(stderr);
21 if (num_callers) {
22 memcpy(rc, p, offsetof(rt_context, next));
23 rc->num_callers = num_callers - 1;
24 rc->top_func = main;
25 __rt_error = _rt_error;
26 set_exception_handler();
27 } else {
28 p->next = rc->next, rc->next = p;
29 }
30 if (__bound_init && p->bounds_start)
31 __bound_init(p->bounds_start);
32}
33
34/* copy a string and truncate it. */
35static char *pstrcpy(char *buf, size_t buf_size, const char *s)
36{
37 int l = strlen(s);
38 if (l >= buf_size)
39 l = buf_size - 1;
40 memcpy(buf, s, l);
41 buf[l] = 0;
42 return buf;
43}
lib/bt-log.c+36−0
@@ -0,0 +1,36 @@
1/* ------------------------------------------------------------- */
2/* function to get a stack backtrace on demand with a message */
3
4#include <stdio.h>
5#include <string.h>
6
7int (*__rt_error)(void*, void*, const char *, va_list);
8
9#ifdef _WIN32
10# define DLL_EXPORT __declspec(dllexport)
11#else
12# define DLL_EXPORT
13#endif
14
15DLL_EXPORT int tcc_backtrace(const char *fmt, ...)
16{
17 va_list ap;
18 int ret;
19
20 if (__rt_error) {
21 void *fp = __builtin_frame_address(1);
22 void *ip = __builtin_return_address(0);
23 va_start(ap, fmt);
24 ret = __rt_error(fp, ip, fmt, ap);
25 va_end(ap);
26 } else {
27 const char *p;
28 if (fmt[0] == '^' && (p = strchr(fmt + 1, fmt[0])))
29 fmt = p + 1;
30 va_start(ap, fmt);
31 ret = vfprintf(stderr, fmt, ap);
32 va_end(ap);
33 fprintf(stderr, "\n"), fflush(stderr);
34 }
35 return ret;
36}
libtcc.c+4−4
@@ -776,9 +776,6 @@ LIBTCCAPI TCCState *tcc_new(void) · 775 unmodified lines
776 /* enable this if you want symbols with leading underscore on windows: */776 /* enable this if you want symbols with leading underscore on windows: */
777#if 0 /* def TCC_TARGET_PE */777#if 0 /* def TCC_TARGET_PE */
778 s->leading_underscore = 1;778 s->leading_underscore = 1;
779#endif
780#ifdef CONFIG_TCC_BACKTRACE
781 s->rt_num_callers = 6;
782#endif779#endif
783 s->ppfp = stdout;780 s->ppfp = stdout;
784 /* might be used in error() before preprocess_start() */781 /* might be used in error() before preprocess_start() */
@@ -1556,7 +1553,7 @@ static const TCCOption tcc_options[] = { · 771 unmodified lines
1556 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG },1553 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG },
1557 { "bench", TCC_OPTION_bench, 0 },1554 { "bench", TCC_OPTION_bench, 0 },
1558#ifdef CONFIG_TCC_BACKTRACE1555#ifdef CONFIG_TCC_BACKTRACE
1559 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },1556 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
1560#endif1557#endif
1561#ifdef CONFIG_TCC_BCHECK1558#ifdef CONFIG_TCC_BCHECK
1562 { "b", TCC_OPTION_b, 0 },1559 { "b", TCC_OPTION_b, 0 },
@@ -1809,11 +1806,14 @@ reparse: · 246 unmodified lines
1809#ifdef CONFIG_TCC_BACKTRACE1806#ifdef CONFIG_TCC_BACKTRACE
1810 case TCC_OPTION_bt:1807 case TCC_OPTION_bt:
1811 s->rt_num_callers = atoi(optarg);1808 s->rt_num_callers = atoi(optarg);
1809 s->do_backtrace = 1;
1810 s->do_debug = 1;
1812 break;1811 break;
1813#endif1812#endif
1814#ifdef CONFIG_TCC_BCHECK1813#ifdef CONFIG_TCC_BCHECK
1815 case TCC_OPTION_b:1814 case TCC_OPTION_b:
1816 s->do_bounds_check = 1;1815 s->do_bounds_check = 1;
1816 s->do_backtrace = 1;
1817 s->do_debug = 1;1817 s->do_debug = 1;
1818 break;1818 break;
1819#endif1819#endif
tcc-doc.texi+6−3
@@ -372,9 +372,12 @@ Try to continue in case of a bound checking error. · 371 unmodified lines
372 372
373Note: @option{-b} is only available on i386 (linux and windows) and x86_64 (linux and windows) for the moment.373Note: @option{-b} is only available on i386 (linux and windows) and x86_64 (linux and windows) for the moment.
374 374
375@item -bt N375@item -bt[N]
376Display N callers in stack traces. This is useful with @option{-g} or376Display N callers in stack traces. This is useful with @option{-g} or @option{-b}.
377@option{-b}.377With executables, additional support for stack traces is included.
378
379A function @code{ int tcc_backtrace(const char *fmt, ...); } is provided
380to trigger a stack trace with a message on demand.
378 381
379@end table382@end table
380 383
tcc.c+1−1
@@ -61,7 +61,7 @@ static const char help[] = · 60 unmodified lines
61 " -b compile with built-in memory and bounds checker (implies -g)\n"61 " -b compile with built-in memory and bounds checker (implies -g)\n"
62#endif62#endif
63#ifdef CONFIG_TCC_BACKTRACE63#ifdef CONFIG_TCC_BACKTRACE
64 " -bt N show N callers in stack traces\n"64 " -bt[N] link with backtrace (stack dump) support [show max N callers]\n"
65#endif65#endif
66 "Misc. options:\n"66 "Misc. options:\n"
67 " -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n"67 " -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n"
tcc.h+11−15
@@ -292,9 +292,6 @@ extern long double strtold (const char *__nptr, char **__endptr); · 291 unmodified lines
292#ifndef TCC_LIBTCC1292#ifndef TCC_LIBTCC1
293# define TCC_LIBTCC1 "libtcc1.a"293# define TCC_LIBTCC1 "libtcc1.a"
294#endif294#endif
295#ifndef TCC_LIBBCHECK
296# define TCC_LIBBCHECK "bcheck.o"
297#endif
298 295
299/* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */296/* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */
300#if defined CONFIG_USE_LIBGCC && !defined TCC_LIBGCC297#if defined CONFIG_USE_LIBGCC && !defined TCC_LIBGCC
@@ -475,7 +472,7 @@ struct SymAttr { · 174 unmodified lines
475 nodecorate : 1,472 nodecorate : 1,
476 dllimport : 1,473 dllimport : 1,
477 addrtaken : 1,474 addrtaken : 1,
478 unused : 3;475 xxxx : 3; /* not used */
479};476};
480 477
481/* function attributes or temporary attributes for parsing */478/* function attributes or temporary attributes for parsing */
@@ -484,7 +481,8 @@ struct FuncAttr { · 2 unmodified lines
484 func_call : 3, /* calling convention (0..5), see below */481 func_call : 3, /* calling convention (0..5), see below */
485 func_type : 2, /* FUNC_OLD/NEW/ELLIPSIS */482 func_type : 2, /* FUNC_OLD/NEW/ELLIPSIS */
486 func_noreturn : 1, /* attribute((noreturn)) */483 func_noreturn : 1, /* attribute((noreturn)) */
487 xxxx : 2,484 func_ctor : 1, /* attribute((constructor)) */
485 func_dtor : 1, /* attribute((destructor)) */
488 func_args : 8; /* PE __stdcall args */486 func_args : 8; /* PE __stdcall args */
489};487};
490 488
@@ -619,8 +617,6 @@ typedef struct TokenString { · 128 unmodified lines
619typedef struct AttributeDef {617typedef struct AttributeDef {
620 struct SymAttr a;618 struct SymAttr a;
621 struct FuncAttr f;619 struct FuncAttr f;
622 unsigned short constructor:1;
623 unsigned short destructor:1;
624 struct Section *section;620 struct Section *section;
625 Sym *cleanup_func;621 Sym *cleanup_func;
626 int alias_target; /* token */622 int alias_target; /* token */
@@ -718,6 +714,7 @@ struct TCCState { · 91 unmodified lines
718 714
719 /* compile with debug symbol (and use them if error during execution) */715 /* compile with debug symbol (and use them if error during execution) */
720 unsigned char do_debug;716 unsigned char do_debug;
717 unsigned char do_backtrace;
721#ifdef CONFIG_TCC_BCHECK718#ifdef CONFIG_TCC_BCHECK
722 /* compile with built-in memory and bounds checker */719 /* compile with built-in memory and bounds checker */
723 unsigned char do_bounds_check;720 unsigned char do_bounds_check;
@@ -884,11 +881,7 @@ struct TCCState { · 160 unmodified lines
884 const char *runtime_main;881 const char *runtime_main;
885 void **runtime_mem;882 void **runtime_mem;
886 int nb_runtime_mem;883 int nb_runtime_mem;
887#ifdef CONFIG_TCC_BACKTRACE
888 int rt_num_callers;884 int rt_num_callers;
889 const char **rt_bound_error_msg;
890 void *rt_prog_main;
891#endif
892#endif885#endif
893 886
894 int fd, cc; /* used by tcc_load_ldscript */887 int fd, cc; /* used by tcc_load_ldscript */
@@ -1259,6 +1252,9 @@ ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags); · 364 unmodified lines
1259#ifdef CONFIG_TCC_BCHECK1252#ifdef CONFIG_TCC_BCHECK
1260ST_FUNC void tcc_add_bcheck(TCCState *s1);1253ST_FUNC void tcc_add_bcheck(TCCState *s1);
1261#endif1254#endif
1255#ifdef CONFIG_TCC_BACKTRACE
1256ST_FUNC void tcc_add_btstub(TCCState *s1);
1257#endif
1262ST_FUNC void tcc_add_pragma_libs(TCCState *s1);1258ST_FUNC void tcc_add_pragma_libs(TCCState *s1);
1263PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);1259PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
1264PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);1260PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
@@ -1485,9 +1481,6 @@ ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type); · 220 unmodified lines
1485#endif1481#endif
1486ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);1482ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
1487 1483
1488ST_FUNC void add_init_array (TCCState *s1, Sym *sym);
1489ST_FUNC void add_fini_array (TCCState *s1, Sym *sym);
1490
1491ST_FUNC int put_elf_str(Section *s, const char *sym);1484ST_FUNC int put_elf_str(Section *s, const char *sym);
1492ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);1485ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
1493ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);1486ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
@@ -1506,7 +1499,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s); · 12 unmodified lines
1506ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h);1499ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h);
1507ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);1500ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
1508ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte);1501ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte);
1509ST_FUNC void tcc_add_runtime(TCCState *s1);1502ST_FUNC void add_array(TCCState *s1, const char *sec, int c);
1510 1503
1511#ifndef ELF_OBJ_ONLY1504#ifndef ELF_OBJ_ONLY
1512ST_FUNC void build_got_entries(TCCState *s1);1505ST_FUNC void build_got_entries(TCCState *s1);
@@ -1521,9 +1514,12 @@ ST_FUNC void list_elf_symbols(TCCState *s, void *ctx, · 8 unmodified lines
1521ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name);1514ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name);
1522#endif1515#endif
1523 1516
1517ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, long offs);
1518
1524#ifndef TCC_TARGET_PE1519#ifndef TCC_TARGET_PE
1525ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level);1520ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level);
1526ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd);1521ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd);
1522ST_FUNC void tcc_add_runtime(TCCState *s1);
1527#endif1523#endif
1528 1524
1529/* ------------ xxx-link.c ------------ */1525/* ------------ xxx-link.c ------------ */
tccelf.c+151−106
@@ -85,33 +85,21 @@ ST_FUNC void tccelf_bounds_new(TCCState *s) · 84 unmodified lines
85 lbounds_section = new_section(s, ".lbounds",85 lbounds_section = new_section(s, ".lbounds",
86 SHT_PROGBITS, SHF_ALLOC);86 SHT_PROGBITS, SHF_ALLOC);
87}87}
88
89ST_FUNC void tcc_add_bcheck(TCCState *s1)
90{
91 addr_t *ptr;
92
93 if (0 == s1->do_bounds_check)
94 return;
95 ptr = section_ptr_add(bounds_section, sizeof(*ptr));
96 *ptr = 0;
97 set_elf_sym(symtab_section, 0, 0,
98 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
99 bounds_section->sh_num, "__bounds_start");
100 /* pull bcheck.o from libtcc1.a */
101 set_elf_sym(symtab_section, 0, 0,
102 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
103 SHN_UNDEF, "__bound_init");
104}
105#endif88#endif
106 89
107ST_FUNC void tccelf_stab_new(TCCState *s)90ST_FUNC void tccelf_stab_new(TCCState *s)
108{91{
109 TCCState *s1 = s;92 TCCState *s1 = s;
110 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);93 int shf = 0;
94#ifdef CONFIG_TCC_BACKTRACE
95 /* include stab info with standalone backtrace support */
96 if (s->do_backtrace && s->output_type != TCC_OUTPUT_MEMORY)
97 shf = SHF_ALLOC;
98#endif
99 stab_section = new_section(s, ".stab", SHT_PROGBITS, shf);
111 stab_section->sh_entsize = sizeof(Stab_Sym);100 stab_section->sh_entsize = sizeof(Stab_Sym);
112 stab_section->sh_addralign = 4;101 stab_section->sh_addralign = sizeof ((Stab_Sym*)0)->n_value;
113 stab_section->link = new_section(s, ".stabstr", SHT_STRTAB, 0);102 stab_section->link = new_section(s, ".stabstr", SHT_STRTAB, shf);
114 put_elf_str(stab_section->link, "");
115 /* put first entry */103 /* put first entry */
116 put_stabs(s, "", 0, 0, 0, 0);104 put_stabs(s, "", 0, 0, 0, 0);
117}105}
@@ -803,6 +791,17 @@ ST_FUNC void put_stabs(TCCState *s1, const char *str, int type, int other, int d · 685 unmodified lines
803{791{
804 Stab_Sym *sym;792 Stab_Sym *sym;
805 793
794 unsigned offset;
795 if (type == N_SLINE
796 && (offset = stab_section->data_offset)
797 && (sym = (Stab_Sym*)(stab_section->data + offset) - 1)
798 && sym->n_type == type
799 && sym->n_value == value) {
800 /* just update line_number in previous entry */
801 sym->n_desc = desc;
802 return;
803 }
804
806 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));805 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
807 if (str) {806 if (str) {
808 sym->n_strx = put_elf_str(stab_section->link, str);807 sym->n_strx = put_elf_str(stab_section->link, str);
@@ -818,10 +817,11 @@ ST_FUNC void put_stabs(TCCState *s1, const char *str, int type, int other, int d · 9 unmodified lines
818ST_FUNC void put_stabs_r(TCCState *s1, const char *str, int type, int other, int desc,817ST_FUNC void put_stabs_r(TCCState *s1, const char *str, int type, int other, int desc,
819 unsigned long value, Section *sec, int sym_index)818 unsigned long value, Section *sec, int sym_index)
820{819{
821 put_stabs(s1, str, type, other, desc, value);
822 put_elf_reloc(symtab_section, stab_section,820 put_elf_reloc(symtab_section, stab_section,
823 stab_section->data_offset - sizeof(unsigned int),821 stab_section->data_offset + 8,
824 R_DATA_32, sym_index);822 sizeof ((Stab_Sym*)0)->n_value == PTR_SIZE ? R_DATA_PTR : R_DATA_32,
823 sym_index);
824 put_stabs(s1, str, type, other, desc, value);
825}825}
826 826
827ST_FUNC void put_stabn(TCCState *s1, int type, int other, int desc, int value)827ST_FUNC void put_stabn(TCCState *s1, int type, int other, int desc, int value)
@@ -990,8 +990,16 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 162 unmodified lines
990 relocate(s1, rel, type, ptr, addr, tgt);990 relocate(s1, rel, type, ptr, addr, tgt);
991 }991 }
992 /* if the relocation is allocated, we change its symbol table */992 /* if the relocation is allocated, we change its symbol table */
993 if (sr->sh_flags & SHF_ALLOC)993 if (sr->sh_flags & SHF_ALLOC) {
994 sr->link = s1->dynsym;994 sr->link = s1->dynsym;
995 if (s1->output_type == TCC_OUTPUT_DLL) {
996 size_t r = (uint8_t*)qrel - sr->data;
997 if (sizeof ((Stab_Sym*)0)->n_value < PTR_SIZE
998 && 0 == strcmp(s->name, ".stab"))
999 r = 0; /* cannot apply 64bit relocation to 32bit value */
1000 sr->data_offset = sr->sh_size = r;
1001 }
1002 }
995}1003}
996 1004
997#ifndef ELF_OBJ_ONLY1005#ifndef ELF_OBJ_ONLY
@@ -1268,16 +1276,20 @@ static void put_dt(Section *dynamic, int dt, addr_t val) · 270 unmodified lines
1268}1276}
1269#endif1277#endif
1270 1278
1279ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, long offs)
1280{
1281 int shn = sec ? sec->sh_num : offs ? SHN_ABS : SHN_UNDEF;
1282 if (sec && offs == -1)
1283 offs = sec->data_offset;
1284 return set_elf_sym(symtab_section, offs, 0,
1285 ELFW(ST_INFO)(name ? STB_GLOBAL : STB_LOCAL, STT_NOTYPE), 0, shn, name);
1286}
1287
1271static void add_init_array_defines(TCCState *s1, const char *section_name)1288static void add_init_array_defines(TCCState *s1, const char *section_name)
1272{1289{
1273 Section *s;1290 Section *s;
1274 long end_offset;1291 long end_offset;
1275 char sym_start[1024];1292 char buf[1024];
1276 char sym_end[1024];
1277
1278 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1279 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1280
1281 s = find_section(s1, section_name);1293 s = find_section(s1, section_name);
1282 if (!s) {1294 if (!s) {
1283 end_offset = 0;1295 end_offset = 0;
@@ -1285,15 +1297,10 @@ static void add_init_array_defines(TCCState *s1, const char *section_name) · 1 unmodified line
1285 } else {1297 } else {
1286 end_offset = s->data_offset;1298 end_offset = s->data_offset;
1287 }1299 }
1288 1300 snprintf(buf, sizeof(buf), "__%s_start", section_name + 1);
1289 set_elf_sym(symtab_section,1301 set_global_sym(s1, buf, s, 0);
1290 0, 0,1302 snprintf(buf, sizeof(buf), "__%s_end", section_name + 1);
1291 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,1303 set_global_sym(s1, buf, s, end_offset);
1292 s->sh_num, sym_start);
1293 set_elf_sym(symtab_section,
1294 end_offset, 0,
1295 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1296 s->sh_num, sym_end);
1297}1304}
1298 1305
1299#ifndef TCC_TARGET_PE1306#ifndef TCC_TARGET_PE
@@ -1305,33 +1312,92 @@ static int tcc_add_support(TCCState *s1, const char *filename) · 5 unmodified lines
1305}1312}
1306#endif1313#endif
1307 1314
1308static void add_array (const char *section, TCCState *s1, Sym *sym, int sh_type)1315ST_FUNC void add_array (TCCState *s1, const char *sec, int c)
1309{1316{
1310 Section *s;1317 Section *s;
1311 unsigned char *ptr;1318 s = find_section(s1, sec);
1312 1319 s->sh_flags |= SHF_WRITE;
1313 s = find_section(s1, section);
1314 if (s) {
1315 s->sh_flags |= SHF_WRITE;
1316#ifndef TCC_TARGET_PE1320#ifndef TCC_TARGET_PE
1317 s->sh_type = sh_type;1321 s->sh_type = sec[1] == 'i' ? SHT_INIT_ARRAY : SHT_FINI_ARRAY;
1318#endif1322#endif
1319 ptr = section_ptr_add(s, PTR_SIZE);1323 put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c);
1320 memset (ptr, 0, PTR_SIZE);1324 section_ptr_add(s, PTR_SIZE);
1321 put_elf_reloc (s1->symtab, s, ptr - s->data, R_DATA_PTR, sym->c);
1322 }
1323}1325}
1324 1326
1325ST_FUNC void add_init_array (TCCState *s1, Sym *sym)1327#ifdef CONFIG_TCC_BCHECK
1328ST_FUNC void tcc_add_bcheck(TCCState *s1)
1326{1329{
1327 add_array (".init_array", s1, sym, SHT_INIT_ARRAY);1330 if (0 == s1->do_bounds_check)
1331 return;
1332 section_ptr_add(bounds_section, sizeof(addr_t));
1333}
1334#endif
1335
1336#ifdef CONFIG_TCC_BACKTRACE
1337static void put_ptr(TCCState *s1, Section *s, int offs)
1338{
1339 int c;
1340 c = set_global_sym(s1, NULL, s, offs);
1341 s = data_section;
1342 put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c);
1343 section_ptr_add(s, PTR_SIZE);
1344}
1345
1346/* set symbol to STB_LOCAL and resolve. The point is to not export it as
1347 a dynamic symbol to allow so's to have one each with a different value. */
1348static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset)
1349{
1350 int c = find_elf_sym(s1->symtab, name);
1351 if (c) {
1352 ElfW(Sym) *esym = (ElfW(Sym)*)s1->symtab->data + c;
1353 esym->st_info = ELFW(ST_INFO)(STB_LOCAL, STT_NOTYPE);
1354 esym->st_value = offset;
1355 esym->st_shndx = s->sh_num;
1356 }
1328}1357}
1329 1358
1330ST_FUNC void add_fini_array (TCCState *s1, Sym *sym)1359ST_FUNC void tcc_add_btstub(TCCState *s1)
1331{1360{
1332 add_array (".fini_array", s1, sym, SHT_FINI_ARRAY);1361 Section *s;
1362 int n, o, b;
1363 CString cstr;
1364
1365 s = data_section;
1366 o = s->data_offset;
1367 /* create (part of) a struct rt_context (see tccrun.c) */
1368 put_ptr(s1, stab_section, 0);
1369 put_ptr(s1, stab_section, -1);
1370 put_ptr(s1, stab_section->link, 0);
1371 section_ptr_add(s, 3 * PTR_SIZE);
1372 /* prog_base */
1373 put_elf_reloc(s1->symtab, s, s->data_offset, R_DATA_PTR, 0);
1374 section_ptr_add(s, PTR_SIZE);
1375 n = 2 * PTR_SIZE, b = 0;
1376#ifdef CONFIG_TCC_BCHECK
1377 if (s1->do_bounds_check) {
1378 put_ptr(s1, bounds_section, 0);
1379 n -= PTR_SIZE, b = 1;
1380 }
1381#endif
1382 section_ptr_add(s, n);
1383
1384 cstr_new(&cstr);
1385 cstr_printf(&cstr,
1386 " extern void __bt_init(),*__rt_info[],__bt_init_dll();"
1387 "__attribute__((constructor)) static void __bt_init_rt(){");
1388#ifdef TCC_TARGET_PE
1389 if (s1->output_type == TCC_OUTPUT_DLL)
1390 cstr_printf(&cstr, "__bt_init_dll(%d);", b);
1391#endif
1392 cstr_printf(&cstr, "__bt_init(__rt_info,%d);}",
1393 s1->output_type == TCC_OUTPUT_DLL ? 0 : s1->rt_num_callers + 1);
1394 tcc_compile_string(s1, cstr.data);
1395 cstr_free(&cstr);
1396 set_local_sym(s1, "__rt_info", s, o);
1333}1397}
1398#endif
1334 1399
1400#ifndef TCC_TARGET_PE
1335/* add tcc runtime libraries */1401/* add tcc runtime libraries */
1336ST_FUNC void tcc_add_runtime(TCCState *s1)1402ST_FUNC void tcc_add_runtime(TCCState *s1)
1337{1403{
@@ -1340,7 +1406,6 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) · 2 unmodified lines
1340 tcc_add_bcheck(s1);1406 tcc_add_bcheck(s1);
1341#endif1407#endif
1342 tcc_add_pragma_libs(s1);1408 tcc_add_pragma_libs(s1);
1343#ifndef TCC_TARGET_PE
1344 /* add libc */1409 /* add libc */
1345 if (!s1->nostdlib) {1410 if (!s1->nostdlib) {
1346 tcc_add_library_err(s1, "c");1411 tcc_add_library_err(s1, "c");
@@ -1356,7 +1421,17 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) · 9 unmodified lines
1356 if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) {1421 if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) {
1357 tcc_add_library_err(s1, "pthread");1422 tcc_add_library_err(s1, "pthread");
1358 tcc_add_library_err(s1, "dl");1423 tcc_add_library_err(s1, "dl");
1359 tcc_add_support(s1, TCC_LIBBCHECK);1424 tcc_add_support(s1, "bcheck.o");
1425 }
1426#endif
1427#ifdef CONFIG_TCC_BACKTRACE
1428 if (s1->do_backtrace) {
1429 if (s1->output_type == TCC_OUTPUT_EXE)
1430 tcc_add_support(s1, "bt-exe.o");
1431 if (s1->output_type != TCC_OUTPUT_DLL)
1432 tcc_add_support(s1, "bt-log.o");
1433 if (s1->output_type != TCC_OUTPUT_MEMORY)
1434 tcc_add_btstub(s1);
1360 }1435 }
1361#endif1436#endif
1362 tcc_add_support(s1, TCC_LIBTCC1);1437 tcc_add_support(s1, TCC_LIBTCC1);
@@ -1364,8 +1439,8 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) · 1 unmodified line
1364 if (s1->output_type != TCC_OUTPUT_MEMORY)1439 if (s1->output_type != TCC_OUTPUT_MEMORY)
1365 tcc_add_crt(s1, "crtn.o");1440 tcc_add_crt(s1, "crtn.o");
1366 }1441 }
1367#endif
1368}1442}
1443#endif
1369 1444
1370/* add various standard linker symbols (must be done after the1445/* add various standard linker symbols (must be done after the
1371 sections are filled (for example after allocating common1446 sections are filled (for example after allocating common
@@ -1376,59 +1451,39 @@ static void tcc_add_linker_symbols(TCCState *s1) · 4 unmodified lines
1376 int i;1451 int i;
1377 Section *s;1452 Section *s;
1378 1453
1379 set_elf_sym(symtab_section,1454 set_global_sym(s1, "_etext", text_section, -1);
1380 text_section->data_offset, 0,1455 set_global_sym(s1, "_edata", data_section, -1);
1381 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,1456 set_global_sym(s1, "_end", bss_section, -1);
1382 text_section->sh_num, "_etext");
1383 set_elf_sym(symtab_section,
1384 data_section->data_offset, 0,
1385 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1386 data_section->sh_num, "_edata");
1387 set_elf_sym(symtab_section,
1388 bss_section->data_offset, 0,
1389 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1390 bss_section->sh_num, "_end");
1391#ifdef TCC_TARGET_RISCV641457#ifdef TCC_TARGET_RISCV64
1392 /* XXX should be .sdata+0x800, not .data+0x800 */1458 /* XXX should be .sdata+0x800, not .data+0x800 */
1393 set_elf_sym(symtab_section,1459 set_global_sym(s1, "__global_pointer$", data_section, 0x800);
1394 0x800, 0,
1395 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1396 data_section->sh_num, "__global_pointer$");
1397#endif1460#endif
1398 /* horrible new standard ldscript defines */1461 /* horrible new standard ldscript defines */
1399 add_init_array_defines(s1, ".preinit_array");1462 add_init_array_defines(s1, ".preinit_array");
1400 add_init_array_defines(s1, ".init_array");1463 add_init_array_defines(s1, ".init_array");
1401 add_init_array_defines(s1, ".fini_array");1464 add_init_array_defines(s1, ".fini_array");
1402
1403 /* add start and stop symbols for sections whose name can be1465 /* add start and stop symbols for sections whose name can be
1404 expressed in C */1466 expressed in C */
1405 for(i = 1; i < s1->nb_sections; i++) {1467 for(i = 1; i < s1->nb_sections; i++) {
1406 s = s1->sections[i];1468 s = s1->sections[i];
1407 if (s->sh_type == SHT_PROGBITS &&1469 if ((s->sh_flags & SHF_ALLOC)
1408 (s->sh_flags & SHF_ALLOC)) {1470 && (s->sh_type == SHT_PROGBITS
1471 || s->sh_type == SHT_STRTAB)) {
1409 const char *p;1472 const char *p;
1410 int ch;
1411
1412 /* check if section name can be expressed in C */1473 /* check if section name can be expressed in C */
1413 p = s->name;1474 p = s->name;
1414 for(;;) {1475 for(;;) {
1415 ch = *p;1476 int c = *p;
1416 if (!ch)1477 if (!c)
1417 break;1478 break;
1418 if (!isid(ch) && !isnum(ch))1479 if (!isid(c) && !isnum(c))
1419 goto next_sec;1480 goto next_sec;
1420 p++;1481 p++;
1421 }1482 }
1422 snprintf(buf, sizeof(buf), "__start_%s", s->name);1483 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1423 set_elf_sym(symtab_section,1484 set_global_sym(s1, buf, s, 0);
1424 0, 0,
1425 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1426 s->sh_num, buf);
1427 snprintf(buf, sizeof(buf), "__stop_%s", s->name);1485 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1428 set_elf_sym(symtab_section,1486 set_global_sym(s1, buf, s, -1);
1429 s->data_offset, 0,
1430 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1431 s->sh_num, buf);
1432 }1487 }
1433 next_sec: ;1488 next_sec: ;
1434 }1489 }
@@ -1699,8 +1754,8 @@ static int alloc_sec_names(TCCState *s1, int file_type, Section *strsec) · 264 unmodified lines
1699 !(s->sh_flags & SHF_ALLOC) &&1754 !(s->sh_flags & SHF_ALLOC) &&
1700 (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC) &&1755 (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC) &&
1701 prepare_dynamic_rel(s1, s)) {1756 prepare_dynamic_rel(s1, s)) {
1702 if (s1->sections[s->sh_info]->sh_flags & SHF_EXECINSTR)1757 if (!(s1->sections[s->sh_info]->sh_flags & SHF_WRITE))
1703 textrel = 1;1758 textrel = 1;
1704 } else1759 } else
1705#endif1760#endif
1706 if ((s1->do_debug && s->sh_type != SHT_RELX) ||1761 if ((s1->do_debug && s->sh_type != SHT_RELX) ||
@@ -1814,9 +1869,10 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 107 unmodified lines
1814 if (s == interp) {1869 if (s == interp) {
1815 if (k != 0)1870 if (k != 0)
1816 continue;1871 continue;
1817 } else if (s->sh_type == SHT_DYNSYM ||1872 } else if ((s->sh_type == SHT_DYNSYM ||
1818 s->sh_type == SHT_STRTAB ||1873 s->sh_type == SHT_STRTAB ||
1819 s->sh_type == SHT_HASH) {1874 s->sh_type == SHT_HASH)
1875 && !strstr(s->name, ".stab")) {
1820 if (k != 1)1876 if (k != 1)
1821 continue;1877 continue;
1822 } else if (s->sh_type == SHT_RELX) {1878 } else if (s->sh_type == SHT_RELX) {
@@ -2060,7 +2116,6 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, · 237 unmodified lines
2060 Section *s;2116 Section *s;
2061 ElfW(Ehdr) ehdr;2117 ElfW(Ehdr) ehdr;
2062 ElfW(Shdr) shdr, *sh;2118 ElfW(Shdr) shdr, *sh;
2063 ElfW(Sym) *sym;
2064 2119
2065 file_type = s1->output_type;2120 file_type = s1->output_type;
2066 shnum = s1->nb_sections;2121 shnum = s1->nb_sections;
@@ -2131,10 +2186,6 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, · 64 unmodified lines
2131 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));2186 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2132 2187
2133 sort_syms(s1, symtab_section);2188 sort_syms(s1, symtab_section);
2134 if (s1->dynsym)
2135 for_each_elem(s1->dynsym, 0, sym, ElfW(Sym))
2136 if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL)
2137 s1->dynsym->sh_info++;
2138 for(i = 1; i < s1->nb_sections; i++) {2189 for(i = 1; i < s1->nb_sections; i++) {
2139 s = s1->sections[sec_order[i]];2190 s = s1->sections[sec_order[i]];
2140 if (s->sh_type != SHT_NOBITS) {2191 if (s->sh_type != SHT_NOBITS) {
@@ -2842,12 +2893,6 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize) · 701 unmodified lines
2842 for (p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {2893 for (p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2843 Section *s = symtab_section;2894 Section *s = symtab_section;
2844 sym_index = find_elf_sym(s, p);2895 sym_index = find_elf_sym(s, p);
2845#ifdef TCC_TARGET_PE /* windows DLL's don't have UNDEF syms */
2846 if (sym_index == 0) {
2847 s = s1->dynsymtab_section;
2848 sym_index = find_elf_sym(s, p);
2849 }
2850#endif
2851 if (!sym_index)2896 if (!sym_index)
2852 continue;2897 continue;
2853 sym = &((ElfW(Sym) *)s->data)[sym_index];2898 sym = &((ElfW(Sym) *)s->data)[sym_index];
tccgen.c+34−52
@@ -103,7 +103,7 @@ ST_DATA struct switch_t { · 102 unmodified lines
103 struct scope *scope;103 struct scope *scope;
104} *cur_switch; /* current switch */104} *cur_switch; /* current switch */
105 105
106#define MAX_TEMP_LOCAL_VARIABLE_NUMBER 0x4106#define MAX_TEMP_LOCAL_VARIABLE_NUMBER 8
107/*list of temporary local variables on the stack in current function. */107/*list of temporary local variables on the stack in current function. */
108ST_DATA struct temp_local_variable {108ST_DATA struct temp_local_variable {
109 int location; //offset on stack. Svalue.c.i109 int location; //offset on stack. Svalue.c.i
@@ -375,11 +375,10 @@ static BufferedFile* put_new_file(TCCState *s1) · 265 unmodified lines
375ST_FUNC void tcc_debug_line(TCCState *s1)375ST_FUNC void tcc_debug_line(TCCState *s1)
376{376{
377 BufferedFile *f;377 BufferedFile *f;
378 if (!s1->do_debug || !(f = put_new_file(s1)))378 if (!s1->do_debug
379 return;379 || cur_text_section != text_section
380 if (last_line_num == f->line_num)380 || !(f = put_new_file(s1))
381 return;381 || last_line_num == f->line_num)
382 if (text_section != cur_text_section)
383 return;382 return;
384 if (func_ind != -1) {383 if (func_ind != -1) {
385 put_stabn(s1, N_SLINE, 0, f->line_num, ind - func_ind);384 put_stabn(s1, N_SLINE, 0, f->line_num, ind - func_ind);
@@ -409,9 +408,7 @@ ST_FUNC void tcc_debug_funcend(TCCState *s1, int size) · 23 unmodified lines
409{408{
410 if (!s1->do_debug)409 if (!s1->do_debug)
411 return;410 return;
412#if 0 // this seems to confuse gnu tools
413 put_stabn(s1, N_FUN, 0, 0, size);411 put_stabn(s1, N_FUN, 0, 0, size);
414#endif
415}412}
416 413
417/* put alternative filename */414/* put alternative filename */
@@ -2592,7 +2589,6 @@ redo: · 2174 unmodified lines
2592 vswap();2589 vswap();
2593 gen_op('-');2590 gen_op('-');
2594 }2591 }
2595 vtop[-1].r &= ~VT_MUSTBOUND;
2596 gen_bounded_ptr_add();2592 gen_bounded_ptr_add();
2597 } else2593 } else
2598#endif2594#endif
@@ -3428,6 +3424,10 @@ ST_FUNC void vstore(void) · 829 unmodified lines
3428 3424
3429 /* destination */3425 /* destination */
3430 vswap();3426 vswap();
3427#ifdef CONFIG_TCC_BCHECK
3428 if (vtop->r & VT_MUSTBOUND)
3429 gbound(); /* check would be wrong after gaddrof() */
3430#endif
3431 vtop->type.t = VT_PTR;3431 vtop->type.t = VT_PTR;
3432 gaddrof();3432 gaddrof();
3433 3433
@@ -3444,8 +3444,11 @@ ST_FUNC void vstore(void) · 10 unmodified lines
3444 3444
3445 vswap();3445 vswap();
3446 /* source */3446 /* source */
3447 vtop->r &= ~VT_MUSTBOUND;
3448 vpushv(vtop - 2);3447 vpushv(vtop - 2);
3448#ifdef CONFIG_TCC_BCHECK
3449 if (vtop->r & VT_MUSTBOUND)
3450 gbound();
3451#endif
3449 vtop->type.t = VT_PTR;3452 vtop->type.t = VT_PTR;
3450 gaddrof();3453 gaddrof();
3451 /* type size */3454 /* type size */
@@ -3662,11 +3665,11 @@ redo: · 210 unmodified lines
3662 }3665 }
3663 case TOK_CONSTRUCTOR1:3666 case TOK_CONSTRUCTOR1:
3664 case TOK_CONSTRUCTOR2:3667 case TOK_CONSTRUCTOR2:
3665 ad->constructor = 1;3668 ad->f.func_ctor = 1;
3666 break;3669 break;
3667 case TOK_DESTRUCTOR1:3670 case TOK_DESTRUCTOR1:
3668 case TOK_DESTRUCTOR2:3671 case TOK_DESTRUCTOR2:
3669 ad->destructor = 1;3672 ad->f.func_dtor = 1;
3670 break;3673 break;
3671 case TOK_SECTION1:3674 case TOK_SECTION1:
3672 case TOK_SECTION2:3675 case TOK_SECTION2:
@@ -4958,6 +4961,10 @@ ST_FUNC void unary(void) · 1285 unmodified lines
4958 Sym *s;4961 Sym *s;
4959 AttributeDef ad;4962 AttributeDef ad;
4960 4963
4964 /* generate line number info */
4965 if (tcc_state->do_debug)
4966 tcc_debug_line(tcc_state);
4967
4961 sizeof_caller = in_sizeof;4968 sizeof_caller = in_sizeof;
4962 in_sizeof = 0;4969 in_sizeof = 0;
4963 type.ref = NULL;4970 type.ref = NULL;
@@ -5522,7 +5529,7 @@ special_math_val: · 558 unmodified lines
5522 vtop->r |= VT_LVAL;5529 vtop->r |= VT_LVAL;
5523#ifdef CONFIG_TCC_BCHECK5530#ifdef CONFIG_TCC_BCHECK
5524 /* if bound checking, the referenced pointer must be checked */5531 /* if bound checking, the referenced pointer must be checked */
5525 if (tcc_state->do_bounds_check && (vtop->r & VT_VALMASK) != VT_LOCAL)5532 if (tcc_state->do_bounds_check)
5526 vtop->r |= VT_MUSTBOUND;5533 vtop->r |= VT_MUSTBOUND;
5527#endif5534#endif
5528 }5535 }
@@ -5538,15 +5545,6 @@ special_math_val: · 9 unmodified lines
5538 Sym *sa;5545 Sym *sa;
5539 int nb_args, ret_nregs, ret_align, regsize, variadic;5546 int nb_args, ret_nregs, ret_align, regsize, variadic;
5540 5547
5541#ifdef CONFIG_TCC_BCHECK
5542 if (tcc_state->do_bounds_check && (vtop->r & VT_SYM) && vtop->sym->v == TOK_alloca) {
5543 addr_t *bounds_ptr;
5544
5545 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(addr_t));
5546 bounds_ptr[0] = 1; /* marks alloca/vla used */
5547 bounds_ptr[1] = 0;
5548 }
5549#endif
5550 /* function call */5548 /* function call */
5551 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {5549 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
5552 /* pointer test (no array accepted) */5550 /* pointer test (no array accepted) */
@@ -6514,10 +6512,10 @@ again: · 961 unmodified lines
6514 }6512 }
6515 6513
6516 prev_scope(&o, is_expr);6514 prev_scope(&o, is_expr);
6517 6515 if (local_scope)
6518 if (0 == local_scope && !nocode_wanted)6516 next();
6517 else if (!nocode_wanted)
6519 check_func_return();6518 check_func_return();
6520 next();
6521 6519
6522 } else if (t == TOK_RETURN) {6520 } else if (t == TOK_RETURN) {
6523 b = (func_vt.t & VT_BTYPE) != VT_VOID;6521 b = (func_vt.t & VT_BTYPE) != VT_VOID;
@@ -7582,16 +7580,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 1058 unmodified lines
7582 gen_vla_sp_save(addr);7580 gen_vla_sp_save(addr);
7583 cur_scope->vla.loc = addr;7581 cur_scope->vla.loc = addr;
7584 cur_scope->vla.num++;7582 cur_scope->vla.num++;
7585#ifdef CONFIG_TCC_BCHECK
7586 if (bcheck) {
7587 addr_t *bounds_ptr;
7588
7589 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(addr_t));
7590 bounds_ptr[0] = 1; /* marks alloca/vla used */
7591 bounds_ptr[1] = 0;
7592 }
7593#endif
7594
7595 } else if (has_init) {7583 } else if (has_init) {
7596 size_t oldreloc_offset = 0;7584 size_t oldreloc_offset = 0;
7597 if (sec && sec->reloc)7585 if (sec && sec->reloc)
@@ -7617,7 +7605,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 19 unmodified lines
7617 7605
7618/* parse a function defined by symbol 'sym' and generate its code in7606/* parse a function defined by symbol 'sym' and generate its code in
7619 'cur_text_section' */7607 'cur_text_section' */
7620static void gen_function(Sym *sym, AttributeDef *ad)7608static void gen_function(Sym *sym)
7621{7609{
7622 /* Initialize VLA state */7610 /* Initialize VLA state */
7623 struct scope f = { 0 };7611 struct scope f = { 0 };
@@ -7632,17 +7620,12 @@ static void gen_function(Sym *sym, AttributeDef *ad) · 8 unmodified lines
7632 }7620 }
7633 /* NOTE: we patch the symbol size later */7621 /* NOTE: we patch the symbol size later */
7634 put_extern_sym(sym, cur_text_section, ind, 0);7622 put_extern_sym(sym, cur_text_section, ind, 0);
7635 7623 if (sym->type.ref->f.func_ctor)
7636 if (ad && ad->constructor) {7624 add_array (tcc_state, ".init_array", sym->c);
7637 add_init_array (tcc_state, sym);7625 if (sym->type.ref->f.func_dtor)
7638 }7626 add_array (tcc_state, ".fini_array", sym->c);
7639 if (ad && ad->destructor) {
7640 add_fini_array (tcc_state, sym);
7641 }
7642
7643 funcname = get_tok_str(sym->v, NULL);7627 funcname = get_tok_str(sym->v, NULL);
7644 func_ind = ind;7628 func_ind = ind;
7645
7646 /* put debug symbol */7629 /* put debug symbol */
7647 tcc_debug_funcstart(tcc_state, sym);7630 tcc_debug_funcstart(tcc_state, sym);
7648 /* push a dummy symbol to enable local sym storage */7631 /* push a dummy symbol to enable local sym storage */
@@ -7675,6 +7658,8 @@ static void gen_function(Sym *sym, AttributeDef *ad) · 26 unmodified lines
7675 ind = 0; /* for safety */7658 ind = 0; /* for safety */
7676 nocode_wanted = 0x80000000;7659 nocode_wanted = 0x80000000;
7677 check_vstack();7660 check_vstack();
7661 /* do this after funcend debug info */
7662 next();
7678}7663}
7679 7664
7680static void gen_inline_functions(TCCState *s)7665static void gen_inline_functions(TCCState *s)
@@ -7698,7 +7683,7 @@ static void gen_inline_functions(TCCState *s) · 17 unmodified lines
7698 begin_macro(fn->func_str, 1);7683 begin_macro(fn->func_str, 1);
7699 next();7684 next();
7700 cur_text_section = text_section;7685 cur_text_section = text_section;
7701 gen_function(sym, NULL);7686 gen_function(sym);
7702 end_macro();7687 end_macro();
7703 7688
7704 inline_generated = 1;7689 inline_generated = 1;
@@ -7866,11 +7851,8 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) · 161 unmodified lines
7866 the compilation unit only if they are used */7851 the compilation unit only if they are used */
7867 if (sym->type.t & VT_INLINE) {7852 if (sym->type.t & VT_INLINE) {
7868 struct InlineFunc *fn;7853 struct InlineFunc *fn;
7869 const char *filename;7854 fn = tcc_malloc(sizeof *fn + strlen(file->filename));
7870 7855 strcpy(fn->filename, file->filename);
7871 filename = file ? file->filename : "";
7872 fn = tcc_malloc(sizeof *fn + strlen(filename));
7873 strcpy(fn->filename, filename);
7874 fn->sym = sym;7856 fn->sym = sym;
7875 skip_or_save_block(&fn->func_str);7857 skip_or_save_block(&fn->func_str);
7876 dynarray_add(&tcc_state->inline_fns,7858 dynarray_add(&tcc_state->inline_fns,
@@ -7880,7 +7862,7 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) · 3 unmodified lines
7880 cur_text_section = ad.section;7862 cur_text_section = ad.section;
7881 if (!cur_text_section)7863 if (!cur_text_section)
7882 cur_text_section = text_section;7864 cur_text_section = text_section;
7883 gen_function(sym, &ad);7865 gen_function(sym);
7884 }7866 }
7885 break;7867 break;
7886 } else {7868 } else {
tccpe.c+176−146
@@ -239,8 +239,6 @@ typedef struct _IMAGE_BASE_RELOCATION { · 238 unmodified lines
239#define IMAGE_SCN_MEM_EXECUTE 0x20000000239#define IMAGE_SCN_MEM_EXECUTE 0x20000000
240#define IMAGE_SCN_MEM_READ 0x40000000240#define IMAGE_SCN_MEM_READ 0x40000000
241#define IMAGE_SCN_MEM_WRITE 0x80000000241#define IMAGE_SCN_MEM_WRITE 0x80000000
242#define IMAGE_SCN_TYPE_NOLOAD 0x00000002
243#define IMAGE_SCN_LNK_REMOVE 0x00000800
244 242
245#pragma pack(pop)243#pragma pack(pop)
246 244
@@ -299,6 +297,7 @@ enum { · 52 unmodified lines
299 sec_other ,297 sec_other ,
300 sec_rsrc ,298 sec_rsrc ,
301 sec_stab ,299 sec_stab ,
300 sec_stabstr ,
302 sec_reloc ,301 sec_reloc ,
303 sec_last302 sec_last
304};303};
@@ -318,12 +317,12 @@ static const DWORD pe_sec_flags[] = { · 13 unmodified lines
318#endif317#endif
319 318
320struct section_info {319struct section_info {
321 int cls, ord;320 int cls;
322 char name[32];321 char name[32];
323 DWORD sh_addr;322 DWORD sh_addr;
324 DWORD sh_size;323 DWORD sh_size;
325 DWORD pe_flags;324 DWORD pe_flags;
326 unsigned char *data;325 Section *sec;
327 DWORD data_size;326 DWORD data_size;
328 IMAGE_SECTION_HEADER ish;327 IMAGE_SECTION_HEADER ish;
329};328};
@@ -359,7 +358,7 @@ struct pe_info { · 29 unmodified lines
359 int subsystem;358 int subsystem;
360 DWORD section_align;359 DWORD section_align;
361 DWORD file_align;360 DWORD file_align;
362 struct section_info *sec_info;361 struct section_info **sec_info;
363 int sec_count;362 int sec_count;
364 struct pe_import_info **imp_info;363 struct pe_import_info **imp_info;
365 int imp_count;364 int imp_count;
@@ -432,12 +431,10 @@ static int dynarray_assoc(void **pp, int n, int key) · 66 unmodified lines
432 return -1;431 return -1;
433}432}
434 433
435#if 0434static DWORD umin(DWORD a, DWORD b)
436ST_FN DWORD umin(DWORD a, DWORD b)
437{435{
438 return a < b ? a : b;436 return a < b ? a : b;
439}437}
440#endif
441 438
442static DWORD umax(DWORD a, DWORD b)439static DWORD umax(DWORD a, DWORD b)
443{440{
@@ -467,26 +464,37 @@ static void pe_set_datadir(struct pe_header *hdr, int dir, DWORD addr, DWORD siz · 23 unmodified lines
467 hdr->opthdr.DataDirectory[dir].Size = size;464 hdr->opthdr.DataDirectory[dir].Size = size;
468}465}
469 466
470static int pe_fwrite(void *data, unsigned len, FILE *fp, DWORD *psum)467struct pe_file {
468 FILE *op;
469 DWORD sum;
470 unsigned pos;
471};
472
473static int pe_fwrite(void *data, int len, struct pe_file *pf)
471{474{
472 if (psum) {475 WORD *p = data;
473 DWORD sum = *psum;476 DWORD sum;
474 WORD *p = data;477 int ret, i;
475 int i;478 pf->pos += (ret = fwrite(data, 1, len, pf->op));
476 for (i = len; i > 0; i -= 2) {479 sum = pf->sum;
477 sum += (i >= 2) ? *p++ : *(BYTE*)p;480 for (i = len; i > 0; i -= 2) {
478 sum = (sum + (sum >> 16)) & 0xFFFF;481 sum += (i >= 2) ? *p++ : *(BYTE*)p;
479 }482 sum = (sum + (sum >> 16)) & 0xFFFF;
480 *psum = sum;
481 }483 }
482 return len == fwrite(data, 1, len, fp) ? 0 : -1;484 pf->sum = sum;
485 return len == ret ? 0 : -1;
483}486}
484 487
485static void pe_fpad(FILE *fp, DWORD new_pos)488static void pe_fpad(struct pe_file *pf, DWORD new_pos)
486{489{
487 DWORD pos = ftell(fp);490 char buf[256];
488 while (++pos <= new_pos)491 int n, diff = new_pos - pf->pos;
489 fputc(0, fp);492 memset(buf, 0, sizeof buf);
493 while (diff > 0) {
494 diff -= n = umin(diff, sizeof buf);
495 fwrite(buf, n, 1, pf->op);
496 }
497 pf->pos = new_pos;
490}498}
491 499
492/*----------------------------------------------------------------------------*/500/*----------------------------------------------------------------------------*/
@@ -598,14 +606,14 @@ static int pe_write(struct pe_info *pe) · 105 unmodified lines
598 struct pe_header pe_header = pe_template;606 struct pe_header pe_header = pe_template;
599 607
600 int i;608 int i;
601 FILE *op;609 struct pe_file pf = {0};
602 DWORD file_offset, sum;610 DWORD file_offset;
603 struct section_info *si;611 struct section_info *si;
604 IMAGE_SECTION_HEADER *psh;612 IMAGE_SECTION_HEADER *psh;
605 TCCState *s1 = pe->s1;613 TCCState *s1 = pe->s1;
606 614
607 op = fopen(pe->filename, "wb");615 pf.op = fopen(pe->filename, "wb");
608 if (NULL == op) {616 if (NULL == pf.op) {
609 tcc_error_noabort("could not write '%s': %s", pe->filename, strerror(errno));617 tcc_error_noabort("could not write '%s': %s", pe->filename, strerror(errno));
610 return -1;618 return -1;
611 }619 }
@@ -624,7 +632,7 @@ static int pe_write(struct pe_info *pe) · 12 unmodified lines
624 DWORD addr, size;632 DWORD addr, size;
625 const char *sh_name;633 const char *sh_name;
626 634
627 si = pe->sec_info + i;635 si = pe->sec_info[i];
628 sh_name = si->name;636 sh_name = si->name;
629 addr = si->sh_addr - pe->imagebase;637 addr = si->sh_addr - pe->imagebase;
630 size = si->sh_size;638 size = si->sh_size;
@@ -663,20 +671,18 @@ static int pe_write(struct pe_info *pe) · 32 unmodified lines
663 break;671 break;
664 }672 }
665 673
666 if (pe->thunk == pe->s1->sections[si->ord]) {674 if (pe->imp_size) {
667 if (pe->imp_size) {675 pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IMPORT,
668 pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IMPORT,676 pe->imp_offs, pe->imp_size);
669 pe->imp_offs + addr, pe->imp_size);677 pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IAT,
670 pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IAT,678 pe->iat_offs, pe->iat_size);
671 pe->iat_offs + addr, pe->iat_size);679 }
672 }680 if (pe->exp_size) {
673 if (pe->exp_size) {681 pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_EXPORT,
674 pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_EXPORT,682 pe->exp_offs, pe->exp_size);
675 pe->exp_offs + addr, pe->exp_size);
676 }
677 }683 }
678 684
679 strncpy((char*)psh->Name, sh_name, sizeof psh->Name);685 memcpy(psh->Name, sh_name, umin(strlen(sh_name), sizeof psh->Name));
680 686
681 psh->Characteristics = si->pe_flags;687 psh->Characteristics = si->pe_flags;
682 psh->VirtualAddress = addr;688 psh->VirtualAddress = addr;
@@ -707,25 +713,29 @@ static int pe_write(struct pe_info *pe) · 24 unmodified lines
707 pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;713 pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;
708 pe_header.filehdr.Characteristics |= pe->s1->pe_characteristics;714 pe_header.filehdr.Characteristics |= pe->s1->pe_characteristics;
709 715
710 sum = 0;716 pe_fwrite(&pe_header, sizeof pe_header, &pf);
711 pe_fwrite(&pe_header, sizeof pe_header, op, &sum);
712 for (i = 0; i < pe->sec_count; ++i)717 for (i = 0; i < pe->sec_count; ++i)
713 pe_fwrite(&pe->sec_info[i].ish, sizeof(IMAGE_SECTION_HEADER), op, &sum);718 pe_fwrite(&pe->sec_info[i]->ish, sizeof(IMAGE_SECTION_HEADER), &pf);
714 pe_fpad(op, pe->sizeofheaders);719
720 file_offset = pe->sizeofheaders;
715 for (i = 0; i < pe->sec_count; ++i) {721 for (i = 0; i < pe->sec_count; ++i) {
716 si = pe->sec_info + i;722 Section *s;
717 psh = &si->ish;723 si = pe->sec_info[i];
718 if (si->data_size) {724 for (s = si->sec; s; s = s->prev) {
719 pe_fwrite(si->data, si->data_size, op, &sum);725 pe_fpad(&pf, file_offset);
720 file_offset = psh->PointerToRawData + psh->SizeOfRawData;726 pe_fwrite(s->data, s->data_offset, &pf);
721 pe_fpad(op, file_offset);727 if (s->prev)
728 file_offset += s->prev->sh_addr - s->sh_addr;
722 }729 }
730 file_offset = si->ish.PointerToRawData + si->ish.SizeOfRawData;
731 pe_fpad(&pf, file_offset);
723 }732 }
724 733
725 pe_header.opthdr.CheckSum = sum + file_offset;734 pf.sum += file_offset;
726 fseek(op, offsetof(struct pe_header, opthdr.CheckSum), SEEK_SET);735 fseek(pf.op, offsetof(struct pe_header, opthdr.CheckSum), SEEK_SET);
727 pe_fwrite(&pe_header.opthdr.CheckSum, sizeof pe_header.opthdr.CheckSum, op, NULL);736 pe_fwrite(&pf.sum, sizeof (DWORD), &pf);
728 fclose (op);737
738 fclose (pf.op);
729#ifndef _WIN32739#ifndef _WIN32
730 chmod(pe->filename, 0777);740 chmod(pe->filename, 0777);
731#endif741#endif
@@ -796,16 +806,15 @@ static void pe_build_imports(struct pe_info *pe) · 64 unmodified lines
796 return;806 return;
797 807
798 pe_align_section(pe->thunk, 16);808 pe_align_section(pe->thunk, 16);
799
800 pe->imp_offs = dll_ptr = pe->thunk->data_offset;
801 pe->imp_size = (ndlls + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR);809 pe->imp_size = (ndlls + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR);
802 pe->iat_offs = dll_ptr + pe->imp_size;
803 pe->iat_size = (sym_cnt + ndlls) * sizeof(ADDR3264);810 pe->iat_size = (sym_cnt + ndlls) * sizeof(ADDR3264);
811 dll_ptr = pe->thunk->data_offset;
812 thk_ptr = dll_ptr + pe->imp_size;
813 ent_ptr = thk_ptr + pe->iat_size;
814 pe->imp_offs = dll_ptr + rva_base;
815 pe->iat_offs = thk_ptr + rva_base;
804 section_ptr_add(pe->thunk, pe->imp_size + 2*pe->iat_size);816 section_ptr_add(pe->thunk, pe->imp_size + 2*pe->iat_size);
805 817
806 thk_ptr = pe->iat_offs;
807 ent_ptr = pe->iat_offs + pe->iat_size;
808
809 for (i = 0; i < pe->imp_count; ++i) {818 for (i = 0; i < pe->imp_count; ++i) {
810 IMAGE_IMPORT_DESCRIPTOR *hdr;819 IMAGE_IMPORT_DESCRIPTOR *hdr;
811 int k, n, dllindex;820 int k, n, dllindex;
@@ -895,7 +904,7 @@ static void pe_build_exports(struct pe_info *pe) · 83 unmodified lines
895{904{
896 ElfW(Sym) *sym;905 ElfW(Sym) *sym;
897 int sym_index, sym_end;906 int sym_index, sym_end;
898 DWORD rva_base, func_o, name_o, ord_o, str_o;907 DWORD rva_base, base_o, func_o, name_o, ord_o, str_o;
899 IMAGE_EXPORT_DIRECTORY *hdr;908 IMAGE_EXPORT_DIRECTORY *hdr;
900 int sym_count, ord;909 int sym_count, ord;
901 struct pe_sort_sym **sorted, *p;910 struct pe_sort_sym **sorted, *p;
@@ -937,13 +946,13 @@ static void pe_build_exports(struct pe_info *pe) · 35 unmodified lines
937 pe_align_section(pe->thunk, 16);946 pe_align_section(pe->thunk, 16);
938 dllname = tcc_basename(pe->filename);947 dllname = tcc_basename(pe->filename);
939 948
940 pe->exp_offs = pe->thunk->data_offset;949 base_o = pe->thunk->data_offset;
941 func_o = pe->exp_offs + sizeof(IMAGE_EXPORT_DIRECTORY);950 func_o = base_o + sizeof(IMAGE_EXPORT_DIRECTORY);
942 name_o = func_o + sym_count * sizeof (DWORD);951 name_o = func_o + sym_count * sizeof (DWORD);
943 ord_o = name_o + sym_count * sizeof (DWORD);952 ord_o = name_o + sym_count * sizeof (DWORD);
944 str_o = ord_o + sym_count * sizeof(WORD);953 str_o = ord_o + sym_count * sizeof(WORD);
945 954
946 hdr = section_ptr_add(pe->thunk, str_o - pe->exp_offs);955 hdr = section_ptr_add(pe->thunk, str_o - base_o);
947 hdr->Characteristics = 0;956 hdr->Characteristics = 0;
948 hdr->Base = 1;957 hdr->Base = 1;
949 hdr->NumberOfFunctions = sym_count;958 hdr->NumberOfFunctions = sym_count;
@@ -985,7 +994,9 @@ static void pe_build_exports(struct pe_info *pe) · 35 unmodified lines
985 if (op)994 if (op)
986 fprintf(op, "%s\n", name);995 fprintf(op, "%s\n", name);
987 }996 }
988 pe->exp_size = pe->thunk->data_offset - pe->exp_offs;997
998 pe->exp_offs = base_o + rva_base;
999 pe->exp_size = pe->thunk->data_offset - base_o;
989 dynarray_reset(&sorted, &sym_count);1000 dynarray_reset(&sorted, &sym_count);
990 if (op)1001 if (op)
991 fclose(op);1002 fclose(op);
@@ -994,18 +1005,19 @@ static void pe_build_exports(struct pe_info *pe) · 2 unmodified lines
994/* ------------------------------------------------------------- */1005/* ------------------------------------------------------------- */
995static void pe_build_reloc (struct pe_info *pe)1006static void pe_build_reloc (struct pe_info *pe)
996{1007{
997 DWORD offset, block_ptr, addr;1008 DWORD offset, block_ptr, sh_addr, addr;
998 int count, i;1009 int count, i;
999 ElfW_Rel *rel, *rel_end;1010 ElfW_Rel *rel, *rel_end;
1000 Section *s = NULL, *sr;1011 Section *s = NULL, *sr;
1012 struct pe_reloc_header *hdr;
1001 1013
1002 offset = addr = block_ptr = count = i = 0;1014 sh_addr = offset = block_ptr = count = i = 0;
1003 rel = rel_end = NULL;1015 rel = rel_end = NULL;
1004 1016
1005 for(;;) {1017 for(;;) {
1006 if (rel < rel_end) {1018 if (rel < rel_end) {
1007 int type = ELFW(R_TYPE)(rel->r_info);1019 int type = ELFW(R_TYPE)(rel->r_info);
1008 addr = rel->r_offset + s->sh_addr;1020 addr = rel->r_offset + sh_addr;
1009 ++ rel;1021 ++ rel;
1010 if (type != REL_TYPE_DIRECT)1022 if (type != REL_TYPE_DIRECT)
1011 continue;1023 continue;
@@ -1022,28 +1034,30 @@ static void pe_build_reloc (struct pe_info *pe) · 10 unmodified lines
1022 }1034 }
1023 -- rel;1035 -- rel;
1024 1036
1025 } else if (i < pe->sec_count) {1037 } else if (s) {
1026 sr = (s = pe->s1->sections[pe->sec_info[i++].ord])->reloc;1038 sr = s->reloc;
1027 if (sr) {1039 if (sr) {
1028 rel = (ElfW_Rel *)sr->data;1040 rel = (ElfW_Rel *)sr->data;
1029 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);1041 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
1042 sh_addr = s->sh_addr;
1030 }1043 }
1044 s = s->prev;
1031 continue;1045 continue;
1032 }
1033 1046
1034 if (count) {1047 } else if (i < pe->sec_count) {
1035 /* store the last block and ready for a new one */1048 s = pe->sec_info[i]->sec, ++i;
1036 struct pe_reloc_header *hdr;1049 continue;
1037 if (count & 1) /* align for DWORDS */
1038 section_ptr_add(pe->reloc, sizeof(WORD)), ++count;
1039 hdr = (struct pe_reloc_header *)(pe->reloc->data + block_ptr);
1040 hdr -> offset = offset - pe->imagebase;
1041 hdr -> size = count * sizeof(WORD) + sizeof(struct pe_reloc_header);
1042 count = 0;
1043 }
1044 1050
1045 if (rel >= rel_end)1051 } else if (!count)
1046 break;1052 break;
1053
1054 /* fill the last block and ready for a new one */
1055 if (count & 1) /* align for DWORDS */
1056 section_ptr_add(pe->reloc, sizeof(WORD)), ++count;
1057 hdr = (struct pe_reloc_header *)(pe->reloc->data + block_ptr);
1058 hdr -> offset = offset - pe->imagebase;
1059 hdr -> size = count * sizeof(WORD) + sizeof(struct pe_reloc_header);
1060 count = 0;
1047 }1061 }
1048}1062}
1049 1063
@@ -1072,13 +1086,14 @@ static int pe_section_class(Section *s) · 22 unmodified lines
1072 if (flags & SHF_WRITE)1086 if (flags & SHF_WRITE)
1073 return sec_bss;1087 return sec_bss;
1074 }1088 }
1075 return sec_other;
1076 } else {1089 } else {
1077 if (0 == strcmp(name, ".reloc"))1090 if (0 == strcmp(name, ".reloc"))
1078 return sec_reloc;1091 return sec_reloc;
1079 if (0 == memcmp(name, ".stab", 5))
1080 return sec_stab;
1081 }1092 }
1093 if (0 == memcmp(name, ".stab", 5))
1094 return name[5] ? sec_stabstr : sec_stab;
1095 if (flags & SHF_ALLOC)
1096 return sec_other;
1082 return -1;1097 return -1;
1083}1098}
1084 1099
@@ -1092,47 +1107,62 @@ static int pe_assign_addresses (struct pe_info *pe) · 7 unmodified lines
1092 1107
1093 if (PE_DLL == pe->type)1108 if (PE_DLL == pe->type)
1094 pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0);1109 pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0);
1095
1096 // pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);1110 // pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
1097 1111
1098 section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int));1112 section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int));
1099 for (o = k = 0 ; k < sec_last; ++k) {1113 for (o = k = 0 ; k < sec_last; ++k) {
1100 for (i = 1; i < pe->s1->nb_sections; ++i) {1114 for (i = 1; i < pe->s1->nb_sections; ++i) {
1101 s = pe->s1->sections[i];1115 s = pe->s1->sections[i];
1102 if (k == pe_section_class(s)) {1116 if (k == pe_section_class(s))
1103 // printf("%s %d\n", s->name, k);
1104 s->sh_addr = pe->imagebase;
1105 section_order[o++] = i;1117 section_order[o++] = i;
1106 }
1107 }1118 }
1108 }1119 }
1109 1120
1110 pe->sec_info = tcc_mallocz(o * sizeof (struct section_info));1121 si = NULL;
1111 addr = pe->imagebase + 1;1122 addr = pe->imagebase + 1;
1112 1123
1113 for (i = 0; i < o; ++i)1124 for (i = 0; i < o; ++i) {
1114 {
1115 k = section_order[i];1125 k = section_order[i];
1116 s = pe->s1->sections[k];1126 s = pe->s1->sections[k];
1117 c = pe_section_class(s);1127 c = pe_section_class(s);
1118 si = &pe->sec_info[pe->sec_count];
1119 1128
1120#ifdef PE_MERGE_DATA1129 if ((c == sec_stab || c == sec_stabstr) && 0 == pe->s1->do_debug)
1121 if (c == sec_bss && pe->sec_count && si[-1].cls == sec_data) {
1122 /* append .bss to .data */
1123 s->sh_addr = addr = ((addr-1) | (s->sh_addralign-1)) + 1;
1124 addr += s->data_offset;
1125 si[-1].sh_size = addr - si[-1].sh_addr;
1126 continue;1130 continue;
1127 }1131
1132#ifdef PE_MERGE_DATA
1133 if (c == sec_bss)
1134 c = sec_data;
1128#endif1135#endif
1129 if (c == sec_stab && 0 == pe->s1->do_debug)1136 if (si && c == si->cls) {
1137 /* merge with previous section */
1138 s->sh_addr = addr = ((addr - 1) | (16 - 1)) + 1;
1139 } else {
1140 si = NULL;
1141 s->sh_addr = addr = pe_virtual_align(pe, addr);
1142 }
1143
1144 if (c == sec_data && NULL == pe->thunk)
1145 pe->thunk = s;
1146
1147 if (s == pe->thunk) {
1148 pe_build_imports(pe);
1149 pe_build_exports(pe);
1150 }
1151 if (s == pe->reloc)
1152 pe_build_reloc (pe);
1153
1154 if (0 == s->data_offset)
1130 continue;1155 continue;
1131 1156
1157 if (si)
1158 goto add_section;
1159
1160 si = tcc_mallocz(sizeof *si);
1161 dynarray_add(&pe->sec_info, &pe->sec_count, si);
1162
1132 strcpy(si->name, s->name);1163 strcpy(si->name, s->name);
1133 si->cls = c;1164 si->cls = c;
1134 si->ord = k;1165 si->sh_addr = addr;
1135 si->sh_addr = s->sh_addr = addr = pe_virtual_align(pe, addr);
1136 1166
1137 si->pe_flags = IMAGE_SCN_MEM_READ;1167 si->pe_flags = IMAGE_SCN_MEM_READ;
1138 if (s->sh_flags & SHF_EXECINSTR)1168 if (s->sh_flags & SHF_EXECINSTR)
@@ -1143,48 +1173,35 @@ static int pe_assign_addresses (struct pe_info *pe) · 4 unmodified lines
1143 si->pe_flags |= IMAGE_SCN_CNT_INITIALIZED_DATA;1173 si->pe_flags |= IMAGE_SCN_CNT_INITIALIZED_DATA;
1144 if (s->sh_flags & SHF_WRITE)1174 if (s->sh_flags & SHF_WRITE)
1145 si->pe_flags |= IMAGE_SCN_MEM_WRITE;1175 si->pe_flags |= IMAGE_SCN_MEM_WRITE;
1146 if (0 == (s->sh_flags & SHF_ALLOC)) {1176 if (0 == (s->sh_flags & SHF_ALLOC))
1147 si->pe_flags |= IMAGE_SCN_MEM_DISCARDABLE;1177 si->pe_flags |= IMAGE_SCN_MEM_DISCARDABLE;
1148 if (c == sec_stab)
1149 si->pe_flags |= 0x802; //IMAGE_SCN_TYPE_NOLOAD|IMAGE_SCN_LNK_REMOVE
1150 }
1151
1152 if (c == sec_data && NULL == pe->thunk)
1153 pe->thunk = s;
1154 1178
1155 if (s == pe->thunk) {1179add_section:
1156 pe_build_imports(pe);1180 addr += s->data_offset;
1157 pe_build_exports(pe);1181 si->sh_size = addr - si->sh_addr;
1182 if (s->sh_type != SHT_NOBITS) {
1183 Section **ps = &si->sec;
1184 while (*ps)
1185 ps = &(*ps)->prev;
1186 *ps = s, s->prev = NULL;
1187 si->data_size = si->sh_size;
1158 }1188 }
1159 1189 //printf("%08x %05x %08x %s\n", si->sh_addr, si->sh_size, si->pe_flags, s->name);
1160 if (c == sec_reloc)
1161 pe_build_reloc (pe);
1162
1163 if (s->data_offset)
1164 {
1165 if (s->sh_type != SHT_NOBITS) {
1166 si->data = s->data;
1167 si->data_size = s->data_offset;
1168 }
1169
1170 addr += s->data_offset;
1171 si->sh_size = s->data_offset;
1172 ++pe->sec_count;
1173 }
1174 //printf("%08x %05x %s %08x\n", si->sh_addr, si->sh_size, si->name, si->pe_flags);
1175 }1190 }
1191 tcc_free(section_order);
1176#if 01192#if 0
1177 for (i = 1; i < pe->s1->nb_sections; ++i) {1193 for (i = 1; i < pe->s1->nb_sections; ++i) {
1178 Section *s = pe->s1->sections[i];1194 Section *s = pe->s1->sections[i];
1179 int type = s->sh_type;1195 int type = s->sh_type;
1180 int flags = s->sh_flags;1196 int flags = s->sh_flags;
1181 printf("section %-16s %-10s %5x %s,%s,%s\n",1197 printf("section %-16s %-10s %08x %04x %s,%s,%s\n",
1182 s->name,1198 s->name,
1183 type == SHT_PROGBITS ? "progbits" :1199 type == SHT_PROGBITS ? "progbits" :
1184 type == SHT_NOBITS ? "nobits" :1200 type == SHT_NOBITS ? "nobits" :
1185 type == SHT_SYMTAB ? "symtab" :1201 type == SHT_SYMTAB ? "symtab" :
1186 type == SHT_STRTAB ? "strtab" :1202 type == SHT_STRTAB ? "strtab" :
1187 type == SHT_RELX ? "rel" : "???",1203 type == SHT_RELX ? "rel" : "???",
1204 s->sh_addr,
1188 s->data_offset,1205 s->data_offset,
1189 flags & SHF_ALLOC ? "alloc" : "",1206 flags & SHF_ALLOC ? "alloc" : "",
1190 flags & SHF_WRITE ? "write" : "",1207 flags & SHF_WRITE ? "write" : "",
@@ -1193,8 +1210,6 @@ static int pe_assign_addresses (struct pe_info *pe) · 2 unmodified lines
1193 }1210 }
1194 pe->s1->verbose = 2;1211 pe->s1->verbose = 2;
1195#endif1212#endif
1196
1197 tcc_free(section_order);
1198 return 0;1213 return 0;
1199}1214}
1200 1215
@@ -1860,8 +1875,6 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) · 659 unmodified lines
1860 else1875 else
1861 if (TCC_OUTPUT_DLL == s1->output_type) {1876 if (TCC_OUTPUT_DLL == s1->output_type) {
1862 pe_type = PE_DLL;1877 pe_type = PE_DLL;
1863 /* need this for 'tccelf.c:relocate_section()' */
1864 s1->output_type = TCC_OUTPUT_EXE;
1865 }1878 }
1866 else {1879 else {
1867 pe_type = PE_EXE;1880 pe_type = PE_EXE;
@@ -1881,24 +1894,34 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) · 13 unmodified lines
1881 if (!s1->leading_underscore || strchr(start_symbol, '@'))1894 if (!s1->leading_underscore || strchr(start_symbol, '@'))
1882 ++start_symbol;1895 ++start_symbol;
1883 1896
1884 /* grab the startup code from libtcc1 */1897#ifdef CONFIG_TCC_BACKTRACE
1898 if (s1->do_backtrace) {
1899#ifdef CONFIG_TCC_BCHECK
1900 if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL)
1901 tcc_add_support(s1, "bcheck.o");
1902#endif
1903 if (s1->output_type == TCC_OUTPUT_EXE)
1904 tcc_add_support(s1, "bt-exe.o");
1905 if (s1->output_type == TCC_OUTPUT_DLL)
1906 tcc_add_support(s1, "bt-dll.o");
1907 if (s1->output_type != TCC_OUTPUT_DLL)
1908 tcc_add_support(s1, "bt-log.o");
1909 if (s1->output_type != TCC_OUTPUT_MEMORY)
1910 tcc_add_btstub(s1);
1911 }
1912#endif
1913
1914 /* grab the startup code from libtcc1.a */
1885#ifdef TCC_IS_NATIVE1915#ifdef TCC_IS_NATIVE
1886 if (TCC_OUTPUT_MEMORY != s1->output_type || s1->runtime_main)1916 if (TCC_OUTPUT_MEMORY != s1->output_type || s1->runtime_main)
1887#endif1917#endif
1888 set_elf_sym(symtab_section,1918 set_global_sym(s1, start_symbol, NULL, 0);
1889 0, 0,
1890 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1891 SHN_UNDEF, start_symbol);
1892 1919
1893 if (0 == s1->nostdlib) {1920 if (0 == s1->nostdlib) {
1894 static const char *libs[] = {1921 static const char *libs[] = {
1895 "msvcrt", "kernel32", "", "user32", "gdi32", NULL1922 "msvcrt", "kernel32", "", "user32", "gdi32", NULL
1896 };1923 };
1897 const char **pp, *p;1924 const char **pp, *p;
1898#ifdef TCC_IS_NATIVE
1899 if (s1->do_bounds_check)
1900 tcc_add_support(s1, TCC_LIBBCHECK);
1901#endif
1902 tcc_add_support(s1, TCC_LIBTCC1);1925 tcc_add_support(s1, TCC_LIBTCC1);
1903 for (pp = libs; 0 != (p = *pp); ++pp) {1926 for (pp = libs; 0 != (p = *pp); ++pp) {
1904 if (*p)1927 if (*p)
@@ -1907,6 +1930,10 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) · 2 unmodified lines
1907 break;1930 break;
1908 }1931 }
1909 }1932 }
1933
1934 /* need this for 'tccelf.c:relocate_section()' */
1935 if (TCC_OUTPUT_DLL == s1->output_type)
1936 s1->output_type = TCC_OUTPUT_EXE;
1910 if (TCC_OUTPUT_MEMORY == s1->output_type)1937 if (TCC_OUTPUT_MEMORY == s1->output_type)
1911 pe_type = PE_RUN;1938 pe_type = PE_RUN;
1912 pe->type = pe_type;1939 pe->type = pe_type;
@@ -1970,7 +1997,10 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) · 57 unmodified lines
1970 pe.filename = filename;1997 pe.filename = filename;
1971 pe.s1 = s1;1998 pe.s1 = s1;
1972 1999
1973 tcc_add_runtime(s1);2000#ifdef CONFIG_TCC_BCHECK
2001 tcc_add_bcheck(s1);
2002#endif
2003 tcc_add_pragma_libs(s1);
1974 pe_add_runtime(s1, &pe);2004 pe_add_runtime(s1, &pe);
1975 resolve_common_syms(s1);2005 resolve_common_syms(s1);
1976 pe_set_options(s1, &pe);2006 pe_set_options(s1, &pe);
@@ -1995,7 +2025,7 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) · 18 unmodified lines
1995 ret = -1;2025 ret = -1;
1996 else2026 else
1997 ret = pe_write(&pe);2027 ret = pe_write(&pe);
1998 tcc_free(pe.sec_info);2028 dynarray_reset(&pe.sec_info, &pe.sec_count);
1999 } else {2029 } else {
2000#ifdef TCC_IS_NATIVE2030#ifdef TCC_IS_NATIVE
2001 pe.thunk = data_section;2031 pe.thunk = data_section;
tccpp.c+9−8
@@ -109,9 +109,7 @@ ST_FUNC void expect(const char *msg) · 108 unmodified lines
109/* ------------------------------------------------------------------------- */109/* ------------------------------------------------------------------------- */
110/* Custom allocator for tiny objects */110/* Custom allocator for tiny objects */
111 111
112#ifndef __BOUNDS_CHECKING_ON
113#define USE_TAL112#define USE_TAL
114#endif
115 113
116#ifndef USE_TAL114#ifndef USE_TAL
117#define tal_free(al, p) tcc_free(p)115#define tal_free(al, p) tcc_free(p)
@@ -250,7 +248,7 @@ static void *tal_realloc_impl(TinyAlloc **pal, void *p, unsigned size TAL_DEBUG_ · 132 unmodified lines
250tail_call:248tail_call:
251 is_own = (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size);249 is_own = (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size);
252 if ((!p || is_own) && size <= al->limit) {250 if ((!p || is_own) && size <= al->limit) {
253 if (al->p + adj_size + sizeof(tal_header_t) < al->buffer + al->size) {251 if (al->p - al->buffer + adj_size + sizeof(tal_header_t) < al->size) {
254 header = (tal_header_t *)al->p;252 header = (tal_header_t *)al->p;
255 header->size = adj_size;253 header->size = adj_size;
256#ifdef TAL_DEBUG254#ifdef TAL_DEBUG
@@ -1958,7 +1956,11 @@ include_done: · 1701 unmodified lines
1958 if (tok == TOK_STR) {1956 if (tok == TOK_STR) {
1959 if (file->true_filename == file->filename)1957 if (file->true_filename == file->filename)
1960 file->true_filename = tcc_strdup(file->filename);1958 file->true_filename = tcc_strdup(file->filename);
1961 tcc_debug_putfile(s1, (char *)tokc.str.data);1959 /* prepend directory from real file */
1960 pstrcpy(buf, sizeof buf, file->true_filename);
1961 *tcc_basename(buf) = 0;
1962 pstrcat(buf, sizeof buf, (char *)tokc.str.data);
1963 tcc_debug_putfile(s1, buf);
1962 } else if (parse_flags & PARSE_FLAG_ASM_FILE)1964 } else if (parse_flags & PARSE_FLAG_ASM_FILE)
1963 break;1965 break;
1964 else1966 else
@@ -3529,9 +3531,6 @@ no_subst: · 1564 unmodified lines
3529/* return next token with macro substitution */3531/* return next token with macro substitution */
3530ST_FUNC void next(void)3532ST_FUNC void next(void)
3531{3533{
3532 /* generate line number info */
3533 if (tcc_state->do_debug)
3534 tcc_debug_line(tcc_state);
3535 redo:3534 redo:
3536 if (parse_flags & PARSE_FLAG_SPACES)3535 if (parse_flags & PARSE_FLAG_SPACES)
3537 next_nomacro_spc();3536 next_nomacro_spc();
@@ -3607,6 +3606,8 @@ ST_FUNC void preprocess_start(TCCState *s1, int is_asm) · 69 unmodified lines
3607 cstr_printf(&cstr, "#define __BASE_FILE__ \"%s\"\n", file->filename);3606 cstr_printf(&cstr, "#define __BASE_FILE__ \"%s\"\n", file->filename);
3608 if (is_asm)3607 if (is_asm)
3609 cstr_printf(&cstr, "#define __ASSEMBLER__ 1\n");3608 cstr_printf(&cstr, "#define __ASSEMBLER__ 1\n");
3609 if (s1->output_type == TCC_OUTPUT_MEMORY)
3610 cstr_printf(&cstr, "#define __TCC_RUN__ 1\n");
3610 if (s1->cmdline_incl.size)3611 if (s1->cmdline_incl.size)
3611 cstr_cat(&cstr, s1->cmdline_incl.data, s1->cmdline_incl.size);3612 cstr_cat(&cstr, s1->cmdline_incl.data, s1->cmdline_incl.size);
3612 //printf("%s\n", (char*)cstr.data);3613 //printf("%s\n", (char*)cstr.data);
@@ -3657,7 +3658,7 @@ ST_FUNC void tccpp_new(TCCState *s) · 44 unmodified lines
3657 cstr_realloc(&cstr_buf, STRING_MAX_SIZE);3658 cstr_realloc(&cstr_buf, STRING_MAX_SIZE);
3658 tok_str_new(&tokstr_buf);3659 tok_str_new(&tokstr_buf);
3659 tok_str_realloc(&tokstr_buf, TOKSTR_MAX_SIZE);3660 tok_str_realloc(&tokstr_buf, TOKSTR_MAX_SIZE);
3660 3661
3661 tok_ident = TOK_IDENT;3662 tok_ident = TOK_IDENT;
3662 p = tcc_keywords;3663 p = tcc_keywords;
3663 while (*p) {3664 while (*p) {
tccrun.c+188−149
@@ -23,27 +23,36 @@ · 22 unmodified lines
23/* only native compiler supports -run */23/* only native compiler supports -run */
24#ifdef TCC_IS_NATIVE24#ifdef TCC_IS_NATIVE
25 25
26#ifndef _WIN32
27# include <sys/mman.h>
28#endif
29
30#ifdef CONFIG_TCC_BACKTRACE26#ifdef CONFIG_TCC_BACKTRACE
31static void set_exception_handler(void);27typedef struct rt_context
32#ifdef _WIN32
33static DWORD s1_for_run_idx;
34void set_s1_for_run(TCCState *s)
35{28{
36 if (!s1_for_run_idx)29 /* --> tccelf.c:tcc_add_btstub wants those below in that order: */
37 s1_for_run_idx = TlsAlloc();30 Stab_Sym *stab_sym, *stab_sym_end;
38 TlsSetValue(s1_for_run_idx, s);31 char *stab_str;
39}32 ElfW(Sym) *esym_start, *esym_end;
40#define get_s1_for_run() ((TCCState*)TlsGetValue(s1_for_run_idx))33 char *elf_str;
41#else34 addr_t prog_base;
42/* XXX: add tls support for linux */35 void *bounds_start;
43static TCCState *s1_for_run;36 struct rt_context *next;
44#define set_s1_for_run(s) (s1_for_run = s)37 /* <-- */
45#define get_s1_for_run() s1_for_run38 int num_callers;
46#endif39 addr_t ip, fp, sp;
40 void *top_func;
41 jmp_buf jmp_buf;
42 char do_jmp;
43} rt_context;
44
45static rt_context g_rtctxt;
46static void set_exception_handler(void);
47static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap);
48static void rt_exit(int code);
49#endif /* CONFIG_TCC_BACKTRACE */
50
51/* defined when included from lib/bt.c */
52#ifndef CONFIG_TCC_BACKTRACE_ONLY
53
54#ifndef _WIN32
55# include <sys/mman.h>
47#endif56#endif
48 57
49static void set_pages_executable(TCCState *s1, void *ptr, unsigned long length);58static void set_pages_executable(TCCState *s1, void *ptr, unsigned long length);
@@ -113,72 +122,73 @@ ST_FUNC void tcc_run_free(TCCState *s1) · 63 unmodified lines
113#endif122#endif
114 }123 }
115 tcc_free(s1->runtime_mem);124 tcc_free(s1->runtime_mem);
116 if (get_s1_for_run() == s1)125}
117 set_s1_for_run(NULL);126
127static void run_cdtors(TCCState *s1, const char *start, const char *end)
128{
129 void **a = tcc_get_symbol(s1, start);
130 void **b = tcc_get_symbol(s1, end);
131 while (a != b)
132 ((void(*)(void))*a++)();
118}133}
119 134
120/* launch the compiled program with the given arguments */135/* launch the compiled program with the given arguments */
121LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)136LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
122{137{
123/* PE target overwrites runtime_main */138 int (*prog_main)(int, char **), ret;
124#ifndef TCC_TARGET_PE139#ifdef CONFIG_TCC_BACKTRACE
125 typedef void (*init_array_func)(int, char **, char **);140 rt_context *rc = &g_rtctxt;
126 typedef void (*fini_array_func)(void);
127 init_array_func *__init_array_start;
128 init_array_func *__init_array_end;
129 fini_array_func *__fini_array_start;
130 fini_array_func *__fini_array_end;
131#endif141#endif
132 int i;
133 int ret;
134 int (*prog_main)(int, char **);
135 142
136 s1->runtime_main = s1->nostdlib ? "_start" : "main";143 s1->runtime_main = s1->nostdlib ? "_start" : "main";
137 if ((s1->dflag & 16) && !find_elf_sym(s1->symtab, s1->runtime_main))144 if ((s1->dflag & 16) && !find_elf_sym(s1->symtab, s1->runtime_main))
138 return 0;145 return 0;
146#ifdef CONFIG_TCC_BACKTRACE
147 if (s1->do_debug)
148 tcc_add_symbol(s1, "exit", rt_exit);
149#endif
139 if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)150 if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
140 return -1;151 return -1;
141 prog_main = tcc_get_symbol_err(s1, s1->runtime_main);152 prog_main = tcc_get_symbol_err(s1, s1->runtime_main);
142 153
143#ifdef CONFIG_TCC_BACKTRACE154#ifdef CONFIG_TCC_BACKTRACE
155 memset(rc, 0, sizeof *rc);
144 if (s1->do_debug) {156 if (s1->do_debug) {
157 void *p;
158 rc->stab_sym = (Stab_Sym *)stab_section->data;
159 rc->stab_sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
160 rc->stab_str = (char *)stab_section->link->data;
161 rc->esym_start = (ElfW(Sym) *)(symtab_section->data);
162 rc->esym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
163 rc->elf_str = (char *)symtab_section->link->data;
164 rc->top_func = tcc_get_symbol(s1, "main");
165 rc->num_callers = s1->rt_num_callers;
166 rc->do_jmp = 1;
167 if ((p = tcc_get_symbol(s1, "__rt_error")))
168 *(void**)p = _rt_error;
169#ifdef CONFIG_TCC_BCHECK
170 if (s1->do_bounds_check) {
171 if ((p = tcc_get_symbol(s1, "__bound_init")))
172 ((void(*)(void*))p)(bounds_section->data);
173 }
174#endif
145 set_exception_handler();175 set_exception_handler();
146 s1->rt_prog_main = prog_main;
147 /* set global state pointer for exception handlers*/
148 set_s1_for_run(s1);
149 }176 }
150#endif177#endif
151 178
152 errno = 0; /* clean errno value */179 errno = 0; /* clean errno value */
153 180 fflush(stdout);
154#ifdef CONFIG_TCC_BCHECK181 fflush(stderr);
155 if (s1->do_bounds_check)182 run_cdtors(s1, "__init_array_start", "__init_array_end");
156 /* set error function */183#ifdef CONFIG_TCC_BACKTRACE
157 s1->rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");184 if (!rc->do_jmp || !(ret = setjmp(rc->jmp_buf)))
158#endif
159
160#ifndef TCC_TARGET_PE
161 __init_array_start = tcc_get_symbol_err(s1, "__init_array_start");
162 __init_array_end = tcc_get_symbol_err(s1, "__init_array_end");
163 __fini_array_start = tcc_get_symbol_err(s1, "__fini_array_start");
164 __fini_array_end = tcc_get_symbol_err(s1, "__fini_array_end");
165
166 if (__init_array_start && __init_array_end) {
167 i = 0;
168 while (&__init_array_start[i] != __init_array_end)
169 (*__init_array_start[i++])(argc, argv, environ);
170 }
171#endif185#endif
172 186 {
173 ret = (*prog_main)(argc, argv);187 ret = prog_main(argc, argv);
174
175#ifndef TCC_TARGET_PE
176 if (__fini_array_start && __fini_array_end) {
177 i = 0;
178 while (&__fini_array_end[i] != __fini_array_start)
179 (*__fini_array_end[--i])();
180 }188 }
181#endif189 run_cdtors(s1, "__fini_array_start", "__fini_array_end");
190 if ((s1->dflag & 16) && ret)
191 fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp);
182 return ret;192 return ret;
183}193}
184 194
@@ -336,11 +346,10 @@ static void win64_del_function_table(void *p) · 151 unmodified lines
336 }346 }
337}347}
338#endif348#endif
339 349#endif //ndef CONFIG_TCC_BACKTRACE_ONLY
340/* ------------------------------------------------------------- */350/* ------------------------------------------------------------- */
341#ifdef CONFIG_TCC_BACKTRACE351#ifdef CONFIG_TCC_BACKTRACE
342 352
343#define INCLUDE_STACK_SIZE 32
344static int rt_vprintf(const char *fmt, va_list ap)353static int rt_vprintf(const char *fmt, va_list ap)
345{354{
346 int ret = vfprintf(stderr, fmt, ap);355 int ret = vfprintf(stderr, fmt, ap);
@@ -358,21 +367,22 @@ static int rt_printf(const char *fmt, ...) · 11 unmodified lines
358 return r;367 return r;
359}368}
360 369
370#define INCLUDE_STACK_SIZE 32
371
361/* print the position in the source file of PC value 'pc' by reading372/* print the position in the source file of PC value 'pc' by reading
362 the stabs debug information */373 the stabs debug information */
363static addr_t rt_printline(TCCState *s1, addr_t wanted_pc, const char *msg)374static addr_t rt_printline (rt_context *rc, addr_t wanted_pc,
375 const char *msg, const char *skip)
364{376{
365 char func_name[128];377 char func_name[128];
366 addr_t func_addr, last_pc, pc;378 addr_t func_addr, last_pc, pc;
367 const char *incl_files[INCLUDE_STACK_SIZE];379 const char *incl_files[INCLUDE_STACK_SIZE];
368 int incl_index, last_incl_index, len, last_line_num, i;380 int incl_index, last_incl_index, len, last_line_num, i;
369 const char *str, *p;381 const char *str, *p;
382 ElfW(Sym) *esym;
383 Stab_Sym *sym;
370 384
371 ElfW(Sym) *esym_start = NULL, *esym_end = NULL, *esym;385next:
372 Stab_Sym *stab_sym = NULL, *stab_sym_end = NULL, *sym;
373 char *stab_str = NULL;
374 char *elf_str = NULL;
375
376 func_name[0] = '\0';386 func_name[0] = '\0';
377 func_addr = 0;387 func_addr = 0;
378 incl_index = 0;388 incl_index = 0;
@@ -380,19 +390,8 @@ static addr_t rt_printline(TCCState *s1, addr_t wanted_pc, const char *msg) · 1 unmodified line
380 last_line_num = 1;390 last_line_num = 1;
381 last_incl_index = 0;391 last_incl_index = 0;
382 392
383 if (stab_section) {393 for (sym = rc->stab_sym + 1; sym < rc->stab_sym_end; ++sym) {
384 stab_sym = (Stab_Sym *)stab_section->data;394 str = rc->stab_str + sym->n_strx;
385 stab_sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
386 stab_str = (char *) stab_section->link->data;
387 }
388 if (symtab_section) {
389 esym_start = (ElfW(Sym) *)(symtab_section->data);
390 esym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
391 elf_str = (char *) symtab_section->link->data;
392 }
393
394 for (sym = stab_sym + 1; sym < stab_sym_end; ++sym) {
395 str = stab_str + sym->n_strx;
396 pc = sym->n_value;395 pc = sym->n_value;
397 396
398 switch(sym->n_type) {397 switch(sym->n_type) {
@@ -406,16 +405,18 @@ static addr_t rt_printline(TCCState *s1, addr_t wanted_pc, const char *msg) · 7 unmodified lines
406 if (sym->n_strx == 0) /* end of function */405 if (sym->n_strx == 0) /* end of function */
407 goto rel_pc;406 goto rel_pc;
408 abs_pc:407 abs_pc:
409 if (sizeof pc == 8)408 if (sizeof sym->n_value < PTR_SIZE) {
410 /* Stab_Sym.n_value is only 32bits */409 /* Stab_Sym.n_value is only 32bits */
411 pc |= wanted_pc & 0xffffffff00000000ULL;410 //fprintf(stderr, "pc = %p %p %p\n", pc, rc->prog_base, wanted_pc), fflush(stderr);
411 pc += rc->prog_base;
412 }
412 break;413 break;
413 rel_pc:414 rel_pc:
414 pc += func_addr;415 pc += func_addr;
415 break;416 break;
416 }417 }
417 418
418 if (pc > wanted_pc && wanted_pc > last_pc)419 if (pc >= wanted_pc && wanted_pc >= last_pc)
419 goto found;420 goto found;
420 421
421 switch(sym->n_type) {422 switch(sym->n_type) {
@@ -434,8 +435,6 @@ static addr_t rt_printline(TCCState *s1, addr_t wanted_pc, const char *msg) · 12 unmodified lines
434 last_pc = pc;435 last_pc = pc;
435 last_line_num = sym->n_desc;436 last_line_num = sym->n_desc;
436 last_incl_index = incl_index;437 last_incl_index = incl_index;
437 if (pc == wanted_pc)
438 goto found;
439 break;438 break;
440 /* include files */439 /* include files */
441 case N_BINCL:440 case N_BINCL:
@@ -468,31 +467,38 @@ static addr_t rt_printline(TCCState *s1, addr_t wanted_pc, const char *msg) · 26 unmodified lines
468 }467 }
469 }468 }
470 469
470 func_name[0] = '\0';
471 func_addr = 0;
472 last_incl_index = 0;
473
471 /* we try symtab symbols (no line number info) */474 /* we try symtab symbols (no line number info) */
472 for (esym = esym_start + 1; esym < esym_end; ++esym) {475 for (esym = rc->esym_start + 1; esym < rc->esym_end; ++esym) {
473 int type = ELFW(ST_TYPE)(esym->st_info);476 int type = ELFW(ST_TYPE)(esym->st_info);
474 if (type == STT_FUNC || type == STT_GNU_IFUNC) {477 if (type == STT_FUNC || type == STT_GNU_IFUNC) {
475 if (wanted_pc >= esym->st_value &&478 if (wanted_pc >= esym->st_value &&
476 wanted_pc < esym->st_value + esym->st_size) {479 wanted_pc < esym->st_value + esym->st_size) {
477 pstrcpy(func_name, sizeof(func_name),480 pstrcpy(func_name, sizeof(func_name),
478 elf_str + esym->st_name);481 rc->elf_str + esym->st_name);
479 func_addr = esym->st_value;482 func_addr = esym->st_value;
480 last_incl_index = 0;
481 goto found;483 goto found;
482 }484 }
483 }485 }
484 }486 }
485 /* did not find any info: */
486 rt_printf("%s %p ???", msg, (void*)wanted_pc);
487 return 0;
488 487
489 found:488 if ((rc = rc->next))
489 goto next;
490
491found:
490 i = last_incl_index;492 i = last_incl_index;
491 if (i > 0)493 if (i > 0) {
492 rt_printf("%s:%d: ", incl_files[--i], last_line_num);494 str = incl_files[--i];
493 rt_printf("%s %p", msg, (void*)wanted_pc);495 if (skip[0] && strstr(str, skip))
494 if (func_name[0] != '\0')496 return (addr_t)-1;
495 rt_printf(" %s()", func_name);497 rt_printf("%s:%d: ", str, last_line_num);
498 } else
499 rt_printf("%08llx : ", (long long)wanted_pc);
500 rt_printf("%s %s", msg, func_name[0] ? func_name : "???");
501#if 0
496 if (--i >= 0) {502 if (--i >= 0) {
497 rt_printf(" (included from ");503 rt_printf(" (included from ");
498 for (;;) {504 for (;;) {
@@ -503,48 +509,79 @@ static addr_t rt_printline(TCCState *s1, addr_t wanted_pc, const char *msg) · 4 unmodified lines
503 }509 }
504 rt_printf(")");510 rt_printf(")");
505 }511 }
512#endif
506 return func_addr;513 return func_addr;
507}514}
508 515
509typedef struct rt_context {
510 addr_t ip, fp, sp, pc;
511} rt_context;
512
513static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level);516static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level);
514 517
515/* emit a run time error at position 'pc' */518static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
516static void rt_error(rt_context *rc, const char *fmt, ...)
517{519{
518 va_list ap;520 rt_context *rc = &g_rtctxt;
519 addr_t pc;521 addr_t pc = 0;
520 int i;522 char skip[100];
521 TCCState *s1;523 int i, level, ret, n;
522 524 const char *a, *b, *msg;
523 s1 = get_s1_for_run();525
524 if (*fmt == ' ') {526 if (fp) {
525 if (s1 && s1->rt_bound_error_msg && *s1->rt_bound_error_msg)527 /* we're called from tcc_backtrace. */
526 fmt = *s1->rt_bound_error_msg;528 rc->fp = (addr_t)fp;
527 else529 rc->ip = (addr_t)ip;
528 ++fmt;530 msg = "";
531 } else {
532 /* we're called from signal/exception handler */
533 msg = "RUNTIME ERROR: ";
529 }534 }
530 535
531 rt_printf("Runtime error: ");536 skip[0] = 0;
532 va_start(ap, fmt);537 /* If fmt is like "^file.c^..." then skip calls from 'file.c' */
533 rt_vprintf(fmt, ap);538 if (fmt[0] == '^' && (b = strchr(a = fmt + 1, fmt[0]))) {
534 va_end(ap);539 memcpy(skip, a, b - a), skip[b - a] = 0;
535 rt_printf("\n");540 fmt = b + 1;
536 541 }
537 if (!s1)
538 return;
539 542
540 for(i=0; i<s1->rt_num_callers; i++) {543 n = rc->num_callers ? rc->num_callers : 6;
541 if (rt_get_caller_pc(&pc, rc, i) < 0)544 for (i = level = 0; level < n; i++) {
545 ret = rt_get_caller_pc(&pc, rc, i);
546 a = "%s";
547 if (ret != -1) {
548 pc = rt_printline(rc, pc, level ? "by" : "at", skip);
549 if (pc == (addr_t)-1)
550 continue;
551 a = ": %s";
552 }
553 if (level == 0) {
554 rt_printf(a, msg);
555 rt_vprintf(fmt, ap);
556 } else if (ret == -1)
542 break;557 break;
543 pc = rt_printline(s1, pc, i ? "by" : "at");
544 rt_printf("\n");558 rt_printf("\n");
545 if (pc == (addr_t)s1->rt_prog_main && pc)559 if (ret == -1 || (pc == (addr_t)rc->top_func && pc))
546 break;560 break;
561 ++level;
547 }562 }
563
564 rc->ip = rc->fp = 0;
565 return 0;
566}
567
568/* emit a run time error at position 'pc' */
569static int rt_error(const char *fmt, ...)
570{
571 va_list ap;
572 int ret;
573 va_start(ap, fmt);
574 ret = _rt_error(0, 0, fmt, ap);
575 va_end(ap);
576 return ret;
577}
578
579static void rt_exit(int code)
580{
581 rt_context *rc = &g_rtctxt;
582 if (rc->do_jmp)
583 longjmp(rc->jmp_buf, code ? code : 256);
584 exit(code);
548}585}
549 586
550/* ------------------------------------------------------------- */587/* ------------------------------------------------------------- */
@@ -621,36 +658,36 @@ static void rt_getcontext(ucontext_t *uc, rt_context *rc) · 70 unmodified lines
621/* signal handler for fatal errors */658/* signal handler for fatal errors */
622static void sig_error(int signum, siginfo_t *siginf, void *puc)659static void sig_error(int signum, siginfo_t *siginf, void *puc)
623{660{
624 rt_context rc;661 rt_context *rc = &g_rtctxt;
662 rt_getcontext(puc, rc);
625 663
626 rt_getcontext(puc, &rc);
627 switch(signum) {664 switch(signum) {
628 case SIGFPE:665 case SIGFPE:
629 switch(siginf->si_code) {666 switch(siginf->si_code) {
630 case FPE_INTDIV:667 case FPE_INTDIV:
631 case FPE_FLTDIV:668 case FPE_FLTDIV:
632 rt_error(&rc, "division by zero");669 rt_error("division by zero");
633 break;670 break;
634 default:671 default:
635 rt_error(&rc, "floating point exception");672 rt_error("floating point exception");
636 break;673 break;
637 }674 }
638 break;675 break;
639 case SIGBUS:676 case SIGBUS:
640 case SIGSEGV:677 case SIGSEGV:
641 rt_error(&rc, " dereferencing invalid pointer");678 rt_error("invalid memory access");
642 break;679 break;
643 case SIGILL:680 case SIGILL:
644 rt_error(&rc, "illegal instruction");681 rt_error("illegal instruction");
645 break;682 break;
646 case SIGABRT:683 case SIGABRT:
647 rt_error(&rc, "abort() called");684 rt_error("abort() called");
648 break;685 break;
649 default:686 default:
650 rt_error(&rc, "caught signal %d", signum);687 rt_error("caught signal %d", signum);
651 break;688 break;
652 }689 }
653 exit(255);690 rt_exit(255);
654}691}
655 692
656#ifndef SA_SIGINFO693#ifndef SA_SIGINFO
@@ -664,7 +701,7 @@ static void set_exception_handler(void) · 7 unmodified lines
664 /* install TCC signal handlers to print debug info on fatal701 /* install TCC signal handlers to print debug info on fatal
665 runtime errors */702 runtime errors */
666 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;703 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
667#ifdef SIGSTKSZ704#if 0//def SIGSTKSZ // this causes signals not to work at all on some (older) linuxes
668 sigact.sa_flags |= SA_ONSTACK;705 sigact.sa_flags |= SA_ONSTACK;
669#endif706#endif
670 sigact.sa_sigaction = sig_error;707 sigact.sa_sigaction = sig_error;
@@ -674,7 +711,7 @@ static void set_exception_handler(void) · 3 unmodified lines
674 sigaction(SIGSEGV, &sigact, NULL);711 sigaction(SIGSEGV, &sigact, NULL);
675 sigaction(SIGBUS, &sigact, NULL);712 sigaction(SIGBUS, &sigact, NULL);
676 sigaction(SIGABRT, &sigact, NULL);713 sigaction(SIGABRT, &sigact, NULL);
677#ifdef SIGSTKSZ714#if 0//def SIGSTKSZ
678 /* This allows stack overflow to be reported instead of a SEGV */715 /* This allows stack overflow to be reported instead of a SEGV */
679 {716 {
680 stack_t ss;717 stack_t ss;
@@ -689,32 +726,35 @@ static void set_exception_handler(void) · 8 unmodified lines
689}726}
690 727
691#else /* WIN32 */728#else /* WIN32 */
729
692/* signal handler for fatal errors */730/* signal handler for fatal errors */
693static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info)731static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info)
694{732{
695 rt_context rc;733 rt_context *rc = &g_rtctxt;
696 unsigned code;734 unsigned code;
735 rt_getcontext(ex_info->ContextRecord, rc);
697 736
698 rt_getcontext(ex_info->ContextRecord, &rc);
699 switch (code = ex_info->ExceptionRecord->ExceptionCode) {737 switch (code = ex_info->ExceptionRecord->ExceptionCode) {
700 case EXCEPTION_ACCESS_VIOLATION:738 case EXCEPTION_ACCESS_VIOLATION:
701 rt_error(&rc, " access violation");739 rt_error("invalid memory access");
702 break;740 break;
703 case EXCEPTION_STACK_OVERFLOW:741 case EXCEPTION_STACK_OVERFLOW:
704 rt_error(&rc, "stack overflow");742 rt_error("stack overflow");
705 break;743 break;
706 case EXCEPTION_INT_DIVIDE_BY_ZERO:744 case EXCEPTION_INT_DIVIDE_BY_ZERO:
707 rt_error(&rc, "division by zero");745 rt_error("division by zero");
708 break;746 break;
709 case EXCEPTION_BREAKPOINT:747 case EXCEPTION_BREAKPOINT:
710 case EXCEPTION_SINGLE_STEP:748 case EXCEPTION_SINGLE_STEP:
711 rc.ip = *(addr_t*)rc.sp;749 rc->ip = *(addr_t*)rc->sp;
712 rt_error(&rc, "^breakpoint/single-step exception:");750 rt_error("breakpoint/single-step exception:");
713 return EXCEPTION_CONTINUE_SEARCH;751 return EXCEPTION_CONTINUE_SEARCH;
714 default:752 default:
715 rt_error(&rc, "caught exception %08x", code);753 rt_error("caught exception %08x", code);
716 break;754 break;
717 }755 }
756 if (rc->do_jmp)
757 rt_exit(255);
718 return EXCEPTION_EXECUTE_HANDLER;758 return EXCEPTION_EXECUTE_HANDLER;
719}759}
720 760
@@ -807,7 +847,6 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) · 86 unmodified lines
807 847
808#endif848#endif
809#endif /* CONFIG_TCC_BACKTRACE */849#endif /* CONFIG_TCC_BACKTRACE */
810
811/* ------------------------------------------------------------- */850/* ------------------------------------------------------------- */
812#ifdef CONFIG_TCC_STATIC851#ifdef CONFIG_TCC_STATIC
813 852
tests/Makefile+23−23
@@ -73,6 +73,7 @@ endif · 72 unmodified lines
73RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS)73RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS)
74DISAS = objdump -d74DISAS = objdump -d
75DUMPTCC = (set -x; $(TOP)/tcc -vv; ldd $(TOP)/tcc; exit 1)75DUMPTCC = (set -x; $(TOP)/tcc -vv; ldd $(TOP)/tcc; exit 1)
76Q = # >/dev/null 2>&1
76 77
77all test :78all test :
78 $(MAKE) clean-s79 $(MAKE) clean-s
@@ -88,7 +89,7 @@ hello-run: ../examples/ex1.c · 9 unmodified lines
88 89
89libtes%: libtcc_tes%$(EXESUF)90libtes%: libtcc_tes%$(EXESUF)
90 @echo ------------ $@ ------------91 @echo ------------ $@ ------------
91 ./libtcc_tes$*$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES)92 ./libtcc_tes$*$(EXESUF) $(TOPSRC)/tcc.c $(TCCFLAGS) $(NATIVE_DEFINES)
92 93
93libtcc_tes%$(EXESUF): libtcc_tes%.c $(LIBTCC)94libtcc_tes%$(EXESUF): libtcc_tes%.c $(LIBTCC)
94 $(CC) -o $@ $^ $(CFLAGS) $(LIBS)95 $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
@@ -105,22 +106,24 @@ test.ref: tcctest.c · 10 unmodified lines
105# auto test106# auto test
106test1 test1b: tcctest.c test.ref107test1 test1b: tcctest.c test.ref
107 @echo ------------ $@ ------------108 @echo ------------ $@ ------------
108 $(TCC) -run $< > test.out1109 $(TCC) -w -run $< > test.out1 $Q
109 @diff -u test.ref test.out1 && echo "Auto Test OK"110 @diff -u test.ref test.out1 && echo "$(AUTO_TEST) OK"
110 111
111# iterated test2 (compile tcc then compile tcctest.c !)112# iterated test2 (compile tcc then compile tcctest.c !)
112test2 test2b: tcctest.c test.ref113test2 test2b: tcctest.c test.ref
113 @echo ------------ $@ ------------114 @echo ------------ $@ ------------
114 $(TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out2115 $(TCC) $(RUN_TCC) $(RUN_TCC) -w -run $< > test.out2 $Q
115 @diff -u test.ref test.out2 && echo "Auto Test2 OK"116 @diff -u test.ref test.out2 && echo "$(AUTO_TEST)2 OK"
116 117
117# iterated test3 (compile tcc then compile tcc then compile tcctest.c !)118# iterated test3 (compile tcc then compile tcc then compile tcctest.c !)
118test3 test3b: tcctest.c test.ref119test3 test3b: tcctest.c test.ref
119 @echo ------------ $@ ------------120 @echo ------------ $@ ------------
120 $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out3121 $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -w -run $< > test.out3 $Q
121 @diff -u test.ref test.out3 && echo "Auto Test3 OK"122 @diff -u test.ref test.out3 && echo "$(AUTO_TEST)3 OK"
122 123
123test%b : TCCFLAGS += -b124AUTO_TEST = Auto Test
125test%b : TCCFLAGS += -b -bt1
126test%b : AUTO_TEST = Auto Bound-Test
124 127
125# binary output test128# binary output test
126test4: tcctest.c test.ref129test4: tcctest.c test.ref
@@ -129,21 +132,21 @@ test4: tcctest.c test.ref · 2 unmodified lines
129 $(TCC) -c -o tcctest3.o $<132 $(TCC) -c -o tcctest3.o $<
130 $(TCC) -o tcctest3 tcctest3.o133 $(TCC) -o tcctest3 tcctest3.o
131 ./tcctest3 > test3.out134 ./tcctest3 > test3.out
132 @if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi135 @if diff -u test.ref test3.out ; then echo "Object $(AUTO_TEST) OK"; fi
133# dynamic output136# dynamic output
134 $(TCC) -o tcctest1 $<137 $(TCC) -o tcctest1 $<
135 ./tcctest1 > test1.out138 ./tcctest1 > test1.out
136 @if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi139 @if diff -u test.ref test1.out ; then echo "Dynamic $(AUTO_TEST) OK"; fi
137# dynamic output + bound check140# dynamic output + bound check
138 $(TCC) -b -o tcctest4 $<141 $(TCC) -b -o tcctest4 $<
139 ./tcctest4 > test4.out142 ./tcctest4 > test4.out
140 @if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi143 @if diff -u test.ref test4.out ; then echo "BCheck $(AUTO_TEST) OK"; fi
141 144
142test4_static: tcctest.c test.ref145test4_static: tcctest.c test.ref
143# static output.146# static output.
144 $(TCC) -static -o tcctest2 $<147 $(TCC) -static -o tcctest2 $<
145 ./tcctest2 > test2.out148 ./tcctest2 > test2.out
146 @if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi149 @if diff -u test.ref test2.out ; then echo "Static $(AUTO_TEST) OK"; fi
147 150
148# use tcc to create libtcc.so/.dll and the tcc(.exe) frontend and run them151# use tcc to create libtcc.so/.dll and the tcc(.exe) frontend and run them
149dlltest:152dlltest:
@@ -164,32 +167,29 @@ memtest: · 14 unmodified lines
164 @echo ------------ $@ ------------167 @echo ------------ $@ ------------
165 $(CC) $(CFLAGS) $(NATIVE_DEFINES) -DMEM_DEBUG=2 $(TOPSRC)/tcc.c $(LIBS) -o memtest-tcc$(EXESUF)168 $(CC) $(CFLAGS) $(NATIVE_DEFINES) -DMEM_DEBUG=2 $(TOPSRC)/tcc.c $(LIBS) -o memtest-tcc$(EXESUF)
166 ./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) $(TOPSRC)/tcc.c $(LIBS)169 ./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) $(TOPSRC)/tcc.c $(LIBS)
167 ./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) $(TOPSRC)/tests/tcctest.c170 ./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) -w $(TOPSRC)/tests/tcctest.c
168
169 171
170# memory and bound check auto test172# memory and bound check auto test
171BOUNDS_OK = 1 4 8 10 14 16 18173BOUNDS_OK = 1 4 8 10 14 16
172BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17174BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17
173 175
174btest: boundtest.c176btest: boundtest.c
175 @echo ------------ $@ ------------177 @echo ------------ $@ ------------
176 @for i in $(BOUNDS_OK); do \178 @for i in $(BOUNDS_OK); do \
177 echo ; echo --- boundtest $$i ---; \
178 if $(TCC) -b -run $< $$i ; then \179 if $(TCC) -b -run $< $$i ; then \
179 echo succeeded as expected; \180 echo "- Test $$i succeeded as expected" ; \
180 else\181 else\
181 echo Failed positive test $$i ; exit 1 ; \182 echo "- Failed positive test $$i" ; exit 1 ; \
182 fi ;\183 fi ;\
183 done ;\184 done ;\
184 for i in $(BOUNDS_FAIL); do \185 for i in $(BOUNDS_FAIL); do \
185 echo ; echo --- boundtest $$i ---; \186 if $(TCC) -b -bt1 -run $< $$i ; then \
186 if $(TCC) -b -run $< $$i ; then \187 echo "- Failed negative test $$i" ; exit 1 ;\
187 echo Failed negative test $$i ; exit 1 ;\
188 else\188 else\
189 echo failed as expected; \189 echo "- Test $$i failed as expected" ; \
190 fi ;\190 fi ;\
191 done ;\191 done ;\
192 echo; echo Bound test OK192 echo Bound test OK
193 193
194# speed test194# speed test
195speedtest: ex2 ex3195speedtest: ex2 ex3
tests/boundtest.c+3−214
@@ -50,15 +50,12 @@ int test4(void) · 49 unmodified lines
50 int i, sum = 0;50 int i, sum = 0;
51 int *tab4;51 int *tab4;
52 52
53 fprintf(stderr, "%s start\n", __FUNCTION__);
54
55 tab4 = malloc(20 * sizeof(int));53 tab4 = malloc(20 * sizeof(int));
56 for(i=0;i<20;i++) {54 for(i=0;i<20;i++) {
57 sum += tab4[i];55 sum += tab4[i];
58 }56 }
59 free(tab4);57 free(tab4);
60 58
61 fprintf(stderr, "%s end\n", __FUNCTION__);
62 return sum;59 return sum;
63}60}
64 61
@@ -68,15 +65,12 @@ int test5(void) · 3 unmodified lines
68 int i, sum = 0;65 int i, sum = 0;
69 int *tab4;66 int *tab4;
70 67
71 fprintf(stderr, "%s start\n", __FUNCTION__);
72
73 tab4 = malloc(20 * sizeof(int));68 tab4 = malloc(20 * sizeof(int));
74 for(i=0;i<21;i++) {69 for(i=0;i<21;i++) {
75 sum += tab4[i];70 sum += tab4[i];
76 }71 }
77 free(tab4);72 free(tab4);
78 73
79 fprintf(stderr, "%s end\n", __FUNCTION__);
80 return sum;74 return sum;
81}75}
82 76
@@ -198,16 +192,12 @@ int test16() · 115 unmodified lines
198 char *demo = "This is only a test.";192 char *demo = "This is only a test.";
199 char *p;193 char *p;
200 194
201 fprintf(stderr, "%s start\n", __FUNCTION__);
202
203 p = alloca(16);195 p = alloca(16);
204 strcpy(p,"12345678901234");196 strcpy(p,"12345678901234");
205 printf("alloca: p is %s\n", p);
206 197
207 /* Test alloca embedded in a larger expression */198 /* Test alloca embedded in a larger expression */
208 printf("alloca: %s\n", strcpy(alloca(strlen(demo)+1),demo) );199 printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)+1),demo) );
209 200
210 fprintf(stderr, "%s end\n", __FUNCTION__);
211 return 0;201 return 0;
212}202}
213 203
@@ -217,211 +207,11 @@ int test17() · 3 unmodified lines
217 char *demo = "This is only a test.";207 char *demo = "This is only a test.";
218 char *p;208 char *p;
219 209
220 fprintf(stderr, "%s start\n", __FUNCTION__);
221
222 p = alloca(16);210 p = alloca(16);
223 strcpy(p,"12345678901234");211 strcpy(p,"12345678901234");
224 printf("alloca: p is %s\n", p);
225 212
226 /* Test alloca embedded in a larger expression */213 /* Test alloca embedded in a larger expression */
227 printf("alloca: %s\n", strcpy(alloca(strlen(demo)),demo) );214 printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)),demo) );
228
229 fprintf(stderr, "%s end\n", __FUNCTION__);
230 return 0;
231}
232
233#define CHECK(s) if (strstr (__bound_error_msg, s) == 0) abort();
234
235extern void __bound_never_fatal (int neverfatal);
236extern const char *__bound_error_msg;
237
238static void init18(char *a, char *b)
239{
240 memset (a, 'a', 10);
241 a[3] = 0;
242 a[9] = 0;
243 memset (b, 'b', 10);
244 __bound_error_msg = "";
245}
246
247/* ok (catch all errors) */
248int test18()
249{
250 char pad1[10];
251 char a[10];
252 char pad2[10];
253 char b[10];
254 char pad3[10];
255
256 memset (pad1, 0, sizeof(pad1));
257 memset (pad2, 0, sizeof(pad2));
258 memset (pad3, 0, sizeof(pad3));
259
260 /* -2 in case TCC_BOUNDS_NEVER_FATAL is set */
261 __bound_never_fatal (-2);
262
263 /* memcpy */
264 init18(a,b);
265 memcpy(&a[1],&b[0],10);
266 CHECK("memcpy dest");
267 init18(a,b);
268 memcpy(&a[0],&b[1],10);
269 CHECK("memcpy src");
270 init18(a,b);
271 memcpy(&a[0],&a[3],4);
272 CHECK("overlapping regions");
273 init18(a,b);
274 memcpy(&a[3],&a[0],4);
275 CHECK("overlapping regions");
276
277 /* memcmp */
278 init18(a,b);
279 memcmp(&b[1],&b[0],10);
280 CHECK("memcmp s1");
281 init18(a,b);
282 memcmp(&b[0],&b[1],10);
283 CHECK("memcmp s2");
284
285 /* memmove */
286 init18(a,b);
287 memmove(&b[1],&b[0],10);
288 CHECK("memmove dest");
289 init18(a,b);
290 memmove(&b[0],&b[1],10);
291 CHECK("memmove src");
292
293 /* memset */
294 init18(a,b);
295 memset(&b[1],'b',10);
296 CHECK("memset");
297
298 /* strlen */
299 init18(a,b);
300 strlen(&b[0]);
301 CHECK("strlen");
302
303 /* strcpy */
304 init18(a,b);
305 strcpy(&a[7], &a[0]);
306 CHECK("strcpy dest");
307 init18(a,b);
308 strcpy(&a[0], &b[7]);
309 CHECK("strcpy src");
310 init18(a,b);
311 strcpy(&a[0], &a[1]);
312 CHECK("overlapping regions");
313 init18(a,b);
314 strcpy(&a[2], &a[0]);
315 CHECK("overlapping regions");
316
317 /* strncpy */
318 init18(a,b);
319 strncpy(&a[7], &a[0], 10);
320 CHECK("strncpy dest");
321 init18(a,b);
322 strncpy(&a[0], &b[7], 10);
323 CHECK("strncpy src");
324 init18(a,b);
325 strncpy(&a[0], &a[1], 10);
326 CHECK("overlapping regions");
327 strncpy(&a[2], &a[0], 10);
328 CHECK("overlapping regions");
329
330 /* strcmp */
331 init18(a,b);
332 strcmp(&b[2], &b[0]);
333 CHECK("strcmp s1");
334 init18(a,b);
335 strcmp(&b[0], &b[2]);
336 CHECK("strcmp s2");
337
338 /* strncmp */
339 init18(a,b);
340 strncmp(&b[5], &b[0], 10);
341 CHECK("strncmp s1");
342 init18(a,b);
343 strncmp(&b[0], &b[5], 10);
344 CHECK("strncmp s2");
345
346 /* strcat */
347 init18(a,b);
348 strcat(&a[7], &a[0]);
349 CHECK("strcat dest");
350 init18(a,b);
351 strcat(&a[0], &b[5]);
352 CHECK("strcat src");
353 init18(a,b);
354 strcat(&a[0], &a[4]);
355 CHECK("overlapping regions");
356 init18(a,b);
357 strcat(&a[3], &a[0]);
358 CHECK("overlapping regions");
359
360 /* strchr */
361 init18(a,b);
362 strchr(&b[0], 'a');
363 CHECK("strchr");
364
365 /* strdup */
366 init18(a,b);
367 free(strdup(&b[0]));
368 CHECK("strdup");
369
370 __bound_never_fatal (2);
371
372 /* memcpy */
373 init18(a,b);
374 memcpy(&a[0],&b[0],10);
375 init18(a,b);
376 memcpy(&a[0],&a[3],3);
377 init18(a,b);
378 memcpy(&a[3],&a[0],3);
379
380 /* memcmp */
381 init18(a,b);
382 memcmp(&b[0],&b[0],10);
383
384 /* memmove */
385 init18(a,b);
386 memmove(&b[0],&b[5],5);
387 init18(a,b);
388 memmove(&b[5],&b[0],5);
389
390 /* memset */
391 init18(a,b);
392 memset(&b[0],'b',10);
393
394 /* strlen */
395 init18(a,b);
396 strlen (&a[0]);
397
398 /* strcpy */
399 init18(a,b);
400 strcpy (&a[0], &a[7]);
401
402 /* strncpy */
403 init18(a,b);
404 strncpy (&a[0], &a[7], 4);
405
406 /* strcmp */
407 init18(a,b);
408 strcmp (&a[0], &a[4]);
409
410 /* strncmp */
411 init18(a,b);
412 strncmp (&a[0], &a[4], 10);
413
414 /* strcat */
415 init18(a,b);
416 strcat (&a[0], &a[7]);
417
418 /* strchr */
419 init18(a,b);
420 strchr (&a[0], 0);
421
422 /* strdup */
423 init18(a,b);
424 free (strdup (&a[0]));
425 215
426 return 0;216 return 0;
427}217}
@@ -443,8 +233,7 @@ int (*table_test[])(void) = { · 15 unmodified lines
443 test14,233 test14,
444 test15,234 test15,
445 test16,235 test16,
446 test17,236 test17
447 test18,
448};237};
449 238
450int main(int argc, char **argv)239int main(int argc, char **argv)
tests/libtcc_test_mt.c+12−9
@@ -203,14 +203,11 @@ TF_TYPE(thread_test_complex, vn) · 202 unmodified lines
203 203
204 sprintf(b, "%d", F(n));204 sprintf(b, "%d", F(n));
205 205
206 argv[argc++] = "../tcc.c";
207 for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i];206 for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i];
208#if 0207#if 0
209 argv[argc++] = "-run";208 argv[argc++] = "-run";
210 argv[argc++] = "../tcc.c";
211 for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i];209 for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i];
212#endif210#endif
213 argv[argc++] = "-g";
214 argv[argc++] = "-DFIB";211 argv[argc++] = "-DFIB";
215 argv[argc++] = "-run";212 argv[argc++] = "-run";
216 argv[argc++] = __FILE__;213 argv[argc++] = __FILE__;
@@ -221,23 +218,24 @@ TF_TYPE(thread_test_complex, vn) · 4 unmodified lines
221 sleep_ms(2);218 sleep_ms(2);
222 ret = tcc_add_file(s, argv[0]);219 ret = tcc_add_file(s, argv[0]);
223 sleep_ms(3);220 sleep_ms(3);
224 if (ret >= 0)221 if (ret < 0)
225 tcc_run(s, argc, argv);222 exit(1);
223 tcc_run(s, argc, argv);
226 tcc_delete(s);224 tcc_delete(s);
227 fflush(stdout);225 fflush(stdout);
228 return 0;226 return 0;
229}227}
230 228
231void time_tcc(int n)229void time_tcc(int n, const char *src)
232{230{
233 TCCState *s;231 TCCState *s;
234 int ret;232 int ret;
235 while (--n >= 0) {233 while (--n >= 0) {
236 s = new_state(1);234 s = new_state(1);
237 ret = tcc_add_file(s, "../tcc.c");235 ret = tcc_add_file(s, src);
238 tcc_delete(s);236 tcc_delete(s);
239 if (ret < 0)237 if (ret < 0)
240 break;238 exit(1);
241 }239 }
242}240}
243 241
@@ -260,6 +258,11 @@ int main(int argc, char **argv) · 16 unmodified lines
260 g_argc = argc;258 g_argc = argc;
261 g_argv = argv;259 g_argv = argv;
262 260
261 if (argc < 2) {
262 fprintf(stderr, "usage: libtcc_test_mt tcc.c <options>\n");
263 return 1;
264 }
265
263#if 1266#if 1
264 printf("----- libtest : mixed calls -------\n"), fflush(stdout);267 printf("----- libtest : mixed calls -------\n"), fflush(stdout);
265 t = getclock_ms();268 t = getclock_ms();
@@ -285,7 +288,7 @@ int main(int argc, char **argv) · 19 unmodified lines
285#if 1288#if 1
286 printf("----- compilation of tcc -----------\n"), fflush(stdout);289 printf("----- compilation of tcc -----------\n"), fflush(stdout);
287 t = getclock_ms();290 t = getclock_ms();
288 time_tcc(10);291 time_tcc(10, argv[1]);
289 printf("(%u ms)\n", (getclock_ms() - t) / 10), fflush(stdout);292 printf("(%u ms)\n", (getclock_ms() - t) / 10), fflush(stdout);
290#endif293#endif
291 return 0;294 return 0;
tests/tcctest.c+15−9
@@ -1725,10 +1725,6 @@ void cast_test() · 1724 unmodified lines
1725 printf("sizeof(-(char)'a') = %d\n", sizeof(-(char)'a'));1725 printf("sizeof(-(char)'a') = %d\n", sizeof(-(char)'a'));
1726 printf("sizeof(~(char)'a') = %d\n", sizeof(-(char)'a'));1726 printf("sizeof(~(char)'a') = %d\n", sizeof(-(char)'a'));
1727 1727
1728#ifdef __TINYC__
1729# pragma comment(option, "-w")
1730#endif
1731
1732 /* from pointer to integer types */1728 /* from pointer to integer types */
1733 printf("%d %d %ld %ld %lld %lld\n",1729 printf("%d %d %ld %ld %lld %lld\n",
1734 (int)p, (unsigned int)p,1730 (int)p, (unsigned int)p,
@@ -1739,10 +1735,6 @@ void cast_test() · 4 unmodified lines
1739 printf("%p %p %p %p\n",1735 printf("%p %p %p %p\n",
1740 (void *)a, (void *)b, (void *)c, (void *)d);1736 (void *)a, (void *)b, (void *)c, (void *)d);
1741 1737
1742#ifdef __TINYC__
1743# pragma comment(option, "-W")
1744#endif
1745
1746 /* int to int with sign set */1738 /* int to int with sign set */
1747 printf("0x%lx\n", (unsigned long)(int)ul);1739 printf("0x%lx\n", (unsigned long)(int)ul);
1748}1740}
@@ -3406,7 +3398,7 @@ void clobber_r12(void) · 1657 unmodified lines
3406}3398}
3407#endif3399#endif
3408 3400
3409void test_high_clobbers(void)3401void test_high_clobbers_really(void)
3410{3402{
3411#if defined __x86_64__ && !defined _WIN643403#if defined __x86_64__ && !defined _WIN64
3412 register long val asm("r12");3404 register long val asm("r12");
@@ -3422,6 +3414,20 @@ void test_high_clobbers(void) · 9 unmodified lines
3422#endif3414#endif
3423}3415}
3424 3416
3417void test_high_clobbers(void)
3418{
3419#if defined __x86_64__ && !defined _WIN64
3420 long x1, x2;
3421 asm volatile("mov %%r12,%0" :: "m" (x1)); /* save r12 */
3422 test_high_clobbers_really();
3423 asm volatile("mov %%r12,%0" :: "m" (x2)); /* new r12 */
3424 asm volatile("mov %0,%%r12" :: "m" (x1)); /* restore r12 */
3425 /* should be 0 but tcc doesn't save r12 automatically, which has
3426 bad effects when gcc helds TCCState *s in r12 in tcc.c:main */
3427 //printf("r12-clobber-diff: %lx\n", x2 - x1);
3428#endif
3429}
3430
3425static long cpu_number;3431static long cpu_number;
3426void trace_console(long len, long len2)3432void trace_console(long len, long len2)
3427{3433{
tests/tests2/112_backtrace.c+165−0
@@ -0,0 +1,165 @@
1#include <stdio.h>
2
3/* ------------------------------------------------------- */
4#if defined test_backtrace_1
5
6void f3()
7{
8 printf("* f3()\n"), fflush(stdout);
9 *(void**)0 = 0;
10}
11void f2()
12{
13 printf("* f2()\n"), fflush(stdout);
14 f3();
15}
16void f1()
17{
18 printf("* f1()\n"), fflush(stdout);
19 f2();
20}
21int main(int argc, char **argv)
22{
23 printf("* main\n"), fflush(stdout);
24 f1();
25 printf("* exit main\n"), fflush(stdout);
26 return 0;
27}
28
29/* ------------------------------------------------------- */
30#elif defined test_bcheck_1
31
32struct s { int a,b,c,d,e; };
33struct s s[3];
34struct s *ps = s;
35void f1()
36{
37 printf("* f1()\n"), fflush(stdout);
38 ps[3] = ps[2];
39}
40int main(int argc, char **argv)
41{
42 printf("* main\n"), fflush(stdout);
43 f1();
44 printf("* exit main\n"), fflush(stdout);
45 return 0;
46}
47
48/* ------------------------------------------------------- */
49#elif defined test_tcc_backtrace_2
50
51/* test custom backtrace and 'exit()' redirection */
52int tcc_backtrace(const char *fmt, ...);
53void exit(int);
54
55void f2()
56{
57 printf("* f2()\n");
58 printf("* exit f2\n"), fflush(stdout);
59 exit(34);
60}
61void f1()
62{
63 printf("* f1()\n"), fflush(stdout);
64 tcc_backtrace("Hello from %s!", "f1");
65 f2();
66}
67int main(int argc, char **argv)
68{
69 printf("* main\n"), fflush(stdout);
70 f1();
71 printf("* exit main\n"), fflush(stdout);
72 return 0;
73}
74
75/* ------------------------------------------------------- */
76#elif defined test_tcc_backtrace_3
77
78/* this test should be run despite of the exit(34) above */
79int main(int argc, char **argv)
80{
81 printf("* main\n"), fflush(stdout);
82 return 1;
83}
84
85/* ------------------------------------------------------- */
86#else
87#include <malloc.h>
88#include <string.h>
89char *strdup();
90int main()
91{
92 char pad1[10];
93 char a[10];
94 char pad2[10];
95 char b[10];
96 char pad3[10];
97 memset (pad1, 0, sizeof(pad1));
98 memset (pad2, 0, sizeof(pad2));
99 memset (pad3, 0, sizeof(pad3));
100
101 memset (a, 'a', 10);
102 a[3] = 0;
103 a[9] = 0;
104 memset (b, 'b', 10);
105
106#if defined test_bcheck_100
107 memcpy(&a[1],&b[0],10);
108#elif defined test_bcheck_101
109 memcpy(&a[0],&b[1],10);
110#elif defined test_bcheck_102
111 memcpy(&a[0],&a[3],4);
112#elif defined test_bcheck_103
113 memcpy(&a[3],&a[0],4);
114#elif defined test_bcheck_104
115 memcmp(&b[1],&b[0],10);
116#elif defined test_bcheck_105
117 memcmp(&b[0],&b[1],10);
118#elif defined test_bcheck_106
119 memmove(&b[1],&b[0],10);
120#elif defined test_bcheck_107
121 memmove(&b[0],&b[1],10);
122#elif defined test_bcheck_108
123 memset(&b[1],'b',10);
124#elif defined test_bcheck_109
125 strlen(&b[0]);
126#elif defined test_bcheck_110
127 strcpy(&a[7], &a[0]);
128#elif defined test_bcheck_111
129 strcpy(&a[0], &b[7]);
130#elif defined test_bcheck_112
131 strcpy(&a[0], &a[1]);
132#elif defined test_bcheck_113
133 strcpy(&a[2], &a[0]);
134#elif defined test_bcheck_114
135 strncpy(&a[7], &a[0], 10);
136#elif defined test_bcheck_115
137 strncpy(&a[0], &b[7], 10);
138#elif defined test_bcheck_116
139 strncpy(&a[0], &a[1], 10);
140#elif defined test_bcheck_117
141 strncpy(&a[2], &a[0], 10);
142#elif defined test_bcheck_118
143 strcmp(&b[2], &b[0]);
144#elif defined test_bcheck_119
145 strcmp(&b[0], &b[2]);
146#elif defined test_bcheck_120
147 strncmp(&b[5], &b[0], 10);
148#elif defined test_bcheck_121
149 strncmp(&b[0], &b[5], 10);
150#elif defined test_bcheck_122
151 strcat(&a[7], &a[0]);
152#elif defined test_bcheck_123
153 strcat(&a[0], &b[5]);
154#elif defined test_bcheck_124
155 strcat(&a[0], &a[4]);
156#elif defined test_bcheck_125
157 strcat(&a[3], &a[0]);
158#elif defined test_bcheck_126
159 strchr(&b[0], 'a');
160#elif defined test_bcheck_127
161 free(strdup(&b[0]));
162#endif
163}
164/* ------------------------------------------------------- */
165#endif
tests/tests2/112_backtrace.expect+164−0
@@ -0,0 +1,164 @@
1[test_backtrace_1]
2* main
3* f1()
4* f2()
5* f3()
6112_backtrace.c:9: at f3: RUNTIME ERROR: invalid memory access
7112_backtrace.c:14: by f2
8112_backtrace.c:19: by f1
9112_backtrace.c:24: by main
10[returns 255]
11
12[test_bcheck_1]
13* main
14* f1()
15112_backtrace.c:38: at f1: BCHECK: ........ is outside of the region
16112_backtrace.c:43: by main
17112_backtrace.c:38: at f1: BCHECK: invalid pointer ........, size 0x14 in memmove dest
18112_backtrace.c:43: by main
19[returns 255]
20
21[test_tcc_backtrace_2]
22* main
23* f1()
24112_backtrace.c:64: at f1: Hello from f1!
25112_backtrace.c:70: by main
26* f2()
27* exit f2
28[returns 34]
29
30[test_tcc_backtrace_3]
31* main
32[returns 1]
33
34[test_bcheck_100]
35112_backtrace.c:107: at main: BCHECK: ........ is outside of the region
36112_backtrace.c:107: at main: BCHECK: invalid pointer ........, size 0xa in memcpy dest
37[returns 255]
38
39[test_bcheck_101]
40112_backtrace.c:109: at main: BCHECK: ........ is outside of the region
41112_backtrace.c:109: at main: BCHECK: invalid pointer ........, size 0xa in memcpy src
42[returns 255]
43
44[test_bcheck_102]
45112_backtrace.c:111: at main: BCHECK: overlapping regions ........(0x4), ........(0x4) in memcpy
46[returns 255]
47
48[test_bcheck_103]
49112_backtrace.c:113: at main: BCHECK: overlapping regions ........(0x4), ........(0x4) in memcpy
50[returns 255]
51
52[test_bcheck_104]
53112_backtrace.c:115: at main: BCHECK: ........ is outside of the region
54112_backtrace.c:115: at main: BCHECK: invalid pointer ........, size 0xa in memcmp s1
55[returns 255]
56
57[test_bcheck_105]
58112_backtrace.c:117: at main: BCHECK: ........ is outside of the region
59112_backtrace.c:117: at main: BCHECK: invalid pointer ........, size 0xa in memcmp s2
60[returns 255]
61
62[test_bcheck_106]
63112_backtrace.c:119: at main: BCHECK: ........ is outside of the region
64112_backtrace.c:119: at main: BCHECK: invalid pointer ........, size 0xa in memmove dest
65[returns 255]
66
67[test_bcheck_107]
68112_backtrace.c:121: at main: BCHECK: ........ is outside of the region
69112_backtrace.c:121: at main: BCHECK: invalid pointer ........, size 0xa in memmove src
70[returns 255]
71
72[test_bcheck_108]
73112_backtrace.c:123: at main: BCHECK: ........ is outside of the region
74112_backtrace.c:123: at main: BCHECK: invalid pointer ........, size 0xa in memset
75[returns 255]
76
77[test_bcheck_109]
78112_backtrace.c:125: at main: BCHECK: ........ is outside of the region
79112_backtrace.c:125: at main: BCHECK: invalid pointer ........, size 0xb in strlen
80[returns 255]
81
82[test_bcheck_110]
83112_backtrace.c:127: at main: BCHECK: ........ is outside of the region
84112_backtrace.c:127: at main: BCHECK: invalid pointer ........, size 0x4 in strcpy dest
85[returns 255]
86
87[test_bcheck_111]
88112_backtrace.c:129: at main: BCHECK: ........ is outside of the region
89112_backtrace.c:129: at main: BCHECK: invalid pointer ........, size 0x4 in strcpy src
90[returns 255]
91
92[test_bcheck_112]
93112_backtrace.c:131: at main: BCHECK: overlapping regions ........(0x3), ........(0x3) in strcpy
94[returns 255]
95
96[test_bcheck_113]
97112_backtrace.c:133: at main: BCHECK: overlapping regions ........(0x4), ........(0x4) in strcpy
98[returns 255]
99
100[test_bcheck_114]
101112_backtrace.c:135: at main: BCHECK: ........ is outside of the region
102112_backtrace.c:135: at main: BCHECK: invalid pointer ........, size 0x4 in strncpy dest
103[returns 255]
104
105[test_bcheck_115]
106112_backtrace.c:137: at main: BCHECK: ........ is outside of the region
107112_backtrace.c:137: at main: BCHECK: invalid pointer ........, size 0x4 in strncpy src
108[returns 255]
109
110[test_bcheck_116]
111112_backtrace.c:139: at main: BCHECK: overlapping regions ........(0x3), ........(0x3) in strncpy
112[returns 255]
113
114[test_bcheck_117]
115112_backtrace.c:141: at main: BCHECK: overlapping regions ........(0x4), ........(0x4) in strncpy
116[returns 255]
117
118[test_bcheck_118]
119112_backtrace.c:143: at main: BCHECK: ........ is outside of the region
120112_backtrace.c:143: at main: BCHECK: invalid pointer ........, size 0x9 in strcmp s1
121[returns 255]
122
123[test_bcheck_119]
124112_backtrace.c:145: at main: BCHECK: ........ is outside of the region
125112_backtrace.c:145: at main: BCHECK: invalid pointer ........, size 0x9 in strcmp s2
126[returns 255]
127
128[test_bcheck_120]
129112_backtrace.c:147: at main: BCHECK: ........ is outside of the region
130112_backtrace.c:147: at main: BCHECK: invalid pointer ........, size 0x6 in strncmp s1
131[returns 255]
132
133[test_bcheck_121]
134112_backtrace.c:149: at main: BCHECK: ........ is outside of the region
135112_backtrace.c:149: at main: BCHECK: invalid pointer ........, size 0x6 in strncmp s2
136[returns 255]
137
138[test_bcheck_122]
139112_backtrace.c:151: at main: BCHECK: ........ is outside of the region
140112_backtrace.c:151: at main: BCHECK: invalid pointer ........, size 0x6 in strcat dest
141[returns 255]
142
143[test_bcheck_123]
144112_backtrace.c:153: at main: BCHECK: ........ is outside of the region
145112_backtrace.c:153: at main: BCHECK: invalid pointer ........, size 0x6 in strcat src
146[returns 255]
147
148[test_bcheck_124]
149112_backtrace.c:155: at main: BCHECK: overlapping regions ........(0x9), ........(0x6) in strcat
150[returns 255]
151
152[test_bcheck_125]
153112_backtrace.c:157: at main: BCHECK: overlapping regions ........(0x4), ........(0x4) in strcat
154[returns 255]
155
156[test_bcheck_126]
157112_backtrace.c:159: at main: BCHECK: ........ is outside of the region
158112_backtrace.c:159: at main: BCHECK: invalid pointer ........, size 0xb in strchr
159[returns 255]
160
161[test_bcheck_127]
162112_backtrace.c:161: at main: BCHECK: ........ is outside of the region
163112_backtrace.c:161: at main: BCHECK: invalid pointer ........, size 0xb in strdup
164[returns 255]
tests/tests2/60_errors_and_warnings.expect+1−0
@@ -20,6 +20,7 @@ · 19 unmodified lines
2060_errors_and_warnings.c:26: error: redefinition of enumerator 'RED'2060_errors_and_warnings.c:26: error: redefinition of enumerator 'RED'
21 21
22[test_63_local_enumerator_redefinition]22[test_63_local_enumerator_redefinition]
23[returns 1]
23 24
24[test_61_undefined_enum]25[test_61_undefined_enum]
2560_errors_and_warnings.c:46: error: unknown type size2660_errors_and_warnings.c:46: error: unknown type size
tests/tests2/Makefile+5−5
@@ -24,6 +24,7 @@ ifeq (,$(filter i386,$(ARCH))) · 23 unmodified lines
24endif24endif
25ifeq (,$(filter i386 x86_64,$(ARCH)))25ifeq (,$(filter i386 x86_64,$(ARCH)))
26 SKIP += 85_asm-outside-function.test26 SKIP += 85_asm-outside-function.test
27 SKIP += 112_backtrace.test
27endif28endif
28ifeq (-$(findstring gcc,$(CC))-,--)29ifeq (-$(findstring gcc,$(CC))-,--)
29 SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS))30 SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS))
@@ -70,12 +71,11 @@ GEN-ALWAYS = · 40 unmodified lines
70# constructor/destructor71# constructor/destructor
71108_constructor.test: NORUN = true72108_constructor.test: NORUN = true
72 73
74112_backtrace.test: FLAGS += -dt -b
75112_backtrace.test: FILTER += -e 's;[0-9A-Fa-fx]\{8,\};........;g'
76
73# Filter source directory in warnings/errors (out-of-tree builds)77# Filter source directory in warnings/errors (out-of-tree builds)
74FILTER = 2>&1 | sed 's,$(SRC)/,,g'78FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'
75# Filter some always-warning
76ifeq (-$(findstring arm,$(ARCH))-,-arm-)
77FILTER += 2>&1 | grep -v 'warning: soft float ABI currently not supported'
78endif
79 79
80all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ;80all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ;
81 81
win32/build-tcc.bat+6−4
@@ -138,7 +138,7 @@ copy>nul tcc-win32.txt doc · 137 unmodified lines
138@if errorlevel 1 goto :the_end138@if errorlevel 1 goto :the_end
139 139
140:libtcc1.a140:libtcc1.a
141@set O1=libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o bcheck.o141@set O1=libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o
142.\tcc -m32 -c ../lib/libtcc1.c142.\tcc -m32 -c ../lib/libtcc1.c
143.\tcc -m32 -c lib/crt1.c143.\tcc -m32 -c lib/crt1.c
144.\tcc -m32 -c lib/crt1w.c144.\tcc -m32 -c lib/crt1w.c
@@ -147,7 +147,6 @@ copy>nul tcc-win32.txt doc · 2 unmodified lines
147.\tcc -m32 -c lib/dllcrt1.c147.\tcc -m32 -c lib/dllcrt1.c
148.\tcc -m32 -c lib/dllmain.c148.\tcc -m32 -c lib/dllmain.c
149.\tcc -m32 -c lib/chkstk.S149.\tcc -m32 -c lib/chkstk.S
150.\tcc -m32 -w -c ../lib/bcheck.c
151.\tcc -m32 -c ../lib/alloca86.S150.\tcc -m32 -c ../lib/alloca86.S
152.\tcc -m32 -c ../lib/alloca86-bt.S151.\tcc -m32 -c ../lib/alloca86-bt.S
153.\tcc -m32 -ar lib/libtcc1-32.a %O1% alloca86.o alloca86-bt.o152.\tcc -m32 -ar lib/libtcc1-32.a %O1% alloca86.o alloca86-bt.o
@@ -160,11 +159,14 @@ copy>nul tcc-win32.txt doc · 6 unmodified lines
160.\tcc -m64 -c lib/dllcrt1.c159.\tcc -m64 -c lib/dllcrt1.c
161.\tcc -m64 -c lib/dllmain.c160.\tcc -m64 -c lib/dllmain.c
162.\tcc -m64 -c lib/chkstk.S161.\tcc -m64 -c lib/chkstk.S
163.\tcc -m64 -w -c ../lib/bcheck.c
164.\tcc -m64 -c ../lib/alloca86_64.S162.\tcc -m64 -c ../lib/alloca86_64.S
165.\tcc -m64 -c ../lib/alloca86_64-bt.S163.\tcc -m64 -c ../lib/alloca86_64-bt.S
166.\tcc -m64 -ar lib/libtcc1-64.a %O1% alloca86_64.o alloca86_64-bt.o164.\tcc -m64 -ar lib/libtcc1-64.a %O1% alloca86_64.o alloca86_64-bt.o
167@if errorlevel 1 goto :the_end165@if errorlevel 1 goto :the_end
166.\tcc -m%T% -c ../lib/bcheck.c -o lib/bcheck.o
167.\tcc -m%T% -c ../lib/bt-exe.c -o lib/bt-exe.o
168.\tcc -m%T% -c ../lib/bt-log.c -o lib/bt-log.o
169.\tcc -m%T% -c ../lib/bt-dll.c -o lib/bt-dll.o
168 170
169:tcc-doc.html171:tcc-doc.html
170@if not (%DOC%)==(yes) goto :doc-done172@if not (%DOC%)==(yes) goto :doc-done
@@ -182,7 +184,7 @@ if not exist %INST% mkdir %INST% · 11 unmodified lines
182if not exist %BIN% mkdir %BIN%184if not exist %BIN% mkdir %BIN%
183for %%f in (*tcc.exe *tcc.dll) do @copy>nul %%f %BIN%\%%f185for %%f in (*tcc.exe *tcc.dll) do @copy>nul %%f %BIN%\%%f
184@if not exist %INST%\lib mkdir %INST%\lib186@if not exist %INST%\lib mkdir %INST%\lib
185for %%f in (lib\*.a lib\*.def) do @copy>nul %%f %INST%\%%f187for %%f in (lib\*.a lib\*.o lib\*.def) do @copy>nul %%f %INST%\%%f
186for %%f in (include examples libtcc doc) do @xcopy>nul /s/i/q/y %%f %INST%\%%f188for %%f in (include examples libtcc doc) do @xcopy>nul /s/i/q/y %%f %INST%\%%f
187 189
188:the_end190:the_end
win32/lib/crt1.c+1−1
@@ -99,7 +99,7 @@ int _runtmain(int argc, /* as tcc passed in */ char **argv) · 98 unmodified lines
99#if defined __i386__ || defined __x86_64__99#if defined __i386__ || defined __x86_64__
100 _controlfp(_PC_53, _MCW_PC);100 _controlfp(_PC_53, _MCW_PC);
101#endif101#endif
102 return do_main(__argc, __targv, _tenviron);102 return _tmain(__argc, __targv, _tenviron);
103}103}
104 104
105// =============================================105// =============================================
x86_64-link.c+1−0
@@ -191,6 +191,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t · 190 unmodified lines
191 if (s1->output_type == TCC_OUTPUT_DLL) {191 if (s1->output_type == TCC_OUTPUT_DLL) {
192 /* XXX: this logic may depend on TCC's codegen192 /* XXX: this logic may depend on TCC's codegen
193 now TCC uses R_X86_64_32 even for a 64bit pointer */193 now TCC uses R_X86_64_32 even for a 64bit pointer */
194 qrel->r_offset = rel->r_offset;
194 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);195 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
195 /* Use sign extension! */196 /* Use sign extension! */
196 qrel->r_addend = (int)read32le(ptr) + val;197 qrel->r_addend = (int)read32le(ptr) + val;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t