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 */