summaryrefslogtreecommitdiff
path: root/src/x86/Gos-linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/x86/Gos-linux.c')
-rw-r--r--src/x86/Gos-linux.c25
1 files changed, 23 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