diff options
author | Jason King <jason.king@joyent.com> | 2020-04-05 04:30:55 +0000 |
---|---|---|
committer | Dave Watson <dade.watson@gmail.com> | 2020-04-29 08:35:38 -0700 |
commit | d433df57a7fa72cda1513a77683e932e25845e79 (patch) | |
tree | ff9da001ddac38ea67fa2e2f65b1cfcd3d907708 | |
parent | af5bef639ea471f9224fec71a53d276286a02085 (diff) | |
download | libunwind-d433df57a7fa72cda1513a77683e932e25845e79.tar.gz |
Fix signal stacks on illumos/Solaris
-rw-r--r-- | include/tdep-x86_64/libunwind_i.h | 5 | ||||
-rw-r--r-- | src/x86_64/Gos-solaris.c | 119 |
2 files changed, 51 insertions, 73 deletions
diff --git a/include/tdep-x86_64/libunwind_i.h b/include/tdep-x86_64/libunwind_i.h index 8713b39d..6b798c71 100644 --- a/include/tdep-x86_64/libunwind_i.h +++ b/include/tdep-x86_64/libunwind_i.h @@ -89,6 +89,7 @@ struct cursor X86_64_SCF_LINUX_RT_SIGFRAME, /* Linux ucontext_t */ X86_64_SCF_FREEBSD_SIGFRAME, /* FreeBSD signal frame */ X86_64_SCF_FREEBSD_SYSCALL, /* FreeBSD syscall */ + X86_64_SCF_SOLARIS_SIGFRAME, /* illumos/Solaris signal frame */ } sigcontext_format; unw_word_t sigcontext_addr; @@ -200,7 +201,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) #define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) #define tdep_access_reg UNW_OBJ(access_reg) #define tdep_access_fpreg UNW_OBJ(access_fpreg) -#if __linux__ || __sun +#if __linux__ # define tdep_fetch_frame UNW_OBJ(fetch_frame) # define tdep_cache_frame UNW_OBJ(cache_frame) # define tdep_reuse_frame UNW_OBJ(reuse_frame) @@ -252,7 +253,7 @@ extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, int write); extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, int write); -#if __linux__ || __sun +#if __linux__ extern void tdep_fetch_frame (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info); extern int tdep_cache_frame (struct dwarf_cursor *c); diff --git a/src/x86_64/Gos-solaris.c b/src/x86_64/Gos-solaris.c index 10e15230..75258d61 100644 --- a/src/x86_64/Gos-solaris.c +++ b/src/x86_64/Gos-solaris.c @@ -30,75 +30,65 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include <sys/syscall.h> -HIDDEN void -tdep_fetch_frame (struct dwarf_cursor *dw, unw_word_t ip, int need_unwind_info) -{ - struct cursor *c = (struct cursor *) dw; - assert(! need_unwind_info || dw->pi_valid); - assert(! need_unwind_info || dw->pi.unwind_info); - if (dw->pi_valid - && dw->pi.unwind_info - && ((struct dwarf_cie_info *) dw->pi.unwind_info)->signal_frame) - c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; - else - c->sigcontext_format = X86_64_SCF_NONE; - - Debug(5, "fetch frame ip=0x%lx cfa=0x%lx format=%d\n", - dw->ip, dw->cfa, c->sigcontext_format); -} - -HIDDEN int -tdep_cache_frame (struct dwarf_cursor *dw) -{ - struct cursor *c = (struct cursor *) dw; - - Debug(5, "cache frame ip=0x%lx cfa=0x%lx format=%d\n", - dw->ip, dw->cfa, c->sigcontext_format); - return c->sigcontext_format; -} - -HIDDEN void -tdep_reuse_frame (struct dwarf_cursor *dw, int frame) -{ - struct cursor *c = (struct cursor *) dw; - c->sigcontext_format = frame; - if (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME) - { - c->frame_info.frame_type = UNW_X86_64_FRAME_SIGRETURN; - /* Offset from cfa to ucontext_t in signal frame. */ - c->frame_info.cfa_reg_offset = 0; - c->sigcontext_addr = dw->cfa; - } - else - c->sigcontext_addr = 0; - - Debug(5, "reuse frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx offset=%+d\n", - dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr, - (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME - ? c->frame_info.cfa_reg_offset : 0)); -} +struct sigframe { + uint64_t signo; + uint64_t sip; +}; int unw_is_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; - return c->sigcontext_format != X86_64_SCF_NONE; + + c->sigcontext_format = (c->dwarf.ip == (unw_word_t)-1) ? + X86_64_SCF_SOLARIS_SIGFRAME : X86_64_SCF_NONE; + + return (c->sigcontext_format); } HIDDEN int x86_64_handle_signal_frame (unw_cursor_t *cursor) { -#if UNW_DEBUG /* To silence compiler warnings */ - /* Should not get here because we now use kernel-provided dwarf - information for the signal trampoline and dwarf_step() works. - Hence unw_step() should never call this function. Maybe - restore old non-dwarf signal handling here, but then the - gating on unw_is_signal_frame() needs to be removed. */ struct cursor *c = (struct cursor *) cursor; - Debug(1, "old format signal frame? format=%d addr=0x%lx cfa=0x%lx\n", - c->sigcontext_format, c->sigcontext_addr, c->dwarf.cfa); -#endif - return -UNW_EBADFRAME; + unw_word_t ucontext = c->dwarf.cfa + sizeof (struct sigframe); + + if (c->sigcontext_format != X86_64_SCF_SOLARIS_SIGFRAME) + return -UNW_EBADFRAME; + + c->sigcontext_addr = c->dwarf.cfa; + + Debug(1, "signal frame cfa = %lx ucontext = %lx\n", + (uint64_t)c->dwarf.cfa, (uint64_t)ucontext); + + struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); + int ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa); + + if (ret < 0) + { + Debug (2, "return %d\n", ret); + return ret; + } + + c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0); + c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0); + c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0); + c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0); + c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0); + c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0); + c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); + c->dwarf.loc[RSP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); + c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); + c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); + c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); + c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); + c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); + c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); + c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); + c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); + c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); + + c->dwarf.use_prev_instr = 1; + return 0; } #ifndef UNW_REMOTE_ONLY @@ -134,22 +124,9 @@ x86_64_r_uc_addr (ucontext_t *uc, int reg) return addr; } -/* sigreturn() is a no-op on x86_64 glibc. */ HIDDEN NORETURN void x86_64_sigreturn (unw_cursor_t *cursor) { -#if 0 - struct cursor *c = (struct cursor *) cursor; - struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; - - Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", - (unsigned long long) c->dwarf.ip, sc); - __asm__ __volatile__ ("mov %0, %%rsp;" - "mov %1, %%rax;" - "syscall" - :: "r"(sc), "i"(SYS_rt_sigreturn) - : "memory"); -#endif // 0 abort(); } |