diff options
author | Dave Watson <davejwatson@fb.com> | 2017-08-16 15:35:38 -0700 |
---|---|---|
committer | Dave Watson <davejwatson@fb.com> | 2017-08-24 08:51:27 -0700 |
commit | 7f1aebadbfcbb2e96ca885663d1f8c9213b23e94 (patch) | |
tree | 8dfe9a0d3d81f163ab48c0eb1c27ee60853d04bb | |
parent | 3d9a694de85f2ba10368b4fbc2aff1c6b8b76f58 (diff) | |
download | libunwind-7f1aebadbfcbb2e96ca885663d1f8c9213b23e94.tar.gz |
x86: Add sigreturn asm stub
glibc no longer defines sigreturn, but we want to use it
when unwinding through signal stacks to resture the signal mask,
without forcing all uses of getcontext/setcontext to save and
restore the signal mask
-rw-r--r-- | src/x86/Gos-linux.c | 25 | ||||
-rw-r--r-- | src/x86/unwind_i.h | 3 |
2 files changed, 26 insertions, 2 deletions
diff --git a/src/x86/Gos-linux.c b/src/x86/Gos-linux.c index 17aebc29..37a22b97 100644 --- a/src/x86/Gos-linux.c +++ b/src/x86/Gos-linux.c @@ -52,7 +52,7 @@ unw_is_signal_frame (unw_cursor_t *cursor) __restore_rt: 0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax 0xcd 0x80 int 0x80 - 0x00 + 0x00 if SA_SIGINFO is specified. */ @@ -296,7 +296,7 @@ x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); - sigreturn (sc); + x86_sigreturn (sc); } else { @@ -305,4 +305,25 @@ x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) } return -UNW_EINVAL; } + +/* sigreturn() is a no-op on x86 glibc. */ +HIDDEN void +x86_sigreturn (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; + mcontext_t *sc_mcontext = &((struct ucontext*)sc)->uc_mcontext; + /* Copy in saved uc - all preserved regs are at the start of sigcontext */ + memcpy(sc_mcontext, &c->uc->uc_mcontext, + DWARF_NUM_PRESERVED_REGS * sizeof(unw_word_t)); + + Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", + (unsigned long long) c->dwarf.ip, sc); + __asm__ __volatile__ ("mov %0, %%esp;" + "mov %1, %%eax;" + "syscall" + :: "r"(sc), "i"(SYS_rt_sigreturn) + : "memory"); + abort(); +} #endif diff --git a/src/x86/unwind_i.h b/src/x86/unwind_i.h index cd528242..d2aed609 100644 --- a/src/x86/unwind_i.h +++ b/src/x86/unwind_i.h @@ -52,6 +52,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define x86_scratch_loc UNW_OBJ(scratch_loc) #define x86_get_scratch_loc UNW_OBJ(get_scratch_loc) #define x86_r_uc_addr UNW_OBJ(r_uc_addr) +#define x86_sigreturn UNW_OBJ(sigreturn) extern void x86_local_addr_space_init (void); extern int x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, @@ -60,4 +61,6 @@ extern dwarf_loc_t x86_scratch_loc (struct cursor *c, unw_regnum_t reg); extern dwarf_loc_t x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg); extern void *x86_r_uc_addr (ucontext_t *uc, int reg); +extern void x86_sigreturn (unw_cursor_t *cursor); + #endif /* unwind_i_h */ |