1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-11-26 00:57:39 +01:00

Refactor os specific code for x86 (both 32 and 64 bit).

Move Linux specific code into ${arch}/Gos-linux.c
This commit is contained in:
Arun Sharma 2010-04-04 16:17:32 -07:00
parent 2b7ca45acc
commit 8e53e62db9
10 changed files with 213 additions and 182 deletions

View file

@ -220,6 +220,7 @@ unw_save_loc_t;
#define unw_set_fpreg UNW_OBJ(set_fpreg) #define unw_set_fpreg UNW_OBJ(set_fpreg)
#define unw_get_save_loc UNW_OBJ(get_save_loc) #define unw_get_save_loc UNW_OBJ(get_save_loc)
#define unw_is_signal_frame UNW_OBJ(is_signal_frame) #define unw_is_signal_frame UNW_OBJ(is_signal_frame)
#define unw_handle_signal_frame UNW_OBJ(handle_signal_frame)
#define unw_get_proc_name UNW_OBJ(get_proc_name) #define unw_get_proc_name UNW_OBJ(get_proc_name)
#define unw_set_caching_policy UNW_OBJ(set_caching_policy) #define unw_set_caching_policy UNW_OBJ(set_caching_policy)
#define unw_regname UNW_ARCH_OBJ(regname) #define unw_regname UNW_ARCH_OBJ(regname)
@ -246,6 +247,7 @@ extern int unw_get_fpreg (unw_cursor_t *, int, unw_fpreg_t *);
extern int unw_set_fpreg (unw_cursor_t *, int, unw_fpreg_t); extern int unw_set_fpreg (unw_cursor_t *, int, unw_fpreg_t);
extern int unw_get_save_loc (unw_cursor_t *, int, unw_save_loc_t *); extern int unw_get_save_loc (unw_cursor_t *, int, unw_save_loc_t *);
extern int unw_is_signal_frame (unw_cursor_t *); extern int unw_is_signal_frame (unw_cursor_t *);
extern int unw_handle_signal_frame (unw_cursor_t *);
extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *); extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *);
extern const char *unw_strerror (int); extern const char *unw_strerror (int);

View file

