mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-12-01 10:47:38 +01:00
New libunwind is ported on solaris
This commit is contained in:
parent
44cb8e68d8
commit
24176a0073
8 changed files with 262 additions and 7 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
67
src/os-solaris.c
Normal file
67
src/os-solaris.c
Normal file
|
@ -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 */
|
157
src/x86_64/Gos-solaris.c
Normal file
157
src/x86_64/Gos-solaris.c
Normal file
|
@ -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
|
5
src/x86_64/Los-solaris.c
Normal file
5
src/x86_64/Los-solaris.c
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue