summaryrefslogtreecommitdiff
path: root/src/x86_64
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 /src/x86_64
parent2270e2c6038830cd16f7141c8fb1cd20a94c5812 (diff)
downloadlibunwind-434e9095cbaaa74a99d13dd5bab4db071b999be4.tar.gz
solaris port
Diffstat (limited to 'src/x86_64')
-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
5 files changed, 205 insertions, 3 deletions
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