@ -221,22 +221,24 @@ libunwind_la_SOURCES_x86_common = $(libunwind_la_SOURCES_common) \
# The list of files that go into libunwind: # The list of files that go into libunwind:
libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \
$(libunwind_la_SOURCES_x86_os_local) \
$(libunwind_la_SOURCES_local) \ $(libunwind_la_SOURCES_local) \
$(dwarf_SOURCES_local) \ $(dwarf_SOURCES_local) \
dwarf/Lfind_proc_info-lsb.c \ dwarf/Lfind_proc_info-lsb.c \
x86/Lcreate_addr_space.c x86/Lget_save_loc.c x86/Lglobal.c \ x86/Lcreate_addr_space.c x86/Lget_save_loc.c x86/Lglobal.c \
x86/Linit.c x86/Linit_local.c x86/Linit_remote.c \ x86/Linit.c x86/Linit_local.c x86/Linit_remote.c \
x86/Lis_signal_frame.c x86/Lget_proc_info.c x86/Lregs.c \ x86/Lget_proc_info.c x86/Lregs.c \
x86/Lresume.c x86/Lstep.c x86/getcontext.S x86/Lresume.c x86/Lstep.c x86/getcontext.S
# The list of files that go into libunwind-x86: # The list of files that go into libunwind-x86:
libunwind_x86_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ libunwind_x86_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \
$(libunwind_la_SOURCES_x86_os) \
$(libunwind_la_SOURCES_generic) \ $(libunwind_la_SOURCES_generic) \
$(dwarf_SOURCES_generic) \ $(dwarf_SOURCES_generic) \
dwarf/Gfind_proc_info-lsb.c \ dwarf/Gfind_proc_info-lsb.c \
x86/Gcreate_addr_space.c x86/Gget_save_loc.c x86/Gglobal.c \ x86/Gcreate_addr_space.c x86/Gget_save_loc.c x86/Gglobal.c \
x86/Ginit.c x86/Ginit_local.c x86/Ginit_remote.c \ x86/Ginit.c x86/Ginit_local.c x86/Ginit_remote.c \
x86/Gis_signal_frame.c x86/Gget_proc_info.c x86/Gregs.c \ x86/Gget_proc_info.c x86/Gregs.c \
x86/Gresume.c x86/Gstep.c x86/Gresume.c x86/Gstep.c
# The list of files that go both into libunwind and libunwind-x86_64: # The list of files that go both into libunwind and libunwind-x86_64:
@ -248,23 +250,25 @@ libunwind_la_SOURCES_x86_64_common = $(libunwind_la_SOURCES_common) \
# The list of files that go into libunwind: # The list of files that go into libunwind:
libunwind_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \ libunwind_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \
$(libunwind_la_SOURCES_x86_64_os_local) \
$(libunwind_la_SOURCES_local) \ $(libunwind_la_SOURCES_local) \
$(dwarf_SOURCES_local) \ $(dwarf_SOURCES_local) \
dwarf/Lfind_proc_info-lsb.c \ dwarf/Lfind_proc_info-lsb.c \
x86_64/setcontext.S \ x86_64/setcontext.S \
x86_64/Lcreate_addr_space.c x86_64/Lget_save_loc.c x86_64/Lglobal.c \ x86_64/Lcreate_addr_space.c x86_64/Lget_save_loc.c x86_64/Lglobal.c \
x86_64/Linit.c x86_64/Linit_local.c x86_64/Linit_remote.c \ x86_64/Linit.c x86_64/Linit_local.c x86_64/Linit_remote.c \
x86_64/Lis_signal_frame.c x86_64/Lget_proc_info.c x86_64/Lregs.c \ x86_64/Lget_proc_info.c x86_64/Lregs.c \
x86_64/Lresume.c x86_64/Lstep.c x86_64/getcontext.S x86_64/Lresume.c x86_64/Lstep.c x86_64/getcontext.S
# The list of files that go into libunwind-x86_64: # The list of files that go into libunwind-x86_64:
libunwind_x86_64_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \ libunwind_x86_64_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \
$(libunwind_la_SOURCES_x86_64_os) \
$(libunwind_la_SOURCES_generic) \ $(libunwind_la_SOURCES_generic) \
$(dwarf_SOURCES_generic) \ $(dwarf_SOURCES_generic) \
dwarf/Gfind_proc_info-lsb.c \ dwarf/Gfind_proc_info-lsb.c \
x86_64/Gcreate_addr_space.c x86_64/Gget_save_loc.c x86_64/Gglobal.c \ x86_64/Gcreate_addr_space.c x86_64/Gget_save_loc.c x86_64/Gglobal.c \
x86_64/Ginit.c x86_64/Ginit_local.c x86_64/Ginit_remote.c \ x86_64/Ginit.c x86_64/Ginit_local.c x86_64/Ginit_remote.c \
x86_64/Gis_signal_frame.c x86_64/Gget_proc_info.c x86_64/Gregs.c \ x86_64/Gget_proc_info.c x86_64/Gregs.c \
x86_64/Gresume.c x86_64/Gstep.c x86_64/Gresume.c x86_64/Gstep.c
# The list of local files that go to Power 64 and 32: # The list of local files that go to Power 64 and 32:
@ -342,8 +346,12 @@ install-exec-hook:
endif endif
if OS_LINUX if OS_LINUX
libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_linux) libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_linux)
libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_linux_local) libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_linux_local)
libunwind_la_SOURCES_x86_os = x86/Gos-linux.c
libunwind_la_SOURCES_x86_os_local = x86/Los-linux.c
libunwind_la_SOURCES_x86_64_os = x86_64/Gos-linux.c
libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-linux.c
endif endif
if OS_HPUX if OS_HPUX

View file

