summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdeel <adeelbm@outlook.com>2019-05-25 14:00:00 +0300
committerDave Watson <dade.watson@gmail.com>2019-06-12 09:00:40 -0700
commitedc427a9eccd6db583fd0cd920e2af23b4b544a9 (patch)
tree06c88d139c0d7c950b56f89d645f80ab492fbe09
parent434e9095cbaaa74a99d13dd5bab4db071b999be4 (diff)
downloadlibunwind-edc427a9eccd6db583fd0cd920e2af23b4b544a9.tar.gz
Add initial support for Solaris x86-64
-rw-r--r--README15
-rw-r--r--configure.ac9
-rw-r--r--include/libunwind-common.h.in13
-rw-r--r--include/libunwind_i.h2
-rw-r--r--include/tdep-x86_64/jmpbuf.h5
-rw-r--r--include/tdep-x86_64/libunwind_i.h4
-rw-r--r--src/Makefile.am9
-rw-r--r--src/dwarf/Gfind_proc_info-lsb.c48
-rw-r--r--src/elfxx.c1
-rw-r--r--src/os-solaris.c73
-rw-r--r--src/setjmp/siglongjmp.c10
-rw-r--r--src/x86_64/Gos-solaris.c16
-rw-r--r--src/x86_64/getcontext.S2
-rw-r--r--src/x86_64/setcontext.S17
-rw-r--r--src/x86_64/ucontext_i.h4
-rw-r--r--tests/forker.c1
16 files changed, 145 insertions, 84 deletions
diff --git a/README b/README
index 2fc98d86..c729c52d 100644
--- a/README
+++ b/README
@@ -21,6 +21,7 @@ several architecture/operating-system combinations:
| FreeBSD | x86-64 | ✓ |
| FreeBSD | x86 | ✓ |
| FreeBSD | AArch64 | ✓ |
+| Solaris | x86-64 | Initial support |
## General Build Instructions
@@ -179,6 +180,20 @@ only test programs that are known to work at this time are:
`make check` should run with no more than 10 out of 24 tests failed.
+### Expected results on Solaris x86-64
+
+`make check` is passing 23 out of 32 tests. The following nine tests are consistently
+failing:
+
+* `Gtest-resume-sig`
+* `Ltest-resume-sig`
+* `Gtest-resume-sig-rt`
+* `Ltest-resume-sig-rt`
+* `Gtest-trace`
+* `Ltest-trace`
+* `Ltest-init-local-signal`
+* `test-setjmp`
+* `run-check-namespace`
## Performance Testing
diff --git a/configure.ac b/configure.ac
index dfe40146..2697065e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -180,6 +180,7 @@ AM_CONDITIONAL(OS_LINUX, expr x$target_os : xlinux >/dev/null)
AM_CONDITIONAL(OS_HPUX, expr x$target_os : xhpux >/dev/null)
AM_CONDITIONAL(OS_FREEBSD, expr x$target_os : xfreebsd >/dev/null)
AM_CONDITIONAL(OS_QNX, expr x$target_os : xnto-qnx >/dev/null)
+AM_CONDITIONAL(OS_SOLARIS, expr x$target_os : xsolaris >/dev/null)
AC_MSG_CHECKING([for ELF helper width])
case "${target_arch}" in
@@ -322,6 +323,14 @@ if test x$GCC = xyes -a x$intel_compiler != xyes; then
fi
AC_MSG_RESULT([$intel_compiler])
+AC_MSG_CHECKING([if building on Solaris then define __EXTENSIONS__ macro])
+if $OS_SOLARIS; then
+ CFLAGS="${CFLAGS} -D__EXTENSIONS__"
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
AC_MSG_CHECKING([for QCC compiler])
AS_CASE([$CC], [qcc*|QCC*], [qcc_compiler=yes], [qcc_compiler=no])
AC_MSG_RESULT([$qcc_compiler])
diff --git a/include/libunwind-common.h.in b/include/libunwind-common.h.in
index c82a8b90..9dbb415f 100644
--- a/include/libunwind-common.h.in
+++ b/include/libunwind-common.h.in
@@ -30,6 +30,19 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#define UNW_VERSION_CODE(maj,min) (((maj) << 16) | (min))
#define UNW_VERSION UNW_VERSION_CODE(UNW_VERSION_MAJOR, UNW_VERSION_MINOR)
+#ifdef __sun
+// On SmartOS, gcc fails with the following error:
+//
+// ../include/libunwind-common.h:43:41: error: expected identifier or '(' before numeric constant
+// # define UNW_PREFIX UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_)
+// ^
+//
+// workaround is to undefine _U explicitly.
+// see https://github.com/libunwind/libunwind/issues/118 for more details.
+//
+#undef _U
+#endif
+
#define UNW_PASTE2(x,y) x##y
#define UNW_PASTE(x,y) UNW_PASTE2(x,y)
#define UNW_OBJ(fn) UNW_PASTE(UNW_PREFIX, fn)
diff --git a/include/libunwind_i.h b/include/libunwind_i.h
index 966cf889..e0f45401 100644
--- a/include/libunwind_i.h
+++ b/include/libunwind_i.h
@@ -90,8 +90,6 @@ 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/jmpbuf.h b/include/tdep-x86_64/jmpbuf.h
index d5719667..b2e5332b 100644
--- a/include/tdep-x86_64/jmpbuf.h
+++ b/include/tdep-x86_64/jmpbuf.h
@@ -23,9 +23,10 @@ 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. */
-#if defined __linux__
+#if defined __linux__ || defined __sun
-/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+/* Use glibc's jump-buffer indices; NPTL peeks at SP:
+ https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=sysdeps/x86_64/jmpbuf-offsets.h;h=ea94a1f90554deecceaf995ca5ee485ae8bffab7;hb=HEAD */
#define JB_SP 6
#define JB_RP 7
diff --git a/include/tdep-x86_64/libunwind_i.h b/include/tdep-x86_64/libunwind_i.h
index 1d5e711d..8713b39d 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 defined(__linux__) || defined(__sun)
+#if __linux__ || __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)
@@ -252,7 +252,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__
+#if __linux__ || __sun
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/Makefile.am b/src/Makefile.am
index 8d72ef0b..bc37b123 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -154,6 +154,8 @@ libunwind_la_SOURCES_os_freebsd = os-freebsd.c
libunwind_la_SOURCES_os_qnx = os-qnx.c
+libunwind_la_SOURCES_os_solaris = os-solaris.c
+
libunwind_dwarf_common_la_SOURCES = dwarf/global.c
libunwind_dwarf_local_la_SOURCES = \
@@ -538,6 +540,12 @@ if OS_FREEBSD
libunwind_coredump_la_SOURCES += coredump/_UCD_access_reg_freebsd.c
endif
+if OS_SOLARIS
+ libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_solaris)
+ libunwind_la_SOURCES_x86_64_os = x86_64/Gos-solaris.c
+ libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-solaris.c
+endif
+
if OS_QNX
libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_qnx)
libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_qnx_local)
@@ -741,6 +749,7 @@ EXTRA_DIST = $(libunwind_la_SOURCES_aarch64) \
$(libunwind_la_SOURCES_os_linux) \
$(libunwind_la_SOURCES_os_hpux) \
$(libunwind_la_SOURCES_os_qnx) \
+ $(libunwind_la_SOURCES_os_solaris) \
$(libunwind_la_SOURCES_common) \
$(libunwind_la_SOURCES_local) \
$(libunwind_la_SOURCES_generic) \
diff --git a/src/dwarf/Gfind_proc_info-lsb.c b/src/dwarf/Gfind_proc_info-lsb.c
index 4edea668..7d0c70f2 100644
--- a/src/dwarf/Gfind_proc_info-lsb.c
+++ b/src/dwarf/Gfind_proc_info-lsb.c
@@ -480,8 +480,6 @@ 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. */
@@ -698,52 +696,6 @@ 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/elfxx.c b/src/elfxx.c
index b03dfcb7..2589a3d4 100644
--- a/src/elfxx.c
+++ b/src/elfxx.c
@@ -28,6 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include <stdio.h>
#include <sys/param.h>
+#include <limits.h>
#ifdef HAVE_LZMA
#include <lzma.h>
diff --git a/src/os-solaris.c b/src/os-solaris.c
new file mode 100644
index 00000000..3c140ef2
--- /dev/null
+++ b/src/os-solaris.c
@@ -0,0 +1,73 @@
+/* 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. */
+
+#include <limits.h>
+#include <stdio.h>
+
+#include "libunwind_i.h"
+#include "os-linux.h" // using linux header for map_iterator implementation
+
+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;
+}
+
+#ifndef UNW_REMOTE_ONLY
+
+void
+tdep_get_exe_image_path (char *path)
+{
+ strcpy(path, getexecname());
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/setjmp/siglongjmp.c b/src/setjmp/siglongjmp.c
index 0e286f6f..dd330ce9 100644
--- a/src/setjmp/siglongjmp.c
+++ b/src/setjmp/siglongjmp.c
@@ -31,8 +31,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "jmpbuf.h"
#include "setjmp_i.h"
-#if !defined(_NSIG) && defined(_SIG_MAXSIG)
-# define _NSIG (_SIG_MAXSIG - 1)
+#if !defined(_NSIG)
+# if defined(_SIG_MAXSIG)
+# define _NSIG (_SIG_MAXSIG - 1)
+# elif defined(NSIG)
+# define _NSIG NSIG
+# endif
#endif
#if defined(__GLIBC__)
@@ -92,7 +96,7 @@ siglongjmp (sigjmp_buf env, int val)
if (!resume_restores_sigmask (&c, wp) && wp[JB_MASK_SAVED])
{
/* sigmask was saved */
-#if defined(__linux__)
+#if defined(__linux__) || defined(__sun)
if (UNW_NUM_EH_REGS < 4 || _NSIG > 16 * sizeof (unw_word_t))
/* signal mask doesn't fit into EH arguments and we can't
put it on the stack without overwriting something
diff --git a/src/x86_64/Gos-solaris.c b/src/x86_64/Gos-solaris.c
index 6e764463..10e15230 100644
--- a/src/x86_64/Gos-solaris.c
+++ b/src/x86_64/Gos-solaris.c
@@ -47,21 +47,21 @@ tdep_fetch_frame (struct dwarf_cursor *dw, unw_word_t ip, int need_unwind_info)
dw->ip, dw->cfa, c->sigcontext_format);
}
-HIDDEN void
-tdep_cache_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs)
+HIDDEN int
+tdep_cache_frame (struct dwarf_cursor *dw)
{
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);
+ return c->sigcontext_format;
}
HIDDEN void
-tdep_reuse_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs)
+tdep_reuse_frame (struct dwarf_cursor *dw, int frame)
{
struct cursor *c = (struct cursor *) dw;
- c->sigcontext_format = rs->signal_frame;
+ c->sigcontext_format = frame;
if (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME)
{
c->frame_info.frame_type = UNW_X86_64_FRAME_SIGRETURN;
@@ -78,15 +78,15 @@ tdep_reuse_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs)
? c->frame_info.cfa_reg_offset : 0));
}
-PROTECTED int
+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)
+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
diff --git a/src/x86_64/getcontext.S b/src/x86_64/getcontext.S
index 6f5d0a14..e1450719 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__) || defined(__sun__)
+#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 4cbefe08..17e5ae12 100644
--- a/src/x86_64/setcontext.S
+++ b/src/x86_64/setcontext.S
@@ -37,22 +37,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
_Ux86_64_setcontext:
-#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
-
+#if defined __linux__ || defined __sun
/* restore fp state */
#ifdef UC_MCONTEXT_FPREGS_PTR
mov UC_MCONTEXT_FPREGS_PTR(%rdi),%r8
diff --git a/src/x86_64/ucontext_i.h b/src/x86_64/ucontext_i.h
index e41e5629..e886c948 100644
--- a/src/x86_64/ucontext_i.h
+++ b/src/x86_64/ucontext_i.h
@@ -78,7 +78,7 @@ 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)
+#elif defined __sun
#define UC_MCONTEXT_GREGS_R8 0x78
#define UC_MCONTEXT_GREGS_R9 0x70
#define UC_MCONTEXT_GREGS_R10 0x68
@@ -98,5 +98,5 @@ 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
+
#endif
diff --git a/tests/forker.c b/tests/forker.c
index b03f86a7..c91fc3f3 100644
--- a/tests/forker.c
+++ b/tests/forker.c
@@ -24,6 +24,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <alloca.h>
#include <sys/time.h>
#include <sys/types.h>