| @@ -24,6 +24,7 @@ · 23 unmodified lines |
| 24 | #ifdef TCC_IS_NATIVE | 24 | #ifdef TCC_IS_NATIVE |
| 25 | | 25 | |
| 26 | #ifdef CONFIG_TCC_BACKTRACE | 26 | #ifdef CONFIG_TCC_BACKTRACE |
| | 27 | /* runtime debug info block */ |
| 27 | typedef struct rt_context | 28 | typedef struct rt_context |
| 28 | { | 29 | { |
| 29 | /* tccelf.c:tcc_add_btstub() wants these in that order: */ | 30 | /* tccelf.c:tcc_add_btstub() wants these in that order: */ |
| @@ -42,32 +43,33 @@ typedef struct rt_context · 12 unmodified lines |
| 42 | ElfW(Sym) *esym_start; | 43 | ElfW(Sym) *esym_start; |
| 43 | ElfW(Sym) *esym_end; | 44 | ElfW(Sym) *esym_end; |
| 44 | char *elf_str; | 45 | char *elf_str; |
| 45 | // 6 | 46 | // 6 * PTR_SIZE |
| 46 | addr_t prog_base; | 47 | addr_t prog_base; |
| 47 | void *bounds_start; | 48 | void *bounds_start; |
| 48 | void *top_func; | 49 | void *top_func; |
| 49 | TCCState *s1; | | |
| 50 | struct rt_context *next; | 50 | struct rt_context *next; |
| 51 | // 11 | 51 | // 10 * PTR_SIZE |
| 52 | int num_callers; | 52 | int num_callers; |
| 53 | int dwarf; | 53 | int dwarf; |
| 54 | } rt_context; /* size = 11 * PTR_SIZE + 2 * sizeof (int) */ | 54 | } rt_context; |
| | 55 | |
| | 56 | /* linked list of rt_contexts */ |
| | 57 | static rt_context *g_rc; |
| | 58 | static int signal_set; |
| | 59 | static void set_exception_handler(void); |
| | 60 | #endif /* def CONFIG_TCC_BACKTRACE */ |
| 55 | | 61 | |
| 56 | typedef struct rt_frame { | 62 | typedef struct rt_frame { |
| 57 | addr_t ip, fp, sp; | 63 | addr_t ip, fp, sp; |
| 58 | } rt_frame; | 64 | } rt_frame; |
| 59 | | 65 | |
| 60 | /* linked list of rt_contexts */ | | |
| 61 | static rt_context *g_rc; | | |
| 62 | static TCCState *g_s1; | 66 | static TCCState *g_s1; |
| 63 | /* semaphore to protect it */ | 67 | /* semaphore to protect it */ |
| 64 | TCC_SEM(static rt_sem); | 68 | TCC_SEM(static rt_sem); |
| 65 | static int signal_set; | | |
| 66 | static void set_exception_handler(void); | | |
| 67 | static void rt_wait_sem(void) { WAIT_SEM(&rt_sem); } | 69 | static void rt_wait_sem(void) { WAIT_SEM(&rt_sem); } |
| 68 | static void rt_post_sem(void) { POST_SEM(&rt_sem); } | 70 | static void rt_post_sem(void) { POST_SEM(&rt_sem); } |
| 69 | static int rt_get_caller_pc(addr_t *paddr, rt_frame *f, int level); | 71 | static int rt_get_caller_pc(addr_t *paddr, rt_frame *f, int level); |
| 70 | #endif /* def CONFIG_TCC_BACKTRACE */ | 72 | static void rt_exit(rt_frame *f, int code); |
| 71 | | 73 | |
| 72 | /* ------------------------------------------------------------- */ | 74 | /* ------------------------------------------------------------- */ |
| 73 | /* defined when included from lib/bt-exe.c */ | 75 | /* defined when included from lib/bt-exe.c */ |
| @@ -79,73 +81,26 @@ static int rt_get_caller_pc(addr_t *paddr, rt_frame *f, int level); · 5 unmodified lines |
| 79 | | 81 | |
| 80 | static int protect_pages(void *ptr, unsigned long length, int mode); | 82 | static int protect_pages(void *ptr, unsigned long length, int mode); |
| 81 | static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff); | 83 | static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff); |
| 82 | static int __rt_dump(rt_frame *f, const char *msg, const char *fmt, va_list ap); | 84 | static void st_link(TCCState *s1); |
| 83 | static void rt_longjmp(rt_frame *f, int code); | 85 | static void st_unlink(TCCState *s1); |
| | 86 | #ifdef CONFIG_TCC_BACKTRACE |
| | 87 | static int _tcc_backtrace(rt_frame *f, const char *fmt, va_list ap); |
| | 88 | #endif |
| 84 | #ifdef _WIN64 | 89 | #ifdef _WIN64 |
| 85 | static void *win64_add_function_table(TCCState *s1); | 90 | static void *win64_add_function_table(TCCState *s1); |
| 86 | static void win64_del_function_table(void *); | 91 | static void win64_del_function_table(void *); |
| 87 | #endif | 92 | #endif |
| 88 | | 93 | |
| 89 | static void bt_link(TCCState *s1) | 94 | #ifdef __APPLE__ |
| 90 | { | 95 | # define CONFIG_RUNMEM_ALIGNED 0 |
| 91 | #ifdef CONFIG_TCC_BACKTRACE | 96 | #else |
| 92 | rt_context *rc; | 97 | # ifndef CONFIG_RUNMEM_ALIGNED |
| 93 | void *p; | 98 | # define CONFIG_RUNMEM_ALIGNED 1 |
| 94 | | 99 | # endif |
| 95 | if (!s1->do_backtrace) | 100 | # if CONFIG_RUNMEM_ALIGNED |
| 96 | return; | 101 | # include <malloc.h> /* memalign() */ |
| 97 | rc = tcc_get_symbol(s1, "__rt_info"); | 102 | # endif |
| 98 | if (!rc) | | |
| 99 | return; | | |
| 100 | rc->esym_start = (ElfW(Sym) *)(symtab_section->data); | | |
| 101 | rc->esym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset); | | |
| 102 | rc->elf_str = (char *)symtab_section->link->data; | | |
| 103 | if (PTR_SIZE == 8 && !s1->dwarf) | | |
| 104 | rc->prog_base &= 0xffffffff00000000ULL; | | |
| 105 | #ifdef CONFIG_TCC_BCHECK | | |
| 106 | if (s1->do_bounds_check) { | | |
| 107 | if ((p = tcc_get_symbol(s1, "__bound_init"))) | | |
| 108 | ((void(*)(void*,int))p)(rc->bounds_start, 1); | | |
| 109 | } | | |
| 110 | #endif | | |
| 111 | rc->next = g_rc, g_rc = rc, rc->s1 = s1, s1->rc = rc; | | |
| 112 | if (0 == signal_set) | | |
| 113 | set_exception_handler(), signal_set = 1; | | |
| 114 | #endif | | |
| 115 | } | | |
| 116 | | | |
| 117 | static void bt_unlink(TCCState *s1) | | |
| 118 | { | | |
| 119 | #ifdef CONFIG_TCC_BACKTRACE | | |
| 120 | rt_context *rc, **pp; | | |
| 121 | for (pp = &g_rc; rc = *pp, rc; pp = &rc->next) | | |
| 122 | if (rc->s1 == s1) { | | |
| 123 | *pp = rc->next; | | |
| 124 | break; | | |
| 125 | } | | |
| 126 | #endif | 103 | #endif |
| 127 | } | | |
| 128 | | | |
| 129 | static void st_link(TCCState *s1) | | |
| 130 | { | | |
| 131 | rt_wait_sem(); | | |
| 132 | s1->next = g_s1, g_s1 = s1; | | |
| 133 | bt_link(s1); | | |
| 134 | rt_post_sem(); | | |
| 135 | } | | |
| 136 | | | |
| 137 | static void st_unlink(TCCState *s1) | | |
| 138 | { | | |
| 139 | TCCState *s2, **pp; | | |
| 140 | rt_wait_sem(); | | |
| 141 | bt_unlink(s1); | | |
| 142 | for (pp = &g_s1; s2 = *pp, s2; pp = &s2->next) | | |
| 143 | if (s2 == s1) { | | |
| 144 | *pp = s2->next; | | |
| 145 | break; | | |
| 146 | } | | |
| 147 | rt_post_sem(); | | |
| 148 | } | | |
| 149 | | 104 | |
| 150 | #if !_WIN32 && !__APPLE__ | 105 | #if !_WIN32 && !__APPLE__ |
| 151 | //#define HAVE_SELINUX 1 | 106 | //#define HAVE_SELINUX 1 |
| @@ -172,7 +127,15 @@ static int rt_mem(TCCState *s1, int size) · 20 unmodified lines |
| 172 | ptr_diff = (char*)prw - (char*)ptr; /* = size; */ | 127 | ptr_diff = (char*)prw - (char*)ptr; /* = size; */ |
| 173 | //printf("map %p %p %p\n", ptr, prw, (void*)ptr_diff); | 128 | //printf("map %p %p %p\n", ptr, prw, (void*)ptr_diff); |
| 174 | #else | 129 | #else |
| 175 | ptr = tcc_malloc(size); | 130 | # if !CONFIG_RUNMEM_ALIGNED |
| | 131 | ptr = tcc_malloc(size += PAGESIZE); |
| | 132 | # elif _WIN32 |
| | 133 | ptr = _aligned_malloc(size, PAGESIZE); |
| | 134 | # else |
| | 135 | ptr = memalign(PAGESIZE, size); |
| | 136 | # endif |
| | 137 | if (NULL == ptr) |
| | 138 | return tcc_error_noabort("tccrun: could not allocate memory"); |
| 176 | #endif | 139 | #endif |
| 177 | s1->run_ptr = ptr; | 140 | s1->run_ptr = ptr; |
| 178 | s1->run_size = size; | 141 | s1->run_size = size; |
| @@ -189,12 +152,10 @@ LIBTCCAPI int tcc_relocate(TCCState *s1) · 10 unmodified lines |
| 189 | | 152 | |
| 190 | if (s1->run_ptr) | 153 | if (s1->run_ptr) |
| 191 | exit(tcc_error_noabort("'tcc_relocate()' twice is no longer supported")); | 154 | exit(tcc_error_noabort("'tcc_relocate()' twice is no longer supported")); |
| 192 | | | |
| 193 | #ifdef CONFIG_TCC_BACKTRACE | 155 | #ifdef CONFIG_TCC_BACKTRACE |
| 194 | if (s1->do_backtrace) | 156 | if (s1->do_backtrace) |
| 195 | tcc_add_symbol(s1, "__rt_dump", __rt_dump); /* for bt-log.c */ | 157 | tcc_add_symbol(s1, "_tcc_backtrace", _tcc_backtrace); /* for bt-log.c */ |
| 196 | #endif | 158 | #endif |
| 197 | | | |
| 198 | size = tcc_relocate_ex(s1, NULL, 0); | 159 | size = tcc_relocate_ex(s1, NULL, 0); |
| 199 | if (size < 0) | 160 | if (size < 0) |
| 200 | return -1; | 161 | return -1; |
| @@ -236,31 +197,24 @@ ST_FUNC void tcc_run_free(TCCState *s1) · 35 unmodified lines |
| 236 | #else | 197 | #else |
| 237 | /* unprotect memory to make it usable for malloc again */ | 198 | /* unprotect memory to make it usable for malloc again */ |
| 238 | protect_pages(ptr, size, 2 /*rw*/); | 199 | protect_pages(ptr, size, 2 /*rw*/); |
| 239 | #ifdef _WIN64 | 200 | # ifdef _WIN64 |
| 240 | win64_del_function_table(s1->run_function_table); | 201 | win64_del_function_table(s1->run_function_table); |
| 241 | #endif | 202 | # endif |
| | 203 | # if !CONFIG_RUNMEM_ALIGNED |
| 242 | tcc_free(ptr); | 204 | tcc_free(ptr); |
| | 205 | # elif _WIN32 |
| | 206 | _aligned_free(ptr); |
| | 207 | # else |
| | 208 | libc_free(ptr); |
| | 209 | # endif |
| 243 | #endif | 210 | #endif |
| 244 | } | 211 | } |
| 245 | | 212 | |
| 246 | LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *p_longjmp, void *p_jmp_buf, void *func) | | |
| 247 | { | | |
| 248 | s1->run_lj = p_longjmp; | | |
| 249 | s1->run_jb = p_jmp_buf; | | |
| 250 | if (func && s1->rc) | | |
| 251 | s1->rc->top_func = func; | | |
| 252 | return p_jmp_buf; | | |
| 253 | } | | |
| 254 | | | |
| 255 | LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, TCCBtFunc *func) | | |
| 256 | { | | |
| 257 | s1->bt_func = func; | | |
| 258 | } | | |
| 259 | | | |
| 260 | /* launch the compiled program with the given arguments */ | 213 | /* launch the compiled program with the given arguments */ |
| 261 | LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) | 214 | LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) |
| 262 | { | 215 | { |
| 263 | int (*prog_main)(int, char **, char **), ret; | 216 | int (*prog_main)(int, char **, char **), ret; |
| | 217 | const char *top_sym; |
| 264 | jmp_buf main_jb; | 218 | jmp_buf main_jb; |
| 265 | | 219 | |
| 266 | #if defined(__APPLE__) || defined(__FreeBSD__) | 220 | #if defined(__APPLE__) || defined(__FreeBSD__) |
| @@ -276,20 +230,25 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 9 unmodified lines |
| 276 | if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, "main", 0, 1)) | 230 | if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, "main", 0, 1)) |
| 277 | return 0; | 231 | return 0; |
| 278 | | 232 | |
| 279 | tcc_add_support(s1, "runmain.o"); | 233 | tcc_add_symbol(s1, "__rt_exit", rt_exit); |
| 280 | tcc_add_symbol(s1, "__rt_longjmp", rt_longjmp); | 234 | if (s1->nostdlib) { |
| 281 | s1->run_main = (s1->nostdlib ? "_start" : "_runmain"); | 235 | s1->run_main = top_sym = "_start"; |
| | 236 | } else { |
| | 237 | tcc_add_support(s1, "runmain.o"); |
| | 238 | s1->run_main = "_runmain"; |
| | 239 | top_sym = "main"; |
| | 240 | } |
| 282 | if (tcc_relocate(s1) < 0) | 241 | if (tcc_relocate(s1) < 0) |
| 283 | return -1; | 242 | return 1; |
| 284 | | 243 | |
| 285 | prog_main = (void*)get_sym_addr(s1, s1->run_main, 1, 1); | 244 | prog_main = (void*)get_sym_addr(s1, s1->run_main, 1, 1); |
| 286 | if ((addr_t)-1 == (addr_t)prog_main) | 245 | if ((addr_t)-1 == (addr_t)prog_main) |
| 287 | return -1; | 246 | return 1; |
| 288 | errno = 0; /* clean errno value */ | 247 | errno = 0; /* clean errno value */ |
| 289 | fflush(stdout); | 248 | fflush(stdout); |
| 290 | fflush(stderr); | 249 | fflush(stderr); |
| 291 | | 250 | |
| 292 | ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, "main")); | 251 | ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, top_sym)); |
| 293 | if (0 == ret) | 252 | if (0 == ret) |
| 294 | ret = prog_main(argc, argv, envp); | 253 | ret = prog_main(argc, argv, envp); |
| 295 | else if (256 == ret) | 254 | else if (256 == ret) |
| @@ -344,8 +303,6 @@ static void cleanup_sections(TCCState *s1) · 48 unmodified lines |
| 344 | # define CONFIG_RUNMEM_RO 1 | 303 | # define CONFIG_RUNMEM_RO 1 |
| 345 | #endif | 304 | #endif |
| 346 | | 305 | |
| 347 | #define DEBUG_RUNMEN 0 | | |
| 348 | | | |
| 349 | /* relocate code. Return -1 on error, required size if ptr is NULL, | 306 | /* relocate code. Return -1 on error, required size if ptr is NULL, |
| 350 | otherwise copy code into buffer passed by the caller */ | 307 | otherwise copy code into buffer passed by the caller */ |
| 351 | static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff) | 308 | static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff) |
| @@ -367,16 +324,17 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff) · 15 unmodified lines |
| 367 | | 324 | |
| 368 | offset = copy = 0; | 325 | offset = copy = 0; |
| 369 | mem = (addr_t)ptr; | 326 | mem = (addr_t)ptr; |
| 370 | | | |
| 371 | #if DEBUG_RUNMEN | | |
| 372 | if (mem) | | |
| 373 | fprintf(stderr, "X: <base> %p len %5x\n", | | |
| 374 | ptr, s1->run_size); | | |
| 375 | #endif | | |
| 376 | | | |
| 377 | redo: | 327 | redo: |
| | 328 | if (s1->verbose == 2 && copy) { |
| | 329 | printf(&"-----------------------------------------------------\n"[PTR_SIZE*2 - 8]); |
| | 330 | if (1 == copy) |
| | 331 | printf("memory %p len %05x\n", ptr, s1->run_size); |
| | 332 | } |
| 378 | if (s1->nb_errors) | 333 | if (s1->nb_errors) |
| 379 | return -1; | 334 | return -1; |
| | 335 | if (copy == 2) |
| | 336 | return 0; |
| | 337 | |
| 380 | for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */ | 338 | for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */ |
| 381 | n = 0; addr = 0; | 339 | n = 0; addr = 0; |
| 382 | for(i = 1; i < s1->nb_sections; i++) { | 340 | for(i = 1; i < s1->nb_sections; i++) { |
| @@ -389,7 +347,9 @@ redo: · 6 unmodified lines |
| 389 | length = s->data_offset; | 347 | length = s->data_offset; |
| 390 | | 348 | |
| 391 | if (copy) { /* final step: copy section data to memory */ | 349 | if (copy) { /* final step: copy section data to memory */ |
| 392 | void *ptr; | 350 | if (s1->verbose == 2) |
| | 351 | printf("%d: %-16s %p len %05x align %04x\n", |
| | 352 | k, s->name, (void*)s->sh_addr, length, s->sh_addralign); |
| 393 | if (addr == 0) | 353 | if (addr == 0) |
| 394 | addr = s->sh_addr; | 354 | addr = s->sh_addr; |
| 395 | n = (s->sh_addr - addr) + length; | 355 | n = (s->sh_addr - addr) + length; |
| @@ -407,28 +367,25 @@ redo: · 11 unmodified lines |
| 407 | continue; | 367 | continue; |
| 408 | } | 368 | } |
| 409 | | 369 | |
| 410 | align = s->sh_addralign - 1; | 370 | align = s->sh_addralign; |
| 411 | if (++n == 1) { | 371 | if (++n == 1) { |
| 412 | #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 | 372 | #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 |
| 413 | /* To avoid that x86 processors would reload cached instructions | 373 | /* To avoid that x86 processors would reload cached instructions |
| 414 | each time when data is written in the near, we need to make | 374 | each time when data is written in the near, we need to make |
| 415 | sure that code and data do not share the same 64 byte unit */ | 375 | sure that code and data do not share the same 64 byte unit */ |
| 416 | if (align < 63) | 376 | if (align < 64) |
| 417 | align = 63; | 377 | align = 64; |
| 418 | #endif | 378 | #endif |
| 419 | /* start new page for different permissions */ | 379 | /* start new page for different permissions */ |
| 420 | if (CONFIG_RUNMEM_RO || k < 2) | 380 | if (CONFIG_RUNMEM_RO || k < 2) |
| 421 | align = PAGESIZE - 1; | 381 | align = PAGESIZE; |
| 422 | } | 382 | } |
| | 383 | s->sh_addralign = align; |
| | 384 | |
| 423 | addr = k ? mem + ptr_diff : mem; | 385 | addr = k ? mem + ptr_diff : mem; |
| 424 | offset += -(addr + offset) & align; | 386 | offset += -(addr + offset) & (align - 1); |
| 425 | s->sh_addr = mem ? addr + offset : 0; | 387 | s->sh_addr = mem ? addr + offset : 0; |
| 426 | offset += length; | 388 | offset += length; |
| 427 | #if DEBUG_RUNMEN | | |
| 428 | if (mem) | | |
| 429 | fprintf(stderr, "%d: %-16s %p len %5x align %04x\n", | | |
| 430 | k, s->name, (void*)s->sh_addr, length, align + 1); | | |
| 431 | #endif | | |
| 432 | } | 389 | } |
| 433 | if (copy) { /* set permissions */ | 390 | if (copy) { /* set permissions */ |
| 434 | if (n == 0) /* no data */ | 391 | if (n == 0) /* no data */ |
| @@ -443,30 +400,25 @@ redo: · 8 unmodified lines |
| 443 | continue; | 400 | continue; |
| 444 | f = 3; /* change only SHF_EXECINSTR to rwx */ | 401 | f = 3; /* change only SHF_EXECINSTR to rwx */ |
| 445 | } | 402 | } |
| 446 | #if DEBUG_RUNMEN | 403 | n = (n + PAGESIZE-1) & ~(PAGESIZE-1); |
| 447 | fprintf(stderr, "protect %3s %p len %5x\n", | 404 | if (s1->verbose == 2) { |
| 448 | &"rx\0r \0rw\0rwx"[f*3], | 405 | printf("protect %3s %p len %05x\n", |
| 449 | (void*)addr, (unsigned)((n + PAGESIZE-1) & ~(PAGESIZE-1))); | 406 | &"rx\0r \0rw\0rwx"[f*3], (void*)addr, (unsigned)n); |
| 450 | #endif | 407 | } |
| 451 | if (protect_pages((void*)addr, n, f) < 0) | 408 | if (protect_pages((void*)addr, n, f) < 0) |
| 452 | return tcc_error_noabort( | 409 | return tcc_error_noabort( |
| 453 | "mprotect failed (did you mean to configure --with-selinux?)"); | 410 | "mprotect failed (did you mean to configure --with-selinux?)"); |
| 454 | } | 411 | } |
| 455 | } | 412 | } |
| 456 | | 413 | |
| 457 | if (0 == mem) { | 414 | if (0 == mem) |
| 458 | offset = (offset + (PAGESIZE-1)) & ~(PAGESIZE-1); | 415 | return (offset + (PAGESIZE-1)) & ~(PAGESIZE-1); |
| 459 | #ifndef HAVE_SELINUX | | |
| 460 | offset += PAGESIZE; /* extra space to align malloc memory start */ | | |
| 461 | #endif | | |
| 462 | return offset; | | |
| 463 | } | | |
| 464 | | 416 | |
| 465 | if (copy) { | 417 | if (++copy == 2) { |
| 466 | /* remove local symbols and free sections except symtab */ | 418 | /* remove local symbols and free sections except symtab */ |
| 467 | cleanup_symbols(s1); | 419 | cleanup_symbols(s1); |
| 468 | cleanup_sections(s1); | 420 | cleanup_sections(s1); |
| 469 | return 0; | 421 | goto redo; |
| 470 | } | 422 | } |
| 471 | | 423 | |
| 472 | /* relocate symbols */ | 424 | /* relocate symbols */ |
| @@ -478,7 +430,6 @@ redo: · 5 unmodified lines |
| 478 | relocate_plt(s1); | 430 | relocate_plt(s1); |
| 479 | #endif | 431 | #endif |
| 480 | relocate_sections(s1); | 432 | relocate_sections(s1); |
| 481 | copy = 1; | | |
| 482 | goto redo; | 433 | goto redo; |
| 483 | } | 434 | } |
| 484 | | 435 | |
| @@ -546,6 +497,152 @@ static void win64_del_function_table(void *p) · 61 unmodified lines |
| 546 | } | 497 | } |
| 547 | #endif | 498 | #endif |
| 548 | | 499 | |
| | 500 | static void bt_link(TCCState *s1) |
| | 501 | { |
| | 502 | #ifdef CONFIG_TCC_BACKTRACE |
| | 503 | rt_context *rc; |
| | 504 | void *p; |
| | 505 | |
| | 506 | if (!s1->do_backtrace) |
| | 507 | return; |
| | 508 | rc = tcc_get_symbol(s1, "__rt_info"); |
| | 509 | if (!rc) |
| | 510 | return; |
| | 511 | rc->esym_start = (ElfW(Sym) *)(symtab_section->data); |
| | 512 | rc->esym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset); |
| | 513 | rc->elf_str = (char *)symtab_section->link->data; |
| | 514 | if (PTR_SIZE == 8 && !s1->dwarf) |
| | 515 | rc->prog_base &= 0xffffffff00000000ULL; |
| | 516 | #ifdef CONFIG_TCC_BCHECK |
| | 517 | if (s1->do_bounds_check) { |
| | 518 | if ((p = tcc_get_symbol(s1, "__bound_init"))) |
| | 519 | ((void(*)(void*,int))p)(rc->bounds_start, 1); |
| | 520 | } |
| | 521 | #endif |
| | 522 | rc->next = g_rc, g_rc = rc, s1->rc = rc; |
| | 523 | if (0 == signal_set) |
| | 524 | set_exception_handler(), signal_set = 1; |
| | 525 | #endif |
| | 526 | } |
| | 527 | |
| | 528 | static void st_link(TCCState *s1) |
| | 529 | { |
| | 530 | rt_wait_sem(); |
| | 531 | s1->next = g_s1, g_s1 = s1; |
| | 532 | bt_link(s1); |
| | 533 | rt_post_sem(); |
| | 534 | } |
| | 535 | |
| | 536 | /* remove 'el' from 'list' */ |
| | 537 | static void ptr_unlink(void *list, void *e, unsigned next) |
| | 538 | { |
| | 539 | void **pp, **nn, *p; |
| | 540 | for (pp = list; !!(p = *pp); pp = nn) { |
| | 541 | nn = (void*)((char*)p + next); /* nn = &p->next; */ |
| | 542 | if (p == e) { |
| | 543 | *pp = *nn; |
| | 544 | break; |
| | 545 | } |
| | 546 | } |
| | 547 | } |
| | 548 | |
| | 549 | static void st_unlink(TCCState *s1) |
| | 550 | { |
| | 551 | rt_wait_sem(); |
| | 552 | #ifdef CONFIG_TCC_BACKTRACE |
| | 553 | ptr_unlink(&g_rc, s1->rc, offsetof(rt_context, next)); |
| | 554 | #endif |
| | 555 | ptr_unlink(&g_s1, s1, offsetof(TCCState, next)); |
| | 556 | rt_post_sem(); |
| | 557 | } |
| | 558 | |
| | 559 | #ifdef _WIN32 |
| | 560 | # define GETTID() GetCurrentThreadId() |
| | 561 | #elif defined __linux__ |
| | 562 | # define GETTID() gettid() |
| | 563 | #elif 0 |
| | 564 | # define GETTID() 1234 // threads not supported |
| | 565 | #endif |
| | 566 | |
| | 567 | LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *p_jmp_buf, void *func, void *p_longjmp) |
| | 568 | { |
| | 569 | #ifdef GETTID |
| | 570 | int tid = GETTID(); |
| | 571 | TCCState *s; |
| | 572 | rt_wait_sem(); |
| | 573 | for (s = g_s1; s; s = s->next) |
| | 574 | if (s->run_tid == tid) |
| | 575 | s->run_tid = -1; |
| | 576 | s1->run_tid = (int)tid; |
| | 577 | rt_post_sem(); |
| | 578 | #endif |
| | 579 | s1->run_lj = p_longjmp; |
| | 580 | s1->run_jb = p_jmp_buf; |
| | 581 | #ifdef CONFIG_TCC_BACKTRACE |
| | 582 | if (s1->rc) |
| | 583 | s1->rc->top_func = func; |
| | 584 | #endif |
| | 585 | return p_jmp_buf; |
| | 586 | } |
| | 587 | |
| | 588 | LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, void *data, TCCBtFunc *func) |
| | 589 | { |
| | 590 | s1->bt_func = func; |
| | 591 | s1->bt_data = data; |
| | 592 | } |
| | 593 | |
| | 594 | static TCCState *rt_find_state(rt_frame *f) |
| | 595 | { |
| | 596 | #ifdef GETTID |
| | 597 | int tid = GETTID(); |
| | 598 | TCCState *s; |
| | 599 | for (s = g_s1; s; s = s->next) |
| | 600 | if (s->run_tid == tid) |
| | 601 | break; |
| | 602 | return s; |
| | 603 | #else |
| | 604 | TCCState *s; |
| | 605 | int level; |
| | 606 | addr_t pc; |
| | 607 | |
| | 608 | s = g_s1; |
| | 609 | if (NULL == s || NULL == s->next) { |
| | 610 | /* play it safe in the simple case when there is only one state */ |
| | 611 | return s; |
| | 612 | } |
| | 613 | for (level = 0; level < 8; ++level) { |
| | 614 | if (rt_get_caller_pc(&pc, f, level) < 0) |
| | 615 | break; |
| | 616 | for (s = g_s1; s; s = s->next) { |
| | 617 | if (pc >= (addr_t)s->run_ptr |
| | 618 | && pc < (addr_t)s->run_ptr + s->run_size) |
| | 619 | return s; |
| | 620 | } |
| | 621 | } |
| | 622 | return NULL; |
| | 623 | #endif |
| | 624 | } |
| | 625 | |
| | 626 | static void rt_exit(rt_frame *f, int code) |
| | 627 | { |
| | 628 | TCCState *s; |
| | 629 | rt_wait_sem(); |
| | 630 | s = rt_find_state(f); |
| | 631 | rt_post_sem(); |
| | 632 | if (s && s->run_lj) { |
| | 633 | if (code == 0) |
| | 634 | code = 256; |
| | 635 | ((void(*)(void*,int))s->run_lj)(s->run_jb, code); |
| | 636 | } |
| | 637 | exit(code); |
| | 638 | } |
| | 639 | |
| | 640 | /* ------------------------------------------------------------- */ |
| | 641 | #else // if defined CONFIG_TCC_BACKTRACE_ONLY |
| | 642 | static void rt_exit(rt_frame *f, int code) |
| | 643 | { |
| | 644 | exit(code); |
| | 645 | } |
| 549 | #endif //ndef CONFIG_TCC_BACKTRACE_ONLY | 646 | #endif //ndef CONFIG_TCC_BACKTRACE_ONLY |
| 550 | /* ------------------------------------------------------------- */ | 647 | /* ------------------------------------------------------------- */ |
| 551 | #ifdef CONFIG_TCC_BACKTRACE | 648 | #ifdef CONFIG_TCC_BACKTRACE |
| @@ -582,11 +679,17 @@ static char *rt_elfsym(rt_context *rc, addr_t wanted_pc, addr_t *func_addr) · 30 unmodified lines |
| 582 | return NULL; | 679 | return NULL; |
| 583 | } | 680 | } |
| 584 | | 681 | |
| | 682 | typedef struct bt_info |
| | 683 | { |
| | 684 | char file[100]; |
| | 685 | int line; |
| | 686 | char func[100]; |
| | 687 | addr_t func_pc; |
| | 688 | } bt_info; |
| 585 | | 689 | |
| 586 | /* print the position in the source file of PC value 'pc' by reading | 690 | /* print the position in the source file of PC value 'pc' by reading |
| 587 | the stabs debug information */ | 691 | the stabs debug information */ |
| 588 | static addr_t rt_printline (rt_context *rc, addr_t wanted_pc, | 692 | static addr_t rt_printline (rt_context *rc, addr_t wanted_pc, bt_info *bi) |
| 589 | rt_context** prc, const char *msg, const char *skip) | | |
| 590 | { | 693 | { |
| 591 | char func_name[128]; | 694 | char func_name[128]; |
| 592 | addr_t func_addr, last_pc, pc; | 695 | addr_t func_addr, last_pc, pc; |
| @@ -595,15 +698,12 @@ static addr_t rt_printline (rt_context *rc, addr_t wanted_pc, · 2 unmodified lines |
| 595 | const char *str, *p; | 698 | const char *str, *p; |
| 596 | Stab_Sym *sym; | 699 | Stab_Sym *sym; |
| 597 | | 700 | |
| 598 | next: | | |
| 599 | func_name[0] = '\0'; | 701 | func_name[0] = '\0'; |
| 600 | func_addr = 0; | 702 | func_addr = 0; |
| 601 | incl_index = 0; | 703 | incl_index = 0; |
| 602 | last_pc = (addr_t)-1; | 704 | last_pc = (addr_t)-1; |
| 603 | last_line_num = 1; | 705 | last_line_num = 1; |
| 604 | last_incl_index = 0; | 706 | last_incl_index = 0; |
| 605 | if (NULL == rc) | | |
| 606 | goto found; | | |
| 607 | | 707 | |
| 608 | for (sym = rc->stab_sym + 1; sym < rc->stab_sym_end; ++sym) { | 708 | for (sym = rc->stab_sym + 1; sym < rc->stab_sym_end; ++sym) { |
| 609 | str = rc->stab_str + sym->n_strx; | 709 | str = rc->stab_str + sym->n_strx; |
| @@ -680,50 +780,15 @@ next: · 70 unmodified lines |
| 680 | break; | 780 | break; |
| 681 | } | 781 | } |
| 682 | } | 782 | } |
| 683 | | 783 | last_incl_index = 0, func_name[0] = 0, func_addr = 0; |
| 684 | func_name[0] = '\0'; | | |
| 685 | func_addr = 0; | | |
| 686 | last_incl_index = 0; | | |
| 687 | | | |
| 688 | /* we try symtab symbols (no line number info) */ | | |
| 689 | p = rt_elfsym(rc, wanted_pc, &func_addr); | | |
| 690 | if (p) { | | |
| 691 | pstrcpy(func_name, sizeof func_name, p); | | |
| 692 | goto found; | | |
| 693 | } | | |
| 694 | rc = rc->next; | | |
| 695 | goto next; | | |
| 696 | | | |
| 697 | found: | 784 | found: |
| 698 | i = last_incl_index; | 785 | i = last_incl_index; |
| 699 | str = NULL; | | |
| 700 | if (i > 0) { | 786 | if (i > 0) { |
| 701 | str = incl_files[--i]; | 787 | pstrcpy(bi->file, sizeof bi->file, incl_files[--i]); |
| 702 | if (skip[0] && strstr(str, skip)) | 788 | bi->line = last_line_num; |
| 703 | return (addr_t)-1; | | |
| 704 | } | | |
| 705 | if (rc && rc->s1 && rc->s1->bt_func) { | | |
| 706 | rc->s1->bt_func((void*)wanted_pc, str, last_line_num, func_name[0] ? func_name : NULL); | | |
| 707 | } else { | | |
| 708 | if (str) | | |
| 709 | rt_printf("%s:%d: ", str, last_line_num); | | |
| 710 | else | | |
| 711 | rt_printf("%08llx : ", (long long)wanted_pc); | | |
| 712 | rt_printf("%s %s", msg, func_name[0] ? func_name : "???"); | | |
| 713 | } | | |
| 714 | #if 0 | | |
| 715 | if (--i >= 0) { | | |
| 716 | rt_printf(" (included from "); | | |
| 717 | for (;;) { | | |
| 718 | rt_printf("%s", incl_files[i]); | | |
| 719 | if (--i < 0) | | |
| 720 | break; | | |
| 721 | rt_printf(", "); | | |
| 722 | } | | |
| 723 | rt_printf(")"); | | |
| 724 | } | 789 | } |
| 725 | #endif | 790 | pstrcpy(bi->func, sizeof bi->func, func_name); |
| 726 | *prc = rc; | 791 | bi->func_pc = func_addr; |
| 727 | return func_addr; | 792 | return func_addr; |
| 728 | } | 793 | } |
| 729 | | 794 | |
| @@ -793,8 +858,7 @@ dwarf_read_sleb128(unsigned char **ln, unsigned char *end) · 63 unmodified lines |
| 793 | return retval; | 858 | return retval; |
| 794 | } | 859 | } |
| 795 | | 860 | |
| 796 | static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc, | 861 | static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc, bt_info *bi) |
| 797 | rt_context** prc, const char *msg, const char *skip) | | |
| 798 | { | 862 | { |
| 799 | unsigned char *ln; | 863 | unsigned char *ln; |
| 800 | unsigned char *cp; | 864 | unsigned char *cp; |
| @@ -834,12 +898,10 @@ static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc, · 33 unmodified lines |
| 834 | char *filename; | 898 | char *filename; |
| 835 | char *function; | 899 | char *function; |
| 836 | | 900 | |
| 837 | next: | | |
| 838 | filename = NULL; | 901 | filename = NULL; |
| | 902 | function = NULL; |
| 839 | func_addr = 0; | 903 | func_addr = 0; |
| 840 | line = 0; | 904 | line = 0; |
| 841 | if (NULL == rc) | | |
| 842 | goto found; | | |
| 843 | | 905 | |
| 844 | ln = rc->dwarf_line; | 906 | ln = rc->dwarf_line; |
| 845 | while (ln < rc->dwarf_line_end) { | 907 | while (ln < rc->dwarf_line_end) { |
| @@ -1070,44 +1132,28 @@ check_pc: · 224 unmodified lines |
| 1070 | next_line: | 1132 | next_line: |
| 1071 | ln = end; | 1133 | ln = end; |
| 1072 | } | 1134 | } |
| 1073 | | 1135 | filename = function = NULL, func_addr = 0; |
| 1074 | filename = NULL; | | |
| 1075 | func_addr = 0; | | |
| 1076 | /* we try symtab symbols (no line number info) */ | | |
| 1077 | function = rt_elfsym(rc, wanted_pc, &func_addr); | | |
| 1078 | if (function) | | |
| 1079 | goto found; | | |
| 1080 | rc = rc->next; | | |
| 1081 | goto next; | | |
| 1082 | | | |
| 1083 | found: | 1136 | found: |
| 1084 | if (rc && rc->s1 && rc->s1->bt_func) { | 1137 | if (filename) |
| 1085 | rc->s1->bt_func((void*)wanted_pc, filename, line, function); | 1138 | pstrcpy(bi->file, sizeof bi->file, filename), bi->line = line; |
| 1086 | } else { | 1139 | if (function) |
| 1087 | if (filename) { | 1140 | pstrcpy(bi->func, sizeof bi->func, function); |
| 1088 | if (skip[0] && strstr(filename, skip)) | 1141 | bi->func_pc = func_addr; |
| 1089 | return (addr_t)-1; | | |
| 1090 | rt_printf("%s:%d: ", filename, line); | | |
| 1091 | } | | |
| 1092 | else | | |
| 1093 | rt_printf("0x%08llx : ", (long long)wanted_pc); | | |
| 1094 | rt_printf("%s %s", msg, function ? function : "???"); | | |
| 1095 | } | | |
| 1096 | *prc = rc; | | |
| 1097 | return (addr_t)func_addr; | 1142 | return (addr_t)func_addr; |
| 1098 | } | 1143 | } |
| 1099 | /* ------------------------------------------------------------- */ | 1144 | /* ------------------------------------------------------------- */ |
| 1100 | #ifndef CONFIG_TCC_BACKTRACE_ONLY | 1145 | #ifndef CONFIG_TCC_BACKTRACE_ONLY |
| 1101 | static | 1146 | static |
| 1102 | #endif | 1147 | #endif |
| 1103 | int __rt_dump(rt_frame *f, const char *msg, const char *fmt, va_list ap) | 1148 | int _tcc_backtrace(rt_frame *f, const char *fmt, va_list ap) |
| 1104 | { | 1149 | { |
| 1105 | rt_context *rc, *rd; | 1150 | rt_context *rc, *rc2; |
| 1106 | addr_t pc = 0; | 1151 | addr_t pc; |
| 1107 | char skip[100]; | 1152 | char skip[40], msg[200]; |
| 1108 | int i, level, ret, n, one; | 1153 | int i, level, ret, n, one; |
| 1109 | const char *a, *b; | 1154 | const char *a, *b; |
| 1110 | addr_t (*printline)(rt_context*, addr_t, rt_context**, const char*, const char*); | 1155 | bt_info bi; |
| | 1156 | addr_t (*getinfo)(rt_context*, addr_t, bt_info*); |
| 1111 | | 1157 | |
| 1112 | skip[0] = 0; | 1158 | skip[0] = 0; |
| 1113 | /* If fmt is like "^file.c^..." then skip calls from 'file.c' */ | 1159 | /* If fmt is like "^file.c^..." then skip calls from 'file.c' */ |
| @@ -1119,41 +1165,73 @@ int __rt_dump(rt_frame *f, const char *msg, const char *fmt, va_list ap) · 5 unmodified lines |
| 1119 | /* hack for bcheck.c:dprintf(): one level, no newline */ | 1165 | /* hack for bcheck.c:dprintf(): one level, no newline */ |
| 1120 | if (fmt[0] == '\001') | 1166 | if (fmt[0] == '\001') |
| 1121 | ++fmt, one = 1; | 1167 | ++fmt, one = 1; |
| | 1168 | vsnprintf(msg, sizeof msg, fmt, ap); |
| 1122 | | 1169 | |
| 1123 | rt_wait_sem(); | 1170 | rt_wait_sem(); |
| 1124 | rc = g_rc; | 1171 | rc = g_rc; |
| 1125 | printline = rt_printline, n = 6; | 1172 | getinfo = rt_printline, n = 6; |
| 1126 | if (rc) { | 1173 | if (rc) { |
| 1127 | if (rc->dwarf) | 1174 | if (rc->dwarf) |
| 1128 | printline = rt_printline_dwarf; | 1175 | getinfo = rt_printline_dwarf; |
| 1129 | if (rc->num_callers) | 1176 | if (rc->num_callers) |
| 1130 | n = rc->num_callers; | 1177 | n = rc->num_callers; |
| 1131 | } | 1178 | } |
| | 1179 | |
| 1132 | for (i = level = 0; level < n; i++) { | 1180 | for (i = level = 0; level < n; i++) { |
| 1133 | ret = rt_get_caller_pc(&pc, f, i); | 1181 | ret = rt_get_caller_pc(&pc, f, i); |
| 1134 | if (ret != -1) { | 1182 | if (ret == -1) |
| 1135 | pc = printline(rc, pc, &rd, level ? "by" : "at", skip); | 1183 | break; |
| 1136 | if (pc == (addr_t)-1) | 1184 | memset(&bi, 0, sizeof bi); |
| 1137 | continue; | 1185 | for (rc2 = rc; rc2; rc2 = rc2->next) { |
| | 1186 | if (getinfo(rc2, pc, &bi)) |
| | 1187 | break; |
| | 1188 | /* we try symtab symbols (no line number info) */ |
| | 1189 | if (!!(a = rt_elfsym(rc2, pc, &bi.func_pc))) { |
| | 1190 | pstrcpy(bi.func, sizeof bi.func, a); |
| | 1191 | break; |
| | 1192 | } |
| | 1193 | } |
| | 1194 | //fprintf(stderr, "%d rc %p %p\n", i, (void*)pcfunc, (void*)pc); |
| | 1195 | if (skip[0] && strstr(bi.file, skip)) |
| | 1196 | continue; |
| | 1197 | #ifndef CONFIG_TCC_BACKTRACE_ONLY |
| | 1198 | { |
| | 1199 | TCCState *s = rt_find_state(f); |
| | 1200 | if (s && s->bt_func) { |
| | 1201 | ret = s->bt_func( |
| | 1202 | s->bt_data, |
| | 1203 | (void*)pc, |
| | 1204 | bi.file[0] ? bi.file : NULL, |
| | 1205 | bi.line, |
| | 1206 | bi.func[0] ? bi.func : NULL, |
| | 1207 | level == 0 ? msg : NULL |
| | 1208 | ); |
| | 1209 | if (ret == 0) |
| | 1210 | break; |
| | 1211 | goto check_break; |
| | 1212 | } |
| | 1213 | } |
| | 1214 | #endif |
| | 1215 | if (bi.file[0]) { |
| | 1216 | rt_printf("%s:%d", bi.file, bi.line); |
| | 1217 | } else { |
| | 1218 | rt_printf("0x%08llx", (long long)pc); |
| 1138 | } | 1219 | } |
| | 1220 | rt_printf(": %s %s", level ? "by" : "at", bi.func[0] ? bi.func : "???"); |
| 1139 | if (level == 0) { | 1221 | if (level == 0) { |
| 1140 | if (rd && rd->s1 && rd->s1->bt_func) | 1222 | rt_printf(": %s", msg); |
| | 1223 | if (one) |
| 1141 | break; | 1224 | break; |
| 1142 | if (ret != -1) | 1225 | } |
| 1143 | rt_printf(": "); | | |
| 1144 | if (msg) | | |
| 1145 | rt_printf("%s: ", msg); | | |
| 1146 | rt_vprintf(fmt, ap); | | |
| 1147 | } else if (ret == -1) | | |
| 1148 | break; | | |
| 1149 | if (one) | | |
| 1150 | break; | | |
| 1151 | rt_printf("\n"); | 1226 | rt_printf("\n"); |
| 1152 | if (ret == -1 || (rd && pc == (addr_t)rd->top_func && pc)) | 1227 | |
| | 1228 | check_break: |
| | 1229 | if (rc2 |
| | 1230 | && bi.func_pc |
| | 1231 | && bi.func_pc == (addr_t)rc2->top_func) |
| 1153 | break; | 1232 | break; |
| 1154 | ++level; | 1233 | ++level; |
| 1155 | } | 1234 | } |
| 1156 | | | |
| 1157 | rt_post_sem(); | 1235 | rt_post_sem(); |
| 1158 | return 0; | 1236 | return 0; |
| 1159 | } | 1237 | } |
| @@ -1161,49 +1239,14 @@ int __rt_dump(rt_frame *f, const char *msg, const char *fmt, va_list ap) · 1 unmodified line |
| 1161 | /* emit a run time error at position 'pc' */ | 1239 | /* emit a run time error at position 'pc' */ |
| 1162 | static int rt_error(rt_frame *f, const char *fmt, ...) | 1240 | static int rt_error(rt_frame *f, const char *fmt, ...) |
| 1163 | { | 1241 | { |
| 1164 | va_list ap; | 1242 | va_list ap; char msg[200]; int ret; |
| 1165 | int ret; | | |
| 1166 | va_start(ap, fmt); | 1243 | va_start(ap, fmt); |
| 1167 | ret = __rt_dump(f, "RUNTIME ERROR", fmt, ap); | 1244 | snprintf(msg, sizeof msg, "RUNTIME ERROR: %s", fmt); |
| | 1245 | ret = _tcc_backtrace(f, msg, ap); |
| 1168 | va_end(ap); | 1246 | va_end(ap); |
| 1169 | return ret; | 1247 | return ret; |
| 1170 | } | 1248 | } |
| 1171 | | 1249 | |
| 1172 | static TCCState *rt_find_state(rt_frame *f) | | |
| 1173 | { | | |
| 1174 | TCCState *s; | | |
| 1175 | int level; | | |
| 1176 | addr_t pc; | | |
| 1177 | | | |
| 1178 | rt_wait_sem(); | | |
| 1179 | for (s = g_s1; s; s = s->next) { | | |
| 1180 | if (0 == s->run_lj) | | |
| 1181 | continue; | | |
| 1182 | for (level = 0; level < 8; ++level) { | | |
| 1183 | if (rt_get_caller_pc(&pc, f, level) < 0) | | |
| 1184 | break; | | |
| 1185 | if (pc >= (addr_t)s->run_ptr | | |
| 1186 | && pc < (addr_t)s->run_ptr + s->run_size) | | |
| 1187 | goto found; | | |
| 1188 | } | | |
| 1189 | } | | |
| 1190 | found: | | |
| 1191 | rt_post_sem(); | | |
| 1192 | //fprintf(stderr, "\nrt_state found %s %p %p\n", s ? "YES" : "NO", s, s->rc->top_func), fflush(stderr); | | |
| 1193 | return s; | | |
| 1194 | } | | |
| 1195 | | | |
| 1196 | static void rt_longjmp(rt_frame *f, int code) | | |
| 1197 | { | | |
| 1198 | TCCState *s = rt_find_state(f); | | |
| 1199 | if (s && s->run_lj) { | | |
| 1200 | if (code == 0) | | |
| 1201 | code = 256; | | |
| 1202 | ((void(*)(void*,int))s->run_lj)(s->run_jb, code); | | |
| 1203 | } | | |
| 1204 | exit(code); | | |
| 1205 | } | | |
| 1206 | | | |
| 1207 | /* ------------------------------------------------------------- */ | 1250 | /* ------------------------------------------------------------- */ |
| 1208 | | 1251 | |
| 1209 | #ifndef _WIN32 | 1252 | #ifndef _WIN32 |
| @@ -1338,8 +1381,13 @@ static void sig_error(int signum, siginfo_t *siginf, void *puc) · 128 unmodified lines |
| 1338 | rt_error(&f, "caught signal %d", signum); | 1381 | rt_error(&f, "caught signal %d", signum); |
| 1339 | break; | 1382 | break; |
| 1340 | } | 1383 | } |
| 1341 | set_exception_handler(); | 1384 | { |
| 1342 | rt_longjmp(&f, 255); | 1385 | sigset_t s; |
| | 1386 | sigemptyset(&s); |
| | 1387 | sigaddset(&s, signum); |
| | 1388 | sigprocmask(SIG_UNBLOCK, &s, NULL); |
| | 1389 | } |
| | 1390 | rt_exit(&f, 255); |
| 1343 | } | 1391 | } |
| 1344 | | 1392 | |
| 1345 | #ifndef SA_SIGINFO | 1393 | #ifndef SA_SIGINFO |
| @@ -1353,12 +1401,11 @@ static void set_exception_handler(void) · 7 unmodified lines |
| 1353 | /* install TCC signal handlers to print debug info on fatal | 1401 | /* install TCC signal handlers to print debug info on fatal |
| 1354 | runtime errors */ | 1402 | runtime errors */ |
| 1355 | sigemptyset (&sigact.sa_mask); | 1403 | sigemptyset (&sigact.sa_mask); |
| 1356 | sigact.sa_flags = SA_SIGINFO | SA_RESETHAND | SA_NODEFER; | 1404 | sigact.sa_flags = SA_SIGINFO; //| SA_RESETHAND; |
| 1357 | #if 0//def SIGSTKSZ // this causes signals not to work at all on some (older) linuxes | 1405 | #if 0//def SIGSTKSZ // this causes signals not to work at all on some (older) linuxes |
| 1358 | sigact.sa_flags |= SA_ONSTACK; | 1406 | sigact.sa_flags |= SA_ONSTACK; |
| 1359 | #endif | 1407 | #endif |
| 1360 | sigact.sa_sigaction = sig_error; | 1408 | sigact.sa_sigaction = sig_error; |
| 1361 | sigemptyset(&sigact.sa_mask); | | |
| 1362 | sigaction(SIGFPE, &sigact, NULL); | 1409 | sigaction(SIGFPE, &sigact, NULL); |
| 1363 | sigaction(SIGILL, &sigact, NULL); | 1410 | sigaction(SIGILL, &sigact, NULL); |
| 1364 | sigaction(SIGSEGV, &sigact, NULL); | 1411 | sigaction(SIGSEGV, &sigact, NULL); |
| @@ -1406,7 +1453,7 @@ static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info) · 41 unmodified lines |
| 1406 | rt_error(&f, "caught exception %08x", code); | 1453 | rt_error(&f, "caught exception %08x", code); |
| 1407 | break; | 1454 | break; |
| 1408 | } | 1455 | } |
| 1409 | rt_longjmp(&f, 255); | 1456 | rt_exit(&f, 255); |
| 1410 | return EXCEPTION_EXECUTE_HANDLER; | 1457 | return EXCEPTION_EXECUTE_HANDLER; |
| 1411 | } | 1458 | } |
| 1412 | | 1459 | |
| @@ -1506,6 +1553,14 @@ static int rt_get_caller_pc(addr_t *paddr, rt_frame *rc, int level) · 93 unmodified lines |
| 1506 | } | 1553 | } |
| 1507 | | 1554 | |
| 1508 | #endif | 1555 | #endif |
| | 1556 | #else // for runmain.c:exit(); when CONFIG_TCC_BACKTRACE == 0 */ |
| | 1557 | static int rt_get_caller_pc(addr_t *paddr, rt_frame *f, int level) |
| | 1558 | { |
| | 1559 | if (level) |
| | 1560 | return -1; |
| | 1561 | *paddr = f->ip; |
| | 1562 | return 0; |
| | 1563 | } |
| 1509 | #endif /* CONFIG_TCC_BACKTRACE */ | 1564 | #endif /* CONFIG_TCC_BACKTRACE */ |
| 1510 | /* ------------------------------------------------------------- */ | 1565 | /* ------------------------------------------------------------- */ |
| 1511 | #ifdef CONFIG_TCC_STATIC | 1566 | #ifdef CONFIG_TCC_STATIC |