@ -1,71 +0,0 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2002-2003 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 "unwind_i.h"
PROTECTED int
unw_is_signal_frame (unw_cursor_t *cursor)
{
#ifdef __linux__
struct cursor *c = (struct cursor *) cursor;
unw_word_t w0, w1, ip;
unw_addr_space_t as;
unw_accessors_t *a;
void *arg;
int ret;
as = c->dwarf.as;
a = unw_get_accessors (as);
arg = c->dwarf.as_arg;
/* Check if EIP points at sigreturn() sequence. On Linux, this is:
__restore:
0x58 pop %eax
0xb8 0x77 0x00 0x00 0x00 movl 0x77,%eax
0xcd 0x80 int 0x80
without SA_SIGINFO, and
__restore_rt:
0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax
0xcd 0x80 int 0x80
0x00
if SA_SIGINFO is specified.
*/
ip = c->dwarf.ip;
if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0
|| (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0)
return ret;
ret = ((w0 == 0x0077b858 && w1 == 0x80cd0000)
|| (w0 == 0x0000adb8 && (w1 & 0xffffff) == 0x80cd00));
Debug (16, "returning %d\n", ret);
return ret;
#else
printf ("%s: implement me\n", __FUNCTION__);
#endif
return -UNW_ENOINFO;
}

137
src/x86/Gos-linux.c Normal file
View file

@ -0,0 +1,137 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2002-2004 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 "unwind_i.h"
#include "offsets.h"
PROTECTED int
unw_is_signal_frame (unw_cursor_t *cursor)
{
struct cursor *c = (struct cursor *) cursor;
unw_word_t w0, w1, ip;
unw_addr_space_t as;
unw_accessors_t *a;
void *arg;
int ret;
as = c->dwarf.as;
a = unw_get_accessors (as);
arg = c->dwarf.as_arg;
/* Check if EIP points at sigreturn() sequence. On Linux, this is:
__restore:
0x58 pop %eax
0xb8 0x77 0x00 0x00 0x00 movl 0x77,%eax
0xcd 0x80 int 0x80
without SA_SIGINFO, and
__restore_rt:
0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax
0xcd 0x80 int 0x80
0x00
if SA_SIGINFO is specified.
*/
ip = c->dwarf.ip;
if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0
|| (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0)
return ret;
ret = ((w0 == 0x0077b858 && w1 == 0x80cd0000)
|| (w0 == 0x0000adb8 && (w1 & 0xffffff) == 0x80cd00));
Debug (16, "returning %d\n", ret);
return ret;
}
PROTECTED int
unw_handle_signal_frame (unw_cursor_t *cursor)
{
struct cursor *c = (struct cursor *) cursor;
int ret;
/* c->esp points at the arguments to the handler. Without
SA_SIGINFO, the arguments consist of a signal number
followed by a struct sigcontext. With SA_SIGINFO, the
arguments consist a signal number, a siginfo *, and a
ucontext *. */
unw_word_t sc_addr;
unw_word_t siginfo_ptr_addr = c->dwarf.cfa + 4;
unw_word_t sigcontext_ptr_addr = c->dwarf.cfa + 8;
unw_word_t siginfo_ptr, sigcontext_ptr;
struct dwarf_loc esp_loc, siginfo_ptr_loc, sigcontext_ptr_loc;
siginfo_ptr_loc = DWARF_LOC (siginfo_ptr_addr, 0);
sigcontext_ptr_loc = DWARF_LOC (sigcontext_ptr_addr, 0);
ret = (dwarf_get (&c->dwarf, siginfo_ptr_loc, &siginfo_ptr)
| dwarf_get (&c->dwarf, sigcontext_ptr_loc, &sigcontext_ptr));
if (ret < 0)
{
Debug (2, "returning 0\n");
return 0;
}
if (siginfo_ptr < c->dwarf.cfa
|| siginfo_ptr > c->dwarf.cfa + 256
|| sigcontext_ptr < c->dwarf.cfa
|| sigcontext_ptr > c->dwarf.cfa + 256)
{
/* Not plausible for SA_SIGINFO signal */
c->sigcontext_format = X86_SCF_LINUX_SIGFRAME;
c->sigcontext_addr = sc_addr = c->dwarf.cfa + 4;
}
else
{
/* If SA_SIGINFO were not specified, we actually read
various segment pointers instead. We believe that at
least fs and _fsh are always zero for linux, so it is
not just unlikely, but impossible that we would end
up here. */
c->sigcontext_format = X86_SCF_LINUX_RT_SIGFRAME;
c->sigcontext_addr = sigcontext_ptr;
sc_addr = sigcontext_ptr + LINUX_UC_MCONTEXT_OFF;
}
esp_loc = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0);
ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa);
if (ret < 0)
{
Debug (2, "returning 0\n");
return 0;
}
c->dwarf.loc[EAX] = DWARF_LOC (sc_addr + LINUX_SC_EAX_OFF, 0);
c->dwarf.loc[ECX] = DWARF_LOC (sc_addr + LINUX_SC_ECX_OFF, 0);
c->dwarf.loc[EDX] = DWARF_LOC (sc_addr + LINUX_SC_EDX_OFF, 0);
c->dwarf.loc[EBX] = DWARF_LOC (sc_addr + LINUX_SC_EBX_OFF, 0);
c->dwarf.loc[EBP] = DWARF_LOC (sc_addr + LINUX_SC_EBP_OFF, 0);
c->dwarf.loc[ESI] = DWARF_LOC (sc_addr + LINUX_SC_ESI_OFF, 0);
c->dwarf.loc[EDI] = DWARF_LOC (sc_addr + LINUX_SC_EDI_OFF, 0);
c->dwarf.loc[EFLAGS] = DWARF_NULL_LOC;
c->dwarf.loc[TRAPNO] = DWARF_NULL_LOC;
c->dwarf.loc[ST0] = DWARF_NULL_LOC;
c->dwarf.loc[EIP] = DWARF_LOC (sc_addr + LINUX_SC_EIP_OFF, 0);
c->dwarf.loc[ESP] = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0);
return 0;
}

