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 | 281 | IF = $(if $1,mkdir -p $2 && $(INSTALL) $1 $2) |
| 282 | 282 | IFw = $(call IF,$(wildcard $1),$2) |
| 283 | 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 | 286 | # install progs & libs |
| 286 | 287 | install-unx: |
| 287 | 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 | 290 | $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include") |
| 290 | 291 | $(call $(if $(findstring .so,$(LIBTCC)),IBw,IFw),$(LIBTCC),"$(libdir)") |
| 291 | 292 | $(call IF,$(TOPSRC)/libtcc.h,"$(includedir)") |
| @@ -310,7 +311,7 @@ uninstall-unx: · 18 unmodified lines | ||
| 310 | 311 | install-win: |
| 311 | 312 | $(call IBw,$(PROGS) $(PROGS_CROSS) $(subst libtcc.a,,$(LIBTCC)),"$(bindir)") |
| 312 | 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 | 315 | $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include") |
| 315 | 316 | $(call IR,$(TOPSRC)/win32/include,"$(tccdir)/include") |
| 316 | 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 | 172 | float_abi = s->float_abi; |
| 173 | 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 | 175 | #endif |
| 176 | 176 | } |
| 177 | 177 | #else |
| @@ -13,7 +13,7 @@ XCC = $(XTCC) · 12 unmodified lines | ||
| 13 | 13 | XAR = $(XTCC) -ar |
| 14 | 14 | XFLAGS-unx = -B$(TOPSRC) |
| 15 | 15 | XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include |
| 16 | −XFLAGS = $(XFLAGS$(XCFG)) | |
| 16 | +XFLAGS = $(XFLAGS$(XCFG)) -I$(TOP) | |
| 17 | 17 | XCFG = $(or $(findstring -win,$T),-unx) |
| 18 | 18 | |
| 19 | 19 | # in order to use gcc, tyoe: make <target>-libtcc1-usegcc=yes |
| @@ -27,6 +27,8 @@ endif · 7 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | # only for native compiler |
| 29 | 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 | 33 | ifeq ($(CONFIG_musl)$(CONFIG_uClibc),yes) |
| 32 | 34 | BCHECK_O = |
| @@ -38,18 +40,18 @@ ifdef CONFIG_OSX · 5 unmodified lines | ||
| 38 | 40 | XFLAGS += -D_ANSI_SOURCE |
| 39 | 41 | endif |
| 40 | 42 | |
| 41 | −I386_O = libtcc1.o alloca86.o alloca86-bt.o | |
| 42 | −X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o | |
| 43 | −ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o | |
| 44 | −ARM64_O = lib-arm64.o | |
| 45 | −RISCV64_O = lib-arm64.o | |
| 43 | +I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O) | |
| 44 | +X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BT_O) | |
| 45 | +ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o $(BT_O) | |
| 46 | +ARM64_O = lib-arm64.o $(BT_O) | |
| 47 | +RISCV64_O = lib-arm64.o $(BT_O) | |
| 46 | 48 | WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o |
| 47 | 49 | |
| 48 | 50 | OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O) |
| 49 | 51 | OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) $(DSO_O) |
| 50 | 52 | OBJ-x86_64-osx = $(X86_64_O) va_list.o |
| 51 | −OBJ-i386-win32 = $(I386_O) chkstk.o bcheck.o $(WIN_O) | |
| 52 | −OBJ-x86_64-win32 = $(X86_64_O) chkstk.o bcheck.o $(WIN_O) | |
| 53 | +OBJ-i386-win32 = $(I386_O) chkstk.o $(B_O) $(WIN_O) | |
| 54 | +OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(B_O) $(WIN_O) | |
| 53 | 55 | OBJ-arm64 = $(ARM64_O) $(DSO_O) |
| 54 | 56 | OBJ-arm = $(ARM_O) $(DSO_O) |
| 55 | 57 | OBJ-arm-fpa = $(ARM_O) $(DSO_O) |
| @@ -60,7 +62,7 @@ OBJ-arm-eabihf = $(ARM_O) $(DSO_O) · 4 unmodified lines | ||
| 60 | 62 | OBJ-arm-wince = $(ARM_O) $(WIN_O) |
| 61 | 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 | 66 | OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T))) |
| 65 | 67 | |
| 66 | 68 | ALL = $(addprefix $(TOP)/,$(X)libtcc1.a $(OBJ-extra)) |
| @@ -80,8 +82,10 @@ $(TOP)/%.o : %.c · 13 unmodified lines | ||
| 80 | 82 | $(XCC) -c $< -o $@ $(XFLAGS) |
| 81 | 83 | |
| 82 | 84 | $(TOP)/bcheck.o : XFLAGS += -g |
| 85 | +$(TOP)/bt-exe.o : $(TOP)/tccrun.c | |
| 83 | 86 | |
| 84 | 87 | $(X)crt1w.o : crt1.c |
| 85 | 88 | $(X)wincrt1w.o : wincrt1.c |
| 89 | + | |
| 86 | 90 | clean : |
| 87 | 91 | rm -f *.a *.o $(ALL) |
| @@ -49,6 +49,12 @@ · 48 unmodified lines | ||
| 49 | 49 | #endif |
| 50 | 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 | 58 | #if defined(__FreeBSD__) \ |
| 53 | 59 | || defined(__FreeBSD_kernel__) \ |
| 54 | 60 | || defined(__DragonFly__) \ |
| @@ -162,16 +168,16 @@ void splay_printtree(Tree * t, int d); · 107 unmodified lines | ||
| 162 | 168 | /* external interface */ |
| 163 | 169 | void __bound_checking (int no_check); |
| 164 | 170 | void __bound_never_fatal (int no_check); |
| 165 | −void * __bound_ptr_add(void *p, size_t offset); | |
| 166 | −void * __bound_ptr_indir1(void *p, size_t offset); | |
| 167 | −void * __bound_ptr_indir2(void *p, size_t offset); | |
| 168 | −void * __bound_ptr_indir4(void *p, size_t offset); | |
| 169 | −void * __bound_ptr_indir8(void *p, size_t offset); | |
| 170 | −void * __bound_ptr_indir12(void *p, size_t offset); | |
| 171 | −void * __bound_ptr_indir16(void *p, size_t offset); | |
| 172 | −void FASTCALL __bound_local_new(void *p1); | |
| 173 | −void FASTCALL __bound_local_delete(void *p1); | |
| 174 | −void __bound_init(void); | |
| 171 | +DLL_EXPORT void * __bound_ptr_add(void *p, size_t offset); | |
| 172 | +DLL_EXPORT void * __bound_ptr_indir1(void *p, size_t offset); | |
| 173 | +DLL_EXPORT void * __bound_ptr_indir2(void *p, size_t offset); | |
| 174 | +DLL_EXPORT void * __bound_ptr_indir4(void *p, size_t offset); | |
| 175 | +DLL_EXPORT void * __bound_ptr_indir8(void *p, size_t offset); | |
| 176 | +DLL_EXPORT void * __bound_ptr_indir12(void *p, size_t offset); | |
| 177 | +DLL_EXPORT void * __bound_ptr_indir16(void *p, size_t offset); | |
| 178 | +DLL_EXPORT void FASTCALL __bound_local_new(void *p1); | |
| 179 | +DLL_EXPORT void FASTCALL __bound_local_delete(void *p1); | |
| 180 | +void __bound_init(size_t *); | |
| 175 | 181 | void __bound_main_arg(char **p); |
| 176 | 182 | void __bound_exit(void); |
| 177 | 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 | 185 | off_t offset); |
| 180 | 186 | int __bound_munmap (void *start, size_t size); |
| 181 | 187 | #endif |
| 182 | −void __bound_new_region(void *p, size_t size); | |
| 183 | −void *__bound_memcpy(void *dst, const void *src, size_t size); | |
| 184 | −int __bound_memcmp(const void *s1, const void *s2, size_t size); | |
| 185 | −void *__bound_memmove(void *dst, const void *src, size_t size); | |
| 186 | −void *__bound_memset(void *dst, int c, size_t size); | |
| 187 | −int __bound_strlen(const char *s); | |
| 188 | −char *__bound_strcpy(char *dst, const char *src); | |
| 189 | −char *__bound_strncpy(char *dst, const char *src, size_t n); | |
| 190 | −int __bound_strcmp(const char *s1, const char *s2); | |
| 191 | −int __bound_strncmp(const char *s1, const char *s2, size_t n); | |
| 192 | −char *__bound_strcat(char *dest, const char *src); | |
| 193 | −char *__bound_strchr(const char *string, int ch); | |
| 194 | −char *__bound_strdup(const char *s); | |
| 188 | +DLL_EXPORT void __bound_new_region(void *p, size_t size); | |
| 189 | +DLL_EXPORT void *__bound_memcpy(void *dst, const void *src, size_t size); | |
| 190 | +DLL_EXPORT int __bound_memcmp(const void *s1, const void *s2, size_t size); | |
| 191 | +DLL_EXPORT void *__bound_memmove(void *dst, const void *src, size_t size); | |
| 192 | +DLL_EXPORT void *__bound_memset(void *dst, int c, size_t size); | |
| 193 | +DLL_EXPORT int __bound_strlen(const char *s); | |
| 194 | +DLL_EXPORT char *__bound_strcpy(char *dst, const char *src); | |
| 195 | +DLL_EXPORT char *__bound_strncpy(char *dst, const char *src, size_t n); | |
| 196 | +DLL_EXPORT int __bound_strcmp(const char *s1, const char *s2); | |
| 197 | +DLL_EXPORT int __bound_strncmp(const char *s1, const char *s2, size_t n); | |
| 198 | +DLL_EXPORT char *__bound_strcat(char *dest, const char *src); | |
| 199 | +DLL_EXPORT char *__bound_strchr(const char *string, int ch); | |
| 200 | +DLL_EXPORT char *__bound_strdup(const char *s); | |
| 195 | 201 | |
| 196 | 202 | #if !MALLOC_REDIR |
| 197 | −void *__bound_malloc(size_t size, const void *caller); | |
| 198 | −void *__bound_memalign(size_t size, size_t align, const void *caller); | |
| 199 | −void __bound_free(void *ptr, const void *caller); | |
| 200 | −void *__bound_realloc(void *ptr, size_t size, const void *caller); | |
| 201 | −void *__bound_calloc(size_t nmemb, size_t size); | |
| 203 | +DLL_EXPORT void *__bound_malloc(size_t size, const void *caller); | |
| 204 | +DLL_EXPORT void *__bound_memalign(size_t size, size_t align, const void *caller); | |
| 205 | +DLL_EXPORT void __bound_free(void *ptr, const void *caller); | |
| 206 | +DLL_EXPORT void *__bound_realloc(void *ptr, size_t size, const void *caller); | |
| 207 | +DLL_EXPORT void *__bound_calloc(size_t nmemb, size_t size); | |
| 202 | 208 | #endif |
| 203 | 209 | |
| 204 | 210 | #define FREE_REUSE_SIZE (100) |
| 205 | 211 | static unsigned int free_reuse_index; |
| 206 | 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 | 214 | static Tree *tree = NULL; |
| 212 | 215 | #define TREE_REUSE (1) |
| 213 | 216 | #if TREE_REUSE |
| @@ -296,14 +299,18 @@ void __bound_never_fatal (int neverfatal) · 82 unmodified lines | ||
| 296 | 299 | fetch_and_add (&never_fatal, neverfatal); |
| 297 | 300 | } |
| 298 | 301 | |
| 302 | +int tcc_backtrace(const char *fmt, ...); | |
| 303 | + | |
| 299 | 304 | /* print a bound error message */ |
| 300 | −static void bound_error(const char *error) | |
| 301 | −{ | |
| 302 | − __bound_error_msg = error; | |
| 303 | − fprintf(stderr,"%s%s %s: %s\n", exec, __FILE__, __FUNCTION__, error); | |
| 304 | − if (never_fatal == 0) | |
| 305 | − *(void **)0 = 0; /* force a runtime error */ | |
| 306 | −} | |
| 305 | +#define bound_warning(...) \ | |
| 306 | + tcc_backtrace("^bcheck.c^BCHECK: " __VA_ARGS__) | |
| 307 | + | |
| 308 | +#define bound_error(...) \ | |
| 309 | + do { \ | |
| 310 | + bound_warning(__VA_ARGS__); \ | |
| 311 | + if (never_fatal == 0) \ | |
| 312 | + exit(255); \ | |
| 313 | + } while (0) | |
| 307 | 314 | |
| 308 | 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 | 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 | 327 | /* return '(p + offset)' for pointer arithmetic (a pointer can reach |
| 335 | 328 | the end of a region in this case */ |
| 336 | 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 | 353 | if (addr <= tree->size) { |
| 361 | 354 | if (tree->is_invalid || addr + offset > tree->size) { |
| 362 | 355 | POST_SEM (); |
| 363 | − if (print_warn_ptr_add) | |
| 364 | − bound_ptr_add_warning (__FILE__, __FUNCTION__, p + offset); | |
| 356 | + bound_warning("%p is outside of the region", p + offset); | |
| 365 | 357 | if (never_fatal <= 0) |
| 366 | 358 | return INVALID_POINTER; /* return an invalid pointer */ |
| 367 | 359 | return p + offset; |
| @@ -407,8 +399,7 @@ void * __bound_ptr_indir ## dsize (void *p, size_t offset) \ · 39 unmodified lines | ||
| 407 | 399 | if (addr <= tree->size) { \ |
| 408 | 400 | if (tree->is_invalid || addr + offset + dsize > tree->size) { \ |
| 409 | 401 | POST_SEM (); \ |
| 410 | − bound_ptr_indir_error (__FILE__, __FUNCTION__, \ | |
| 411 | − p + offset); \ | |
| 402 | + bound_warning("%p is outside of the region", p + offset); \ | |
| 412 | 403 | if (never_fatal <= 0) \ |
| 413 | 404 | return INVALID_POINTER; /* return an invalid pointer */ \ |
| 414 | 405 | return p + offset; \ |
| @@ -460,8 +451,7 @@ void FASTCALL __bound_local_new(void *p1) · 45 unmodified lines | ||
| 460 | 451 | WAIT_SEM (); |
| 461 | 452 | while ((addr = p[0])) { |
| 462 | 453 | INCR_COUNT(bound_local_new_count); |
| 463 | − if (addr != 1) | |
| 464 | − tree = splay_insert(addr + fp, p[1], tree); | |
| 454 | + tree = splay_insert(addr + fp, p[1], tree); | |
| 465 | 455 | p += 2; |
| 466 | 456 | } |
| 467 | 457 | POST_SEM (); |
| @@ -498,7 +488,10 @@ void FASTCALL __bound_local_delete(void *p1) · 30 unmodified lines | ||
| 498 | 488 | WAIT_SEM (); |
| 499 | 489 | while ((addr = p[0])) { |
| 500 | 490 | INCR_COUNT(bound_local_delete_count); |
| 501 | − if (addr == 1) { | |
| 491 | + tree = splay_delete(addr + fp, tree); | |
| 492 | + p += 2; | |
| 493 | + } | |
| 494 | + { | |
| 502 | 495 | alloca_list_type *last = NULL; |
| 503 | 496 | alloca_list_type *cur = alloca_list; |
| 504 | 497 | |
| @@ -518,11 +511,8 @@ void FASTCALL __bound_local_delete(void *p1) · 13 unmodified lines | ||
| 518 | 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 | 516 | POST_SEM (); |
| 527 | 517 | while (free_list) { |
| 528 | 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 | 597 | #pragma GCC diagnostic pop |
| 608 | 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[]; | |
| 613 | − size_t *p; | |
| 614 | − | |
| 615 | − if (inited) | |
| 616 | − return; | |
| 602 | + dprintf(stderr, "%s, %s(): start\n", __FILE__, __FUNCTION__); | |
| 617 | 603 | |
| 604 | + if (inited) { | |
| 605 | + WAIT_SEM(); | |
| 606 | + goto add_bounds; | |
| 607 | + } | |
| 618 | 608 | inited = 1; |
| 619 | 609 | |
| 620 | 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 | 613 | print_statistic = getenv ("TCC_BOUNDS_PRINT_STATISTIC") != NULL; |
| 624 | 614 | never_fatal = getenv ("TCC_BOUNDS_NEVER_FATAL") != NULL; |
| 625 | 615 | |
| 626 | − dprintf(stderr, "%s, %s(): start\n", __FILE__, __FUNCTION__); | |
| 627 | − | |
| 628 | 616 | INIT_SEM (); |
| 629 | 617 | |
| 630 | 618 | #if MALLOC_REDIR |
| @@ -724,27 +712,26 @@ void __attribute__((constructor)) __bound_init(void) · 93 unmodified lines | ||
| 724 | 712 | tree = splay_insert((size_t) (&errno), sizeof (int), tree); |
| 725 | 713 | #endif |
| 726 | 714 | |
| 715 | +add_bounds: | |
| 716 | + if (!p) | |
| 717 | + goto no_bounds; | |
| 718 | + | |
| 727 | 719 | /* add all static bound check values */ |
| 728 | − p = __bounds_start; | |
| 729 | 720 | while (p[0] != 0) { |
| 730 | 721 | tree = splay_insert(p[0], p[1], tree); |
| 731 | − p += 2; | |
| 732 | − } | |
| 733 | − POST_SEM (); | |
| 734 | 722 | #if BOUND_DEBUG |
| 735 | − if (print_calls) { | |
| 736 | − p = __bounds_start; | |
| 737 | − while (p[0] != 0) { | |
| 723 | + if (print_calls) { | |
| 738 | 724 | dprintf(stderr, "%s, %s(): static var %p 0x%lx\n", |
| 739 | 725 | __FILE__, __FUNCTION__, |
| 740 | 726 | (void *) p[0], (unsigned long) p[1]); |
| 741 | − p += 2; | |
| 742 | 727 | } |
| 743 | − } | |
| 744 | 728 | #endif |
| 729 | + p += 2; | |
| 730 | + } | |
| 731 | +no_bounds: | |
| 745 | 732 | |
| 733 | + POST_SEM (); | |
| 746 | 734 | no_checking = 0; |
| 747 | − | |
| 748 | 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 | 918 | #if MALLOC_REDIR |
| 932 | 919 | /* This will catch the first dlsym call from __bound_init */ |
| 933 | 920 | if (malloc_redir == NULL) { |
| 934 | − __bound_init (); | |
| 921 | + __bound_init (0); | |
| 935 | 922 | if (malloc_redir == NULL) { |
| 936 | 923 | ptr = &initial_pool[pool_index]; |
| 937 | 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 | 1100 | #if MALLOC_REDIR |
| 1114 | 1101 | /* This will catch the first dlsym call from __bound_init */ |
| 1115 | 1102 | if (malloc_redir == NULL) { |
| 1116 | − __bound_init (); | |
| 1103 | + __bound_init (0); | |
| 1117 | 1104 | if (malloc_redir == NULL) { |
| 1118 | 1105 | ptr = &initial_pool[pool_index]; |
| 1119 | 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 | 1178 | if (no_checking == 0 && size != 0 && |
| 1192 | 1179 | __bound_ptr_add((void *)p, size) == INVALID_POINTER) { |
| 1193 | − static char line[100]; | |
| 1194 | − sprintf(line, "invalid pointer %p, size 0x%lx in %s", | |
| 1180 | + bound_error("invalid pointer %p, size 0x%lx in %s", | |
| 1195 | 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 | 1192 | if (no_checking == 0 && n1 != 0 && n2 !=0 && |
| 1208 | 1193 | ((p1 <= p2 && p1e > p2) || /* p1----p2====p1e----p2e */ |
| 1209 | 1194 | (p2 <= p1 && p2e > p1))) { /* p2----p1====p2e----p1e */ |
| 1210 | − static char line[100]; | |
| 1211 | − sprintf(line, "overlapping regions %p(0x%lx), %p(0x%lx) in %s", | |
| 1195 | + bound_error("overlapping regions %p(0x%lx), %p(0x%lx) in %s", | |
| 1212 | 1196 | p1, (unsigned long)n1, p2, (unsigned long)n2, function); |
| 1213 | − bound_error(line); | |
| 1214 | 1197 | return never_fatal < 0; |
| 1215 | 1198 | } |
| 1216 | 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 | 776 | /* enable this if you want symbols with leading underscore on windows: */ |
| 777 | 777 | #if 0 /* def TCC_TARGET_PE */ |
| 778 | 778 | s->leading_underscore = 1; |
| 779 | −#endif | |
| 780 | −#ifdef CONFIG_TCC_BACKTRACE | |
| 781 | − s->rt_num_callers = 6; | |
| 782 | 779 | #endif |
| 783 | 780 | s->ppfp = stdout; |
| 784 | 781 | /* might be used in error() before preprocess_start() */ |
| @@ -1556,7 +1553,7 @@ static const TCCOption tcc_options[] = { · 771 unmodified lines | ||
| 1556 | 1553 | { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG }, |
| 1557 | 1554 | { "bench", TCC_OPTION_bench, 0 }, |
| 1558 | 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 | 1557 | #endif |
| 1561 | 1558 | #ifdef CONFIG_TCC_BCHECK |
| 1562 | 1559 | { "b", TCC_OPTION_b, 0 }, |
| @@ -1809,11 +1806,14 @@ reparse: · 246 unmodified lines | ||
| 1809 | 1806 | #ifdef CONFIG_TCC_BACKTRACE |
| 1810 | 1807 | case TCC_OPTION_bt: |
| 1811 | 1808 | s->rt_num_callers = atoi(optarg); |
| 1809 | + s->do_backtrace = 1; | |
| 1810 | + s->do_debug = 1; | |
| 1812 | 1811 | break; |
| 1813 | 1812 | #endif |
| 1814 | 1813 | #ifdef CONFIG_TCC_BCHECK |
| 1815 | 1814 | case TCC_OPTION_b: |
| 1816 | 1815 | s->do_bounds_check = 1; |
| 1816 | + s->do_backtrace = 1; | |
| 1817 | 1817 | s->do_debug = 1; |
| 1818 | 1818 | break; |
| 1819 | 1819 | #endif |
| @@ -372,9 +372,12 @@ Try to continue in case of a bound checking error. · 371 unmodified lines | ||
| 372 | 372 | |
| 373 | 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 | |
| 376 | −Display N callers in stack traces. This is useful with @option{-g} or | |
| 377 | −@option{-b}. | |
| 375 | +@item -bt[N] | |
| 376 | +Display N callers in stack traces. This is useful with @option{-g} or @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 | 382 | @end table |
| 380 | 383 | |
| @@ -61,7 +61,7 @@ static const char help[] = · 60 unmodified lines | ||
| 61 | 61 | " -b compile with built-in memory and bounds checker (implies -g)\n" |
| 62 | 62 | #endif |
| 63 | 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 | 65 | #endif |
| 66 | 66 | "Misc. options:\n" |
| 67 | 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 | 292 | #ifndef TCC_LIBTCC1 |
| 293 | 293 | # define TCC_LIBTCC1 "libtcc1.a" |
| 294 | 294 | #endif |
| 295 | −#ifndef TCC_LIBBCHECK | |
| 296 | −# define TCC_LIBBCHECK "bcheck.o" | |
| 297 | −#endif | |
| 298 | 295 | |
| 299 | 296 | /* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */ |
| 300 | 297 | #if defined CONFIG_USE_LIBGCC && !defined TCC_LIBGCC |
| @@ -475,7 +472,7 @@ struct SymAttr { · 174 unmodified lines | ||
| 475 | 472 | nodecorate : 1, |
| 476 | 473 | dllimport : 1, |
| 477 | 474 | addrtaken : 1, |
| 478 | − unused : 3; | |
| 475 | + xxxx : 3; /* not used */ | |
| 479 | 476 | }; |
| 480 | 477 | |
| 481 | 478 | /* function attributes or temporary attributes for parsing */ |
| @@ -484,7 +481,8 @@ struct FuncAttr { · 2 unmodified lines | ||
| 484 | 481 | func_call : 3, /* calling convention (0..5), see below */ |
| 485 | 482 | func_type : 2, /* FUNC_OLD/NEW/ELLIPSIS */ |
| 486 | 483 | func_noreturn : 1, /* attribute((noreturn)) */ |
| 487 | − xxxx : 2, | |
| 484 | + func_ctor : 1, /* attribute((constructor)) */ | |
| 485 | + func_dtor : 1, /* attribute((destructor)) */ | |
| 488 | 486 | func_args : 8; /* PE __stdcall args */ |
| 489 | 487 | }; |
| 490 | 488 | |
| @@ -619,8 +617,6 @@ typedef struct TokenString { · 128 unmodified lines | ||
| 619 | 617 | typedef struct AttributeDef { |
| 620 | 618 | struct SymAttr a; |
| 621 | 619 | struct FuncAttr f; |
| 622 | − unsigned short constructor:1; | |
| 623 | − unsigned short destructor:1; | |
| 624 | 620 | struct Section *section; |
| 625 | 621 | Sym *cleanup_func; |
| 626 | 622 | int alias_target; /* token */ |
| @@ -718,6 +714,7 @@ struct TCCState { · 91 unmodified lines | ||
| 718 | 714 | |
| 719 | 715 | /* compile with debug symbol (and use them if error during execution) */ |
| 720 | 716 | unsigned char do_debug; |
| 717 | + unsigned char do_backtrace; | |
| 721 | 718 | #ifdef CONFIG_TCC_BCHECK |
| 722 | 719 | /* compile with built-in memory and bounds checker */ |
| 723 | 720 | unsigned char do_bounds_check; |
| @@ -884,11 +881,7 @@ struct TCCState { · 160 unmodified lines | ||
| 884 | 881 | const char *runtime_main; |
| 885 | 882 | void **runtime_mem; |
| 886 | 883 | int nb_runtime_mem; |
| 887 | −#ifdef CONFIG_TCC_BACKTRACE | |
| 888 | 884 | int rt_num_callers; |
| 889 | − const char **rt_bound_error_msg; | |
| 890 | − void *rt_prog_main; | |
| 891 | −#endif | |
| 892 | 885 | #endif |
| 893 | 886 | |
| 894 | 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 | 1252 | #ifdef CONFIG_TCC_BCHECK |
| 1260 | 1253 | ST_FUNC void tcc_add_bcheck(TCCState *s1); |
| 1261 | 1254 | #endif |
| 1255 | +#ifdef CONFIG_TCC_BACKTRACE | |
| 1256 | +ST_FUNC void tcc_add_btstub(TCCState *s1); | |
| 1257 | +#endif | |
| 1262 | 1258 | ST_FUNC void tcc_add_pragma_libs(TCCState *s1); |
| 1263 | 1259 | PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f); |
| 1264 | 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 | 1481 | #endif |
| 1486 | 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 | 1484 | ST_FUNC int put_elf_str(Section *s, const char *sym); |
| 1492 | 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 | 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 | 1499 | ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h); |
| 1507 | 1500 | ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset); |
| 1508 | 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 | 1504 | #ifndef ELF_OBJ_ONLY |
| 1512 | 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 | 1514 | ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name); |
| 1522 | 1515 | #endif |
| 1523 | 1516 | |
| 1517 | +ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, long offs); | |
| 1518 | + | |
| 1524 | 1519 | #ifndef TCC_TARGET_PE |
| 1525 | 1520 | ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level); |
| 1526 | 1521 | ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd); |
| 1522 | +ST_FUNC void tcc_add_runtime(TCCState *s1); | |
| 1527 | 1523 | #endif |
| 1528 | 1524 | |
| 1529 | 1525 | /* ------------ xxx-link.c ------------ */ |
| @@ -85,33 +85,21 @@ ST_FUNC void tccelf_bounds_new(TCCState *s) · 84 unmodified lines | ||
| 85 | 85 | lbounds_section = new_section(s, ".lbounds", |
| 86 | 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 | 88 | #endif |
| 106 | 89 | |
| 107 | 90 | ST_FUNC void tccelf_stab_new(TCCState *s) |
| 108 | 91 | { |
| 109 | 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 | 100 | stab_section->sh_entsize = sizeof(Stab_Sym); |
| 112 | − stab_section->sh_addralign = 4; | |
| 113 | − stab_section->link = new_section(s, ".stabstr", SHT_STRTAB, 0); | |
| 114 | − put_elf_str(stab_section->link, ""); | |
| 101 | + stab_section->sh_addralign = sizeof ((Stab_Sym*)0)->n_value; | |
| 102 | + stab_section->link = new_section(s, ".stabstr", SHT_STRTAB, shf); | |
| 115 | 103 | /* put first entry */ |
| 116 | 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 | 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 | 805 | sym = section_ptr_add(stab_section, sizeof(Stab_Sym)); |
| 807 | 806 | if (str) { |
| 808 | 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 | 817 | ST_FUNC void put_stabs_r(TCCState *s1, const char *str, int type, int other, int desc, |
| 819 | 818 | unsigned long value, Section *sec, int sym_index) |
| 820 | 819 | { |
| 821 | − put_stabs(s1, str, type, other, desc, value); | |
| 822 | 820 | put_elf_reloc(symtab_section, stab_section, |
| 823 | − stab_section->data_offset - sizeof(unsigned int), | |
| 824 | − R_DATA_32, sym_index); | |
| 821 | + stab_section->data_offset + 8, | |
| 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 | 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 | 990 | relocate(s1, rel, type, ptr, addr, tgt); |
| 991 | 991 | } |
| 992 | 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 | 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 | 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 | 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 | 1288 | static void add_init_array_defines(TCCState *s1, const char *section_name) |
| 1272 | 1289 | { |
| 1273 | 1290 | Section *s; |
| 1274 | 1291 | long end_offset; |
| 1275 | − char sym_start[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 | − | |
| 1292 | + char buf[1024]; | |
| 1281 | 1293 | s = find_section(s1, section_name); |
| 1282 | 1294 | if (!s) { |
| 1283 | 1295 | end_offset = 0; |
| @@ -1285,15 +1297,10 @@ static void add_init_array_defines(TCCState *s1, const char *section_name) · 1 unmodified line | ||
| 1285 | 1297 | } else { |
| 1286 | 1298 | end_offset = s->data_offset; |
| 1287 | 1299 | } |
| 1288 | − | |
| 1289 | − set_elf_sym(symtab_section, | |
| 1290 | − 0, 0, | |
| 1291 | − ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, | |
| 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); | |
| 1300 | + snprintf(buf, sizeof(buf), "__%s_start", section_name + 1); | |
| 1301 | + set_global_sym(s1, buf, s, 0); | |
| 1302 | + snprintf(buf, sizeof(buf), "__%s_end", section_name + 1); | |
| 1303 | + set_global_sym(s1, buf, s, end_offset); | |
| 1297 | 1304 | } |
| 1298 | 1305 | |
| 1299 | 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 | 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 | 1317 | Section *s; |
| 1311 | − unsigned char *ptr; | |
| 1312 | − | |
| 1313 | − s = find_section(s1, section); | |
| 1314 | − if (s) { | |
| 1315 | − s->sh_flags |= SHF_WRITE; | |
| 1318 | + s = find_section(s1, sec); | |
| 1319 | + s->sh_flags |= SHF_WRITE; | |
| 1316 | 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 | 1322 | #endif |
| 1319 | − ptr = section_ptr_add(s, PTR_SIZE); | |
| 1320 | − memset (ptr, 0, PTR_SIZE); | |
| 1321 | − put_elf_reloc (s1->symtab, s, ptr - s->data, R_DATA_PTR, sym->c); | |
| 1322 | − } | |
| 1323 | + put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c); | |
| 1324 | + section_ptr_add(s, PTR_SIZE); | |
| 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 | 1401 | /* add tcc runtime libraries */ |
| 1336 | 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 | 1406 | tcc_add_bcheck(s1); |
| 1341 | 1407 | #endif |
| 1342 | 1408 | tcc_add_pragma_libs(s1); |
| 1343 | −#ifndef TCC_TARGET_PE | |
| 1344 | 1409 | /* add libc */ |
| 1345 | 1410 | if (!s1->nostdlib) { |
| 1346 | 1411 | tcc_add_library_err(s1, "c"); |
| @@ -1356,7 +1421,17 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) · 9 unmodified lines | ||
| 1356 | 1421 | if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) { |
| 1357 | 1422 | tcc_add_library_err(s1, "pthread"); |
| 1358 | 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 | 1436 | #endif |
| 1362 | 1437 | tcc_add_support(s1, TCC_LIBTCC1); |
| @@ -1364,8 +1439,8 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) · 1 unmodified line | ||
| 1364 | 1439 | if (s1->output_type != TCC_OUTPUT_MEMORY) |
| 1365 | 1440 | tcc_add_crt(s1, "crtn.o"); |
| 1366 | 1441 | } |
| 1367 | −#endif | |
| 1368 | 1442 | } |
| 1443 | +#endif | |
| 1369 | 1444 | |
| 1370 | 1445 | /* add various standard linker symbols (must be done after the |
| 1371 | 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 | 1451 | int i; |
| 1377 | 1452 | Section *s; |
| 1378 | 1453 | |
| 1379 | − set_elf_sym(symtab_section, | |
| 1380 | − text_section->data_offset, 0, | |
| 1381 | − ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, | |
| 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"); | |
| 1454 | + set_global_sym(s1, "_etext", text_section, -1); | |
| 1455 | + set_global_sym(s1, "_edata", data_section, -1); | |
| 1456 | + set_global_sym(s1, "_end", bss_section, -1); | |
| 1391 | 1457 | #ifdef TCC_TARGET_RISCV64 |
| 1392 | 1458 | /* XXX should be .sdata+0x800, not .data+0x800 */ |
| 1393 | − set_elf_sym(symtab_section, | |
| 1394 | − 0x800, 0, | |
| 1395 | − ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, | |
| 1396 | − data_section->sh_num, "__global_pointer$"); | |
| 1459 | + set_global_sym(s1, "__global_pointer$", data_section, 0x800); | |
| 1397 | 1460 | #endif |
| 1398 | 1461 | /* horrible new standard ldscript defines */ |
| 1399 | 1462 | add_init_array_defines(s1, ".preinit_array"); |
| 1400 | 1463 | add_init_array_defines(s1, ".init_array"); |
| 1401 | 1464 | add_init_array_defines(s1, ".fini_array"); |
| 1402 | − | |
| 1403 | 1465 | /* add start and stop symbols for sections whose name can be |
| 1404 | 1466 | expressed in C */ |
| 1405 | 1467 | for(i = 1; i < s1->nb_sections; i++) { |
| 1406 | 1468 | s = s1->sections[i]; |
| 1407 | − if (s->sh_type == SHT_PROGBITS && | |
| 1408 | − (s->sh_flags & SHF_ALLOC)) { | |
| 1469 | + if ((s->sh_flags & SHF_ALLOC) | |
| 1470 | + && (s->sh_type == SHT_PROGBITS | |
| 1471 | + || s->sh_type == SHT_STRTAB)) { | |
| 1409 | 1472 | const char *p; |
| 1410 | − int ch; | |
| 1411 | − | |
| 1412 | 1473 | /* check if section name can be expressed in C */ |
| 1413 | 1474 | p = s->name; |
| 1414 | 1475 | for(;;) { |
| 1415 | − ch = *p; | |
| 1416 | − if (!ch) | |
| 1476 | + int c = *p; | |
| 1477 | + if (!c) | |
| 1417 | 1478 | break; |
| 1418 | − if (!isid(ch) && !isnum(ch)) | |
| 1479 | + if (!isid(c) && !isnum(c)) | |
| 1419 | 1480 | goto next_sec; |
| 1420 | 1481 | p++; |
| 1421 | 1482 | } |
| 1422 | 1483 | snprintf(buf, sizeof(buf), "__start_%s", s->name); |
| 1423 | − set_elf_sym(symtab_section, | |
| 1424 | − 0, 0, | |
| 1425 | − ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, | |
| 1426 | − s->sh_num, buf); | |
| 1484 | + set_global_sym(s1, buf, s, 0); | |
| 1427 | 1485 | snprintf(buf, sizeof(buf), "__stop_%s", s->name); |
| 1428 | − set_elf_sym(symtab_section, | |
| 1429 | − s->data_offset, 0, | |
| 1430 | − ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, | |
| 1431 | − s->sh_num, buf); | |
| 1486 | + set_global_sym(s1, buf, s, -1); | |
| 1432 | 1487 | } |
| 1433 | 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 | 1754 | !(s->sh_flags & SHF_ALLOC) && |
| 1700 | 1755 | (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC) && |
| 1701 | 1756 | prepare_dynamic_rel(s1, s)) { |
| 1702 | − if (s1->sections[s->sh_info]->sh_flags & SHF_EXECINSTR) | |
| 1703 | − textrel = 1; | |
| 1757 | + if (!(s1->sections[s->sh_info]->sh_flags & SHF_WRITE)) | |
| 1758 | + textrel = 1; | |
| 1704 | 1759 | } else |
| 1705 | 1760 | #endif |
| 1706 | 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 | 1869 | if (s == interp) { |
| 1815 | 1870 | if (k != 0) |
| 1816 | 1871 | continue; |
| 1817 | − } else if (s->sh_type == SHT_DYNSYM || | |
| 1818 | − s->sh_type == SHT_STRTAB || | |
| 1819 | − s->sh_type == SHT_HASH) { | |
| 1872 | + } else if ((s->sh_type == SHT_DYNSYM || | |
| 1873 | + s->sh_type == SHT_STRTAB || | |
| 1874 | + s->sh_type == SHT_HASH) | |
| 1875 | + && !strstr(s->name, ".stab")) { | |
| 1820 | 1876 | if (k != 1) |
| 1821 | 1877 | continue; |
| 1822 | 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 | 2116 | Section *s; |
| 2061 | 2117 | ElfW(Ehdr) ehdr; |
| 2062 | 2118 | ElfW(Shdr) shdr, *sh; |
| 2063 | − ElfW(Sym) *sym; | |
| 2064 | 2119 | |
| 2065 | 2120 | file_type = s1->output_type; |
| 2066 | 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 | 2186 | offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr)); |
| 2132 | 2187 | |
| 2133 | 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 | 2189 | for(i = 1; i < s1->nb_sections; i++) { |
| 2139 | 2190 | s = s1->sections[sec_order[i]]; |
| 2140 | 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 | 2893 | for (p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) { |
| 2843 | 2894 | Section *s = symtab_section; |
| 2844 | 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 | 2896 | if (!sym_index) |
| 2852 | 2897 | continue; |
| 2853 | 2898 | sym = &((ElfW(Sym) *)s->data)[sym_index]; |
| @@ -103,7 +103,7 @@ ST_DATA struct switch_t { · 102 unmodified lines | ||
| 103 | 103 | struct scope *scope; |
| 104 | 104 | } *cur_switch; /* current switch */ |
| 105 | 105 | |
| 106 | −#define MAX_TEMP_LOCAL_VARIABLE_NUMBER 0x4 | |
| 106 | +#define MAX_TEMP_LOCAL_VARIABLE_NUMBER 8 | |
| 107 | 107 | /*list of temporary local variables on the stack in current function. */ |
| 108 | 108 | ST_DATA struct temp_local_variable { |
| 109 | 109 | int location; //offset on stack. Svalue.c.i |
| @@ -375,11 +375,10 @@ static BufferedFile* put_new_file(TCCState *s1) · 265 unmodified lines | ||
| 375 | 375 | ST_FUNC void tcc_debug_line(TCCState *s1) |
| 376 | 376 | { |
| 377 | 377 | BufferedFile *f; |
| 378 | − if (!s1->do_debug || !(f = put_new_file(s1))) | |
| 379 | − return; | |
| 380 | − if (last_line_num == f->line_num) | |
| 381 | − return; | |
| 382 | − if (text_section != cur_text_section) | |
| 378 | + if (!s1->do_debug | |
| 379 | + || cur_text_section != text_section | |
| 380 | + || !(f = put_new_file(s1)) | |
| 381 | + || last_line_num == f->line_num) | |
| 383 | 382 | return; |
| 384 | 383 | if (func_ind != -1) { |
| 385 | 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 | 409 | if (!s1->do_debug) |
| 411 | 410 | return; |
| 412 | −#if 0 // this seems to confuse gnu tools | |
| 413 | 411 | put_stabn(s1, N_FUN, 0, 0, size); |
| 414 | −#endif | |
| 415 | 412 | } |
| 416 | 413 | |
| 417 | 414 | /* put alternative filename */ |
| @@ -2592,7 +2589,6 @@ redo: · 2174 unmodified lines | ||
| 2592 | 2589 | vswap(); |
| 2593 | 2590 | gen_op('-'); |
| 2594 | 2591 | } |
| 2595 | − vtop[-1].r &= ~VT_MUSTBOUND; | |
| 2596 | 2592 | gen_bounded_ptr_add(); |
| 2597 | 2593 | } else |
| 2598 | 2594 | #endif |
| @@ -3428,6 +3424,10 @@ ST_FUNC void vstore(void) · 829 unmodified lines | ||
| 3428 | 3424 | |
| 3429 | 3425 | /* destination */ |
| 3430 | 3426 | vswap(); |
| 3427 | +#ifdef CONFIG_TCC_BCHECK | |
| 3428 | + if (vtop->r & VT_MUSTBOUND) | |
| 3429 | + gbound(); /* check would be wrong after gaddrof() */ | |
| 3430 | +#endif | |
| 3431 | 3431 | vtop->type.t = VT_PTR; |
| 3432 | 3432 | gaddrof(); |
| 3433 | 3433 | |
| @@ -3444,8 +3444,11 @@ ST_FUNC void vstore(void) · 10 unmodified lines | ||
| 3444 | 3444 | |
| 3445 | 3445 | vswap(); |
| 3446 | 3446 | /* source */ |
| 3447 | − vtop->r &= ~VT_MUSTBOUND; | |
| 3448 | 3447 | vpushv(vtop - 2); |
| 3448 | +#ifdef CONFIG_TCC_BCHECK | |
| 3449 | + if (vtop->r & VT_MUSTBOUND) | |
| 3450 | + gbound(); | |
| 3451 | +#endif | |
| 3449 | 3452 | vtop->type.t = VT_PTR; |
| 3450 | 3453 | gaddrof(); |
| 3451 | 3454 | /* type size */ |
| @@ -3662,11 +3665,11 @@ redo: · 210 unmodified lines | ||
| 3662 | 3665 | } |
| 3663 | 3666 | case TOK_CONSTRUCTOR1: |
| 3664 | 3667 | case TOK_CONSTRUCTOR2: |
| 3665 | − ad->constructor = 1; | |
| 3668 | + ad->f.func_ctor = 1; | |
| 3666 | 3669 | break; |
| 3667 | 3670 | case TOK_DESTRUCTOR1: |
| 3668 | 3671 | case TOK_DESTRUCTOR2: |
| 3669 | − ad->destructor = 1; | |
| 3672 | + ad->f.func_dtor = 1; | |
| 3670 | 3673 | break; |
| 3671 | 3674 | case TOK_SECTION1: |
| 3672 | 3675 | case TOK_SECTION2: |
| @@ -4958,6 +4961,10 @@ ST_FUNC void unary(void) · 1285 unmodified lines | ||
| 4958 | 4961 | Sym *s; |
| 4959 | 4962 | AttributeDef ad; |
| 4960 | 4963 | |
| 4964 | + /* generate line number info */ | |
| 4965 | + if (tcc_state->do_debug) | |
| 4966 | + tcc_debug_line(tcc_state); | |
| 4967 | + | |
| 4961 | 4968 | sizeof_caller = in_sizeof; |
| 4962 | 4969 | in_sizeof = 0; |
| 4963 | 4970 | type.ref = NULL; |
| @@ -5522,7 +5529,7 @@ special_math_val: · 558 unmodified lines | ||
| 5522 | 5529 | vtop->r |= VT_LVAL; |
| 5523 | 5530 | #ifdef CONFIG_TCC_BCHECK |
| 5524 | 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 | 5533 | vtop->r |= VT_MUSTBOUND; |
| 5527 | 5534 | #endif |
| 5528 | 5535 | } |
| @@ -5538,15 +5545,6 @@ special_math_val: · 9 unmodified lines | ||
| 5538 | 5545 | Sym *sa; |
| 5539 | 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 | 5548 | /* function call */ |
| 5551 | 5549 | if ((vtop->type.t & VT_BTYPE) != VT_FUNC) { |
| 5552 | 5550 | /* pointer test (no array accepted) */ |
| @@ -6514,10 +6512,10 @@ again: · 961 unmodified lines | ||
| 6514 | 6512 | } |
| 6515 | 6513 | |
| 6516 | 6514 | prev_scope(&o, is_expr); |
| 6517 | − | |
| 6518 | − if (0 == local_scope && !nocode_wanted) | |
| 6515 | + if (local_scope) | |
| 6516 | + next(); | |
| 6517 | + else if (!nocode_wanted) | |
| 6519 | 6518 | check_func_return(); |
| 6520 | − next(); | |
| 6521 | 6519 | |
| 6522 | 6520 | } else if (t == TOK_RETURN) { |
| 6523 | 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 | 7580 | gen_vla_sp_save(addr); |
| 7583 | 7581 | cur_scope->vla.loc = addr; |
| 7584 | 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 | 7583 | } else if (has_init) { |
| 7596 | 7584 | size_t oldreloc_offset = 0; |
| 7597 | 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 | 7606 | /* parse a function defined by symbol 'sym' and generate its code in |
| 7619 | 7607 | 'cur_text_section' */ |
| 7620 | −static void gen_function(Sym *sym, AttributeDef *ad) | |
| 7608 | +static void gen_function(Sym *sym) | |
| 7621 | 7609 | { |
| 7622 | 7610 | /* Initialize VLA state */ |
| 7623 | 7611 | struct scope f = { 0 }; |
| @@ -7632,17 +7620,12 @@ static void gen_function(Sym *sym, AttributeDef *ad) · 8 unmodified lines | ||
| 7632 | 7620 | } |
| 7633 | 7621 | /* NOTE: we patch the symbol size later */ |
| 7634 | 7622 | put_extern_sym(sym, cur_text_section, ind, 0); |
| 7635 | − | |
| 7636 | − if (ad && ad->constructor) { | |
| 7637 | − add_init_array (tcc_state, sym); | |
| 7638 | − } | |
| 7639 | − if (ad && ad->destructor) { | |
| 7640 | − add_fini_array (tcc_state, sym); | |
| 7641 | − } | |
| 7642 | − | |
| 7623 | + if (sym->type.ref->f.func_ctor) | |
| 7624 | + add_array (tcc_state, ".init_array", sym->c); | |
| 7625 | + if (sym->type.ref->f.func_dtor) | |
| 7626 | + add_array (tcc_state, ".fini_array", sym->c); | |
| 7643 | 7627 | funcname = get_tok_str(sym->v, NULL); |
| 7644 | 7628 | func_ind = ind; |
| 7645 | − | |
| 7646 | 7629 | /* put debug symbol */ |
| 7647 | 7630 | tcc_debug_funcstart(tcc_state, sym); |
| 7648 | 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 | 7658 | ind = 0; /* for safety */ |
| 7676 | 7659 | nocode_wanted = 0x80000000; |
| 7677 | 7660 | check_vstack(); |
| 7661 | + /* do this after funcend debug info */ | |
| 7662 | + next(); | |
| 7678 | 7663 | } |
| 7679 | 7664 | |
| 7680 | 7665 | static void gen_inline_functions(TCCState *s) |
| @@ -7698,7 +7683,7 @@ static void gen_inline_functions(TCCState *s) · 17 unmodified lines | ||
| 7698 | 7683 | begin_macro(fn->func_str, 1); |
| 7699 | 7684 | next(); |
| 7700 | 7685 | cur_text_section = text_section; |
| 7701 | − gen_function(sym, NULL); | |
| 7686 | + gen_function(sym); | |
| 7702 | 7687 | end_macro(); |
| 7703 | 7688 | |
| 7704 | 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 | 7851 | the compilation unit only if they are used */ |
| 7867 | 7852 | if (sym->type.t & VT_INLINE) { |
| 7868 | 7853 | struct InlineFunc *fn; |
| 7869 | − const char *filename; | |
| 7870 | − | |
| 7871 | − filename = file ? file->filename : ""; | |
| 7872 | − fn = tcc_malloc(sizeof *fn + strlen(filename)); | |
| 7873 | − strcpy(fn->filename, filename); | |
| 7854 | + fn = tcc_malloc(sizeof *fn + strlen(file->filename)); | |
| 7855 | + strcpy(fn->filename, file->filename); | |
| 7874 | 7856 | fn->sym = sym; |
| 7875 | 7857 | skip_or_save_block(&fn->func_str); |
| 7876 | 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 | 7862 | cur_text_section = ad.section; |
| 7881 | 7863 | if (!cur_text_section) |
| 7882 | 7864 | cur_text_section = text_section; |
| 7883 | − gen_function(sym, &ad); | |
| 7865 | + gen_function(sym); | |
| 7884 | 7866 | } |
| 7885 | 7867 | break; |
| 7886 | 7868 | } else { |
| @@ -239,8 +239,6 @@ typedef struct _IMAGE_BASE_RELOCATION { · 238 unmodified lines | ||
| 239 | 239 | #define IMAGE_SCN_MEM_EXECUTE 0x20000000 |
| 240 | 240 | #define IMAGE_SCN_MEM_READ 0x40000000 |
| 241 | 241 | #define IMAGE_SCN_MEM_WRITE 0x80000000 |
| 242 | −#define IMAGE_SCN_TYPE_NOLOAD 0x00000002 | |
| 243 | −#define IMAGE_SCN_LNK_REMOVE 0x00000800 | |
| 244 | 242 | |
| 245 | 243 | #pragma pack(pop) |
| 246 | 244 | |
| @@ -299,6 +297,7 @@ enum { · 52 unmodified lines | ||
| 299 | 297 | sec_other , |
| 300 | 298 | sec_rsrc , |
| 301 | 299 | sec_stab , |
| 300 | + sec_stabstr , | |
| 302 | 301 | sec_reloc , |
| 303 | 302 | sec_last |
| 304 | 303 | }; |
| @@ -318,12 +317,12 @@ static const DWORD pe_sec_flags[] = { · 13 unmodified lines | ||
| 318 | 317 | #endif |
| 319 | 318 | |
| 320 | 319 | struct section_info { |
| 321 | − int cls, ord; | |
| 320 | + int cls; | |
| 322 | 321 | char name[32]; |
| 323 | 322 | DWORD sh_addr; |
| 324 | 323 | DWORD sh_size; |
| 325 | 324 | DWORD pe_flags; |
| 326 | − unsigned char *data; | |
| 325 | + Section *sec; | |
| 327 | 326 | DWORD data_size; |
| 328 | 327 | IMAGE_SECTION_HEADER ish; |
| 329 | 328 | }; |
| @@ -359,7 +358,7 @@ struct pe_info { · 29 unmodified lines | ||
| 359 | 358 | int subsystem; |
| 360 | 359 | DWORD section_align; |
| 361 | 360 | DWORD file_align; |
| 362 | − struct section_info *sec_info; | |
| 361 | + struct section_info **sec_info; | |
| 363 | 362 | int sec_count; |
| 364 | 363 | struct pe_import_info **imp_info; |
| 365 | 364 | int imp_count; |
| @@ -432,12 +431,10 @@ static int dynarray_assoc(void **pp, int n, int key) · 66 unmodified lines | ||
| 432 | 431 | return -1; |
| 433 | 432 | } |
| 434 | 433 | |
| 435 | −#if 0 | |
| 436 | −ST_FN DWORD umin(DWORD a, DWORD b) | |
| 434 | +static DWORD umin(DWORD a, DWORD b) | |
| 437 | 435 | { |
| 438 | 436 | return a < b ? a : b; |
| 439 | 437 | } |
| 440 | −#endif | |
| 441 | 438 | |
| 442 | 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 | 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) { | |
| 473 | − DWORD sum = *psum; | |
| 474 | − WORD *p = data; | |
| 475 | − int i; | |
| 476 | − for (i = len; i > 0; i -= 2) { | |
| 477 | − sum += (i >= 2) ? *p++ : *(BYTE*)p; | |
| 478 | − sum = (sum + (sum >> 16)) & 0xFFFF; | |
| 479 | − } | |
| 480 | − *psum = sum; | |
| 475 | + WORD *p = data; | |
| 476 | + DWORD sum; | |
| 477 | + int ret, i; | |
| 478 | + pf->pos += (ret = fwrite(data, 1, len, pf->op)); | |
| 479 | + sum = pf->sum; | |
| 480 | + for (i = len; i > 0; i -= 2) { | |
| 481 | + sum += (i >= 2) ? *p++ : *(BYTE*)p; | |
| 482 | + sum = (sum + (sum >> 16)) & 0xFFFF; | |
| 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); | |
| 488 | − while (++pos <= new_pos) | |
| 489 | − fputc(0, fp); | |
| 490 | + char buf[256]; | |
| 491 | + int n, diff = new_pos - pf->pos; | |
| 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 | 606 | struct pe_header pe_header = pe_template; |
| 599 | 607 | |
| 600 | 608 | int i; |
| 601 | − FILE *op; | |
| 602 | − DWORD file_offset, sum; | |
| 609 | + struct pe_file pf = {0}; | |
| 610 | + DWORD file_offset; | |
| 603 | 611 | struct section_info *si; |
| 604 | 612 | IMAGE_SECTION_HEADER *psh; |
| 605 | 613 | TCCState *s1 = pe->s1; |
| 606 | 614 | |
| 607 | − op = fopen(pe->filename, "wb"); | |
| 608 | − if (NULL == op) { | |
| 615 | + pf.op = fopen(pe->filename, "wb"); | |
| 616 | + if (NULL == pf.op) { | |
| 609 | 617 | tcc_error_noabort("could not write '%s': %s", pe->filename, strerror(errno)); |
| 610 | 618 | return -1; |
| 611 | 619 | } |
| @@ -624,7 +632,7 @@ static int pe_write(struct pe_info *pe) · 12 unmodified lines | ||
| 624 | 632 | DWORD addr, size; |
| 625 | 633 | const char *sh_name; |
| 626 | 634 | |
| 627 | − si = pe->sec_info + i; | |
| 635 | + si = pe->sec_info[i]; | |
| 628 | 636 | sh_name = si->name; |
| 629 | 637 | addr = si->sh_addr - pe->imagebase; |
| 630 | 638 | size = si->sh_size; |
| @@ -663,20 +671,18 @@ static int pe_write(struct pe_info *pe) · 32 unmodified lines | ||
| 663 | 671 | break; |
| 664 | 672 | } |
| 665 | 673 | |
| 666 | − if (pe->thunk == pe->s1->sections[si->ord]) { | |
| 667 | − if (pe->imp_size) { | |
| 668 | − pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IMPORT, | |
| 669 | − pe->imp_offs + addr, pe->imp_size); | |
| 670 | − pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IAT, | |
| 671 | − pe->iat_offs + addr, pe->iat_size); | |
| 672 | − } | |
| 673 | − if (pe->exp_size) { | |
| 674 | − pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_EXPORT, | |
| 675 | − pe->exp_offs + addr, pe->exp_size); | |
| 676 | − } | |
| 674 | + if (pe->imp_size) { | |
| 675 | + pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IMPORT, | |
| 676 | + pe->imp_offs, pe->imp_size); | |
| 677 | + pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IAT, | |
| 678 | + pe->iat_offs, pe->iat_size); | |
| 679 | + } | |
| 680 | + if (pe->exp_size) { | |
| 681 | + pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_EXPORT, | |
| 682 | + pe->exp_offs, pe->exp_size); | |
| 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 | 687 | psh->Characteristics = si->pe_flags; |
| 682 | 688 | psh->VirtualAddress = addr; |
| @@ -707,25 +713,29 @@ static int pe_write(struct pe_info *pe) · 24 unmodified lines | ||
| 707 | 713 | pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL; |
| 708 | 714 | pe_header.filehdr.Characteristics |= pe->s1->pe_characteristics; |
| 709 | 715 | |
| 710 | − sum = 0; | |
| 711 | − pe_fwrite(&pe_header, sizeof pe_header, op, &sum); | |
| 716 | + pe_fwrite(&pe_header, sizeof pe_header, &pf); | |
| 712 | 717 | for (i = 0; i < pe->sec_count; ++i) |
| 713 | − pe_fwrite(&pe->sec_info[i].ish, sizeof(IMAGE_SECTION_HEADER), op, &sum); | |
| 714 | − pe_fpad(op, pe->sizeofheaders); | |
| 718 | + pe_fwrite(&pe->sec_info[i]->ish, sizeof(IMAGE_SECTION_HEADER), &pf); | |
| 719 | + | |
| 720 | + file_offset = pe->sizeofheaders; | |
| 715 | 721 | for (i = 0; i < pe->sec_count; ++i) { |
| 716 | − si = pe->sec_info + i; | |
| 717 | − psh = &si->ish; | |
| 718 | − if (si->data_size) { | |
| 719 | − pe_fwrite(si->data, si->data_size, op, &sum); | |
| 720 | − file_offset = psh->PointerToRawData + psh->SizeOfRawData; | |
| 721 | − pe_fpad(op, file_offset); | |
| 722 | + Section *s; | |
| 723 | + si = pe->sec_info[i]; | |
| 724 | + for (s = si->sec; s; s = s->prev) { | |
| 725 | + pe_fpad(&pf, file_offset); | |
| 726 | + pe_fwrite(s->data, s->data_offset, &pf); | |
| 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; | |
| 726 | − fseek(op, offsetof(struct pe_header, opthdr.CheckSum), SEEK_SET); | |
| 727 | − pe_fwrite(&pe_header.opthdr.CheckSum, sizeof pe_header.opthdr.CheckSum, op, NULL); | |
| 728 | − fclose (op); | |
| 734 | + pf.sum += file_offset; | |
| 735 | + fseek(pf.op, offsetof(struct pe_header, opthdr.CheckSum), SEEK_SET); | |
| 736 | + pe_fwrite(&pf.sum, sizeof (DWORD), &pf); | |
| 737 | + | |
| 738 | + fclose (pf.op); | |
| 729 | 739 | #ifndef _WIN32 |
| 730 | 740 | chmod(pe->filename, 0777); |
| 731 | 741 | #endif |
| @@ -796,16 +806,15 @@ static void pe_build_imports(struct pe_info *pe) · 64 unmodified lines | ||
| 796 | 806 | return; |
| 797 | 807 | |
| 798 | 808 | pe_align_section(pe->thunk, 16); |
| 799 | − | |
| 800 | − pe->imp_offs = dll_ptr = pe->thunk->data_offset; | |
| 801 | 809 | pe->imp_size = (ndlls + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR); |
| 802 | − pe->iat_offs = dll_ptr + pe->imp_size; | |
| 803 | 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 | 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 | 818 | for (i = 0; i < pe->imp_count; ++i) { |
| 810 | 819 | IMAGE_IMPORT_DESCRIPTOR *hdr; |
| 811 | 820 | int k, n, dllindex; |
| @@ -895,7 +904,7 @@ static void pe_build_exports(struct pe_info *pe) · 83 unmodified lines | ||
| 895 | 904 | { |
| 896 | 905 | ElfW(Sym) *sym; |
| 897 | 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 | 908 | IMAGE_EXPORT_DIRECTORY *hdr; |
| 900 | 909 | int sym_count, ord; |
| 901 | 910 | struct pe_sort_sym **sorted, *p; |
| @@ -937,13 +946,13 @@ static void pe_build_exports(struct pe_info *pe) · 35 unmodified lines | ||
| 937 | 946 | pe_align_section(pe->thunk, 16); |
| 938 | 947 | dllname = tcc_basename(pe->filename); |
| 939 | 948 | |
| 940 | − pe->exp_offs = pe->thunk->data_offset; | |
| 941 | − func_o = pe->exp_offs + sizeof(IMAGE_EXPORT_DIRECTORY); | |
| 949 | + base_o = pe->thunk->data_offset; | |
| 950 | + func_o = base_o + sizeof(IMAGE_EXPORT_DIRECTORY); | |
| 942 | 951 | name_o = func_o + sym_count * sizeof (DWORD); |
| 943 | 952 | ord_o = name_o + sym_count * sizeof (DWORD); |
| 944 | 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 | 956 | hdr->Characteristics = 0; |
| 948 | 957 | hdr->Base = 1; |
| 949 | 958 | hdr->NumberOfFunctions = sym_count; |
| @@ -985,7 +994,9 @@ static void pe_build_exports(struct pe_info *pe) · 35 unmodified lines | ||
| 985 | 994 | if (op) |
| 986 | 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 | 1000 | dynarray_reset(&sorted, &sym_count); |
| 990 | 1001 | if (op) |
| 991 | 1002 | fclose(op); |
| @@ -994,18 +1005,19 @@ static void pe_build_exports(struct pe_info *pe) · 2 unmodified lines | ||
| 994 | 1005 | /* ------------------------------------------------------------- */ |
| 995 | 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 | 1009 | int count, i; |
| 999 | 1010 | ElfW_Rel *rel, *rel_end; |
| 1000 | 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 | 1015 | rel = rel_end = NULL; |
| 1004 | 1016 | |
| 1005 | 1017 | for(;;) { |
| 1006 | 1018 | if (rel < rel_end) { |
| 1007 | 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 | 1021 | ++ rel; |
| 1010 | 1022 | if (type != REL_TYPE_DIRECT) |
| 1011 | 1023 | continue; |
| @@ -1022,28 +1034,30 @@ static void pe_build_reloc (struct pe_info *pe) · 10 unmodified lines | ||
| 1022 | 1034 | } |
| 1023 | 1035 | -- rel; |
| 1024 | 1036 | |
| 1025 | − } else if (i < pe->sec_count) { | |
| 1026 | − sr = (s = pe->s1->sections[pe->sec_info[i++].ord])->reloc; | |
| 1037 | + } else if (s) { | |
| 1038 | + sr = s->reloc; | |
| 1027 | 1039 | if (sr) { |
| 1028 | 1040 | rel = (ElfW_Rel *)sr->data; |
| 1029 | 1041 | rel_end = (ElfW_Rel *)(sr->data + sr->data_offset); |
| 1042 | + sh_addr = s->sh_addr; | |
| 1030 | 1043 | } |
| 1044 | + s = s->prev; | |
| 1031 | 1045 | continue; |
| 1032 | − } | |
| 1033 | 1046 | |
| 1034 | − if (count) { | |
| 1035 | − /* store the last block and ready for a new one */ | |
| 1036 | − struct pe_reloc_header *hdr; | |
| 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 | − } | |
| 1047 | + } else if (i < pe->sec_count) { | |
| 1048 | + s = pe->sec_info[i]->sec, ++i; | |
| 1049 | + continue; | |
| 1044 | 1050 | |
| 1045 | − if (rel >= rel_end) | |
| 1051 | + } else if (!count) | |
| 1046 | 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 | 1086 | if (flags & SHF_WRITE) |
| 1073 | 1087 | return sec_bss; |
| 1074 | 1088 | } |
| 1075 | − return sec_other; | |
| 1076 | 1089 | } else { |
| 1077 | 1090 | if (0 == strcmp(name, ".reloc")) |
| 1078 | 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 | 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 | 1108 | if (PE_DLL == pe->type) |
| 1094 | 1109 | pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0); |
| 1095 | − | |
| 1096 | 1110 | // pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC); |
| 1097 | 1111 | |
| 1098 | 1112 | section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int)); |
| 1099 | 1113 | for (o = k = 0 ; k < sec_last; ++k) { |
| 1100 | 1114 | for (i = 1; i < pe->s1->nb_sections; ++i) { |
| 1101 | 1115 | s = pe->s1->sections[i]; |
| 1102 | − if (k == pe_section_class(s)) { | |
| 1103 | − // printf("%s %d\n", s->name, k); | |
| 1104 | − s->sh_addr = pe->imagebase; | |
| 1116 | + if (k == pe_section_class(s)) | |
| 1105 | 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 | 1122 | addr = pe->imagebase + 1; |
| 1112 | 1123 | |
| 1113 | − for (i = 0; i < o; ++i) | |
| 1114 | − { | |
| 1124 | + for (i = 0; i < o; ++i) { | |
| 1115 | 1125 | k = section_order[i]; |
| 1116 | 1126 | s = pe->s1->sections[k]; |
| 1117 | 1127 | c = pe_section_class(s); |
| 1118 | − si = &pe->sec_info[pe->sec_count]; | |
| 1119 | 1128 | |
| 1120 | −#ifdef PE_MERGE_DATA | |
| 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; | |
| 1129 | + if ((c == sec_stab || c == sec_stabstr) && 0 == pe->s1->do_debug) | |
| 1126 | 1130 | continue; |
| 1127 | − } | |
| 1131 | + | |
| 1132 | +#ifdef PE_MERGE_DATA | |
| 1133 | + if (c == sec_bss) | |
| 1134 | + c = sec_data; | |
| 1128 | 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 | 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 | 1163 | strcpy(si->name, s->name); |
| 1133 | 1164 | si->cls = c; |
| 1134 | − si->ord = k; | |
| 1135 | − si->sh_addr = s->sh_addr = addr = pe_virtual_align(pe, addr); | |
| 1165 | + si->sh_addr = addr; | |
| 1136 | 1166 | |
| 1137 | 1167 | si->pe_flags = IMAGE_SCN_MEM_READ; |
| 1138 | 1168 | if (s->sh_flags & SHF_EXECINSTR) |
| @@ -1143,48 +1173,35 @@ static int pe_assign_addresses (struct pe_info *pe) · 4 unmodified lines | ||
| 1143 | 1173 | si->pe_flags |= IMAGE_SCN_CNT_INITIALIZED_DATA; |
| 1144 | 1174 | if (s->sh_flags & SHF_WRITE) |
| 1145 | 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 | 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) { | |
| 1156 | − pe_build_imports(pe); | |
| 1157 | − pe_build_exports(pe); | |
| 1179 | +add_section: | |
| 1180 | + addr += s->data_offset; | |
| 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 | − | |
| 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); | |
| 1189 | + //printf("%08x %05x %08x %s\n", si->sh_addr, si->sh_size, si->pe_flags, s->name); | |
| 1175 | 1190 | } |
| 1191 | + tcc_free(section_order); | |
| 1176 | 1192 | #if 0 |
| 1177 | 1193 | for (i = 1; i < pe->s1->nb_sections; ++i) { |
| 1178 | 1194 | Section *s = pe->s1->sections[i]; |
| 1179 | 1195 | int type = s->sh_type; |
| 1180 | 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 | 1198 | s->name, |
| 1183 | 1199 | type == SHT_PROGBITS ? "progbits" : |
| 1184 | 1200 | type == SHT_NOBITS ? "nobits" : |
| 1185 | 1201 | type == SHT_SYMTAB ? "symtab" : |
| 1186 | 1202 | type == SHT_STRTAB ? "strtab" : |
| 1187 | 1203 | type == SHT_RELX ? "rel" : "???", |
| 1204 | + s->sh_addr, | |
| 1188 | 1205 | s->data_offset, |
| 1189 | 1206 | flags & SHF_ALLOC ? "alloc" : "", |
| 1190 | 1207 | flags & SHF_WRITE ? "write" : "", |
| @@ -1193,8 +1210,6 @@ static int pe_assign_addresses (struct pe_info *pe) · 2 unmodified lines | ||
| 1193 | 1210 | } |
| 1194 | 1211 | pe->s1->verbose = 2; |
| 1195 | 1212 | #endif |
| 1196 | − | |
| 1197 | − tcc_free(section_order); | |
| 1198 | 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 | 1875 | else |
| 1861 | 1876 | if (TCC_OUTPUT_DLL == s1->output_type) { |
| 1862 | 1877 | pe_type = PE_DLL; |
| 1863 | − /* need this for 'tccelf.c:relocate_section()' */ | |
| 1864 | − s1->output_type = TCC_OUTPUT_EXE; | |
| 1865 | 1878 | } |
| 1866 | 1879 | else { |
| 1867 | 1880 | pe_type = PE_EXE; |
| @@ -1881,24 +1894,34 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) · 13 unmodified lines | ||
| 1881 | 1894 | if (!s1->leading_underscore || strchr(start_symbol, '@')) |
| 1882 | 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 | 1915 | #ifdef TCC_IS_NATIVE |
| 1886 | 1916 | if (TCC_OUTPUT_MEMORY != s1->output_type || s1->runtime_main) |
| 1887 | 1917 | #endif |
| 1888 | − set_elf_sym(symtab_section, | |
| 1889 | − 0, 0, | |
| 1890 | − ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, | |
| 1891 | − SHN_UNDEF, start_symbol); | |
| 1918 | + set_global_sym(s1, start_symbol, NULL, 0); | |
| 1892 | 1919 | |
| 1893 | 1920 | if (0 == s1->nostdlib) { |
| 1894 | 1921 | static const char *libs[] = { |
| 1895 | 1922 | "msvcrt", "kernel32", "", "user32", "gdi32", NULL |
| 1896 | 1923 | }; |
| 1897 | 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 | 1925 | tcc_add_support(s1, TCC_LIBTCC1); |
| 1903 | 1926 | for (pp = libs; 0 != (p = *pp); ++pp) { |
| 1904 | 1927 | if (*p) |
| @@ -1907,6 +1930,10 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) · 2 unmodified lines | ||
| 1907 | 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 | 1937 | if (TCC_OUTPUT_MEMORY == s1->output_type) |
| 1911 | 1938 | pe_type = PE_RUN; |
| 1912 | 1939 | pe->type = pe_type; |
| @@ -1970,7 +1997,10 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) · 57 unmodified lines | ||
| 1970 | 1997 | pe.filename = filename; |
| 1971 | 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 | 2004 | pe_add_runtime(s1, &pe); |
| 1975 | 2005 | resolve_common_syms(s1); |
| 1976 | 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 | 2025 | ret = -1; |
| 1996 | 2026 | else |
| 1997 | 2027 | ret = pe_write(&pe); |
| 1998 | − tcc_free(pe.sec_info); | |
| 2028 | + dynarray_reset(&pe.sec_info, &pe.sec_count); | |
| 1999 | 2029 | } else { |
| 2000 | 2030 | #ifdef TCC_IS_NATIVE |
| 2001 | 2031 | pe.thunk = data_section; |
| @@ -109,9 +109,7 @@ ST_FUNC void expect(const char *msg) · 108 unmodified lines | ||
| 109 | 109 | /* ------------------------------------------------------------------------- */ |
| 110 | 110 | /* Custom allocator for tiny objects */ |
| 111 | 111 | |
| 112 | −#ifndef __BOUNDS_CHECKING_ON | |
| 113 | 112 | #define USE_TAL |
| 114 | −#endif | |
| 115 | 113 | |
| 116 | 114 | #ifndef USE_TAL |
| 117 | 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 | 248 | tail_call: |
| 251 | 249 | is_own = (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size); |
| 252 | 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 | 252 | header = (tal_header_t *)al->p; |
| 255 | 253 | header->size = adj_size; |
| 256 | 254 | #ifdef TAL_DEBUG |
| @@ -1958,7 +1956,11 @@ include_done: · 1701 unmodified lines | ||
| 1958 | 1956 | if (tok == TOK_STR) { |
| 1959 | 1957 | if (file->true_filename == file->filename) |
| 1960 | 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 | 1964 | } else if (parse_flags & PARSE_FLAG_ASM_FILE) |
| 1963 | 1965 | break; |
| 1964 | 1966 | else |
| @@ -3529,9 +3531,6 @@ no_subst: · 1564 unmodified lines | ||
| 3529 | 3531 | /* return next token with macro substitution */ |
| 3530 | 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 | 3534 | redo: |
| 3536 | 3535 | if (parse_flags & PARSE_FLAG_SPACES) |
| 3537 | 3536 | next_nomacro_spc(); |
| @@ -3607,6 +3606,8 @@ ST_FUNC void preprocess_start(TCCState *s1, int is_asm) · 69 unmodified lines | ||
| 3607 | 3606 | cstr_printf(&cstr, "#define __BASE_FILE__ \"%s\"\n", file->filename); |
| 3608 | 3607 | if (is_asm) |
| 3609 | 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 | 3611 | if (s1->cmdline_incl.size) |
| 3611 | 3612 | cstr_cat(&cstr, s1->cmdline_incl.data, s1->cmdline_incl.size); |
| 3612 | 3613 | //printf("%s\n", (char*)cstr.data); |
| @@ -3657,7 +3658,7 @@ ST_FUNC void tccpp_new(TCCState *s) · 44 unmodified lines | ||
| 3657 | 3658 | cstr_realloc(&cstr_buf, STRING_MAX_SIZE); |
| 3658 | 3659 | tok_str_new(&tokstr_buf); |
| 3659 | 3660 | tok_str_realloc(&tokstr_buf, TOKSTR_MAX_SIZE); |
| 3660 | − | |
| 3661 | + | |
| 3661 | 3662 | tok_ident = TOK_IDENT; |
| 3662 | 3663 | p = tcc_keywords; |
| 3663 | 3664 | while (*p) { |
| @@ -23,27 +23,36 @@ · 22 unmodified lines | ||
| 23 | 23 | /* only native compiler supports -run */ |
| 24 | 24 | #ifdef TCC_IS_NATIVE |
| 25 | 25 | |
| 26 | −#ifndef _WIN32 | |
| 27 | −# include <sys/mman.h> | |
| 28 | −#endif | |
| 29 | − | |
| 30 | 26 | #ifdef CONFIG_TCC_BACKTRACE |
| 31 | −static void set_exception_handler(void); | |
| 32 | −#ifdef _WIN32 | |
| 33 | −static DWORD s1_for_run_idx; | |
| 34 | −void set_s1_for_run(TCCState *s) | |
| 27 | +typedef struct rt_context | |
| 35 | 28 | { |
| 36 | − if (!s1_for_run_idx) | |
| 37 | − s1_for_run_idx = TlsAlloc(); | |
| 38 | − TlsSetValue(s1_for_run_idx, s); | |
| 39 | −} | |
| 40 | −#define get_s1_for_run() ((TCCState*)TlsGetValue(s1_for_run_idx)) | |
| 41 | −#else | |
| 42 | −/* XXX: add tls support for linux */ | |
| 43 | −static TCCState *s1_for_run; | |
| 44 | −#define set_s1_for_run(s) (s1_for_run = s) | |
| 45 | −#define get_s1_for_run() s1_for_run | |
| 46 | −#endif | |
| 29 | + /* --> tccelf.c:tcc_add_btstub wants those below in that order: */ | |
| 30 | + Stab_Sym *stab_sym, *stab_sym_end; | |
| 31 | + char *stab_str; | |
| 32 | + ElfW(Sym) *esym_start, *esym_end; | |
| 33 | + char *elf_str; | |
| 34 | + addr_t prog_base; | |
| 35 | + void *bounds_start; | |
| 36 | + struct rt_context *next; | |
| 37 | + /* <-- */ | |
| 38 | + int num_callers; | |
| 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 | 56 | #endif |
| 48 | 57 | |
| 49 | 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 | 122 | #endif |
| 114 | 123 | } |
| 115 | 124 | tcc_free(s1->runtime_mem); |
| 116 | − if (get_s1_for_run() == s1) | |
| 117 | − set_s1_for_run(NULL); | |
| 125 | +} | |
| 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 | 135 | /* launch the compiled program with the given arguments */ |
| 121 | 136 | LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) |
| 122 | 137 | { |
| 123 | −/* PE target overwrites runtime_main */ | |
| 124 | −#ifndef TCC_TARGET_PE | |
| 125 | − typedef void (*init_array_func)(int, char **, char **); | |
| 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; | |
| 138 | + int (*prog_main)(int, char **), ret; | |
| 139 | +#ifdef CONFIG_TCC_BACKTRACE | |
| 140 | + rt_context *rc = &g_rtctxt; | |
| 131 | 141 | #endif |
| 132 | − int i; | |
| 133 | − int ret; | |
| 134 | − int (*prog_main)(int, char **); | |
| 135 | 142 | |
| 136 | 143 | s1->runtime_main = s1->nostdlib ? "_start" : "main"; |
| 137 | 144 | if ((s1->dflag & 16) && !find_elf_sym(s1->symtab, s1->runtime_main)) |
| 138 | 145 | return 0; |
| 146 | +#ifdef CONFIG_TCC_BACKTRACE | |
| 147 | + if (s1->do_debug) | |
| 148 | + tcc_add_symbol(s1, "exit", rt_exit); | |
| 149 | +#endif | |
| 139 | 150 | if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0) |
| 140 | 151 | return -1; |
| 141 | 152 | prog_main = tcc_get_symbol_err(s1, s1->runtime_main); |
| 142 | 153 | |
| 143 | 154 | #ifdef CONFIG_TCC_BACKTRACE |
| 155 | + memset(rc, 0, sizeof *rc); | |
| 144 | 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 | 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 | 177 | #endif |
| 151 | 178 | |
| 152 | 179 | errno = 0; /* clean errno value */ |
| 153 | − | |
| 154 | −#ifdef CONFIG_TCC_BCHECK | |
| 155 | − if (s1->do_bounds_check) | |
| 156 | − /* set error function */ | |
| 157 | − s1->rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg"); | |
| 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 | − } | |
| 180 | + fflush(stdout); | |
| 181 | + fflush(stderr); | |
| 182 | + run_cdtors(s1, "__init_array_start", "__init_array_end"); | |
| 183 | +#ifdef CONFIG_TCC_BACKTRACE | |
| 184 | + if (!rc->do_jmp || !(ret = setjmp(rc->jmp_buf))) | |
| 171 | 185 | #endif |
| 172 | − | |
| 173 | − 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])(); | |
| 186 | + { | |
| 187 | + ret = prog_main(argc, argv); | |
| 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 | 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 | 348 | #endif |
| 339 | − | |
| 349 | +#endif //ndef CONFIG_TCC_BACKTRACE_ONLY | |
| 340 | 350 | /* ------------------------------------------------------------- */ |
| 341 | 351 | #ifdef CONFIG_TCC_BACKTRACE |
| 342 | 352 | |
| 343 | −#define INCLUDE_STACK_SIZE 32 | |
| 344 | 353 | static int rt_vprintf(const char *fmt, va_list ap) |
| 345 | 354 | { |
| 346 | 355 | int ret = vfprintf(stderr, fmt, ap); |
| @@ -358,21 +367,22 @@ static int rt_printf(const char *fmt, ...) · 11 unmodified lines | ||
| 358 | 367 | return r; |
| 359 | 368 | } |
| 360 | 369 | |
| 370 | +#define INCLUDE_STACK_SIZE 32 | |
| 371 | + | |
| 361 | 372 | /* print the position in the source file of PC value 'pc' by reading |
| 362 | 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 | 377 | char func_name[128]; |
| 366 | 378 | addr_t func_addr, last_pc, pc; |
| 367 | 379 | const char *incl_files[INCLUDE_STACK_SIZE]; |
| 368 | 380 | int incl_index, last_incl_index, len, last_line_num, i; |
| 369 | 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; | |
| 372 | − Stab_Sym *stab_sym = NULL, *stab_sym_end = NULL, *sym; | |
| 373 | − char *stab_str = NULL; | |
| 374 | − char *elf_str = NULL; | |
| 375 | − | |
| 385 | +next: | |
| 376 | 386 | func_name[0] = '\0'; |
| 377 | 387 | func_addr = 0; |
| 378 | 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 | 390 | last_line_num = 1; |
| 381 | 391 | last_incl_index = 0; |
| 382 | 392 | |
| 383 | − if (stab_section) { | |
| 384 | − stab_sym = (Stab_Sym *)stab_section->data; | |
| 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; | |
| 393 | + for (sym = rc->stab_sym + 1; sym < rc->stab_sym_end; ++sym) { | |
| 394 | + str = rc->stab_str + sym->n_strx; | |
| 396 | 395 | pc = sym->n_value; |
| 397 | 396 | |
| 398 | 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 | 405 | if (sym->n_strx == 0) /* end of function */ |
| 407 | 406 | goto rel_pc; |
| 408 | 407 | abs_pc: |
| 409 | − if (sizeof pc == 8) | |
| 408 | + if (sizeof sym->n_value < PTR_SIZE) { | |
| 410 | 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 | 413 | break; |
| 413 | 414 | rel_pc: |
| 414 | 415 | pc += func_addr; |
| 415 | 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 | 420 | goto found; |
| 420 | 421 | |
| 421 | 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 | 435 | last_pc = pc; |
| 435 | 436 | last_line_num = sym->n_desc; |
| 436 | 437 | last_incl_index = incl_index; |
| 437 | − if (pc == wanted_pc) | |
| 438 | − goto found; | |
| 439 | 438 | break; |
| 440 | 439 | /* include files */ |
| 441 | 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 | 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 | 476 | int type = ELFW(ST_TYPE)(esym->st_info); |
| 474 | 477 | if (type == STT_FUNC || type == STT_GNU_IFUNC) { |
| 475 | 478 | if (wanted_pc >= esym->st_value && |
| 476 | 479 | wanted_pc < esym->st_value + esym->st_size) { |
| 477 | 480 | pstrcpy(func_name, sizeof(func_name), |
| 478 | − elf_str + esym->st_name); | |
| 481 | + rc->elf_str + esym->st_name); | |
| 479 | 482 | func_addr = esym->st_value; |
| 480 | − last_incl_index = 0; | |
| 481 | 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 | 492 | i = last_incl_index; |
| 491 | − if (i > 0) | |
| 492 | − rt_printf("%s:%d: ", incl_files[--i], last_line_num); | |
| 493 | − rt_printf("%s %p", msg, (void*)wanted_pc); | |
| 494 | − if (func_name[0] != '\0') | |
| 495 | − rt_printf(" %s()", func_name); | |
| 493 | + if (i > 0) { | |
| 494 | + str = incl_files[--i]; | |
| 495 | + if (skip[0] && strstr(str, skip)) | |
| 496 | + return (addr_t)-1; | |
| 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 | 502 | if (--i >= 0) { |
| 497 | 503 | rt_printf(" (included from "); |
| 498 | 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 | 510 | rt_printf(")"); |
| 505 | 511 | } |
| 512 | +#endif | |
| 506 | 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 | 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' */ | |
| 516 | −static void rt_error(rt_context *rc, const char *fmt, ...) | |
| 518 | +static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap) | |
| 517 | 519 | { |
| 518 | − va_list ap; | |
| 519 | − addr_t pc; | |
| 520 | − int i; | |
| 521 | − TCCState *s1; | |
| 522 | − | |
| 523 | − s1 = get_s1_for_run(); | |
| 524 | − if (*fmt == ' ') { | |
| 525 | − if (s1 && s1->rt_bound_error_msg && *s1->rt_bound_error_msg) | |
| 526 | − fmt = *s1->rt_bound_error_msg; | |
| 527 | − else | |
| 528 | − ++fmt; | |
| 520 | + rt_context *rc = &g_rtctxt; | |
| 521 | + addr_t pc = 0; | |
| 522 | + char skip[100]; | |
| 523 | + int i, level, ret, n; | |
| 524 | + const char *a, *b, *msg; | |
| 525 | + | |
| 526 | + if (fp) { | |
| 527 | + /* we're called from tcc_backtrace. */ | |
| 528 | + rc->fp = (addr_t)fp; | |
| 529 | + rc->ip = (addr_t)ip; | |
| 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: "); | |
| 532 | − va_start(ap, fmt); | |
| 533 | − rt_vprintf(fmt, ap); | |
| 534 | − va_end(ap); | |
| 535 | − rt_printf("\n"); | |
| 536 | − | |
| 537 | − if (!s1) | |
| 538 | − return; | |
| 536 | + skip[0] = 0; | |
| 537 | + /* If fmt is like "^file.c^..." then skip calls from 'file.c' */ | |
| 538 | + if (fmt[0] == '^' && (b = strchr(a = fmt + 1, fmt[0]))) { | |
| 539 | + memcpy(skip, a, b - a), skip[b - a] = 0; | |
| 540 | + fmt = b + 1; | |
| 541 | + } | |
| 539 | 542 | |
| 540 | − for(i=0; i<s1->rt_num_callers; i++) { | |
| 541 | − if (rt_get_caller_pc(&pc, rc, i) < 0) | |
| 543 | + n = rc->num_callers ? rc->num_callers : 6; | |
| 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 | 557 | break; |
| 543 | − pc = rt_printline(s1, pc, i ? "by" : "at"); | |
| 544 | 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 | 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 | 658 | /* signal handler for fatal errors */ |
| 622 | 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 | 664 | switch(signum) { |
| 628 | 665 | case SIGFPE: |
| 629 | 666 | switch(siginf->si_code) { |
| 630 | 667 | case FPE_INTDIV: |
| 631 | 668 | case FPE_FLTDIV: |
| 632 | − rt_error(&rc, "division by zero"); | |
| 669 | + rt_error("division by zero"); | |
| 633 | 670 | break; |
| 634 | 671 | default: |
| 635 | − rt_error(&rc, "floating point exception"); | |
| 672 | + rt_error("floating point exception"); | |
| 636 | 673 | break; |
| 637 | 674 | } |
| 638 | 675 | break; |
| 639 | 676 | case SIGBUS: |
| 640 | 677 | case SIGSEGV: |
| 641 | − rt_error(&rc, " dereferencing invalid pointer"); | |
| 678 | + rt_error("invalid memory access"); | |
| 642 | 679 | break; |
| 643 | 680 | case SIGILL: |
| 644 | − rt_error(&rc, "illegal instruction"); | |
| 681 | + rt_error("illegal instruction"); | |
| 645 | 682 | break; |
| 646 | 683 | case SIGABRT: |
| 647 | − rt_error(&rc, "abort() called"); | |
| 684 | + rt_error("abort() called"); | |
| 648 | 685 | break; |
| 649 | 686 | default: |
| 650 | − rt_error(&rc, "caught signal %d", signum); | |
| 687 | + rt_error("caught signal %d", signum); | |
| 651 | 688 | break; |
| 652 | 689 | } |
| 653 | − exit(255); | |
| 690 | + rt_exit(255); | |
| 654 | 691 | } |
| 655 | 692 | |
| 656 | 693 | #ifndef SA_SIGINFO |
| @@ -664,7 +701,7 @@ static void set_exception_handler(void) · 7 unmodified lines | ||
| 664 | 701 | /* install TCC signal handlers to print debug info on fatal |
| 665 | 702 | runtime errors */ |
| 666 | 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 | 705 | sigact.sa_flags |= SA_ONSTACK; |
| 669 | 706 | #endif |
| 670 | 707 | sigact.sa_sigaction = sig_error; |
| @@ -674,7 +711,7 @@ static void set_exception_handler(void) · 3 unmodified lines | ||
| 674 | 711 | sigaction(SIGSEGV, &sigact, NULL); |
| 675 | 712 | sigaction(SIGBUS, &sigact, NULL); |
| 676 | 713 | sigaction(SIGABRT, &sigact, NULL); |
| 677 | −#ifdef SIGSTKSZ | |
| 714 | +#if 0//def SIGSTKSZ | |
| 678 | 715 | /* This allows stack overflow to be reported instead of a SEGV */ |
| 679 | 716 | { |
| 680 | 717 | stack_t ss; |
| @@ -689,32 +726,35 @@ static void set_exception_handler(void) · 8 unmodified lines | ||
| 689 | 726 | } |
| 690 | 727 | |
| 691 | 728 | #else /* WIN32 */ |
| 729 | + | |
| 692 | 730 | /* signal handler for fatal errors */ |
| 693 | 731 | static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info) |
| 694 | 732 | { |
| 695 | − rt_context rc; | |
| 733 | + rt_context *rc = &g_rtctxt; | |
| 696 | 734 | unsigned code; |
| 735 | + rt_getcontext(ex_info->ContextRecord, rc); | |
| 697 | 736 | |
| 698 | − rt_getcontext(ex_info->ContextRecord, &rc); | |
| 699 | 737 | switch (code = ex_info->ExceptionRecord->ExceptionCode) { |
| 700 | 738 | case EXCEPTION_ACCESS_VIOLATION: |
| 701 | − rt_error(&rc, " access violation"); | |
| 739 | + rt_error("invalid memory access"); | |
| 702 | 740 | break; |
| 703 | 741 | case EXCEPTION_STACK_OVERFLOW: |
| 704 | − rt_error(&rc, "stack overflow"); | |
| 742 | + rt_error("stack overflow"); | |
| 705 | 743 | break; |
| 706 | 744 | case EXCEPTION_INT_DIVIDE_BY_ZERO: |
| 707 | − rt_error(&rc, "division by zero"); | |
| 745 | + rt_error("division by zero"); | |
| 708 | 746 | break; |
| 709 | 747 | case EXCEPTION_BREAKPOINT: |
| 710 | 748 | case EXCEPTION_SINGLE_STEP: |
| 711 | − rc.ip = *(addr_t*)rc.sp; | |
| 712 | − rt_error(&rc, "^breakpoint/single-step exception:"); | |
| 749 | + rc->ip = *(addr_t*)rc->sp; | |
| 750 | + rt_error("breakpoint/single-step exception:"); | |
| 713 | 751 | return EXCEPTION_CONTINUE_SEARCH; |
| 714 | 752 | default: |
| 715 | − rt_error(&rc, "caught exception %08x", code); | |
| 753 | + rt_error("caught exception %08x", code); | |
| 716 | 754 | break; |
| 717 | 755 | } |
| 756 | + if (rc->do_jmp) | |
| 757 | + rt_exit(255); | |
| 718 | 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 | 848 | #endif |
| 809 | 849 | #endif /* CONFIG_TCC_BACKTRACE */ |
| 810 | − | |
| 811 | 850 | /* ------------------------------------------------------------- */ |
| 812 | 851 | #ifdef CONFIG_TCC_STATIC |
| 813 | 852 | |
| @@ -73,6 +73,7 @@ endif · 72 unmodified lines | ||
| 73 | 73 | RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) |
| 74 | 74 | DISAS = objdump -d |
| 75 | 75 | DUMPTCC = (set -x; $(TOP)/tcc -vv; ldd $(TOP)/tcc; exit 1) |
| 76 | +Q = # >/dev/null 2>&1 | |
| 76 | 77 | |
| 77 | 78 | all test : |
| 78 | 79 | $(MAKE) clean-s |
| @@ -88,7 +89,7 @@ hello-run: ../examples/ex1.c · 9 unmodified lines | ||
| 88 | 89 | |
| 89 | 90 | libtes%: libtcc_tes%$(EXESUF) |
| 90 | 91 | @echo ------------ $@ ------------ |
| 91 | − ./libtcc_tes$*$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) | |
| 92 | + ./libtcc_tes$*$(EXESUF) $(TOPSRC)/tcc.c $(TCCFLAGS) $(NATIVE_DEFINES) | |
| 92 | 93 | |
| 93 | 94 | libtcc_tes%$(EXESUF): libtcc_tes%.c $(LIBTCC) |
| 94 | 95 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) |
| @@ -105,22 +106,24 @@ test.ref: tcctest.c · 10 unmodified lines | ||
| 105 | 106 | # auto test |
| 106 | 107 | test1 test1b: tcctest.c test.ref |
| 107 | 108 | @echo ------------ $@ ------------ |
| 108 | − $(TCC) -run $< > test.out1 | |
| 109 | − @diff -u test.ref test.out1 && echo "Auto Test OK" | |
| 109 | + $(TCC) -w -run $< > test.out1 $Q | |
| 110 | + @diff -u test.ref test.out1 && echo "$(AUTO_TEST) OK" | |
| 110 | 111 | |
| 111 | 112 | # iterated test2 (compile tcc then compile tcctest.c !) |
| 112 | 113 | test2 test2b: tcctest.c test.ref |
| 113 | 114 | @echo ------------ $@ ------------ |
| 114 | − $(TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out2 | |
| 115 | − @diff -u test.ref test.out2 && echo "Auto Test2 OK" | |
| 115 | + $(TCC) $(RUN_TCC) $(RUN_TCC) -w -run $< > test.out2 $Q | |
| 116 | + @diff -u test.ref test.out2 && echo "$(AUTO_TEST)2 OK" | |
| 116 | 117 | |
| 117 | 118 | # iterated test3 (compile tcc then compile tcc then compile tcctest.c !) |
| 118 | 119 | test3 test3b: tcctest.c test.ref |
| 119 | 120 | @echo ------------ $@ ------------ |
| 120 | − $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out3 | |
| 121 | − @diff -u test.ref test.out3 && echo "Auto Test3 OK" | |
| 121 | + $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -w -run $< > test.out3 $Q | |
| 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 | 128 | # binary output test |
| 126 | 129 | test4: tcctest.c test.ref |
| @@ -129,21 +132,21 @@ test4: tcctest.c test.ref · 2 unmodified lines | ||
| 129 | 132 | $(TCC) -c -o tcctest3.o $< |
| 130 | 133 | $(TCC) -o tcctest3 tcctest3.o |
| 131 | 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 | 136 | # dynamic output |
| 134 | 137 | $(TCC) -o tcctest1 $< |
| 135 | 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 | 140 | # dynamic output + bound check |
| 138 | 141 | $(TCC) -b -o tcctest4 $< |
| 139 | 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 | 145 | test4_static: tcctest.c test.ref |
| 143 | 146 | # static output. |
| 144 | 147 | $(TCC) -static -o tcctest2 $< |
| 145 | 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 | 151 | # use tcc to create libtcc.so/.dll and the tcc(.exe) frontend and run them |
| 149 | 152 | dlltest: |
| @@ -164,32 +167,29 @@ memtest: · 14 unmodified lines | ||
| 164 | 167 | @echo ------------ $@ ------------ |
| 165 | 168 | $(CC) $(CFLAGS) $(NATIVE_DEFINES) -DMEM_DEBUG=2 $(TOPSRC)/tcc.c $(LIBS) -o memtest-tcc$(EXESUF) |
| 166 | 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 | |
| 168 | − | |
| 170 | + ./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) -w $(TOPSRC)/tests/tcctest.c | |
| 169 | 171 | |
| 170 | 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 | 174 | BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17 |
| 173 | 175 | |
| 174 | 176 | btest: boundtest.c |
| 175 | 177 | @echo ------------ $@ ------------ |
| 176 | 178 | @for i in $(BOUNDS_OK); do \ |
| 177 | − echo ; echo --- boundtest $$i ---; \ | |
| 178 | 179 | if $(TCC) -b -run $< $$i ; then \ |
| 179 | − echo succeeded as expected; \ | |
| 180 | + echo "- Test $$i succeeded as expected" ; \ | |
| 180 | 181 | else\ |
| 181 | − echo Failed positive test $$i ; exit 1 ; \ | |
| 182 | + echo "- Failed positive test $$i" ; exit 1 ; \ | |
| 182 | 183 | fi ;\ |
| 183 | 184 | done ;\ |
| 184 | 185 | for i in $(BOUNDS_FAIL); do \ |
| 185 | − echo ; echo --- boundtest $$i ---; \ | |
| 186 | − if $(TCC) -b -run $< $$i ; then \ | |
| 187 | − echo Failed negative test $$i ; exit 1 ;\ | |
| 186 | + if $(TCC) -b -bt1 -run $< $$i ; then \ | |
| 187 | + echo "- Failed negative test $$i" ; exit 1 ;\ | |
| 188 | 188 | else\ |
| 189 | − echo failed as expected; \ | |
| 189 | + echo "- Test $$i failed as expected" ; \ | |
| 190 | 190 | fi ;\ |
| 191 | 191 | done ;\ |
| 192 | − echo; echo Bound test OK | |
| 192 | + echo Bound test OK | |
| 193 | 193 | |
| 194 | 194 | # speed test |
| 195 | 195 | speedtest: ex2 ex3 |
| @@ -50,15 +50,12 @@ int test4(void) · 49 unmodified lines | ||
| 50 | 50 | int i, sum = 0; |
| 51 | 51 | int *tab4; |
| 52 | 52 | |
| 53 | − fprintf(stderr, "%s start\n", __FUNCTION__); | |
| 54 | − | |
| 55 | 53 | tab4 = malloc(20 * sizeof(int)); |
| 56 | 54 | for(i=0;i<20;i++) { |
| 57 | 55 | sum += tab4[i]; |
| 58 | 56 | } |
| 59 | 57 | free(tab4); |
| 60 | 58 | |
| 61 | − fprintf(stderr, "%s end\n", __FUNCTION__); | |
| 62 | 59 | return sum; |
| 63 | 60 | } |
| 64 | 61 | |
| @@ -68,15 +65,12 @@ int test5(void) · 3 unmodified lines | ||
| 68 | 65 | int i, sum = 0; |
| 69 | 66 | int *tab4; |
| 70 | 67 | |
| 71 | − fprintf(stderr, "%s start\n", __FUNCTION__); | |
| 72 | − | |
| 73 | 68 | tab4 = malloc(20 * sizeof(int)); |
| 74 | 69 | for(i=0;i<21;i++) { |
| 75 | 70 | sum += tab4[i]; |
| 76 | 71 | } |
| 77 | 72 | free(tab4); |
| 78 | 73 | |
| 79 | − fprintf(stderr, "%s end\n", __FUNCTION__); | |
| 80 | 74 | return sum; |
| 81 | 75 | } |
| 82 | 76 | |
| @@ -198,16 +192,12 @@ int test16() · 115 unmodified lines | ||
| 198 | 192 | char *demo = "This is only a test."; |
| 199 | 193 | char *p; |
| 200 | 194 | |
| 201 | − fprintf(stderr, "%s start\n", __FUNCTION__); | |
| 202 | − | |
| 203 | 195 | p = alloca(16); |
| 204 | 196 | strcpy(p,"12345678901234"); |
| 205 | − printf("alloca: p is %s\n", p); | |
| 206 | 197 | |
| 207 | 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 | 201 | return 0; |
| 212 | 202 | } |
| 213 | 203 | |
| @@ -217,211 +207,11 @@ int test17() · 3 unmodified lines | ||
| 217 | 207 | char *demo = "This is only a test."; |
| 218 | 208 | char *p; |
| 219 | 209 | |
| 220 | − fprintf(stderr, "%s start\n", __FUNCTION__); | |
| 221 | − | |
| 222 | 210 | p = alloca(16); |
| 223 | 211 | strcpy(p,"12345678901234"); |
| 224 | − printf("alloca: p is %s\n", p); | |
| 225 | 212 | |
| 226 | 213 | /* Test alloca embedded in a larger expression */ |
| 227 | − printf("alloca: %s\n", 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])); | |
| 214 | + printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)),demo) ); | |
| 425 | 215 | |
| 426 | 216 | return 0; |
| 427 | 217 | } |
| @@ -443,8 +233,7 @@ int (*table_test[])(void) = { · 15 unmodified lines | ||
| 443 | 233 | test14, |
| 444 | 234 | test15, |
| 445 | 235 | test16, |
| 446 | − test17, | |
| 447 | − test18, | |
| 236 | + test17 | |
| 448 | 237 | }; |
| 449 | 238 | |
| 450 | 239 | int main(int argc, char **argv) |
| @@ -203,14 +203,11 @@ TF_TYPE(thread_test_complex, vn) · 202 unmodified lines | ||
| 203 | 203 | |
| 204 | 204 | sprintf(b, "%d", F(n)); |
| 205 | 205 | |
| 206 | − argv[argc++] = "../tcc.c"; | |
| 207 | 206 | for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i]; |
| 208 | 207 | #if 0 |
| 209 | 208 | argv[argc++] = "-run"; |
| 210 | − argv[argc++] = "../tcc.c"; | |
| 211 | 209 | for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i]; |
| 212 | 210 | #endif |
| 213 | − argv[argc++] = "-g"; | |
| 214 | 211 | argv[argc++] = "-DFIB"; |
| 215 | 212 | argv[argc++] = "-run"; |
| 216 | 213 | argv[argc++] = __FILE__; |
| @@ -221,23 +218,24 @@ TF_TYPE(thread_test_complex, vn) · 4 unmodified lines | ||
| 221 | 218 | sleep_ms(2); |
| 222 | 219 | ret = tcc_add_file(s, argv[0]); |
| 223 | 220 | sleep_ms(3); |
| 224 | − if (ret >= 0) | |
| 225 | − tcc_run(s, argc, argv); | |
| 221 | + if (ret < 0) | |
| 222 | + exit(1); | |
| 223 | + tcc_run(s, argc, argv); | |
| 226 | 224 | tcc_delete(s); |
| 227 | 225 | fflush(stdout); |
| 228 | 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 | 231 | TCCState *s; |
| 234 | 232 | int ret; |
| 235 | 233 | while (--n >= 0) { |
| 236 | 234 | s = new_state(1); |
| 237 | − ret = tcc_add_file(s, "../tcc.c"); | |
| 235 | + ret = tcc_add_file(s, src); | |
| 238 | 236 | tcc_delete(s); |
| 239 | 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 | 258 | g_argc = argc; |
| 261 | 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 | 266 | #if 1 |
| 264 | 267 | printf("----- libtest : mixed calls -------\n"), fflush(stdout); |
| 265 | 268 | t = getclock_ms(); |
| @@ -285,7 +288,7 @@ int main(int argc, char **argv) · 19 unmodified lines | ||
| 285 | 288 | #if 1 |
| 286 | 289 | printf("----- compilation of tcc -----------\n"), fflush(stdout); |
| 287 | 290 | t = getclock_ms(); |
| 288 | − time_tcc(10); | |
| 291 | + time_tcc(10, argv[1]); | |
| 289 | 292 | printf("(%u ms)\n", (getclock_ms() - t) / 10), fflush(stdout); |
| 290 | 293 | #endif |
| 291 | 294 | return 0; |
| @@ -1725,10 +1725,6 @@ void cast_test() · 1724 unmodified lines | ||
| 1725 | 1725 | printf("sizeof(-(char)'a') = %d\n", sizeof(-(char)'a')); |
| 1726 | 1726 | printf("sizeof(~(char)'a') = %d\n", sizeof(-(char)'a')); |
| 1727 | 1727 | |
| 1728 | −#ifdef __TINYC__ | |
| 1729 | −# pragma comment(option, "-w") | |
| 1730 | −#endif | |
| 1731 | − | |
| 1732 | 1728 | /* from pointer to integer types */ |
| 1733 | 1729 | printf("%d %d %ld %ld %lld %lld\n", |
| 1734 | 1730 | (int)p, (unsigned int)p, |
| @@ -1739,10 +1735,6 @@ void cast_test() · 4 unmodified lines | ||
| 1739 | 1735 | printf("%p %p %p %p\n", |
| 1740 | 1736 | (void *)a, (void *)b, (void *)c, (void *)d); |
| 1741 | 1737 | |
| 1742 | −#ifdef __TINYC__ | |
| 1743 | −# pragma comment(option, "-W") | |
| 1744 | −#endif | |
| 1745 | − | |
| 1746 | 1738 | /* int to int with sign set */ |
| 1747 | 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 | 3399 | #endif |
| 3408 | 3400 | |
| 3409 | −void test_high_clobbers(void) | |
| 3401 | +void test_high_clobbers_really(void) | |
| 3410 | 3402 | { |
| 3411 | 3403 | #if defined __x86_64__ && !defined _WIN64 |
| 3412 | 3404 | register long val asm("r12"); |
| @@ -3422,6 +3414,20 @@ void test_high_clobbers(void) · 9 unmodified lines | ||
| 3422 | 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 | 3431 | static long cpu_number; |
| 3426 | 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 | 20 | 60_errors_and_warnings.c:26: error: redefinition of enumerator 'RED' |
| 21 | 21 | |
| 22 | 22 | [test_63_local_enumerator_redefinition] |
| 23 | +[returns 1] | |
| 23 | 24 | |
| 24 | 25 | [test_61_undefined_enum] |
| 25 | 26 | 60_errors_and_warnings.c:46: error: unknown type size |
| @@ -24,6 +24,7 @@ ifeq (,$(filter i386,$(ARCH))) · 23 unmodified lines | ||
| 24 | 24 | endif |
| 25 | 25 | ifeq (,$(filter i386 x86_64,$(ARCH))) |
| 26 | 26 | SKIP += 85_asm-outside-function.test |
| 27 | + SKIP += 112_backtrace.test | |
| 27 | 28 | endif |
| 28 | 29 | ifeq (-$(findstring gcc,$(CC))-,--) |
| 29 | 30 | SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS)) |
| @@ -70,12 +71,11 @@ GEN-ALWAYS = · 40 unmodified lines | ||
| 70 | 71 | # constructor/destructor |
| 71 | 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 | 77 | # Filter source directory in warnings/errors (out-of-tree builds) |
| 74 | −FILTER = 2>&1 | sed '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 | |
| 78 | +FILTER = 2>&1 | sed -e 's,$(SRC)/,,g' | |
| 79 | 79 | |
| 80 | 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 | 138 | @if errorlevel 1 goto :the_end |
| 139 | 139 | |
| 140 | 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 | 142 | .\tcc -m32 -c ../lib/libtcc1.c |
| 143 | 143 | .\tcc -m32 -c lib/crt1.c |
| 144 | 144 | .\tcc -m32 -c lib/crt1w.c |
| @@ -147,7 +147,6 @@ copy>nul tcc-win32.txt doc · 2 unmodified lines | ||
| 147 | 147 | .\tcc -m32 -c lib/dllcrt1.c |
| 148 | 148 | .\tcc -m32 -c lib/dllmain.c |
| 149 | 149 | .\tcc -m32 -c lib/chkstk.S |
| 150 | −.\tcc -m32 -w -c ../lib/bcheck.c | |
| 151 | 150 | .\tcc -m32 -c ../lib/alloca86.S |
| 152 | 151 | .\tcc -m32 -c ../lib/alloca86-bt.S |
| 153 | 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 | 159 | .\tcc -m64 -c lib/dllcrt1.c |
| 161 | 160 | .\tcc -m64 -c lib/dllmain.c |
| 162 | 161 | .\tcc -m64 -c lib/chkstk.S |
| 163 | −.\tcc -m64 -w -c ../lib/bcheck.c | |
| 164 | 162 | .\tcc -m64 -c ../lib/alloca86_64.S |
| 165 | 163 | .\tcc -m64 -c ../lib/alloca86_64-bt.S |
| 166 | 164 | .\tcc -m64 -ar lib/libtcc1-64.a %O1% alloca86_64.o alloca86_64-bt.o |
| 167 | 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 | 171 | :tcc-doc.html |
| 170 | 172 | @if not (%DOC%)==(yes) goto :doc-done |
| @@ -182,7 +184,7 @@ if not exist %INST% mkdir %INST% · 11 unmodified lines | ||
| 182 | 184 | if not exist %BIN% mkdir %BIN% |
| 183 | 185 | for %%f in (*tcc.exe *tcc.dll) do @copy>nul %%f %BIN%\%%f |
| 184 | 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 | 188 | for %%f in (include examples libtcc doc) do @xcopy>nul /s/i/q/y %%f %INST%\%%f |
| 187 | 189 | |
| 188 | 190 | :the_end |
| @@ -99,7 +99,7 @@ int _runtmain(int argc, /* as tcc passed in */ char **argv) · 98 unmodified lines | ||
| 99 | 99 | #if defined __i386__ || defined __x86_64__ |
| 100 | 100 | _controlfp(_PC_53, _MCW_PC); |
| 101 | 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 | 191 | if (s1->output_type == TCC_OUTPUT_DLL) { |
| 192 | 192 | /* XXX: this logic may depend on TCC's codegen |
| 193 | 193 | now TCC uses R_X86_64_32 even for a 64bit pointer */ |
| 194 | + qrel->r_offset = rel->r_offset; | |
| 194 | 195 | qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE); |
| 195 | 196 | /* Use sign extension! */ |
| 196 | 197 | qrel->r_addend = (int)read32le(ptr) + val; |