From 8e53e62db913470952b8eb541834b876f7a6882c Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sun, 4 Apr 2010 16:17:32 -0700 Subject: [PATCH] Refactor os specific code for x86 (both 32 and 64 bit). Move Linux specific code into ${arch}/Gos-linux.c --- include/libunwind-common.h.in | 2 + src/Makefile.am | 22 ++- src/x86/Gis_signal_frame.c | 71 --------- src/x86/Gos-linux.c | 137 ++++++++++++++++++ src/x86/Gstep.c | 67 +-------- src/x86/{Lis_signal_frame.c => Los-linux.c} | 2 +- .../{Gis_signal_frame.c => Gos-linux.c} | 45 +++++- src/x86_64/Gstep.c | 42 +----- src/x86_64/Los-linux.c | 5 + tests/check-namespace.sh.in | 2 + 10 files changed, 213 insertions(+), 182 deletions(-) delete mode 100644 src/x86/Gis_signal_frame.c create mode 100644 src/x86/Gos-linux.c rename src/x86/{Lis_signal_frame.c => Los-linux.c} (78%) rename src/x86_64/{Gis_signal_frame.c => Gos-linux.c} (53%) create mode 100644 src/x86_64/Los-linux.c diff --git a/include/libunwind-common.h.in b/include/libunwind-common.h.in index 9005a6c2..228460a9 100644 --- a/include/libunwind-common.h.in +++ b/include/libunwind-common.h.in @@ -220,6 +220,7 @@ unw_save_loc_t; #define unw_set_fpreg UNW_OBJ(set_fpreg) #define unw_get_save_loc UNW_OBJ(get_save_loc) #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_set_caching_policy UNW_OBJ(set_caching_policy) #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_get_save_loc (unw_cursor_t *, int, unw_save_loc_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 const char *unw_strerror (int); diff --git a/src/Makefile.am b/src/Makefile.am index c110e768..2635d8d9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -221,22 +221,24 @@ libunwind_la_SOURCES_x86_common = $(libunwind_la_SOURCES_common) \ # The list of files that go into libunwind: libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ + $(libunwind_la_SOURCES_x86_os_local) \ $(libunwind_la_SOURCES_local) \ $(dwarf_SOURCES_local) \ dwarf/Lfind_proc_info-lsb.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/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 # The list of files that go into libunwind-x86: libunwind_x86_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ + $(libunwind_la_SOURCES_x86_os) \ $(libunwind_la_SOURCES_generic) \ $(dwarf_SOURCES_generic) \ dwarf/Gfind_proc_info-lsb.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/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 # 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: libunwind_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \ + $(libunwind_la_SOURCES_x86_64_os_local) \ $(libunwind_la_SOURCES_local) \ $(dwarf_SOURCES_local) \ 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/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 # The list of files that go into libunwind-x86_64: libunwind_x86_64_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \ + $(libunwind_la_SOURCES_x86_64_os) \ $(libunwind_la_SOURCES_generic) \ $(dwarf_SOURCES_generic) \ dwarf/Gfind_proc_info-lsb.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/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 # The list of local files that go to Power 64 and 32: @@ -342,8 +346,12 @@ install-exec-hook: endif if 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 = $(libunwind_la_SOURCES_os_linux) + 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 if OS_HPUX diff --git a/src/x86/Gis_signal_frame.c b/src/x86/Gis_signal_frame.c deleted file mode 100644 index 686da02c..00000000 --- a/src/x86/Gis_signal_frame.c +++ /dev/null @@ -1,71 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -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; -} diff --git a/src/x86/Gos-linux.c b/src/x86/Gos-linux.c new file mode 100644 index 00000000..63888a5c --- /dev/null +++ b/src/x86/Gos-linux.c @@ -0,0 +1,137 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +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; +} diff --git a/src/x86/Gstep.c b/src/x86/Gstep.c index 266f89f4..e4055ae0 100644 --- a/src/x86/Gstep.c +++ b/src/x86/Gstep.c @@ -56,70 +56,14 @@ unw_step (unw_cursor_t *cursor) Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); if (unw_is_signal_frame (cursor)) - { - /* 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)); + { + ret = unw_handle_signal_frame(cursor); 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); - 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 { ret = dwarf_get (&c->dwarf, c->dwarf.loc[EBP], &c->dwarf.cfa); @@ -141,9 +85,10 @@ unw_step (unw_cursor_t *cursor) EIP. */ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) 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; if (!DWARF_IS_NULL_LOC (c->dwarf.loc[EBP])) diff --git a/src/x86/Lis_signal_frame.c b/src/x86/Los-linux.c similarity index 78% rename from src/x86/Lis_signal_frame.c rename to src/x86/Los-linux.c index b9a7c4f5..3cc18aab 100644 --- a/src/x86/Lis_signal_frame.c +++ b/src/x86/Los-linux.c @@ -1,5 +1,5 @@ #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gis_signal_frame.c" +#include "Gos-linux.c" #endif diff --git a/src/x86_64/Gis_signal_frame.c b/src/x86_64/Gos-linux.c similarity index 53% rename from src/x86_64/Gis_signal_frame.c rename to src/x86_64/Gos-linux.c index 72edf46e..4b99e280 100644 --- a/src/x86_64/Gis_signal_frame.c +++ b/src/x86_64/Gos-linux.c @@ -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. */ #include "unwind_i.h" +#include "ucontext_i.h" -#ifdef __linux__ PROTECTED int 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); } -#else /* __linux__ */ - PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) +unw_handle_signal_frame (unw_cursor_t *cursor) { - printf ("%s: implement me\n", __FUNCTION__); - return -UNW_ENOINFO; + struct cursor *c = (struct cursor *) cursor; + 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__ */ diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c index 2da1c25d..d23be8ea 100644 --- a/src/x86_64/Gstep.c +++ b/src/x86_64/Gstep.c @@ -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. */ #include "unwind_i.h" -#include "ucontext_i.h" #include PROTECTED int @@ -79,40 +78,12 @@ unw_step (unw_cursor_t *cursor) if (unw_is_signal_frame (cursor)) { - 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; - - 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); + ret = unw_handle_signal_frame(cursor); if (ret < 0) { - Debug (2, "returning %d\n", ret); - return ret; + Debug (2, "returning 0\n"); + 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 { @@ -153,11 +124,12 @@ unw_step (unw_cursor_t *cursor) /* Mark all registers unsaved */ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) 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; if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) diff --git a/src/x86_64/Los-linux.c b/src/x86_64/Los-linux.c new file mode 100644 index 00000000..3cc18aab --- /dev/null +++ b/src/x86_64/Los-linux.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gos-linux.c" +#endif diff --git a/tests/check-namespace.sh.in b/tests/check-namespace.sh.in index 66078a12..343349f7 100644 --- a/tests/check-namespace.sh.in +++ b/tests/check-namespace.sh.in @@ -83,6 +83,7 @@ check_local_unw_abi () { match _UL${plat}_init_local match _UL${plat}_init_remote match _UL${plat}_is_signal_frame + match _UL${plat}_handle_signal_frame match _UL${plat}_local_addr_space match _UL${plat}_resume match _UL${plat}_set_caching_policy @@ -144,6 +145,7 @@ check_generic_unw_abi () { match _U${plat}_init_local match _U${plat}_init_remote match _U${plat}_is_signal_frame + match _U${plat}_handle_signal_frame match _U${plat}_local_addr_space match _U${plat}_regname match _U${plat}_resume