diff --git a/i386-gen.c b/i386-gen.c index b2f2bddc..4fb556f5 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -363,7 +363,12 @@ static void gcall_or_jmp(int is_jmp) if (tcc_state->do_bounds_check && (vtop->sym->v == TOK_alloca || vtop->sym->v == TOK_setjmp || - vtop->sym->v == TOK__setjmp)) + vtop->sym->v == TOK__setjmp +#ifndef TCC_TARGET_PE + || vtop->sym->v == TOK_sigsetjmp + || vtop->sym->v == TOK___sigsetjmp +#endif + )) func_bound_add_epilog = 1; #endif } else { @@ -1092,15 +1097,18 @@ static void gen_bounds_epilog(void) bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); *bounds_ptr = 0; - /* generate bound local allocation */ - saved_ind = ind; - ind = func_bound_ind; sym_data = get_sym_ref(&char_pointer_type, lbounds_section, func_bound_offset, lbounds_section->data_offset); - greloc(cur_text_section, sym_data, ind + 1, R_386_32); - ind = ind + 5; - gen_static_call(TOK___bound_local_new); - ind = saved_ind; + + /* generate bound local allocation */ + if (func_bound_offset != lbounds_section->data_offset) { + saved_ind = ind; + ind = func_bound_ind; + greloc(cur_text_section, sym_data, ind + 1, R_386_32); + ind = ind + 5; + gen_static_call(TOK___bound_local_new); + ind = saved_ind; + } /* generate bound check local freeing */ o(0x5250); /* save returned value, if any */ diff --git a/lib/bcheck.c b/lib/bcheck.c index 762e488e..e8f20d06 100644 --- a/lib/bcheck.c +++ b/lib/bcheck.c @@ -205,6 +205,7 @@ void __bound_exit(void); void *__bound_mmap (void *start, size_t size, int prot, int flags, int fd, off_t offset); int __bound_munmap (void *start, size_t size); +DLL_EXPORT void __bound_siglongjmp(jmp_buf env, int val); #endif DLL_EXPORT void __bound_new_region(void *p, size_t size); DLL_EXPORT void __bound_setjmp(jmp_buf env); @@ -510,8 +511,6 @@ void FASTCALL __bound_local_new(void *p1) void FASTCALL __bound_local_delete(void *p1) { size_t addr, fp, *p = p1; - alloca_list_type *alloca_free_list = NULL; - jmp_list_type *jmp_free_list = NULL; if (no_checking) return; @@ -524,65 +523,51 @@ void FASTCALL __bound_local_delete(void *p1) tree = splay_delete(addr + fp, tree); p += 2; } - { + if (alloca_list) { alloca_list_type *last = NULL; alloca_list_type *cur = alloca_list; - while (cur) { + do { if (cur->fp == fp) { if (last) last->next = cur->next; else alloca_list = cur->next; tree = splay_delete ((size_t) cur->p, tree); - cur->next = alloca_free_list; - alloca_free_list = cur; + dprintf(stderr, "%s, %s(): remove alloca/vla %p\n", + __FILE__, __FUNCTION__, cur->p); + BOUND_FREE (cur); cur = last ? last->next : alloca_list; } else { last = cur; cur = cur->next; } - } + } while (cur); } - { + if (jmp_list) { jmp_list_type *last = NULL; jmp_list_type *cur = jmp_list; - while (cur) { + do { if (cur->fp == fp) { if (last) last->next = cur->next; else jmp_list = cur->next; - cur->next = jmp_free_list; - jmp_free_list = cur; + dprintf(stderr, "%s, %s(): remove setjmp %p\n", + __FILE__, __FUNCTION__, cur->penv); + BOUND_FREE (cur); cur = last ? last->next : jmp_list; } else { last = cur; cur = cur->next; } - } + } while (cur); } POST_SEM (); - while (alloca_free_list) { - alloca_list_type *next = alloca_free_list->next; - - dprintf(stderr, "%s, %s(): remove alloca/vla %p\n", - __FILE__, __FUNCTION__, alloca_free_list->p); - BOUND_FREE (alloca_free_list); - alloca_free_list = next; - } - while (jmp_free_list) { - jmp_list_type *next = jmp_free_list->next; - - dprintf(stderr, "%s, %s(): remove setjmp %p\n", - __FILE__, __FUNCTION__, jmp_free_list->penv); - BOUND_FREE (jmp_free_list); - jmp_free_list = next; - } #if BOUND_DEBUG if (print_calls) { p = p1; @@ -647,107 +632,128 @@ void __bound_setjmp(jmp_buf env) jmp_list_type *jl; void *e = (void *) env; - dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, e); - WAIT_SEM (); - INCR_COUNT(bound_setjmp_count); - jl = jmp_list; - while (jl) { - if (jl->penv == e) - break; - jl = jl->next; - } - if (jl == NULL) { - jl = BOUND_MALLOC (sizeof (jmp_list_type)); - if (jl) { - jl->penv = e; - jl->next = jmp_list; - jmp_list = jl; + if (no_checking == 0) { + dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, e); + WAIT_SEM (); + INCR_COUNT(bound_setjmp_count); + jl = jmp_list; + while (jl) { + if (jl->penv == e) + break; + jl = jl->next; } - } - if (jl) { - size_t fp; + if (jl == NULL) { + jl = BOUND_MALLOC (sizeof (jmp_list_type)); + if (jl) { + jl->penv = e; + jl->next = jmp_list; + jmp_list = jl; + } + } + if (jl) { + size_t fp; - GET_CALLER_FP (fp); - jl->fp = fp; - jl->end_fp = (size_t)__builtin_frame_address(0); - jl->tid = BOUND_GET_TID; + GET_CALLER_FP (fp); + jl->fp = fp; + jl->end_fp = (size_t)__builtin_frame_address(0); + jl->tid = BOUND_GET_TID; + } + POST_SEM (); } - POST_SEM (); +} + +static void __bound_long_jump(jmp_buf env, int val, int sig, const char *func) +{ + jmp_list_type *jl; + void *e; + BOUND_TID_TYPE tid; + + if (no_checking == 0) { + e = (void *)env; + tid = BOUND_GET_TID; + dprintf(stderr, "%s, %s(): %p\n", __FILE__, func, e); + WAIT_SEM(); + INCR_COUNT(bound_longjmp_count); + jl = jmp_list; + while (jl) { + if (jl->penv == e && jl->tid == tid) { + size_t start_fp = (size_t)__builtin_frame_address(0); + size_t end_fp = jl->end_fp; + jmp_list_type *cur = jmp_list; + jmp_list_type *last = NULL; + + while (cur->penv != e || cur->tid != tid) { + if (cur->tid == tid) { + dprintf(stderr, "%s, %s(): remove setjmp %p\n", + __FILE__, func, cur->penv); + if (last) + last->next = cur->next; + else + jmp_list = cur->next; + BOUND_FREE (cur); + cur = last ? last->next : jmp_list; + } + else { + last = cur; + cur = cur->next; + } + } + for (;;) { + Tree *t = tree; + alloca_list_type *last; + alloca_list_type *cur; + + while (t && (t->start < start_fp || t->start > end_fp)) + if (t->start < start_fp) + t = t->right; + else + t = t->left; + if (t == NULL) + break; + last = NULL; + cur = alloca_list; + while (cur) { + if ((size_t) cur->p == t->start) { + dprintf(stderr, "%s, %s(): remove alloca/vla %p\n", + __FILE__, func, cur->p); + if (last) + last->next = cur->next; + else + alloca_list = cur->next; + BOUND_FREE (cur); + break; + } + last = cur; + cur = cur->next; + } + dprintf(stderr, "%s, %s(): delete %p\n", + __FILE__, func, (void *) t->start); + tree = splay_delete(t->start, tree); + } + break; + } + jl = jl->next; + } + POST_SEM(); + } +#if !defined(_WIN32) + sig ? siglongjmp(env, val) : +#endif + longjmp (env, val); } void __bound_longjmp(jmp_buf env, int val) { - jmp_list_type *jl; - void *e = (void *)env; - BOUND_TID_TYPE tid = BOUND_GET_TID; - - dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, e); - WAIT_SEM(); - INCR_COUNT(bound_longjmp_count); - jl = jmp_list; - while (jl) { - if (jl->penv == e && jl->tid == tid) { - size_t start_fp = (size_t)__builtin_frame_address(0); - size_t end_fp = jl->end_fp; - jmp_list_type *cur = jmp_list; - jmp_list_type *last = NULL; - - while (cur->penv != e || cur->tid != tid) { - if (cur->tid == tid) { - dprintf(stderr, "%s, %s(): remove setjmp %p\n", - __FILE__, __FUNCTION__, cur->penv); - if (last) - last->next = cur->next; - else - jmp_list = cur->next; - BOUND_FREE (cur); - cur = last ? last->next : jmp_list; - } - else { - last = cur; - cur = cur->next; - } - } - for (;;) { - Tree *t = tree; - alloca_list_type *last; - alloca_list_type *cur; - - while (t && (t->start < start_fp || t->start > end_fp)) - if (t->start < start_fp) - t = t->right; - else - t = t->left; - if (t == NULL) - break; - last = NULL; - cur = alloca_list; - while (cur) { - if ((size_t) cur->p == t->start) { - dprintf(stderr, "%s, %s(): remove alloca/vla %p\n", - __FILE__, __FUNCTION__, cur->p); - if (last) - last->next = cur->next; - else - alloca_list = cur->next; - BOUND_FREE (cur); - break; - } - last = cur; - cur = cur->next; - } - dprintf(stderr, "%s, %s(): delete %p\n", - __FILE__, __FUNCTION__, (void *) t->start); - tree = splay_delete(t->start, tree); - } - break; - } - jl = jl->next; - } - POST_SEM(); - longjmp (env, val); + __bound_long_jump(env,val, 0, __FUNCTION__); } +#if !defined(_WIN32) +void __bound_siglongjmp(jmp_buf env, int val) +{ + __bound_long_jump(env,val, 1, __FUNCTION__); +} +#endif + #if defined(__GNUC__) && (__GNUC__ >= 6) #pragma GCC diagnostic pop #endif diff --git a/tccgen.c b/tccgen.c index 4aa65a70..889d43a8 100644 --- a/tccgen.c +++ b/tccgen.c @@ -911,6 +911,9 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, case TOK_mmap: case TOK_munmap: case TOK_longjmp: +#ifndef TCC_TARGET_PE + case TOK_siglongjmp: +#endif strcpy(buf, "__bound_"); strcat(buf, name); name = buf; @@ -6018,7 +6021,12 @@ special_math_val: (nb_args == 1 || nb_args == 2) && (vtop[-nb_args].r & VT_SYM) && (vtop[-nb_args].sym->v == TOK_setjmp || - vtop[-nb_args].sym->v == TOK__setjmp)) { + vtop[-nb_args].sym->v == TOK__setjmp +#ifndef TCC_TARGET_PE + || vtop[-nb_args].sym->v == TOK_sigsetjmp + || vtop[-nb_args].sym->v == TOK___sigsetjmp +#endif + )) { vpush_global_sym(&func_old_type, TOK___bound_setjmp); vpushv(vtop - nb_args); if (nb_args == 2) diff --git a/tcctok.h b/tcctok.h index f76f0c2e..2dfadd60 100644 --- a/tcctok.h +++ b/tcctok.h @@ -315,6 +315,10 @@ DEF(TOK_realloc, "realloc") DEF(TOK_memalign, "memalign") DEF(TOK_calloc, "calloc") +# else + DEF(TOK_sigsetjmp, "sigsetjmp") + DEF(TOK___sigsetjmp, "__sigsetjmp") + DEF(TOK_siglongjmp, "siglongjmp") # endif DEF(TOK_mmap, "mmap") DEF(TOK_munmap, "munmap") diff --git a/tests/tests2/114_bound_signal.c b/tests/tests2/114_bound_signal.c index 55bc4025..be76d812 100644 --- a/tests/tests2/114_bound_signal.c +++ b/tests/tests2/114_bound_signal.c @@ -6,6 +6,7 @@ #include #include #include +#include static volatile int run = 1; static int dummy[10]; @@ -70,6 +71,8 @@ main (void) pthread_t id1, id2; struct sigaction act; struct timespec request; + sigjmp_buf sj; + sigset_t m; memset (&act, 0, sizeof (act)); act.sa_handler = signal_handler; @@ -90,5 +93,19 @@ main (void) pthread_join(id1, NULL); pthread_join(id2, NULL); sem_destroy (&sem); + + sigemptyset (&m); + sigprocmask (SIG_SETMASK, &m, NULL); + if (sigsetjmp (sj, 0) == 0) + { + sigaddset (&m, SIGUSR1); + sigprocmask (SIG_SETMASK, &m, NULL); + siglongjmp (sj, 1); + printf ("failed"); + return 1; + } + sigprocmask (SIG_SETMASK, NULL, &m); + if (!sigismember (&m, SIGUSR1)) + printf ("failed"); return 0; } diff --git a/x86_64-gen.c b/x86_64-gen.c index df7ae1c6..0a5d339b 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -640,7 +640,12 @@ static void gcall_or_jmp(int is_jmp) if (tcc_state->do_bounds_check && (vtop->sym->v == TOK_alloca || vtop->sym->v == TOK_setjmp || - vtop->sym->v == TOK__setjmp)) + vtop->sym->v == TOK__setjmp +#ifndef TCC_TARGET_PE + || vtop->sym->v == TOK_sigsetjmp + || vtop->sym->v == TOK___sigsetjmp +#endif + )) func_bound_add_epilog = 1; #endif } else { @@ -747,15 +752,18 @@ static void gen_bounds_epilog(void) bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); *bounds_ptr = 0; - /* generate bound local allocation */ sym_data = get_sym_ref(&char_pointer_type, lbounds_section, func_bound_offset, lbounds_section->data_offset); - saved_ind = ind; - ind = func_bound_ind; - greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0); - ind = ind + 10; - gen_bounds_call(TOK___bound_local_new); - ind = saved_ind; + + /* generate bound local allocation */ + if (func_bound_offset != lbounds_section->data_offset) { + saved_ind = ind; + ind = func_bound_ind; + greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0); + ind = ind + 10; + gen_bounds_call(TOK___bound_local_new); + ind = saved_ind; + } /* generate bound check local freeing */ o(0x5250); /* save returned value, if any */