summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason King <jason.king@joyent.com>2020-04-05 04:30:55 +0000
committerDave Watson <dade.watson@gmail.com>2020-04-29 08:35:38 -0700
commitd433df57a7fa72cda1513a77683e932e25845e79 (patch)
treeff9da001ddac38ea67fa2e2f65b1cfcd3d907708
parentaf5bef639ea471f9224fec71a53d276286a02085 (diff)
downloadlibunwind-d433df57a7fa72cda1513a77683e932e25845e79.tar.gz
Fix signal stacks on illumos/Solaris
-rw-r--r--include/tdep-x86_64/libunwind_i.h5
-rw-r--r--src/x86_64/Gos-solaris.c119
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();
}