View file

@ -56,70 +56,14 @@ unw_step (unw_cursor_t *cursor)
Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
if (unw_is_signal_frame (cursor)) if (unw_is_signal_frame (cursor))
{ {
/* XXX This code is Linux-specific! */ ret = unw_handle_signal_frame(cursor);
/* c->esp points at the arguments to the handler. Without
SA_SIGINFO, the arguments consist of a signal number
followed by a struct sigcontext. With SA_SIGINFO, the
arguments consist a signal number, a siginfo *, and a
ucontext *. */
unw_word_t sc_addr;
unw_word_t siginfo_ptr_addr = c->dwarf.cfa + 4;
unw_word_t sigcontext_ptr_addr = c->dwarf.cfa + 8;
unw_word_t siginfo_ptr, sigcontext_ptr;
struct dwarf_loc esp_loc, siginfo_ptr_loc, sigcontext_ptr_loc;
siginfo_ptr_loc = DWARF_LOC (siginfo_ptr_addr, 0);
sigcontext_ptr_loc = DWARF_LOC (sigcontext_ptr_addr, 0);
ret = (dwarf_get (&c->dwarf, siginfo_ptr_loc, &siginfo_ptr)
| dwarf_get (&c->dwarf, sigcontext_ptr_loc, &sigcontext_ptr));
if (ret < 0) if (ret < 0)
{ {
Debug (2, "returning 0\n"); Debug (2, "returning 0\n");
return 0; return 0;
} }
if (siginfo_ptr < c->dwarf.cfa }
|| siginfo_ptr > c->dwarf.cfa + 256
|| sigcontext_ptr < c->dwarf.cfa
|| sigcontext_ptr > c->dwarf.cfa + 256)
{
/* Not plausible for SA_SIGINFO signal */
c->sigcontext_format = X86_SCF_LINUX_SIGFRAME;
c->sigcontext_addr = sc_addr = c->dwarf.cfa + 4;
}
else
{
/* If SA_SIGINFO were not specified, we actually read
various segment pointers instead. We believe that at
least fs and _fsh are always zero for linux, so it is
not just unlikely, but impossible that we would end
up here. */
c->sigcontext_format = X86_SCF_LINUX_RT_SIGFRAME;
c->sigcontext_addr = sigcontext_ptr;
sc_addr = sigcontext_ptr + LINUX_UC_MCONTEXT_OFF;
}
esp_loc = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0);
ebp_loc = DWARF_LOC (sc_addr + LINUX_SC_EBP_OFF, 0);
eip_loc = DWARF_LOC (sc_addr + LINUX_SC_EIP_OFF, 0);
ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa);
if (ret < 0)
{
Debug (2, "returning 0\n");
return 0;
}
c->dwarf.loc[EAX] = DWARF_LOC (sc_addr + LINUX_SC_EAX_OFF, 0);
c->dwarf.loc[ECX] = DWARF_LOC (sc_addr + LINUX_SC_ECX_OFF, 0);
c->dwarf.loc[EDX] = DWARF_LOC (sc_addr + LINUX_SC_EDX_OFF, 0);
c->dwarf.loc[EBX] = DWARF_LOC (sc_addr + LINUX_SC_EBX_OFF, 0);
c->dwarf.loc[EBP] = DWARF_LOC (sc_addr + LINUX_SC_EBP_OFF, 0);
c->dwarf.loc[ESI] = DWARF_LOC (sc_addr + LINUX_SC_ESI_OFF, 0);
c->dwarf.loc[EDI] = DWARF_LOC (sc_addr + LINUX_SC_EDI_OFF, 0);
c->dwarf.loc[EFLAGS] = DWARF_NULL_LOC;
c->dwarf.loc[TRAPNO] = DWARF_NULL_LOC;
c->dwarf.loc[ST0] = DWARF_NULL_LOC;
}
else else
{ {
ret = dwarf_get (&c->dwarf, c->dwarf.loc[EBP], &c->dwarf.cfa); ret = dwarf_get (&c->dwarf, c->dwarf.loc[EBP], &c->dwarf.cfa);
@ -141,9 +85,10 @@ unw_step (unw_cursor_t *cursor)
EIP. */ EIP. */
for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
c->dwarf.loc[i] = DWARF_NULL_LOC; c->dwarf.loc[i] = DWARF_NULL_LOC;
c->dwarf.loc[EBP] = ebp_loc;
c->dwarf.loc[EIP] = eip_loc;
} }
c->dwarf.loc[EBP] = ebp_loc;
c->dwarf.loc[EIP] = eip_loc;
c->dwarf.ret_addr_column = EIP; c->dwarf.ret_addr_column = EIP;
if (!DWARF_IS_NULL_LOC (c->dwarf.loc[EBP])) if (!DWARF_IS_NULL_LOC (c->dwarf.loc[EBP]))

