summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Esilevich <aesilevich@pathscale.com>2010-10-25 18:44:19 -0700
committerAlexander Esilevich <aesilevich@pathscale.com>2010-10-25 18:44:19 -0700
commit24176a0073d4963efe5e2a9a6ea2618775c7e208 (patch)
treede2e0bd593a2fd306971dd6097467b185fb81b0e
parent44cb8e68d885f3173434f4f731fa2e335cc0e184 (diff)
downloadlibunwind-24176a0073d4963efe5e2a9a6ea2618775c7e208.tar.gz
New libunwind is ported on solaris
-rw-r--r--include/dwarf.h2
-rw-r--r--src/CMakeLists.txt22
-rw-r--r--src/os-solaris.c67
-rw-r--r--src/x86_64/Gos-solaris.c157
-rw-r--r--src/x86_64/Los-solaris.c5
-rw-r--r--src/x86_64/getcontext.S2
-rw-r--r--src/x86_64/setcontext.S13
-rw-r--r--src/x86_64/ucontext_i.h1
8 files changed, 262 insertions, 7 deletions
diff --git a/include/dwarf.h b/include/dwarf.h
index fa5452d4..3416faf6 100644
--- a/include/dwarf.h
+++ b/include/dwarf.h
@@ -366,8 +366,10 @@ extern int dwarf_init (void);
extern 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);
+#ifdef CONFIG_DEBUG_FRAME
extern int dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug,
struct dl_phdr_info *info, unw_word_t ip);
+#endif // CONFIG_DEBUG_FRAME
extern int dwarf_search_unwind_table (unw_addr_space_t as,
unw_word_t ip,
unw_dyn_info_t *di,
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4f598435..19b108bd 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,7 +3,6 @@
include(config.cmake)
set(libunwind_sources_common
- os-linux.c
mi/init.c
mi/flush_cache.c
mi/mempool.c
@@ -53,6 +52,14 @@ set(libunwind_sources_common
dwarf/Lfind_proc_info-lsb.c
)
+
+if(CMAKE_SYSTEM_NAME MATCHES "Linux")
+ list(APPEND libunwind_sources_common os-linux.c)
+elseif(CMAKE_SYSTEM_NAME MATCHES "SunOS")
+ list(APPEND libunwind_sources_common os-solaris.c)
+endif()
+
+
set(libunwind_sources_x8664_32
elf32.c
x86/is_fpreg.c
@@ -72,15 +79,16 @@ set(libunwind_sources_x8664_32
x86/Los-linux.c
)
+string(REPLACE " " ";" c_flags "${CMAKE_C_FLAGS}")
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/getcontext.o
- COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS}
+ COMMAND ${CMAKE_C_COMPILER} ${c_flags}
-c ${CMAKE_CURRENT_SOURCE_DIR}/x86_64/getcontext.S
-o ${CMAKE_CURRENT_BINARY_DIR}/getcontext.o
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/x86_64/getcontext.S)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/setcontext.o
- COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS}
+ COMMAND ${CMAKE_C_COMPILER} ${c_flags}
-c ${CMAKE_CURRENT_SOURCE_DIR}/x86_64/setcontext.S
-o ${CMAKE_CURRENT_BINARY_DIR}/setcontext.o
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/x86_64/setcontext.S)
@@ -102,10 +110,16 @@ set(libunwind_sources_x8664_64
x86_64/Lstep.c
${CMAKE_CURRENT_BINARY_DIR}/getcontext.o
${CMAKE_CURRENT_BINARY_DIR}/setcontext.o
- x86_64/Los-linux.c
)
+if(CMAKE_SYSTEM_NAME MATCHES "Linux")
+ list(APPEND libunwind_sources_x8664_64 x86_64/Los-linux.c)
+elseif(CMAKE_SYSTEM_NAME MATCHES "SunOS")
+ list(APPEND libunwind_sources_x8664_64 x86_64/Los-solaris.c)
+endif()
+
+
add_definitions(-DHAVE_CONFIG_H
-D_GNU_SOURCE
-fPIC
diff --git a/src/os-solaris.c b/src/os-solaris.c
new file mode 100644
index 00000000..791b27eb
--- /dev/null
+++ b/src/os-solaris.c
@@ -0,0 +1,67 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
+
+#ifndef UNW_REMOTE_ONLY
+
+#include <limits.h>
+#include <stdio.h>
+
+#include "libunwind_i.h"
+#include "os-linux.h"
+
+PROTECTED int
+tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen)
+{
+ struct map_iterator mi;
+ int found = 0, rc;
+ unsigned long hi;
+
+ if (maps_init (&mi, pid) < 0)
+ return -1;
+
+ while (maps_next (&mi, segbase, &hi, mapoff))
+ if (ip >= *segbase && ip < hi)
+ {
+ found = 1;
+ break;
+ }
+
+ if (!found)
+ {
+ maps_close (&mi);
+ return -1;
+ }
+ if (path)
+ {
+ strncpy(path, mi.path, pathlen);
+ }
+ rc = elf_map_image (ei, mi.path);
+ maps_close (&mi);
+ return rc;
+}
+
+#endif /* UNW_REMOTE_ONLY */
diff --git a/src/x86_64/Gos-solaris.c b/src/x86_64/Gos-solaris.c
new file mode 100644
index 00000000..90520313
--- /dev/null
+++ b/src/x86_64/Gos-solaris.c
@@ -0,0 +1,157 @@
+/* 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>
+
+#if 0
+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;
+ c->sigcontext_addr = dw->cfa;
+ }
+ else
+ {
+ c->sigcontext_format = X86_64_SCF_NONE;
+ c->sigcontext_addr = 0;
+ }
+
+ Debug(15, "fetch frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx\n",
+ dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr);
+}
+
+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(15, "cache frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx\n",
+ dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr);
+}
+
+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->sigcontext_addr = dw->cfa;
+ else
+ c->sigcontext_addr = 0;
+
+ Debug(15, "reuse frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx\n",
+ dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr);
+}
+#endif
+
+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 dwarf_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);
+ assert(c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME);
+ assert(c->sigcontext_addr == c->dwarf.cfa);
+ assert(0);
+#endif
+ return 1;
+}
+
+#ifndef UNW_REMOTE_ONLY
+HIDDEN void *
+x86_64_r_uc_addr (ucontext_t *uc, int reg)
+{
+ 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)
+{
+/* 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");*/
+ 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 28c61d0c..46d9f025 100644
--- a/src/x86_64/getcontext.S
+++ b/src/x86_64/getcontext.S
@@ -57,7 +57,7 @@ _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
diff --git a/src/x86_64/setcontext.S b/src/x86_64/setcontext.S
index 061745f6..99d26e09 100644
--- a/src/x86_64/setcontext.S
+++ b/src/x86_64/setcontext.S
@@ -28,6 +28,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#if defined __linux__
#include <asm/unistd.h>
#define SIG_SETMASK 2
+#elif defined __sun__
+#define SYS_sigprocmask 95
+#define SIG_SETMASK 3
#define SIGSET_BYTE_SIZE (64/8)
#elif defined __FreeBSD__
#include <sys/syscall.h>
@@ -44,15 +47,21 @@ 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
+#ifdef __linux__
mov $__NR_rt_sigprocmask, %rax
+#elif defined(__sun__)
+ mov $SYS_sigprocmask, %rax
+#else
+#error Port me
+#endif
lea UC_SIGMASK(%rdi), %rsi
mov $SIG_SETMASK, %rdi
xor %rdx, %rdx
- mov $SIGSET_BYTE_SIZE, %r10
+ mov $8 , %r10
syscall
pop %rdi
diff --git a/src/x86_64/ucontext_i.h b/src/x86_64/ucontext_i.h
index b75b8c2d..3440ba94 100644
--- a/src/x86_64/ucontext_i.h
+++ b/src/x86_64/ucontext_i.h
@@ -98,6 +98,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#define UC_MCONTEXT_GREGS_RIP 0xc8
#define UC_MCONTEXT_FPREGS_MEM 0x120
#define FPREGS_OFFSET_MXCSR 0x18
+#define UC_SIGMASK 0x128
#else
#error "Define fields offsets in ucontext structure for your platform"
#endif // __sun