summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Esilevich <aesilevich@pathscale.com>2015-09-04 08:14:00 +0600
committerDave Watson <dade.watson@gmail.com>2019-06-12 09:00:38 -0700
commit434e9095cbaaa74a99d13dd5bab4db071b999be4 (patch)
tree22046a91491c868bb682cb6979c275681437d447
parent2270e2c6038830cd16f7141c8fb1cd20a94c5812 (diff)
downloadlibunwind-434e9095cbaaa74a99d13dd5bab4db071b999be4.tar.gz
solaris port
-rw-r--r--include/libunwind_i.h2
-rw-r--r--include/tdep-x86_64/libunwind_i.h2
-rw-r--r--src/dwarf/Gfind_proc_info-lsb.c48
-rw-r--r--src/x86_64/Gos-solaris.c156
-rw-r--r--src/x86_64/Los-solaris.c5
-rw-r--r--src/x86_64/getcontext.S4
-rw-r--r--src/x86_64/setcontext.S21
-rw-r--r--src/x86_64/ucontext_i.h22
8 files changed, 256 insertions, 4 deletions
diff --git a/include/libunwind_i.h b/include/libunwind_i.h
index e0f45401..966cf889 100644
--- a/include/libunwind_i.h
+++ b/include/libunwind_i.h
@@ -90,6 +90,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
# else
# error Host has unknown byte-order.
# endif
+# elif defined(__sun)
+# define __BYTE_ORDER __LITTLE_ENDIAN
# else
# error Host has unknown byte-order.
# endif
diff --git a/include/tdep-x86_64/libunwind_i.h b/include/tdep-x86_64/libunwind_i.h
index 93d925f2..1d5e711d 100644
--- a/include/tdep-x86_64/libunwind_i.h
+++ b/include/tdep-x86_64/libunwind_i.h
@@ -200,7 +200,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__
+#if defined(__linux__) || defined(__sun)
# define tdep_fetch_frame UNW_OBJ(fetch_frame)
# define tdep_cache_frame UNW_OBJ(cache_frame)
# define tdep_reuse_frame UNW_OBJ(reuse_frame)
diff --git a/src/dwarf/Gfind_proc_info-lsb.c b/src/dwarf/Gfind_proc_info-lsb.c
index 7d0c70f2..4edea668 100644
--- a/src/dwarf/Gfind_proc_info-lsb.c
+++ b/src/dwarf/Gfind_proc_info-lsb.c
@@ -480,6 +480,8 @@ struct dwarf_callback_data
unw_dyn_info_t di_debug; /* additional table info for .debug_frame */
};
+#ifdef HAVE_DL_ITERATE_PHDR
+
/* ptr is a pointer to a dwarf_callback_data structure and, on entry,
member ip contains the instruction-pointer we're looking
for. */
@@ -696,6 +698,52 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
return found;
}
+#else // HAVE_DL_ITERATE_PHDR
+
+static int
+find_proc_fde(unw_word_t ip, unw_word_t *fde_addr,
+ unw_word_t *gp, unw_word_t *fde_base,
+ unw_word_t *ip_offset, void *arg) {
+ Dl_amd64_unwindinfo dlef;
+ void* data;
+ void* data_end;
+ int fp_enc, fc_enc, ft_enc;
+ unsigned char *pi, *pj;
+ ptrdiff_t reloc;
+ uintptr_t base;
+ int ret;
+
+ dlef.dlui_version = 1;
+
+ /* Locate the appropiate exception_range_entry table first */
+ if (0 == dlamd64getunwind((void*)ip, &dlef)) {
+ return -UNW_ENOINFO;
+ }
+
+ /*
+ * you now know size and position of block of data needed for
+ * binary search ??REMOTE??
+ */
+ data = dlef.dlui_unwindstart;
+ if (0 == data)
+ return -UNW_ENOINFO;
+
+ base = (uintptr_t)data;
+ data_end = dlef.dlui_unwindend;
+ reloc = 0;
+ /* ??REMOTE?? */
+
+ *gp = 0;
+ *fde_base = 0;
+ *ip_offset = 0;
+
+ return search_fde_in_eh_frame(ip, (unw_word_t)data, 0,
+ (unw_word_t)data_end, fde_addr, arg, 0,
+ dlef.dlui_objname);
+}
+
+#endif // HAVE_DL_ITERATE_PHDR
+
HIDDEN int
dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
unw_proc_info_t *pi, int need_unwind_info, void *arg)
diff --git a/src/x86_64/Gos-solaris.c b/src/x86_64/Gos-solaris.c
new file mode 100644
index 00000000..6e764463
--- /dev/null
+++ b/src/x86_64/Gos-solaris.c
@@ -0,0 +1,156 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "ucontext_i.h"
+
+#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 void
+tdep_cache_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs)
+{
+ struct cursor *c = (struct cursor *) dw;
+ rs->signal_frame = c->sigcontext_format;
+
+ Debug(5, "cache frame ip=0x%lx cfa=0x%lx format=%d\n",
+ dw->ip, dw->cfa, c->sigcontext_format);
+}
+
+HIDDEN void
+tdep_reuse_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs)
+{
+ struct cursor *c = (struct cursor *) dw;
+ c->sigcontext_format = rs->signal_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));
+}
+
+PROTECTED int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ return c->sigcontext_format != X86_64_SCF_NONE;
+}
+
+PROTECTED int
+unw_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;
+}
+
+#ifndef UNW_REMOTE_ONLY
+HIDDEN void *
+x86_64_r_uc_addr (ucontext_t *uc, int reg)
+{
+ /* NOTE: common_init() in init.h inlines these for fast path access. */
+ void *addr;
+
+ switch (reg)
+ {
+ case UNW_X86_64_R8: addr = &uc->uc_mcontext.gregs[REG_R8]; break;
+ case UNW_X86_64_R9: addr = &uc->uc_mcontext.gregs[REG_R9]; break;
+ case UNW_X86_64_R10: addr = &uc->uc_mcontext.gregs[REG_R10]; break;
+ case UNW_X86_64_R11: addr = &uc->uc_mcontext.gregs[REG_R11]; break;
+ case UNW_X86_64_R12: addr = &uc->uc_mcontext.gregs[REG_R12]; break;
+ case UNW_X86_64_R13: addr = &uc->uc_mcontext.gregs[REG_R13]; break;
+ case UNW_X86_64_R14: addr = &uc->uc_mcontext.gregs[REG_R14]; break;
+ case UNW_X86_64_R15: addr = &uc->uc_mcontext.gregs[REG_R15]; break;
+ case UNW_X86_64_RDI: addr = &uc->uc_mcontext.gregs[REG_RDI]; break;
+ case UNW_X86_64_RSI: addr = &uc->uc_mcontext.gregs[REG_RSI]; break;
+ case UNW_X86_64_RBP: addr = &uc->uc_mcontext.gregs[REG_RBP]; break;
+ case UNW_X86_64_RBX: addr = &uc->uc_mcontext.gregs[REG_RBX]; break;
+ case UNW_X86_64_RDX: addr = &uc->uc_mcontext.gregs[REG_RDX]; break;
+ case UNW_X86_64_RAX: addr = &uc->uc_mcontext.gregs[REG_RAX]; break;
+ case UNW_X86_64_RCX: addr = &uc->uc_mcontext.gregs[REG_RCX]; break;
+ case UNW_X86_64_RSP: addr = &uc->uc_mcontext.gregs[REG_RSP]; break;
+ case UNW_X86_64_RIP: addr = &uc->uc_mcontext.gregs[REG_RIP]; break;
+
+ default:
+ addr = NULL;
+ }
+ 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();
+}
+
+#endif
diff --git a/src/x86_64/Los-solaris.c b/src/x86_64/Los-solaris.c
new file mode 100644
index 00000000..be64b2c6
--- /dev/null
+++ b/src/x86_64/Los-solaris.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gos-solaris.c"
+#endif
diff --git a/src/x86_64/getcontext.S b/src/x86_64/getcontext.S
index 7a8b5664..6f5d0a14 100644
--- a/src/x86_64/getcontext.S
+++ b/src/x86_64/getcontext.S
@@ -57,11 +57,13 @@ _Ux86_64_getcontext:
movq %rax, UC_MCONTEXT_GREGS_RAX(%rdi)
movq %rcx, UC_MCONTEXT_GREGS_RCX(%rdi)
-#if defined __linux__
+#if defined(__linux__) || defined(__sun__)
/* Save fp state (not needed, except for setcontext not
restoring garbage). */
leaq UC_MCONTEXT_FPREGS_MEM(%rdi),%r8
+#ifdef UC_MCONTEXT_FPREGS_PTR
movq %r8, UC_MCONTEXT_FPREGS_PTR(%rdi)
+#endif // UC_MCONTEXT_FPREGS_PTR
fnstenv (%r8)
stmxcsr FPREGS_OFFSET_MXCSR(%r8)
#elif defined __FreeBSD__
diff --git a/src/x86_64/setcontext.S b/src/x86_64/setcontext.S
index 358217de..4cbefe08 100644
--- a/src/x86_64/setcontext.S
+++ b/src/x86_64/setcontext.S
@@ -37,9 +37,28 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
_Ux86_64_setcontext:
-#if defined __linux__
+#if defined(__linux__) || defined(__sun__)
+ /* restore signal mask
+ sigprocmask(SIG_SETMASK, ucp->uc_sigmask, NULL, sizeof(sigset_t)) */
+ push %rdi
+#if defined(__sun__)
+ mov $SYS_sigprocmask, %rax
+#else
+ mov $__NR_rt_sigprocmask, %rax
+#endif
+ lea UC_SIGMASK(%rdi), %rsi
+ mov $SIG_SETMASK, %rdi
+ xor %rdx, %rdx
+ mov $SIGSET_BYTE_SIZE, %r10
+ syscall
+ pop %rdi
+
/* restore fp state */
+#ifdef UC_MCONTEXT_FPREGS_PTR
mov UC_MCONTEXT_FPREGS_PTR(%rdi),%r8
+#else // UC_MCONTEXT_FPREGS_PTR
+ leaq UC_MCONTEXT_FPREGS_MEM(%rdi),%r8
+#endif // UC_MCONTEXT_FPREGS_PTR
fldenv (%r8)
ldmxcsr FPREGS_OFFSET_MXCSR(%r8)
#elif defined __FreeBSD__
diff --git a/src/x86_64/ucontext_i.h b/src/x86_64/ucontext_i.h
index aded941d..e41e5629 100644
--- a/src/x86_64/ucontext_i.h
+++ b/src/x86_64/ucontext_i.h
@@ -78,5 +78,25 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#define UC_MCONTEXT_FPOWNED_FPU 0x20001
#define UC_MCONTEXT_FPFMT_XMM 0x10002
#define UC_MCONTEXT_MC_LEN_VAL 0x320
-
+#elif defined(__sun)
+#define UC_MCONTEXT_GREGS_R8 0x78
+#define UC_MCONTEXT_GREGS_R9 0x70
+#define UC_MCONTEXT_GREGS_R10 0x68
+#define UC_MCONTEXT_GREGS_R11 0x60
+#define UC_MCONTEXT_GREGS_R12 0x58
+#define UC_MCONTEXT_GREGS_R13 0x50
+#define UC_MCONTEXT_GREGS_R14 0x48
+#define UC_MCONTEXT_GREGS_R15 0x40
+#define UC_MCONTEXT_GREGS_RDI 0x80
+#define UC_MCONTEXT_GREGS_RSI 0x88
+#define UC_MCONTEXT_GREGS_RBP 0x90
+#define UC_MCONTEXT_GREGS_RBX 0x98
+#define UC_MCONTEXT_GREGS_RDX 0xa0
+#define UC_MCONTEXT_GREGS_RAX 0xb0
+#define UC_MCONTEXT_GREGS_RCX 0xa8
+#define UC_MCONTEXT_GREGS_RSP 0xe0
+#define UC_MCONTEXT_GREGS_RIP 0xc8
+#define UC_MCONTEXT_FPREGS_MEM 0x120
+#define FPREGS_OFFSET_MXCSR 0x18
+#define UC_SIGMASK 0x128
#endif