View file

@ -1,5 +1,5 @@
#define UNW_LOCAL_ONLY #define UNW_LOCAL_ONLY
#include <libunwind.h> #include <libunwind.h>
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
#include "Gis_signal_frame.c" #include "Gos-linux.c"
#endif #endif

View file

@ -26,8 +26,8 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h" #include "unwind_i.h"
#include "ucontext_i.h"
#ifdef __linux__
PROTECTED int PROTECTED int
unw_is_signal_frame (unw_cursor_t *cursor) unw_is_signal_frame (unw_cursor_t *cursor)
{ {
@ -57,12 +57,43 @@ unw_is_signal_frame (unw_cursor_t *cursor)
return (w0 == 0x0f0000000fc0c748 && w1 == 0x05); return (w0 == 0x0f0000000fc0c748 && w1 == 0x05);
} }
#else /* __linux__ */
PROTECTED int PROTECTED int
unw_is_signal_frame (unw_cursor_t *cursor) unw_handle_signal_frame (unw_cursor_t *cursor)
{ {
printf ("%s: implement me\n", __FUNCTION__); struct cursor *c = (struct cursor *) cursor;
return -UNW_ENOINFO; int ret;
unw_word_t ucontext = c->dwarf.cfa;
Debug(1, "signal frame, skip over trampoline\n");
c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME;
c->sigcontext_addr = c->dwarf.cfa;
struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);
ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa);
if (ret < 0)
{
Debug (2, "returning %d\n", ret);
return ret;
}
c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0);
c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0);
c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0);
c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0);
c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0);
c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0);
c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0);
c->dwarf.loc[RSP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);
c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0);
c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0);
c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0);
c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0);
c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0);
c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0);
c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0);
c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0);
c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0);
return 0;
} }
#endif /* __linux__ */

