mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-22 23:47:39 +01:00
Merge remote branch 'origin/master' into freebsd
Conflicts: src/x86/Gis_signal_frame.c src/x86/Gstep.c src/x86_64/Gis_signal_frame.c src/x86_64/Gstep.c
This commit is contained in:
commit
fd88f41818
13 changed files with 408 additions and 271 deletions
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -223,22 +223,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:
|
||||||
|
@ -250,23 +252,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:
|
||||||
|
@ -344,8 +348,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
|
||||||
|
@ -356,6 +364,10 @@ endif
|
||||||
if OS_FREEBSD
|
if OS_FREEBSD
|
||||||
libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_freebsd)
|
libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_freebsd)
|
||||||
libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_freebsd_local)
|
libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_freebsd_local)
|
||||||
|
libunwind_la_SOURCES_x86_os = x86/Gos-freebsd.c
|
||||||
|
libunwind_la_SOURCES_x86_os_local = x86/Los-freebsd.c
|
||||||
|
libunwind_la_SOURCES_x86_64_os = x86_64/Gos-freebsd.c
|
||||||
|
libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-freebsd.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if ARCH_ARM
|
if ARCH_ARM
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2002-2003 Hewlett-Packard Co
|
Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -23,51 +22,21 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
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. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <ucontext.h>
|
||||||
|
#include <machine/sigframe.h>
|
||||||
|
|
||||||
#include "unwind_i.h"
|
#include "unwind_i.h"
|
||||||
|
#include "offsets.h"
|
||||||
|
|
||||||
PROTECTED int
|
PROTECTED int
|
||||||
unw_is_signal_frame (unw_cursor_t *cursor)
|
unw_is_signal_frame (unw_cursor_t *cursor)
|
||||||
{
|
{
|
||||||
#if defined __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 = X86_SCF_NONE;
|
|
||||||
if (w0 == 0x0077b858 && w1 == 0x80cd0000)
|
|
||||||
ret = X86_SCF_LINUX_SIGFRAME;
|
|
||||||
else if (w0 == 0x0000adb8 && (w1 & 0xffffff) == 0x80cd00)
|
|
||||||
ret = X86_SCF_LINUX_RT_SIGFRAME;
|
|
||||||
Debug (16, "returning %d\n", ret);
|
|
||||||
return ret;
|
|
||||||
#elif defined __FreeBSD__
|
|
||||||
struct cursor *c = (struct cursor *) cursor;
|
struct cursor *c = (struct cursor *) cursor;
|
||||||
unw_word_t w0, w1, w2, w3, w4, w5, ip;
|
unw_word_t w0, w1, w2, w3, w4, w5, ip;
|
||||||
unw_addr_space_t as;
|
unw_addr_space_t as;
|
||||||
|
@ -104,6 +73,7 @@ XXX
|
||||||
*/
|
*/
|
||||||
ip = c->dwarf.ip;
|
ip = c->dwarf.ip;
|
||||||
ret = X86_SCF_NONE;
|
ret = X86_SCF_NONE;
|
||||||
|
c->sigcontext_format = ret;
|
||||||
if ((*a->access_mem) (as, ip, &w0, 0, arg) < 0 ||
|
if ((*a->access_mem) (as, ip, &w0, 0, arg) < 0 ||
|
||||||
(*a->access_mem) (as, ip + 4, &w1, 0, arg) < 0 ||
|
(*a->access_mem) (as, ip + 4, &w1, 0, arg) < 0 ||
|
||||||
(*a->access_mem) (as, ip + 8, &w2, 0, arg) < 0 ||
|
(*a->access_mem) (as, ip + 8, &w2, 0, arg) < 0 ||
|
||||||
|
@ -121,9 +91,47 @@ XXX
|
||||||
ret = X86_SCF_FREEBSD_SIGFRAME;
|
ret = X86_SCF_FREEBSD_SIGFRAME;
|
||||||
}
|
}
|
||||||
Debug (16, "returning %d\n", ret);
|
Debug (16, "returning %d\n", ret);
|
||||||
|
c->sigcontext_format = ret;
|
||||||
return (ret);
|
return (ret);
|
||||||
#else
|
}
|
||||||
#error Port me
|
|
||||||
#endif
|
PROTECTED int
|
||||||
return -UNW_ENOINFO;
|
unw_handle_signal_frame (unw_cursor_t *cursor)
|
||||||
|
{
|
||||||
|
struct cursor *c = (struct cursor *) cursor;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) {
|
||||||
|
struct sigframe *sf;
|
||||||
|
uintptr_t uc_addr;
|
||||||
|
struct dwarf_loc esp_loc;
|
||||||
|
|
||||||
|
sf = (struct sigframe *)c->dwarf.cfa;
|
||||||
|
uc_addr = (uintptr_t)&(sf->sf_uc);
|
||||||
|
|
||||||
|
esp_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_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[EIP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EIP_OFF, 0);
|
||||||
|
c->dwarf.loc[ESP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0);
|
||||||
|
c->dwarf.loc[EAX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EAX_OFF, 0);
|
||||||
|
c->dwarf.loc[ECX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ECX_OFF, 0);
|
||||||
|
c->dwarf.loc[EDX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDX_OFF, 0);
|
||||||
|
c->dwarf.loc[EBX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBX_OFF, 0);
|
||||||
|
c->dwarf.loc[EBP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBP_OFF, 0);
|
||||||
|
c->dwarf.loc[ESI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESI_OFF, 0);
|
||||||
|
c->dwarf.loc[EDI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDI_OFF, 0);
|
||||||
|
c->dwarf.loc[EFLAGS] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EFLAGS_OFF, 0);
|
||||||
|
c->dwarf.loc[TRAPNO] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_TRAPNO_OFF, 0);
|
||||||
|
c->dwarf.loc[ST0] = DWARF_NULL_LOC;
|
||||||
|
} else {
|
||||||
|
Debug (8, "Gstep: not handling frame format %d\n", c->sigcontext_format);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
137
src/x86/Gos-linux.c
Normal file
137
src/x86/Gos-linux.c
Normal 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;
|
||||||
|
}
|
124
src/x86/Gstep.c
124
src/x86/Gstep.c
|
@ -29,10 +29,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#ifdef __FreeBSD__
|
|
||||||
#include <ucontext.h>
|
|
||||||
#include <machine/sigframe.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "unwind_i.h"
|
#include "unwind_i.h"
|
||||||
#include "offsets.h"
|
#include "offsets.h"
|
||||||
|
@ -66,122 +62,15 @@ 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);
|
||||||
|
|
||||||
format = unw_is_signal_frame (cursor);
|
if (unw_is_signal_frame (cursor))
|
||||||
if (format < 0) {
|
{
|
||||||
Debug (13, "unw_is_signal_frame() failed (ret=%d)\n", ret);
|
ret = unw_handle_signal_frame(cursor);
|
||||||
return format;
|
|
||||||
}
|
|
||||||
if (format != X86_SCF_NONE)
|
|
||||||
{
|
|
||||||
#if defined __linux__
|
|
||||||
/* XXX This code is Linux-specific! */
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
#elif defined __FreeBSD__
|
|
||||||
if (format == X86_SCF_FREEBSD_SIGFRAME) {
|
|
||||||
struct sigframe *sf;
|
|
||||||
uintptr_t uc_addr;
|
|
||||||
struct dwarf_loc esp_loc;
|
|
||||||
|
|
||||||
sf = (struct sigframe *)c->dwarf.cfa;
|
|
||||||
uc_addr = (uintptr_t)&(sf->sf_uc);
|
|
||||||
|
|
||||||
esp_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0);
|
|
||||||
ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
Debug (2, "returning 0\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ebp_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBP_OFF, 0);
|
|
||||||
eip_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EIP_OFF, 0);
|
|
||||||
|
|
||||||
c->dwarf.loc[EAX] = DWARF_LOC (uc_addr +
|
|
||||||
FREEBSD_UC_MCONTEXT_EAX_OFF, 0);
|
|
||||||
c->dwarf.loc[ECX] = DWARF_LOC (uc_addr +
|
|
||||||
FREEBSD_UC_MCONTEXT_ECX_OFF, 0);
|
|
||||||
c->dwarf.loc[EDX] = DWARF_LOC (uc_addr +
|
|
||||||
FREEBSD_UC_MCONTEXT_EDX_OFF, 0);
|
|
||||||
c->dwarf.loc[EBX] = DWARF_LOC (uc_addr +
|
|
||||||
FREEBSD_UC_MCONTEXT_EBX_OFF, 0);
|
|
||||||
c->dwarf.loc[EBP] = DWARF_LOC (uc_addr +
|
|
||||||
FREEBSD_UC_MCONTEXT_EBP_OFF, 0);
|
|
||||||
c->dwarf.loc[ESI] = DWARF_LOC (uc_addr +
|
|
||||||
FREEBSD_UC_MCONTEXT_ESI_OFF, 0);
|
|
||||||
c->dwarf.loc[EDI] = DWARF_LOC (uc_addr +
|
|
||||||
FREEBSD_UC_MCONTEXT_EDI_OFF, 0);
|
|
||||||
c->dwarf.loc[EFLAGS] = DWARF_LOC (uc_addr +
|
|
||||||
FREEBSD_UC_MCONTEXT_EFLAGS_OFF, 0);
|
|
||||||
c->dwarf.loc[TRAPNO] = DWARF_LOC (uc_addr +
|
|
||||||
FREEBSD_UC_MCONTEXT_EFLAGS_OFF, 0);
|
|
||||||
c->dwarf.loc[ST0] = DWARF_NULL_LOC;
|
|
||||||
} else {
|
|
||||||
Debug (8, "Gstep: not handling frame format %d\n", format);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#error Port me
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
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);
|
||||||
|
@ -203,9 +92,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]))
|
||||||
|
|
|
@ -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-freebsd.c"
|
||||||
#endif
|
#endif
|
5
src/x86/Los-linux.c
Normal file
5
src/x86/Los-linux.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-linux.c"
|
||||||
|
#endif
|
130
src/x86_64/Gos-freebsd.c
Normal file
130
src/x86_64/Gos-freebsd.c
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/* libunwind - a platform-independent unwind library
|
||||||
|
Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
|
||||||
|
|
||||||
|
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. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/ucontext.h>
|
||||||
|
#include <machine/sigframe.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "unwind_i.h"
|
||||||
|
#include "ucontext_i.h"
|
||||||
|
|
||||||
|
PROTECTED int
|
||||||
|
unw_is_signal_frame (unw_cursor_t *cursor)
|
||||||
|
{
|
||||||
|
/* XXXKIB */
|
||||||
|
struct cursor *c = (struct cursor *) cursor;
|
||||||
|
unw_word_t w0, w1, w2, b0, 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 RIP points at sigreturn sequence.
|
||||||
|
48 8d 7c 24 10 lea SIGF_UC(%rsp),%rdi
|
||||||
|
6a 00 pushq $0
|
||||||
|
48 c7 c0 a1 01 00 00 movq $SYS_sigreturn,%rax
|
||||||
|
0f 05 syscall
|
||||||
|
f4 0: hlt
|
||||||
|
eb fd jmp 0b
|
||||||
|
*/
|
||||||
|
|
||||||
|
ip = c->dwarf.ip;
|
||||||
|
c->sigcontext_format = X86_64_SCF_NONE;
|
||||||
|
if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0
|
||||||
|
|| (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0
|
||||||
|
|| (ret = (*a->access_mem) (as, ip + 16, &w2, 0, arg)) < 0)
|
||||||
|
return 0;
|
||||||
|
w2 &= 0xffffff;
|
||||||
|
if (w0 == 0x48006a10247c8d48 &&
|
||||||
|
w1 == 0x050f000001a1c0c7 &&
|
||||||
|
w2 == 0x0000000000fdebf4)
|
||||||
|
{
|
||||||
|
c->sigcontext_format = X86_64_SCF_FREEBSD_SIGFRAME;
|
||||||
|
return (c->sigcontext_format);
|
||||||
|
}
|
||||||
|
/* Check if RIP points at standard syscall sequence.
|
||||||
|
49 89 ca mov %rcx,%r10
|
||||||
|
0f 05 syscall
|
||||||
|
*/
|
||||||
|
if ((ret = (*a->access_mem) (as, ip - 5, &b0, 0, arg)) < 0)
|
||||||
|
return (0);
|
||||||
|
b0 &= 0xffffffffff;
|
||||||
|
if (b0 == 0x000000050fca8949)
|
||||||
|
{
|
||||||
|
c->sigcontext_format = X86_64_SCF_FREEBSD_SYSCALL;
|
||||||
|
return (c->sigcontext_format);
|
||||||
|
}
|
||||||
|
return (X86_64_SCF_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROTECTED int
|
||||||
|
unw_handle_signal_frame (unw_cursor_t *cursor)
|
||||||
|
{
|
||||||
|
struct cursor *c = (struct cursor *) cursor;
|
||||||
|
unw_word_t ucontext;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (c->sigcontext_format == X86_64_SCF_FREEBSD_SIGFRAME)
|
||||||
|
ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc);
|
||||||
|
else
|
||||||
|
return -UNW_EBADFRAME;
|
||||||
|
|
||||||
|
Debug(1, "signal frame, skip over trampoline\n");
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -54,63 +54,46 @@ unw_is_signal_frame (unw_cursor_t *cursor)
|
||||||
|| (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0)
|
|| (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
w1 &= 0xff;
|
w1 &= 0xff;
|
||||||
return (w0 == 0x0f0000000fc0c748 && w1 == 0x05) ?
|
return (w0 == 0x0f0000000fc0c748 && w1 == 0x05);
|
||||||
X86_64_SCF_LINUX_RT_SIGFRAME : X86_64_SCF_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__FreeBSD__)
|
|
||||||
PROTECTED int
|
PROTECTED int
|
||||||
unw_is_signal_frame (unw_cursor_t *cursor)
|
unw_handle_signal_frame (unw_cursor_t *cursor)
|
||||||
{
|
{
|
||||||
/* XXXKIB */
|
|
||||||
struct cursor *c = (struct cursor *) cursor;
|
struct cursor *c = (struct cursor *) cursor;
|
||||||
unw_word_t w0, w1, w2, b0, ip;
|
|
||||||
unw_addr_space_t as;
|
|
||||||
unw_accessors_t *a;
|
|
||||||
void *arg;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
unw_word_t ucontext = c->dwarf.cfa;
|
||||||
|
|
||||||
as = c->dwarf.as;
|
Debug(1, "signal frame, skip over trampoline\n");
|
||||||
a = unw_get_accessors (as);
|
|
||||||
arg = c->dwarf.as_arg;
|
|
||||||
|
|
||||||
/* Check if RIP points at sigreturn sequence.
|
c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME;
|
||||||
48 8d 7c 24 10 lea SIGF_UC(%rsp),%rdi
|
c->sigcontext_addr = c->dwarf.cfa;
|
||||||
6a 00 pushq $0
|
|
||||||
48 c7 c0 a1 01 00 00 movq $SYS_sigreturn,%rax
|
|
||||||
0f 05 syscall
|
|
||||||
f4 0: hlt
|
|
||||||
eb fd jmp 0b
|
|
||||||
*/
|
|
||||||
|
|
||||||
ip = c->dwarf.ip;
|
struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);
|
||||||
if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0
|
ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa);
|
||||||
|| (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0
|
if (ret < 0)
|
||||||
|| (ret = (*a->access_mem) (as, ip + 16, &w2, 0, arg)) < 0)
|
{
|
||||||
return 0;
|
Debug (2, "returning %d\n", ret);
|
||||||
w2 &= 0xffffff;
|
return ret;
|
||||||
if (w0 == 0x48006a10247c8d48 &&
|
}
|
||||||
w1 == 0x050f000001a1c0c7 &&
|
|
||||||
w2 == 0x0000000000fdebf4)
|
c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0);
|
||||||
return X86_64_SCF_FREEBSD_SIGFRAME;
|
c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0);
|
||||||
/* Check if RIP points at standard syscall sequence.
|
c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0);
|
||||||
49 89 ca mov %rcx,%r10
|
c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0);
|
||||||
0f 05 syscall
|
c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0);
|
||||||
*/
|
c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0);
|
||||||
if ((ret = (*a->access_mem) (as, ip - 5, &b0, 0, arg)) < 0)
|
c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0);
|
||||||
return (0);
|
c->dwarf.loc[RSP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);
|
||||||
b0 &= 0xffffffffff;
|
c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0);
|
||||||
if (b0 == 0x000000050fca8949)
|
c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0);
|
||||||
return X86_64_SCF_FREEBSD_SYSCALL;
|
c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0);
|
||||||
return X86_64_SCF_NONE;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !__linux__ && !__FreeBSD__ */
|
|
||||||
|
|
||||||
PROTECTED int
|
|
||||||
unw_is_signal_frame (unw_cursor_t *cursor)
|
|
||||||
{
|
|
||||||
printf ("%s: implement me\n", __FUNCTION__);
|
|
||||||
return -UNW_ENOINFO;
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -26,15 +26,9 @@ 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>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#if defined __FreeBSD__
|
|
||||||
#include <sys/ucontext.h>
|
|
||||||
#include <machine/sigframe.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PROTECTED int
|
PROTECTED int
|
||||||
unw_step (unw_cursor_t *cursor)
|
unw_step (unw_cursor_t *cursor)
|
||||||
{
|
{
|
||||||
|
@ -102,49 +96,12 @@ unw_step (unw_cursor_t *cursor)
|
||||||
return 1;
|
return 1;
|
||||||
} else if (c->sigcontext_format != X86_64_SCF_NONE)
|
} else if (c->sigcontext_format != X86_64_SCF_NONE)
|
||||||
{
|
{
|
||||||
unw_word_t ucontext;
|
ret = unw_handle_signal_frame(cursor);
|
||||||
|
|
||||||
Debug(1, "signal frame, skip over trampoline\n");
|
|
||||||
|
|
||||||
#if defined __linux__
|
|
||||||
ucontext = c->dwarf.cfa;
|
|
||||||
if (c->sigcontext_format != X86_64_SCF_LINUX_RT_SIGFRAME)
|
|
||||||
return -UNW_EBADFRAME;
|
|
||||||
#elif defined __FreeBSD__
|
|
||||||
if (c->sigcontext_format == X86_64_SCF_FREEBSD_SIGFRAME)
|
|
||||||
ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc);
|
|
||||||
else
|
|
||||||
return -UNW_EBADFRAME;
|
|
||||||
#endif
|
|
||||||
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
|
||||||
{
|
{
|
||||||
|
@ -185,11 +142,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-freebsd.c
Normal file
5
src/x86_64/Los-freebsd.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-freebsd.c"
|
||||||
|
#endif
|
5
src/x86_64/Los-linux.c
Normal file
5
src/x86_64/Los-linux.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-linux.c"
|
||||||
|
#endif
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue