summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Watson <davejwatson@fb.com>2017-08-16 15:35:38 -0700
committerDave Watson <davejwatson@fb.com>2017-08-24 08:51:27 -0700
commit7f1aebadbfcbb2e96ca885663d1f8c9213b23e94 (patch)
tree8dfe9a0d3d81f163ab48c0eb1c27ee60853d04bb
parent3d9a694de85f2ba10368b4fbc2aff1c6b8b76f58 (diff)
downloadlibunwind-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.c25
-rw-r--r--src/x86/unwind_i.h3
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 */