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
Unified · Split
| @@ -281,11 +281,12 @@ IBw = $(call IB,$(wildcard $1),$2) · 280 unmodified lines | |||
| 281 | IF = $(if $1,mkdir -p $2 && $(INSTALL) $1 $2) | 281 | IF = $(if $1,mkdir -p $2 && $(INSTALL) $1 $2) |
| 282 | IFw = $(call IF,$(wildcard $1),$2) | 282 | IFw = $(call IF,$(wildcard $1),$2) |
| 283 | IR = mkdir -p $2 && cp -r $1/. $2 | 283 | IR = mkdir -p $2 && cp -r $1/. $2 |
| 284 | B_O = bcheck.o bt-exe.o bt-log.o bt-dll.o | ||
| 284 | 285 | ||
| 285 | # install progs & libs | 286 | # install progs & libs |
| 286 | install-unx: | 287 | install-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 | |||
| 310 | install-win: | 311 | install-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") |
| @@ -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_HARDFLOAT | 173 | #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 | #endif | 175 | #endif |
| 176 | } | 176 | } |
| 177 | #else | 177 | #else |
| @@ -13,7 +13,7 @@ XCC = $(XTCC) · 12 unmodified lines | |||
| 13 | XAR = $(XTCC) -ar | 13 | XAR = $(XTCC) -ar |
| 14 | XFLAGS-unx = -B$(TOPSRC) | 14 | XFLAGS-unx = -B$(TOPSRC) |
| 15 | XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include | 15 | XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include |
| 16 | XFLAGS = $(XFLAGS$(XCFG)) | 16 | XFLAGS = $(XFLAGS$(XCFG)) -I$(TOP) |
| 17 | XCFG = $(or $(findstring -win,$T),-unx) | 17 | XCFG = $(or $(findstring -win,$T),-unx) |
| 18 | 18 | ||
| 19 | # in order to use gcc, tyoe: make <target>-libtcc1-usegcc=yes | 19 | # 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 compiler | 28 | # only for native compiler |
| 29 | $(X)BCHECK_O = bcheck.o | 29 | $(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 | ||
| 31 | ifeq ($(CONFIG_musl)$(CONFIG_uClibc),yes) | 33 | ifeq ($(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_SOURCE | 40 | XFLAGS += -D_ANSI_SOURCE |
| 39 | endif | 41 | endif |
| 40 | 42 | ||
| 41 | I386_O = libtcc1.o alloca86.o alloca86-bt.o | 43 | I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O) |
| 42 | X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o | 44 | X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BT_O) |
| 43 | ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o | 45 | ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o $(BT_O) |
| 44 | ARM64_O = lib-arm64.o | 46 | ARM64_O = lib-arm64.o $(BT_O) |
| 45 | RISCV64_O = lib-arm64.o | 47 | RISCV64_O = lib-arm64.o $(BT_O) |
| 46 | WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o | 48 | WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o |
| 47 | 49 | ||
| 48 | OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O) | 50 | OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O) |
| 49 | OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) $(DSO_O) | 51 | OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) $(DSO_O) |
| 50 | OBJ-x86_64-osx = $(X86_64_O) va_list.o | 52 | OBJ-x86_64-osx = $(X86_64_O) va_list.o |
| 51 | OBJ-i386-win32 = $(I386_O) chkstk.o bcheck.o $(WIN_O) | 53 | OBJ-i386-win32 = $(I386_O) chkstk.o $(B_O) $(WIN_O) |
| 52 | OBJ-x86_64-win32 = $(X86_64_O) chkstk.o bcheck.o $(WIN_O) | 54 | OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(B_O) $(WIN_O) |
| 53 | OBJ-arm64 = $(ARM64_O) $(DSO_O) | 55 | OBJ-arm64 = $(ARM64_O) $(DSO_O) |
| 54 | OBJ-arm = $(ARM_O) $(DSO_O) | 56 | OBJ-arm = $(ARM_O) $(DSO_O) |
| 55 | OBJ-arm-fpa = $(ARM_O) $(DSO_O) | 57 | OBJ-arm-fpa = $(ARM_O) $(DSO_O) |
| @@ -60,7 +62,7 @@ OBJ-arm-eabihf = $(ARM_O) $(DSO_O) · 4 unmodified lines | |||
| 60 | OBJ-arm-wince = $(ARM_O) $(WIN_O) | 62 | OBJ-arm-wince = $(ARM_O) $(WIN_O) |
| 61 | OBJ-riscv64 = $(RISCV64_O) $(DSO_O) | 63 | OBJ-riscv64 = $(RISCV64_O) $(DSO_O) |
| 62 | 64 | ||
| 63 | OBJ-extra = $(filter bcheck.o,$(OBJ-$T)) | 65 | OBJ-extra = $(filter $(B_O),$(OBJ-$T)) |
| 64 | OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T))) | 66 | OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T))) |
| 65 | 67 | ||
| 66 | ALL = $(addprefix $(TOP)/,$(X)libtcc1.a $(OBJ-extra)) | 68 | ALL = $(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 += -g | 84 | $(TOP)/bcheck.o : XFLAGS += -g |
| 85 | $(TOP)/bt-exe.o : $(TOP)/tccrun.c | ||
| 83 | 86 | ||
| 84 | $(X)crt1w.o : crt1.c | 87 | $(X)crt1w.o : crt1.c |
| 85 | $(X)wincrt1w.o : wincrt1.c | 88 | $(X)wincrt1w.o : wincrt1.c |
| 89 | |||
| 86 | clean : | 90 | clean : |
| 87 | rm -f *.a *.o $(ALL) | 91 | rm -f *.a *.o $(ALL) |
| @@ -49,6 +49,12 @@ · 48 unmodified lines | |||
| 49 | #endif | 49 | #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 */ |
| 163 | void __bound_checking (int no_check); | 169 | void __bound_checking (int no_check); |
| 164 | void __bound_never_fatal (int no_check); | 170 | void __bound_never_fatal (int no_check); |
| 165 | void * __bound_ptr_add(void *p, size_t offset); | 171 | DLL_EXPORT void * __bound_ptr_add(void *p, size_t offset); |
| 166 | void * __bound_ptr_indir1(void *p, size_t offset); | 172 | DLL_EXPORT void * __bound_ptr_indir1(void *p, size_t offset); |
| 167 | void * __bound_ptr_indir2(void *p, size_t offset); | 173 | DLL_EXPORT void * __bound_ptr_indir2(void *p, size_t offset); |
| 168 | void * __bound_ptr_indir4(void *p, size_t offset); | 174 | DLL_EXPORT void * __bound_ptr_indir4(void *p, size_t offset); |
| 169 | void * __bound_ptr_indir8(void *p, size_t offset); | 175 | DLL_EXPORT void * __bound_ptr_indir8(void *p, size_t offset); |
| 170 | void * __bound_ptr_indir12(void *p, size_t offset); | 176 | DLL_EXPORT void * __bound_ptr_indir12(void *p, size_t offset); |
| 171 | void * __bound_ptr_indir16(void *p, size_t offset); | 177 | DLL_EXPORT void * __bound_ptr_indir16(void *p, size_t offset); |
| 172 | void FASTCALL __bound_local_new(void *p1); | 178 | DLL_EXPORT void FASTCALL __bound_local_new(void *p1); |
| 173 | void FASTCALL __bound_local_delete(void *p1); | 179 | DLL_EXPORT void FASTCALL __bound_local_delete(void *p1); |
| 174 | void __bound_init(void); | 180 | void __bound_init(size_t *); |
| 175 | void __bound_main_arg(char **p); | 181 | void __bound_main_arg(char **p); |
| 176 | void __bound_exit(void); | 182 | void __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); |
| 180 | int __bound_munmap (void *start, size_t size); | 186 | int __bound_munmap (void *start, size_t size); |
| 181 | #endif | 187 | #endif |
| 182 | void __bound_new_region(void *p, size_t size); | 188 | DLL_EXPORT void __bound_new_region(void *p, size_t size); |
| 183 | void *__bound_memcpy(void *dst, const void *src, size_t size); | 189 | DLL_EXPORT void *__bound_memcpy(void *dst, const void *src, size_t size); |
| 184 | int __bound_memcmp(const void *s1, const void *s2, size_t size); | 190 | DLL_EXPORT int __bound_memcmp(const void *s1, const void *s2, size_t size); |
| 185 | void *__bound_memmove(void *dst, const void *src, size_t size); | 191 | DLL_EXPORT void *__bound_memmove(void *dst, const void *src, size_t size); |
| 186 | void *__bound_memset(void *dst, int c, size_t size); | 192 | DLL_EXPORT void *__bound_memset(void *dst, int c, size_t size); |
| 187 | int __bound_strlen(const char *s); | 193 | DLL_EXPORT int __bound_strlen(const char *s); |
| 188 | char *__bound_strcpy(char *dst, const char *src); | 194 | DLL_EXPORT char *__bound_strcpy(char *dst, const char *src); |
| 189 | char *__bound_strncpy(char *dst, const char *src, size_t n); | 195 | DLL_EXPORT char *__bound_strncpy(char *dst, const char *src, size_t n); |
| 190 | int __bound_strcmp(const char *s1, const char *s2); | 196 | DLL_EXPORT int __bound_strcmp(const char *s1, const char *s2); |
| 191 | int __bound_strncmp(const char *s1, const char *s2, size_t n); | 197 | DLL_EXPORT int __bound_strncmp(const char *s1, const char *s2, size_t n); |
| 192 | char *__bound_strcat(char *dest, const char *src); | 198 | DLL_EXPORT char *__bound_strcat(char *dest, const char *src); |
| 193 | char *__bound_strchr(const char *string, int ch); | 199 | DLL_EXPORT char *__bound_strchr(const char *string, int ch); |
| 194 | char *__bound_strdup(const char *s); | 200 | DLL_EXPORT char *__bound_strdup(const char *s); |
| 195 | 201 | ||
| 196 | #if !MALLOC_REDIR | 202 | #if !MALLOC_REDIR |
| 197 | void *__bound_malloc(size_t size, const void *caller); | 203 | DLL_EXPORT void *__bound_malloc(size_t size, const void *caller); |
| 198 | void *__bound_memalign(size_t size, size_t align, const void *caller); | 204 | DLL_EXPORT void *__bound_memalign(size_t size, size_t align, const void *caller); |
| 199 | void __bound_free(void *ptr, const void *caller); | 205 | DLL_EXPORT void __bound_free(void *ptr, const void *caller); |
| 200 | void *__bound_realloc(void *ptr, size_t size, const void *caller); | 206 | DLL_EXPORT void *__bound_realloc(void *ptr, size_t size, const void *caller); |
| 201 | void *__bound_calloc(size_t nmemb, size_t size); | 207 | DLL_EXPORT void *__bound_calloc(size_t nmemb, size_t size); |
| 202 | #endif | 208 | #endif |
| 203 | 209 | ||
| 204 | #define FREE_REUSE_SIZE (100) | 210 | #define FREE_REUSE_SIZE (100) |
| 205 | static unsigned int free_reuse_index; | 211 | static unsigned int free_reuse_index; |
| 206 | static void *free_reuse_list[FREE_REUSE_SIZE]; | 212 | static void *free_reuse_list[FREE_REUSE_SIZE]; |
| 207 | 213 | ||
| 208 | /* error message, just for TCC */ | ||
| 209 | const char *__bound_error_msg; | ||
| 210 | |||
| 211 | static Tree *tree = NULL; | 214 | static Tree *tree = NULL; |
| 212 | #define TREE_REUSE (1) | 215 | #define TREE_REUSE (1) |
| 213 | #if TREE_REUSE | 216 | #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 | ||
| 302 | int tcc_backtrace(const char *fmt, ...); | ||
| 303 | |||
| 299 | /* print a bound error message */ | 304 | /* print a bound error message */ |
| 300 | static 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 | ||
| 308 | static void bound_alloc_error(const char *s) | 315 | static 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 | ||
| 320 | static 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 | |||
| 327 | static 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 reach | 327 | /* 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 */ |
| 336 | void * __bound_ptr_add(void *p, size_t offset) | 329 | void * __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 pop | 597 | #pragma GCC diagnostic pop |
| 608 | #endif | 598 | #endif |
| 609 | 599 | ||
| 610 | void __attribute__((constructor)) __bound_init(void) | 600 | void __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_REDIR | 618 | #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 | #endif | 713 | #endif |
| 726 | 714 | ||
| 715 | add_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_DEBUG | 722 | #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 | #endif | 728 | #endif |
| 729 | p += 2; | ||
| 730 | } | ||
| 731 | no_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_REDIR | 918 | #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_REDIR | 1100 | #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; |
| @@ -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; | ||
| 39 | static struct { REDIR_ALL } all_ptrs; | ||
| 40 | #undef REDIR | ||
| 41 | #define REDIR(s) #s"\0" | ||
| 42 | static const char all_names[] = REDIR_ALL; | ||
| 43 | #undef REDIR | ||
| 44 | #define REDIR(s) __asm__(".global "#s";"#s": jmp *%0" : : "m" (all_ptrs.s) ); | ||
| 45 | static void all_jmps() { REDIR_ALL } | ||
| 46 | #undef REDIR | ||
| 47 | |||
| 48 | void __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 | } | ||
| @@ -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 | |||
| 8 | int (*__rt_error)(void*, void*, const char *, va_list); | ||
| 9 | |||
| 10 | #ifndef _WIN32 | ||
| 11 | # define __declspec(n) | ||
| 12 | #endif | ||
| 13 | |||
| 14 | __declspec(dllexport) | ||
| 15 | void __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. */ | ||
| 35 | static 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 | } | ||
| @@ -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 | |||
| 7 | int (*__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 | |||
| 15 | DLL_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 | } | ||
| @@ -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 | #endif | 779 | #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_BACKTRACE | 1555 | #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 | #endif | 1557 | #endif |
| 1561 | #ifdef CONFIG_TCC_BCHECK | 1558 | #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_BACKTRACE | 1806 | #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 | #endif | 1812 | #endif |
| 1814 | #ifdef CONFIG_TCC_BCHECK | 1813 | #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 | #endif | 1819 | #endif |
| @@ -372,9 +372,12 @@ Try to continue in case of a bound checking error. · 371 unmodified lines | |||
| 372 | 372 | ||
| 373 | Note: @option{-b} is only available on i386 (linux and windows) and x86_64 (linux and windows) for the moment. | 373 | Note: @option{-b} is only available on i386 (linux and windows) and x86_64 (linux and windows) for the moment. |
| 374 | 374 | ||
| 375 | @item -bt N | 375 | @item -bt[N] |
| 376 | Display N callers in stack traces. This is useful with @option{-g} or | 376 | Display N callers in stack traces. This is useful with @option{-g} or @option{-b}. |
| 377 | @option{-b}. | 377 | With executables, additional support for stack traces is included. |
| 378 | |||
| 379 | A function @code{ int tcc_backtrace(const char *fmt, ...); } is provided | ||
| 380 | to trigger a stack trace with a message on demand. | ||
| 378 | 381 | ||
| 379 | @end table | 382 | @end table |
| 380 | 383 | ||
| @@ -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 | #endif | 62 | #endif |
| 63 | #ifdef CONFIG_TCC_BACKTRACE | 63 | #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 | #endif | 65 | #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" |
| @@ -292,9 +292,6 @@ extern long double strtold (const char *__nptr, char **__endptr); · 291 unmodified lines | |||
| 292 | #ifndef TCC_LIBTCC1 | 292 | #ifndef TCC_LIBTCC1 |
| 293 | # define TCC_LIBTCC1 "libtcc1.a" | 293 | # define TCC_LIBTCC1 "libtcc1.a" |
| 294 | #endif | 294 | #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_LIBGCC | 297 | #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 | |||
| 619 | typedef struct AttributeDef { | 617 | typedef 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_BCHECK | 718 | #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 | #endif | 885 | #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_BCHECK | 1252 | #ifdef CONFIG_TCC_BCHECK |
| 1260 | ST_FUNC void tcc_add_bcheck(TCCState *s1); | 1253 | ST_FUNC void tcc_add_bcheck(TCCState *s1); |
| 1261 | #endif | 1254 | #endif |
| 1255 | #ifdef CONFIG_TCC_BACKTRACE | ||
| 1256 | ST_FUNC void tcc_add_btstub(TCCState *s1); | ||
| 1257 | #endif | ||
| 1262 | ST_FUNC void tcc_add_pragma_libs(TCCState *s1); | 1258 | ST_FUNC void tcc_add_pragma_libs(TCCState *s1); |
| 1263 | PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f); | 1259 | PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f); |
| 1264 | PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time); | 1260 | PUB_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 | #endif | 1481 | #endif |
| 1486 | ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend); | 1482 | ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend); |
| 1487 | 1483 | ||
| 1488 | ST_FUNC void add_init_array (TCCState *s1, Sym *sym); | ||
| 1489 | ST_FUNC void add_fini_array (TCCState *s1, Sym *sym); | ||
| 1490 | |||
| 1491 | ST_FUNC int put_elf_str(Section *s, const char *sym); | 1484 | ST_FUNC int put_elf_str(Section *s, const char *sym); |
| 1492 | ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); | 1485 | ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); |
| 1493 | ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); | 1486 | ST_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 | |||
| 1506 | ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h); | 1499 | ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h); |
| 1507 | ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset); | 1500 | ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset); |
| 1508 | ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte); | 1501 | ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte); |
| 1509 | ST_FUNC void tcc_add_runtime(TCCState *s1); | 1502 | ST_FUNC void add_array(TCCState *s1, const char *sec, int c); |
| 1510 | 1503 | ||
| 1511 | #ifndef ELF_OBJ_ONLY | 1504 | #ifndef ELF_OBJ_ONLY |
| 1512 | ST_FUNC void build_got_entries(TCCState *s1); | 1505 | ST_FUNC void build_got_entries(TCCState *s1); |
| @@ -1521,9 +1514,12 @@ ST_FUNC void list_elf_symbols(TCCState *s, void *ctx, · 8 unmodified lines | |||
| 1521 | ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name); | 1514 | ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name); |
| 1522 | #endif | 1515 | #endif |
| 1523 | 1516 | ||
| 1517 | ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, long offs); | ||
| 1518 | |||
| 1524 | #ifndef TCC_TARGET_PE | 1519 | #ifndef TCC_TARGET_PE |
| 1525 | ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level); | 1520 | ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level); |
| 1526 | ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd); | 1521 | ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd); |
| 1522 | ST_FUNC void tcc_add_runtime(TCCState *s1); | ||
| 1527 | #endif | 1523 | #endif |
| 1528 | 1524 | ||
| 1529 | /* ------------ xxx-link.c ------------ */ | 1525 | /* ------------ xxx-link.c ------------ */ |
| @@ -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 | |||
| 89 | ST_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 | #endif | 88 | #endif |
| 106 | 89 | ||
| 107 | ST_FUNC void tccelf_stab_new(TCCState *s) | 90 | ST_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 | |||
| 818 | ST_FUNC void put_stabs_r(TCCState *s1, const char *str, int type, int other, int desc, | 817 | ST_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 | ||
| 827 | ST_FUNC void put_stabn(TCCState *s1, int type, int other, int desc, int value) | 827 | ST_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_ONLY | 1005 | #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 | #endif | 1277 | #endif |
| 1270 | 1278 | ||
| 1279 | ST_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 | |||
| 1271 | static void add_init_array_defines(TCCState *s1, const char *section_name) | 1288 | static 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_PE | 1306 | #ifndef TCC_TARGET_PE |
| @@ -1305,33 +1312,92 @@ static int tcc_add_support(TCCState *s1, const char *filename) · 5 unmodified lines | |||
| 1305 | } | 1312 | } |
| 1306 | #endif | 1313 | #endif |
| 1307 | 1314 | ||
| 1308 | static void add_array (const char *section, TCCState *s1, Sym *sym, int sh_type) | 1315 | ST_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_PE | 1320 | #ifndef TCC_TARGET_PE |
| 1317 | s->sh_type = sh_type; | 1321 | s->sh_type = sec[1] == 'i' ? SHT_INIT_ARRAY : SHT_FINI_ARRAY; |
| 1318 | #endif | 1322 | #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 | ||
| 1325 | ST_FUNC void add_init_array (TCCState *s1, Sym *sym) | 1327 | #ifdef CONFIG_TCC_BCHECK |
| 1328 | ST_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 | ||
| 1337 | static 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. */ | ||
| 1348 | static 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 | ||
| 1330 | ST_FUNC void add_fini_array (TCCState *s1, Sym *sym) | 1359 | ST_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 */ |
| 1336 | ST_FUNC void tcc_add_runtime(TCCState *s1) | 1402 | ST_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 | #endif | 1407 | #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 | #endif | 1436 | #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 the | 1445 | /* add various standard linker symbols (must be done after the |
| 1371 | sections are filled (for example after allocating common | 1446 | 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_RISCV64 | 1457 | #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 | #endif | 1460 | #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 be | 1465 | /* 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 | } else | 1759 | } else |
| 1705 | #endif | 1760 | #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]; |
| @@ -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 0x4 | 106 | #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. */ |
| 108 | ST_DATA struct temp_local_variable { | 108 | ST_DATA struct temp_local_variable { |
| 109 | int location; //offset on stack. Svalue.c.i | 109 | int location; //offset on stack. Svalue.c.i |
| @@ -375,11 +375,10 @@ static BufferedFile* put_new_file(TCCState *s1) · 265 unmodified lines | |||
| 375 | ST_FUNC void tcc_debug_line(TCCState *s1) | 375 | ST_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 | } else | 2593 | } else |
| 2598 | #endif | 2594 | #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_BCHECK | 5530 | #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 | #endif | 5534 | #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 in | 7606 | /* parse a function defined by symbol 'sym' and generate its code in |
| 7619 | 'cur_text_section' */ | 7607 | 'cur_text_section' */ |
| 7620 | static void gen_function(Sym *sym, AttributeDef *ad) | 7608 | static 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 | ||
| 7680 | static void gen_inline_functions(TCCState *s) | 7665 | static 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 { |
| @@ -239,8 +239,6 @@ typedef struct _IMAGE_BASE_RELOCATION { · 238 unmodified lines | |||
| 239 | #define IMAGE_SCN_MEM_EXECUTE 0x20000000 | 239 | #define IMAGE_SCN_MEM_EXECUTE 0x20000000 |
| 240 | #define IMAGE_SCN_MEM_READ 0x40000000 | 240 | #define IMAGE_SCN_MEM_READ 0x40000000 |
| 241 | #define IMAGE_SCN_MEM_WRITE 0x80000000 | 241 | #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_last | 302 | sec_last |
| 304 | }; | 303 | }; |
| @@ -318,12 +317,12 @@ static const DWORD pe_sec_flags[] = { · 13 unmodified lines | |||
| 318 | #endif | 317 | #endif |
| 319 | 318 | ||
| 320 | struct section_info { | 319 | struct 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 0 | 434 | static DWORD umin(DWORD a, DWORD b) |
| 436 | ST_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 | ||
| 442 | static DWORD umax(DWORD a, DWORD b) | 439 | static 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 | ||
| 470 | static int pe_fwrite(void *data, unsigned len, FILE *fp, DWORD *psum) | 467 | struct pe_file { |
| 468 | FILE *op; | ||
| 469 | DWORD sum; | ||
| 470 | unsigned pos; | ||
| 471 | }; | ||
| 472 | |||
| 473 | static 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 | ||
| 485 | static void pe_fpad(FILE *fp, DWORD new_pos) | 488 | static 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 _WIN32 | 739 | #ifndef _WIN32 |
| 730 | chmod(pe->filename, 0777); | 740 | chmod(pe->filename, 0777); |
| 731 | #endif | 741 | #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 | /* ------------------------------------------------------------- */ |
| 995 | static void pe_build_reloc (struct pe_info *pe) | 1006 | static 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_DATA | 1129 | 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 | #endif | 1135 | #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) { | 1179 | add_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 0 | 1192 | #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 | #endif | 1212 | #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 | else | 1875 | 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_NATIVE | 1915 | #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 | #endif | 1917 | #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", NULL | 1922 | "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 | else | 2026 | 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_NATIVE | 2030 | #ifdef TCC_IS_NATIVE |
| 2001 | pe.thunk = data_section; | 2031 | pe.thunk = data_section; |
| @@ -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_TAL | 112 | #define USE_TAL |
| 114 | #endif | ||
| 115 | 113 | ||
| 116 | #ifndef USE_TAL | 114 | #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 | |||
| 250 | tail_call: | 248 | tail_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_DEBUG | 254 | #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 | else | 1966 | else |
| @@ -3529,9 +3531,6 @@ no_subst: · 1564 unmodified lines | |||
| 3529 | /* return next token with macro substitution */ | 3531 | /* return next token with macro substitution */ |
| 3530 | ST_FUNC void next(void) | 3532 | ST_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) { |
| @@ -23,27 +23,36 @@ · 22 unmodified lines | |||
| 23 | /* only native compiler supports -run */ | 23 | /* only native compiler supports -run */ |
| 24 | #ifdef TCC_IS_NATIVE | 24 | #ifdef TCC_IS_NATIVE |
| 25 | 25 | ||
| 26 | #ifndef _WIN32 | ||
| 27 | # include <sys/mman.h> | ||
| 28 | #endif | ||
| 29 | |||
| 30 | #ifdef CONFIG_TCC_BACKTRACE | 26 | #ifdef CONFIG_TCC_BACKTRACE |
| 31 | static void set_exception_handler(void); | 27 | typedef struct rt_context |
| 32 | #ifdef _WIN32 | ||
| 33 | static DWORD s1_for_run_idx; | ||
| 34 | void 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 | #else | 34 | addr_t prog_base; |
| 42 | /* XXX: add tls support for linux */ | 35 | void *bounds_start; |
| 43 | static 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_run | 38 | int num_callers; |
| 46 | #endif | 39 | addr_t ip, fp, sp; |
| 40 | void *top_func; | ||
| 41 | jmp_buf jmp_buf; | ||
| 42 | char do_jmp; | ||
| 43 | } rt_context; | ||
| 44 | |||
| 45 | static rt_context g_rtctxt; | ||
| 46 | static void set_exception_handler(void); | ||
| 47 | static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap); | ||
| 48 | static 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 | #endif | 56 | #endif |
| 48 | 57 | ||
| 49 | static void set_pages_executable(TCCState *s1, void *ptr, unsigned long length); | 58 | static 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 | #endif | 122 | #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 | |
| 127 | static 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 */ |
| 121 | LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) | 136 | LIBTCCAPI 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_PE | 139 | #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 | #endif | 141 | #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_BACKTRACE | 154 | #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 | #endif | 177 | #endif |
| 151 | 178 | ||
| 152 | errno = 0; /* clean errno value */ | 179 | errno = 0; /* clean errno value */ |
| 153 | 180 | fflush(stdout); | |
| 154 | #ifdef CONFIG_TCC_BCHECK | 181 | 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 | #endif | 185 | #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 | #endif | 189 | 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 | #endif | 348 | #endif |
| 339 | 349 | #endif //ndef CONFIG_TCC_BACKTRACE_ONLY | |
| 340 | /* ------------------------------------------------------------- */ | 350 | /* ------------------------------------------------------------- */ |
| 341 | #ifdef CONFIG_TCC_BACKTRACE | 351 | #ifdef CONFIG_TCC_BACKTRACE |
| 342 | 352 | ||
| 343 | #define INCLUDE_STACK_SIZE 32 | ||
| 344 | static int rt_vprintf(const char *fmt, va_list ap) | 353 | static 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 reading | 372 | /* print the position in the source file of PC value 'pc' by reading |
| 362 | the stabs debug information */ | 373 | the stabs debug information */ |
| 363 | static addr_t rt_printline(TCCState *s1, addr_t wanted_pc, const char *msg) | 374 | static 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; | 385 | next: |
| 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 | |||
| 491 | found: | ||
| 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 | ||
| 509 | typedef struct rt_context { | ||
| 510 | addr_t ip, fp, sp, pc; | ||
| 511 | } rt_context; | ||
| 512 | |||
| 513 | static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level); | 516 | static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level); |
| 514 | 517 | ||
| 515 | /* emit a run time error at position 'pc' */ | 518 | static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap) |
| 516 | static 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 | else | 529 | 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' */ | ||
| 569 | static 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 | |||
| 579 | static 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 */ |
| 622 | static void sig_error(int signum, siginfo_t *siginf, void *puc) | 659 | static 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_SIGINFO | 693 | #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 fatal | 701 | /* 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 SIGSTKSZ | 704 | #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 | #endif | 706 | #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 SIGSTKSZ | 714 | #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 */ |
| 693 | static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info) | 731 | static 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 | #endif | 848 | #endif |
| 809 | #endif /* CONFIG_TCC_BACKTRACE */ | 849 | #endif /* CONFIG_TCC_BACKTRACE */ |
| 810 | |||
| 811 | /* ------------------------------------------------------------- */ | 850 | /* ------------------------------------------------------------- */ |
| 812 | #ifdef CONFIG_TCC_STATIC | 851 | #ifdef CONFIG_TCC_STATIC |
| 813 | 852 | ||
| @@ -73,6 +73,7 @@ endif · 72 unmodified lines | |||
| 73 | RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) | 73 | RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) |
| 74 | DISAS = objdump -d | 74 | DISAS = objdump -d |
| 75 | DUMPTCC = (set -x; $(TOP)/tcc -vv; ldd $(TOP)/tcc; exit 1) | 75 | DUMPTCC = (set -x; $(TOP)/tcc -vv; ldd $(TOP)/tcc; exit 1) |
| 76 | Q = # >/dev/null 2>&1 | ||
| 76 | 77 | ||
| 77 | all test : | 78 | all test : |
| 78 | $(MAKE) clean-s | 79 | $(MAKE) clean-s |
| @@ -88,7 +89,7 @@ hello-run: ../examples/ex1.c · 9 unmodified lines | |||
| 88 | 89 | ||
| 89 | libtes%: libtcc_tes%$(EXESUF) | 90 | libtes%: 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 | ||
| 93 | libtcc_tes%$(EXESUF): libtcc_tes%.c $(LIBTCC) | 94 | libtcc_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 test | 106 | # auto test |
| 106 | test1 test1b: tcctest.c test.ref | 107 | test1 test1b: tcctest.c test.ref |
| 107 | @echo ------------ $@ ------------ | 108 | @echo ------------ $@ ------------ |
| 108 | $(TCC) -run $< > test.out1 | 109 | $(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 !) |
| 112 | test2 test2b: tcctest.c test.ref | 113 | test2 test2b: tcctest.c test.ref |
| 113 | @echo ------------ $@ ------------ | 114 | @echo ------------ $@ ------------ |
| 114 | $(TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out2 | 115 | $(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 !) |
| 118 | test3 test3b: tcctest.c test.ref | 119 | test3 test3b: tcctest.c test.ref |
| 119 | @echo ------------ $@ ------------ | 120 | @echo ------------ $@ ------------ |
| 120 | $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out3 | 121 | $(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 | ||
| 123 | test%b : TCCFLAGS += -b | 124 | AUTO_TEST = Auto Test |
| 125 | test%b : TCCFLAGS += -b -bt1 | ||
| 126 | test%b : AUTO_TEST = Auto Bound-Test | ||
| 124 | 127 | ||
| 125 | # binary output test | 128 | # binary output test |
| 126 | test4: tcctest.c test.ref | 129 | test4: 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.o | 133 | $(TCC) -o tcctest3 tcctest3.o |
| 131 | ./tcctest3 > test3.out | 134 | ./tcctest3 > test3.out |
| 132 | @if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi | 135 | @if diff -u test.ref test3.out ; then echo "Object $(AUTO_TEST) OK"; fi |
| 133 | # dynamic output | 136 | # dynamic output |
| 134 | $(TCC) -o tcctest1 $< | 137 | $(TCC) -o tcctest1 $< |
| 135 | ./tcctest1 > test1.out | 138 | ./tcctest1 > test1.out |
| 136 | @if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi | 139 | @if diff -u test.ref test1.out ; then echo "Dynamic $(AUTO_TEST) OK"; fi |
| 137 | # dynamic output + bound check | 140 | # dynamic output + bound check |
| 138 | $(TCC) -b -o tcctest4 $< | 141 | $(TCC) -b -o tcctest4 $< |
| 139 | ./tcctest4 > test4.out | 142 | ./tcctest4 > test4.out |
| 140 | @if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi | 143 | @if diff -u test.ref test4.out ; then echo "BCheck $(AUTO_TEST) OK"; fi |
| 141 | 144 | ||
| 142 | test4_static: tcctest.c test.ref | 145 | test4_static: tcctest.c test.ref |
| 143 | # static output. | 146 | # static output. |
| 144 | $(TCC) -static -o tcctest2 $< | 147 | $(TCC) -static -o tcctest2 $< |
| 145 | ./tcctest2 > test2.out | 148 | ./tcctest2 > test2.out |
| 146 | @if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi | 149 | @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 them | 151 | # use tcc to create libtcc.so/.dll and the tcc(.exe) frontend and run them |
| 149 | dlltest: | 152 | dlltest: |
| @@ -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.c | 170 | ./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 test | 172 | # memory and bound check auto test |
| 171 | BOUNDS_OK = 1 4 8 10 14 16 18 | 173 | BOUNDS_OK = 1 4 8 10 14 16 |
| 172 | BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17 | 174 | BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17 |
| 173 | 175 | ||
| 174 | btest: boundtest.c | 176 | btest: 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 OK | 192 | echo Bound test OK |
| 193 | 193 | ||
| 194 | # speed test | 194 | # speed test |
| 195 | speedtest: ex2 ex3 | 195 | speedtest: ex2 ex3 |
| @@ -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 | |||
| 235 | extern void __bound_never_fatal (int neverfatal); | ||
| 236 | extern const char *__bound_error_msg; | ||
| 237 | |||
| 238 | static 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) */ | ||
| 248 | int 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 | ||
| 450 | int main(int argc, char **argv) | 239 | int main(int argc, char **argv) |
| @@ -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 0 | 207 | #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 | #endif | 210 | #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 | ||
| 231 | void time_tcc(int n) | 229 | void 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 1 | 266 | #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 1 | 288 | #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 | #endif | 293 | #endif |
| 291 | return 0; | 294 | return 0; |
| @@ -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 | #endif | 3399 | #endif |
| 3408 | 3400 | ||
| 3409 | void test_high_clobbers(void) | 3401 | void test_high_clobbers_really(void) |
| 3410 | { | 3402 | { |
| 3411 | #if defined __x86_64__ && !defined _WIN64 | 3403 | #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 | #endif | 3414 | #endif |
| 3423 | } | 3415 | } |
| 3424 | 3416 | ||
| 3417 | void 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 | |||
| 3425 | static long cpu_number; | 3431 | static long cpu_number; |
| 3426 | void trace_console(long len, long len2) | 3432 | void trace_console(long len, long len2) |
| 3427 | { | 3433 | { |
| @@ -0,0 +1,165 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | |||
| 3 | /* ------------------------------------------------------- */ | ||
| 4 | #if defined test_backtrace_1 | ||
| 5 | |||
| 6 | void f3() | ||
| 7 | { | ||
| 8 | printf("* f3()\n"), fflush(stdout); | ||
| 9 | *(void**)0 = 0; | ||
| 10 | } | ||
| 11 | void f2() | ||
| 12 | { | ||
| 13 | printf("* f2()\n"), fflush(stdout); | ||
| 14 | f3(); | ||
| 15 | } | ||
| 16 | void f1() | ||
| 17 | { | ||
| 18 | printf("* f1()\n"), fflush(stdout); | ||
| 19 | f2(); | ||
| 20 | } | ||
| 21 | int 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 | |||
| 32 | struct s { int a,b,c,d,e; }; | ||
| 33 | struct s s[3]; | ||
| 34 | struct s *ps = s; | ||
| 35 | void f1() | ||
| 36 | { | ||
| 37 | printf("* f1()\n"), fflush(stdout); | ||
| 38 | ps[3] = ps[2]; | ||
| 39 | } | ||
| 40 | int 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 */ | ||
| 52 | int tcc_backtrace(const char *fmt, ...); | ||
| 53 | void exit(int); | ||
| 54 | |||
| 55 | void f2() | ||
| 56 | { | ||
| 57 | printf("* f2()\n"); | ||
| 58 | printf("* exit f2\n"), fflush(stdout); | ||
| 59 | exit(34); | ||
| 60 | } | ||
| 61 | void f1() | ||
| 62 | { | ||
| 63 | printf("* f1()\n"), fflush(stdout); | ||
| 64 | tcc_backtrace("Hello from %s!", "f1"); | ||
| 65 | f2(); | ||
| 66 | } | ||
| 67 | int 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 */ | ||
| 79 | int 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> | ||
| 89 | char *strdup(); | ||
| 90 | int 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 | ||
| @@ -0,0 +1,164 @@ | |||
| 1 | [test_backtrace_1] | ||
| 2 | * main | ||
| 3 | * f1() | ||
| 4 | * f2() | ||
| 5 | * f3() | ||
| 6 | 112_backtrace.c:9: at f3: RUNTIME ERROR: invalid memory access | ||
| 7 | 112_backtrace.c:14: by f2 | ||
| 8 | 112_backtrace.c:19: by f1 | ||
| 9 | 112_backtrace.c:24: by main | ||
| 10 | [returns 255] | ||
| 11 | |||
| 12 | [test_bcheck_1] | ||
| 13 | * main | ||
| 14 | * f1() | ||
| 15 | 112_backtrace.c:38: at f1: BCHECK: ........ is outside of the region | ||
| 16 | 112_backtrace.c:43: by main | ||
| 17 | 112_backtrace.c:38: at f1: BCHECK: invalid pointer ........, size 0x14 in memmove dest | ||
| 18 | 112_backtrace.c:43: by main | ||
| 19 | [returns 255] | ||
| 20 | |||
| 21 | [test_tcc_backtrace_2] | ||
| 22 | * main | ||
| 23 | * f1() | ||
| 24 | 112_backtrace.c:64: at f1: Hello from f1! | ||
| 25 | 112_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] | ||
| 35 | 112_backtrace.c:107: at main: BCHECK: ........ is outside of the region | ||
| 36 | 112_backtrace.c:107: at main: BCHECK: invalid pointer ........, size 0xa in memcpy dest | ||
| 37 | [returns 255] | ||
| 38 | |||
| 39 | [test_bcheck_101] | ||
| 40 | 112_backtrace.c:109: at main: BCHECK: ........ is outside of the region | ||
| 41 | 112_backtrace.c:109: at main: BCHECK: invalid pointer ........, size 0xa in memcpy src | ||
| 42 | [returns 255] | ||
| 43 | |||
| 44 | [test_bcheck_102] | ||
| 45 | 112_backtrace.c:111: at main: BCHECK: overlapping regions ........(0x4), ........(0x4) in memcpy | ||
| 46 | [returns 255] | ||
| 47 | |||
| 48 | [test_bcheck_103] | ||
| 49 | 112_backtrace.c:113: at main: BCHECK: overlapping regions ........(0x4), ........(0x4) in memcpy | ||
| 50 | [returns 255] | ||
| 51 | |||
| 52 | [test_bcheck_104] | ||
| 53 | 112_backtrace.c:115: at main: BCHECK: ........ is outside of the region | ||
| 54 | 112_backtrace.c:115: at main: BCHECK: invalid pointer ........, size 0xa in memcmp s1 | ||
| 55 | [returns 255] | ||
| 56 | |||
| 57 | [test_bcheck_105] | ||
| 58 | 112_backtrace.c:117: at main: BCHECK: ........ is outside of the region | ||
| 59 | 112_backtrace.c:117: at main: BCHECK: invalid pointer ........, size 0xa in memcmp s2 | ||
| 60 | [returns 255] | ||
| 61 | |||
| 62 | [test_bcheck_106] | ||
| 63 | 112_backtrace.c:119: at main: BCHECK: ........ is outside of the region | ||
| 64 | 112_backtrace.c:119: at main: BCHECK: invalid pointer ........, size 0xa in memmove dest | ||
| 65 | [returns 255] | ||
| 66 | |||
| 67 | [test_bcheck_107] | ||
| 68 | 112_backtrace.c:121: at main: BCHECK: ........ is outside of the region | ||
| 69 | 112_backtrace.c:121: at main: BCHECK: invalid pointer ........, size 0xa in memmove src | ||
| 70 | [returns 255] | ||
| 71 | |||
| 72 | [test_bcheck_108] | ||
| 73 | 112_backtrace.c:123: at main: BCHECK: ........ is outside of the region | ||
| 74 | 112_backtrace.c:123: at main: BCHECK: invalid pointer ........, size 0xa in memset | ||
| 75 | [returns 255] | ||
| 76 | |||
| 77 | [test_bcheck_109] | ||
| 78 | 112_backtrace.c:125: at main: BCHECK: ........ is outside of the region | ||
| 79 | 112_backtrace.c:125: at main: BCHECK: invalid pointer ........, size 0xb in strlen | ||
| 80 | [returns 255] | ||
| 81 | |||
| 82 | [test_bcheck_110] | ||
| 83 | 112_backtrace.c:127: at main: BCHECK: ........ is outside of the region | ||
| 84 | 112_backtrace.c:127: at main: BCHECK: invalid pointer ........, size 0x4 in strcpy dest | ||
| 85 | [returns 255] | ||
| 86 | |||
| 87 | [test_bcheck_111] | ||
| 88 | 112_backtrace.c:129: at main: BCHECK: ........ is outside of the region | ||
| 89 | 112_backtrace.c:129: at main: BCHECK: invalid pointer ........, size 0x4 in strcpy src | ||
| 90 | [returns 255] | ||
| 91 | |||
| 92 | [test_bcheck_112] | ||
| 93 | 112_backtrace.c:131: at main: BCHECK: overlapping regions ........(0x3), ........(0x3) in strcpy | ||
| 94 | [returns 255] | ||
| 95 | |||
| 96 | [test_bcheck_113] | ||
| 97 | 112_backtrace.c:133: at main: BCHECK: overlapping regions ........(0x4), ........(0x4) in strcpy | ||
| 98 | [returns 255] | ||
| 99 | |||
| 100 | [test_bcheck_114] | ||
| 101 | 112_backtrace.c:135: at main: BCHECK: ........ is outside of the region | ||
| 102 | 112_backtrace.c:135: at main: BCHECK: invalid pointer ........, size 0x4 in strncpy dest | ||
| 103 | [returns 255] | ||
| 104 | |||
| 105 | [test_bcheck_115] | ||
| 106 | 112_backtrace.c:137: at main: BCHECK: ........ is outside of the region | ||
| 107 | 112_backtrace.c:137: at main: BCHECK: invalid pointer ........, size 0x4 in strncpy src | ||
| 108 | [returns 255] | ||
| 109 | |||
| 110 | [test_bcheck_116] | ||
| 111 | 112_backtrace.c:139: at main: BCHECK: overlapping regions ........(0x3), ........(0x3) in strncpy | ||
| 112 | [returns 255] | ||
| 113 | |||
| 114 | [test_bcheck_117] | ||
| 115 | 112_backtrace.c:141: at main: BCHECK: overlapping regions ........(0x4), ........(0x4) in strncpy | ||
| 116 | [returns 255] | ||
| 117 | |||
| 118 | [test_bcheck_118] | ||
| 119 | 112_backtrace.c:143: at main: BCHECK: ........ is outside of the region | ||
| 120 | 112_backtrace.c:143: at main: BCHECK: invalid pointer ........, size 0x9 in strcmp s1 | ||
| 121 | [returns 255] | ||
| 122 | |||
| 123 | [test_bcheck_119] | ||
| 124 | 112_backtrace.c:145: at main: BCHECK: ........ is outside of the region | ||
| 125 | 112_backtrace.c:145: at main: BCHECK: invalid pointer ........, size 0x9 in strcmp s2 | ||
| 126 | [returns 255] | ||
| 127 | |||
| 128 | [test_bcheck_120] | ||
| 129 | 112_backtrace.c:147: at main: BCHECK: ........ is outside of the region | ||
| 130 | 112_backtrace.c:147: at main: BCHECK: invalid pointer ........, size 0x6 in strncmp s1 | ||
| 131 | [returns 255] | ||
| 132 | |||
| 133 | [test_bcheck_121] | ||
| 134 | 112_backtrace.c:149: at main: BCHECK: ........ is outside of the region | ||
| 135 | 112_backtrace.c:149: at main: BCHECK: invalid pointer ........, size 0x6 in strncmp s2 | ||
| 136 | [returns 255] | ||
| 137 | |||
| 138 | [test_bcheck_122] | ||
| 139 | 112_backtrace.c:151: at main: BCHECK: ........ is outside of the region | ||
| 140 | 112_backtrace.c:151: at main: BCHECK: invalid pointer ........, size 0x6 in strcat dest | ||
| 141 | [returns 255] | ||
| 142 | |||
| 143 | [test_bcheck_123] | ||
| 144 | 112_backtrace.c:153: at main: BCHECK: ........ is outside of the region | ||
| 145 | 112_backtrace.c:153: at main: BCHECK: invalid pointer ........, size 0x6 in strcat src | ||
| 146 | [returns 255] | ||
| 147 | |||
| 148 | [test_bcheck_124] | ||
| 149 | 112_backtrace.c:155: at main: BCHECK: overlapping regions ........(0x9), ........(0x6) in strcat | ||
| 150 | [returns 255] | ||
| 151 | |||
| 152 | [test_bcheck_125] | ||
| 153 | 112_backtrace.c:157: at main: BCHECK: overlapping regions ........(0x4), ........(0x4) in strcat | ||
| 154 | [returns 255] | ||
| 155 | |||
| 156 | [test_bcheck_126] | ||
| 157 | 112_backtrace.c:159: at main: BCHECK: ........ is outside of the region | ||
| 158 | 112_backtrace.c:159: at main: BCHECK: invalid pointer ........, size 0xb in strchr | ||
| 159 | [returns 255] | ||
| 160 | |||
| 161 | [test_bcheck_127] | ||
| 162 | 112_backtrace.c:161: at main: BCHECK: ........ is outside of the region | ||
| 163 | 112_backtrace.c:161: at main: BCHECK: invalid pointer ........, size 0xb in strdup | ||
| 164 | [returns 255] | ||
| @@ -20,6 +20,7 @@ · 19 unmodified lines | |||
| 20 | 60_errors_and_warnings.c:26: error: redefinition of enumerator 'RED' | 20 | 60_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] |
| 25 | 60_errors_and_warnings.c:46: error: unknown type size | 26 | 60_errors_and_warnings.c:46: error: unknown type size |
| @@ -24,6 +24,7 @@ ifeq (,$(filter i386,$(ARCH))) · 23 unmodified lines | |||
| 24 | endif | 24 | endif |
| 25 | ifeq (,$(filter i386 x86_64,$(ARCH))) | 25 | ifeq (,$(filter i386 x86_64,$(ARCH))) |
| 26 | SKIP += 85_asm-outside-function.test | 26 | SKIP += 85_asm-outside-function.test |
| 27 | SKIP += 112_backtrace.test | ||
| 27 | endif | 28 | endif |
| 28 | ifeq (-$(findstring gcc,$(CC))-,--) | 29 | ifeq (-$(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/destructor | 71 | # constructor/destructor |
| 71 | 108_constructor.test: NORUN = true | 72 | 108_constructor.test: NORUN = true |
| 72 | 73 | ||
| 74 | 112_backtrace.test: FLAGS += -dt -b | ||
| 75 | 112_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) |
| 74 | FILTER = 2>&1 | sed 's,$(SRC)/,,g' | 78 | FILTER = 2>&1 | sed -e 's,$(SRC)/,,g' |
| 75 | # Filter some always-warning | ||
| 76 | ifeq (-$(findstring arm,$(ARCH))-,-arm-) | ||
| 77 | FILTER += 2>&1 | grep -v 'warning: soft float ABI currently not supported' | ||
| 78 | endif | ||
| 79 | 79 | ||
| 80 | all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ; | 80 | all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ; |
| 81 | 81 | ||
| @@ -138,7 +138,7 @@ copy>nul tcc-win32.txt doc · 137 unmodified lines | |||
| 138 | @if errorlevel 1 goto :the_end | 138 | @if errorlevel 1 goto :the_end |
| 139 | 139 | ||
| 140 | :libtcc1.a | 140 | :libtcc1.a |
| 141 | @set O1=libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o bcheck.o | 141 | @set O1=libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o |
| 142 | .\tcc -m32 -c ../lib/libtcc1.c | 142 | .\tcc -m32 -c ../lib/libtcc1.c |
| 143 | .\tcc -m32 -c lib/crt1.c | 143 | .\tcc -m32 -c lib/crt1.c |
| 144 | .\tcc -m32 -c lib/crt1w.c | 144 | .\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.c | 147 | .\tcc -m32 -c lib/dllcrt1.c |
| 148 | .\tcc -m32 -c lib/dllmain.c | 148 | .\tcc -m32 -c lib/dllmain.c |
| 149 | .\tcc -m32 -c lib/chkstk.S | 149 | .\tcc -m32 -c lib/chkstk.S |
| 150 | .\tcc -m32 -w -c ../lib/bcheck.c | ||
| 151 | .\tcc -m32 -c ../lib/alloca86.S | 150 | .\tcc -m32 -c ../lib/alloca86.S |
| 152 | .\tcc -m32 -c ../lib/alloca86-bt.S | 151 | .\tcc -m32 -c ../lib/alloca86-bt.S |
| 153 | .\tcc -m32 -ar lib/libtcc1-32.a %O1% alloca86.o alloca86-bt.o | 152 | .\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.c | 159 | .\tcc -m64 -c lib/dllcrt1.c |
| 161 | .\tcc -m64 -c lib/dllmain.c | 160 | .\tcc -m64 -c lib/dllmain.c |
| 162 | .\tcc -m64 -c lib/chkstk.S | 161 | .\tcc -m64 -c lib/chkstk.S |
| 163 | .\tcc -m64 -w -c ../lib/bcheck.c | ||
| 164 | .\tcc -m64 -c ../lib/alloca86_64.S | 162 | .\tcc -m64 -c ../lib/alloca86_64.S |
| 165 | .\tcc -m64 -c ../lib/alloca86_64-bt.S | 163 | .\tcc -m64 -c ../lib/alloca86_64-bt.S |
| 166 | .\tcc -m64 -ar lib/libtcc1-64.a %O1% alloca86_64.o alloca86_64-bt.o | 164 | .\tcc -m64 -ar lib/libtcc1-64.a %O1% alloca86_64.o alloca86_64-bt.o |
| 167 | @if errorlevel 1 goto :the_end | 165 | @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.html | 171 | :tcc-doc.html |
| 170 | @if not (%DOC%)==(yes) goto :doc-done | 172 | @if not (%DOC%)==(yes) goto :doc-done |
| @@ -182,7 +184,7 @@ if not exist %INST% mkdir %INST% · 11 unmodified lines | |||
| 182 | if not exist %BIN% mkdir %BIN% | 184 | if not exist %BIN% mkdir %BIN% |
| 183 | for %%f in (*tcc.exe *tcc.dll) do @copy>nul %%f %BIN%\%%f | 185 | for %%f in (*tcc.exe *tcc.dll) do @copy>nul %%f %BIN%\%%f |
| 184 | @if not exist %INST%\lib mkdir %INST%\lib | 186 | @if not exist %INST%\lib mkdir %INST%\lib |
| 185 | for %%f in (lib\*.a lib\*.def) do @copy>nul %%f %INST%\%%f | 187 | for %%f in (lib\*.a lib\*.o lib\*.def) do @copy>nul %%f %INST%\%%f |
| 186 | for %%f in (include examples libtcc doc) do @xcopy>nul /s/i/q/y %%f %INST%\%%f | 188 | for %%f in (include examples libtcc doc) do @xcopy>nul /s/i/q/y %%f %INST%\%%f |
| 187 | 189 | ||
| 188 | :the_end | 190 | :the_end |
| @@ -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 | #endif | 101 | #endif |
| 102 | return do_main(__argc, __targv, _tenviron); | 102 | return _tmain(__argc, __targv, _tenviron); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | // ============================================= | 105 | // ============================================= |
| @@ -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 codegen | 192 | /* 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; |