View file

@ -26,7 +26,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h" #include "unwind_i.h"
#include "ucontext_i.h"
#include <signal.h> #include <signal.h>
PROTECTED int PROTECTED int
@ -79,40 +78,12 @@ unw_step (unw_cursor_t *cursor)
if (unw_is_signal_frame (cursor)) if (unw_is_signal_frame (cursor))
{ {
unw_word_t ucontext = c->dwarf.cfa; ret = unw_handle_signal_frame(cursor);
Debug(1, "signal frame, skip over trampoline\n");
c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME;
c->sigcontext_addr = c->dwarf.cfa;
rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);
rbp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0);
rip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0);
ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa);
if (ret < 0) if (ret < 0)
{ {
Debug (2, "returning %d\n", ret); Debug (2, "returning 0\n");
return ret; return 0;
} }
c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0);
c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0);
c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0);
c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0);
c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0);
c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0);
c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0);
c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0);
c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0);
c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0);
c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0);
c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0);
c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0);
c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0);
c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0);
c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0);
} }
else else
{ {
@ -153,11 +124,12 @@ unw_step (unw_cursor_t *cursor)
/* Mark all registers unsaved */ /* Mark all registers unsaved */
for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
c->dwarf.loc[i] = DWARF_NULL_LOC; c->dwarf.loc[i] = DWARF_NULL_LOC;
c->dwarf.loc[RBP] = rbp_loc;
c->dwarf.loc[RSP] = rsp_loc;
c->dwarf.loc[RIP] = rip_loc;
} }
c->dwarf.loc[RBP] = rbp_loc;
c->dwarf.loc[RSP] = rsp_loc;
c->dwarf.loc[RIP] = rip_loc;
c->dwarf.ret_addr_column = RIP; c->dwarf.ret_addr_column = RIP;
if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))

5
src/x86_64/Los-linux.c Normal file
View file

@ -0,0 +1,5 @@
#define UNW_LOCAL_ONLY
#include <libunwind.h>
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
#include "Gos-linux.c"
#endif

View file

@ -83,6 +83,7 @@ check_local_unw_abi () {
match _UL${plat}_init_local match _UL${plat}_init_local
match _UL${plat}_init_remote match _UL${plat}_init_remote
match _UL${plat}_is_signal_frame match _UL${plat}_is_signal_frame
match _UL${plat}_handle_signal_frame
match _UL${plat}_local_addr_space match _UL${plat}_local_addr_space
match _UL${plat}_resume match _UL${plat}_resume
match _UL${plat}_set_caching_policy match _UL${plat}_set_caching_policy
@ -144,6 +145,7 @@ check_generic_unw_abi () {
match _U${plat}_init_local match _U${plat}_init_local
match _U${plat}_init_remote match _U${plat}_init_remote
match _U${plat}_is_signal_frame match _U${plat}_is_signal_frame
match _U${plat}_handle_signal_frame
match _U${plat}_local_addr_space match _U${plat}_local_addr_space
match _U${plat}_regname match _U${plat}_regname
match _U${plat}_resume match _U${plat}_resume