diff options
author | Robert Nagy <robert@cvs.openbsd.org> | 2018-09-11 18:03:06 +0000 |
---|---|---|
committer | Robert Nagy <robert@cvs.openbsd.org> | 2018-09-11 18:03:06 +0000 |
commit | 56530cd2942c521fa9c933f5b32ab29ff9e7bf1e (patch) | |
tree | 6f4c30e7cbda6c471c5b1521f60cd1d003c9f7f8 /lib/libunwind | |
parent | a58afdd370872200ee050c6a1ab273e831b12cf1 (diff) |
merge libunwind 6.0.0; ok patrick@, kettenis@
Diffstat (limited to 'lib/libunwind')
-rw-r--r-- | lib/libunwind/include/__libunwind_config.h | 75 | ||||
-rw-r--r-- | lib/libunwind/include/libunwind.h | 211 | ||||
-rw-r--r-- | lib/libunwind/src/AddressSpace.hpp | 352 | ||||
-rw-r--r-- | lib/libunwind/src/DwarfInstructions.hpp | 15 | ||||
-rw-r--r-- | lib/libunwind/src/DwarfParser.hpp | 287 | ||||
-rw-r--r-- | lib/libunwind/src/EHHeaderParser.hpp | 7 | ||||
-rw-r--r-- | lib/libunwind/src/Registers.hpp | 1093 | ||||
-rw-r--r-- | lib/libunwind/src/UnwindCursor.hpp | 169 | ||||
-rw-r--r-- | lib/libunwind/src/UnwindRegistersRestore.S | 335 | ||||
-rw-r--r-- | lib/libunwind/src/UnwindRegistersSave.S | 398 | ||||
-rw-r--r-- | lib/libunwind/src/libunwind.cpp | 81 | ||||
-rw-r--r-- | lib/libunwind/src/unwind_ext.h | 37 |
12 files changed, 2508 insertions, 552 deletions
diff --git a/lib/libunwind/include/__libunwind_config.h b/lib/libunwind/include/__libunwind_config.h index 112ff25fca5..95632e0e467 100644 --- a/lib/libunwind/include/__libunwind_config.h +++ b/lib/libunwind/include/__libunwind_config.h @@ -12,47 +12,77 @@ #if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ !defined(__ARM_DWARF_EH__) -#define _LIBUNWIND_ARM_EHABI 1 -#else -#define _LIBUNWIND_ARM_EHABI 0 +#define _LIBUNWIND_ARM_EHABI #endif +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 8 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 32 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC 112 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64 110 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 95 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM 287 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 31 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65 + #if defined(_LIBUNWIND_IS_NATIVE_ONLY) # if defined(__i386__) -# define _LIBUNWIND_TARGET_I386 1 +# define _LIBUNWIND_TARGET_I386 # define _LIBUNWIND_CONTEXT_SIZE 8 -# define _LIBUNWIND_CURSOR_SIZE 19 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 9 +# define _LIBUNWIND_CURSOR_SIZE 15 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 # elif defined(__x86_64__) # define _LIBUNWIND_TARGET_X86_64 1 -# define _LIBUNWIND_CONTEXT_SIZE 21 -# define _LIBUNWIND_CURSOR_SIZE 33 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 17 +# if defined(_WIN64) +# define _LIBUNWIND_CONTEXT_SIZE 54 +# define _LIBUNWIND_CURSOR_SIZE 66 +# else +# define _LIBUNWIND_CONTEXT_SIZE 21 +# define _LIBUNWIND_CURSOR_SIZE 33 +# endif +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 +# elif defined(__powerpc64__) +# define _LIBUNWIND_TARGET_PPC64 1 +# define _LIBUNWIND_CONTEXT_SIZE 136 +# define _LIBUNWIND_CURSOR_SIZE 148 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64 # elif defined(__ppc__) # define _LIBUNWIND_TARGET_PPC 1 # define _LIBUNWIND_CONTEXT_SIZE 117 -# define _LIBUNWIND_CURSOR_SIZE 128 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 113 +# define _LIBUNWIND_CURSOR_SIZE 124 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC # elif defined(__aarch64__) # define _LIBUNWIND_TARGET_AARCH64 1 # define _LIBUNWIND_CONTEXT_SIZE 66 # define _LIBUNWIND_CURSOR_SIZE 78 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 96 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 # elif defined(__arm__) # define _LIBUNWIND_TARGET_ARM 1 # if defined(__ARM_WMMX) -# define _LIBUNWIND_CONTEXT_SIZE 60 -# define _LIBUNWIND_CURSOR_SIZE 67 +# define _LIBUNWIND_CONTEXT_SIZE 61 +# define _LIBUNWIND_CURSOR_SIZE 68 # else # define _LIBUNWIND_CONTEXT_SIZE 42 # define _LIBUNWIND_CURSOR_SIZE 49 # endif -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 96 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM # elif defined(__or1k__) # define _LIBUNWIND_TARGET_OR1K 1 # define _LIBUNWIND_CONTEXT_SIZE 16 -# define _LIBUNWIND_CURSOR_SIZE 28 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 32 +# define _LIBUNWIND_CURSOR_SIZE 24 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K +# elif defined(__mips__) +# if defined(_ABIO32) && defined(__mips_soft_float) +# define _LIBUNWIND_TARGET_MIPS_O32 1 +# define _LIBUNWIND_CONTEXT_SIZE 18 +# define _LIBUNWIND_CURSOR_SIZE 24 +# elif defined(_ABI64) && defined(__mips_soft_float) +# define _LIBUNWIND_TARGET_MIPS_N64 1 +# define _LIBUNWIND_CONTEXT_SIZE 35 +# define _LIBUNWIND_CURSOR_SIZE 47 +# else +# error "Unsupported MIPS ABI and/or environment" +# endif +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS # elif defined(__sparc__) && defined(__arch64__) # define _LIBUNWIND_TARGET_SPARC64 1 # define _LIBUNWIND_CONTEXT_SIZE 33 @@ -62,15 +92,18 @@ # error "Unsupported architecture." # endif #else // !_LIBUNWIND_IS_NATIVE_ONLY -# define _LIBUNWIND_TARGET_I386 1 +# define _LIBUNWIND_TARGET_I386 # define _LIBUNWIND_TARGET_X86_64 1 # define _LIBUNWIND_TARGET_PPC 1 +# define _LIBUNWIND_TARGET_PPC64 1 # define _LIBUNWIND_TARGET_AARCH64 1 # define _LIBUNWIND_TARGET_ARM 1 # define _LIBUNWIND_TARGET_OR1K 1 -# define _LIBUNWIND_CONTEXT_SIZE 128 -# define _LIBUNWIND_CURSOR_SIZE 140 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 120 +# define _LIBUNWIND_TARGET_MIPS_O32 1 +# define _LIBUNWIND_TARGET_MIPS_N64 1 +# define _LIBUNWIND_CONTEXT_SIZE 136 +# define _LIBUNWIND_CURSOR_SIZE 148 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287 #endif // _LIBUNWIND_IS_NATIVE_ONLY #endif // ____LIBUNWIND_CONFIG_H__ diff --git a/lib/libunwind/include/libunwind.h b/lib/libunwind/include/libunwind.h index 5c8b2ac0565..29cf62e4335 100644 --- a/lib/libunwind/include/libunwind.h +++ b/lib/libunwind/include/libunwind.h @@ -6,7 +6,7 @@ // Source Licenses. See LICENSE.TXT for details. // // -// Compatible with libuwind API documented at: +// Compatible with libunwind API documented at: // http://www.nongnu.org/libunwind/man/libunwind(3).html // //===----------------------------------------------------------------------===// @@ -20,12 +20,26 @@ #include <stddef.h> #ifdef __APPLE__ - #include <Availability.h> - #ifdef __arm__ - #define LIBUNWIND_AVAIL __attribute__((unavailable)) + #if __clang__ + #if __has_include(<Availability.h>) + #include <Availability.h> + #endif + #elif __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 + #include <Availability.h> + #endif + + #ifdef __arm__ + #define LIBUNWIND_AVAIL __attribute__((unavailable)) + #elif defined(__OSX_AVAILABLE_STARTING) + #define LIBUNWIND_AVAIL __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0) + #else + #include <AvailabilityMacros.h> + #ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER + #define LIBUNWIND_AVAIL AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER #else - #define LIBUNWIND_AVAIL __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0) + #define LIBUNWIND_AVAIL __attribute__((unavailable)) #endif + #endif #else #define LIBUNWIND_AVAIL #endif @@ -58,11 +72,10 @@ typedef struct unw_cursor_t unw_cursor_t; typedef struct unw_addr_space *unw_addr_space_t; typedef int unw_regnum_t; -#if _LIBUNWIND_ARM_EHABI -typedef uint32_t unw_word_t; +typedef uintptr_t unw_word_t; +#if defined(__arm__) typedef uint64_t unw_fpreg_t; #else -typedef uint64_t unw_word_t; typedef double unw_fpreg_t; #endif @@ -75,8 +88,8 @@ struct unw_proc_info_t { unw_word_t gp; /* not used */ unw_word_t flags; /* not used */ uint32_t format; /* compact unwind encoding, or zero if none */ - uint32_t unwind_info_size; /* size of dwarf unwind info, or zero if none */ - unw_word_t unwind_info; /* address of dwarf unwind info, or zero */ + uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */ + unw_word_t unwind_info; /* address of DWARF unwind info, or zero */ unw_word_t extra; /* mach_header of mach-o image containing func */ }; typedef struct unw_proc_info_t unw_proc_info_t; @@ -120,7 +133,7 @@ extern int unw_init_remote_thread(unw_cursor_t *, unw_addr_space_t, thread_t *); #endif /* UNW_REMOTE */ /* - * traditional libuwind "remote" API + * traditional libunwind "remote" API * NOT IMPLEMENTED on Mac OS X * * extern int unw_init_remote(unw_cursor_t*, unw_addr_space_t, @@ -151,13 +164,8 @@ enum { UNW_X86_ECX = 1, UNW_X86_EDX = 2, UNW_X86_EBX = 3, -#ifdef __OpenBSD__ - UNW_X86_ESP = 4, - UNW_X86_EBP = 5, -#else UNW_X86_EBP = 4, UNW_X86_ESP = 5, -#endif UNW_X86_ESI = 6, UNW_X86_EDI = 7 }; @@ -179,7 +187,24 @@ enum { UNW_X86_64_R12 = 12, UNW_X86_64_R13 = 13, UNW_X86_64_R14 = 14, - UNW_X86_64_R15 = 15 + UNW_X86_64_R15 = 15, + UNW_X86_64_RIP = 16, + UNW_X86_64_XMM0 = 17, + UNW_X86_64_XMM1 = 18, + UNW_X86_64_XMM2 = 19, + UNW_X86_64_XMM3 = 20, + UNW_X86_64_XMM4 = 21, + UNW_X86_64_XMM5 = 22, + UNW_X86_64_XMM6 = 23, + UNW_X86_64_XMM7 = 24, + UNW_X86_64_XMM8 = 25, + UNW_X86_64_XMM9 = 26, + UNW_X86_64_XMM10 = 27, + UNW_X86_64_XMM11 = 28, + UNW_X86_64_XMM12 = 29, + UNW_X86_64_XMM13 = 30, + UNW_X86_64_XMM14 = 31, + UNW_X86_64_XMM15 = 32, }; @@ -300,6 +325,120 @@ enum { UNW_PPC_SPEFSCR = 112 }; +// 64-bit ppc register numbers +enum { + UNW_PPC64_R0 = 0, + UNW_PPC64_R1 = 1, + UNW_PPC64_R2 = 2, + UNW_PPC64_R3 = 3, + UNW_PPC64_R4 = 4, + UNW_PPC64_R5 = 5, + UNW_PPC64_R6 = 6, + UNW_PPC64_R7 = 7, + UNW_PPC64_R8 = 8, + UNW_PPC64_R9 = 9, + UNW_PPC64_R10 = 10, + UNW_PPC64_R11 = 11, + UNW_PPC64_R12 = 12, + UNW_PPC64_R13 = 13, + UNW_PPC64_R14 = 14, + UNW_PPC64_R15 = 15, + UNW_PPC64_R16 = 16, + UNW_PPC64_R17 = 17, + UNW_PPC64_R18 = 18, + UNW_PPC64_R19 = 19, + UNW_PPC64_R20 = 20, + UNW_PPC64_R21 = 21, + UNW_PPC64_R22 = 22, + UNW_PPC64_R23 = 23, + UNW_PPC64_R24 = 24, + UNW_PPC64_R25 = 25, + UNW_PPC64_R26 = 26, + UNW_PPC64_R27 = 27, + UNW_PPC64_R28 = 28, + UNW_PPC64_R29 = 29, + UNW_PPC64_R30 = 30, + UNW_PPC64_R31 = 31, + UNW_PPC64_F0 = 32, + UNW_PPC64_F1 = 33, + UNW_PPC64_F2 = 34, + UNW_PPC64_F3 = 35, + UNW_PPC64_F4 = 36, + UNW_PPC64_F5 = 37, + UNW_PPC64_F6 = 38, + UNW_PPC64_F7 = 39, + UNW_PPC64_F8 = 40, + UNW_PPC64_F9 = 41, + UNW_PPC64_F10 = 42, + UNW_PPC64_F11 = 43, + UNW_PPC64_F12 = 44, + UNW_PPC64_F13 = 45, + UNW_PPC64_F14 = 46, + UNW_PPC64_F15 = 47, + UNW_PPC64_F16 = 48, + UNW_PPC64_F17 = 49, + UNW_PPC64_F18 = 50, + UNW_PPC64_F19 = 51, + UNW_PPC64_F20 = 52, + UNW_PPC64_F21 = 53, + UNW_PPC64_F22 = 54, + UNW_PPC64_F23 = 55, + UNW_PPC64_F24 = 56, + UNW_PPC64_F25 = 57, + UNW_PPC64_F26 = 58, + UNW_PPC64_F27 = 59, + UNW_PPC64_F28 = 60, + UNW_PPC64_F29 = 61, + UNW_PPC64_F30 = 62, + UNW_PPC64_F31 = 63, + UNW_PPC64_LR = 64, + UNW_PPC64_CTR = 65, + UNW_PPC64_CR0 = 66, + UNW_PPC64_CR1 = 67, + UNW_PPC64_CR2 = 68, + UNW_PPC64_CR3 = 69, + UNW_PPC64_CR4 = 70, + UNW_PPC64_CR5 = 71, + UNW_PPC64_CR6 = 72, + UNW_PPC64_CR7 = 73, + UNW_PPC64_XER = 74, + UNW_PPC64_V0 = 75, + UNW_PPC64_V1 = 76, + UNW_PPC64_V2 = 77, + UNW_PPC64_V3 = 78, + UNW_PPC64_V4 = 79, + UNW_PPC64_V5 = 80, + UNW_PPC64_V6 = 81, + UNW_PPC64_V7 = 82, + UNW_PPC64_V8 = 83, + UNW_PPC64_V9 = 84, + UNW_PPC64_V10 = 85, + UNW_PPC64_V11 = 86, + UNW_PPC64_V12 = 87, + UNW_PPC64_V13 = 88, + UNW_PPC64_V14 = 89, + UNW_PPC64_V15 = 90, + UNW_PPC64_V16 = 91, + UNW_PPC64_V17 = 92, + UNW_PPC64_V18 = 93, + UNW_PPC64_V19 = 94, + UNW_PPC64_V20 = 95, + UNW_PPC64_V21 = 96, + UNW_PPC64_V22 = 97, + UNW_PPC64_V23 = 98, + UNW_PPC64_V24 = 99, + UNW_PPC64_V25 = 100, + UNW_PPC64_V26 = 101, + UNW_PPC64_V27 = 102, + UNW_PPC64_V28 = 103, + UNW_PPC64_V29 = 104, + UNW_PPC64_V30 = 105, + UNW_PPC64_V31 = 106, + UNW_PPC64_VRSAVE = 107, + UNW_PPC64_VSCR = 108, + UNW_PPC64_FPSCR = 109 +}; + // 64-bit ARM64 registers enum { UNW_ARM64_X0 = 0, @@ -538,4 +677,42 @@ enum { UNW_OR1K_R31 = 31, }; +// MIPS registers +enum { + UNW_MIPS_R0 = 0, + UNW_MIPS_R1 = 1, + UNW_MIPS_R2 = 2, + UNW_MIPS_R3 = 3, + UNW_MIPS_R4 = 4, + UNW_MIPS_R5 = 5, + UNW_MIPS_R6 = 6, + UNW_MIPS_R7 = 7, + UNW_MIPS_R8 = 8, + UNW_MIPS_R9 = 9, + UNW_MIPS_R10 = 10, + UNW_MIPS_R11 = 11, + UNW_MIPS_R12 = 12, + UNW_MIPS_R13 = 13, + UNW_MIPS_R14 = 14, + UNW_MIPS_R15 = 15, + UNW_MIPS_R16 = 16, + UNW_MIPS_R17 = 17, + UNW_MIPS_R18 = 18, + UNW_MIPS_R19 = 19, + UNW_MIPS_R20 = 20, + UNW_MIPS_R21 = 21, + UNW_MIPS_R22 = 22, + UNW_MIPS_R23 = 23, + UNW_MIPS_R24 = 24, + UNW_MIPS_R25 = 25, + UNW_MIPS_R26 = 26, + UNW_MIPS_R27 = 27, + UNW_MIPS_R28 = 28, + UNW_MIPS_R29 = 29, + UNW_MIPS_R30 = 30, + UNW_MIPS_R31 = 31, + UNW_MIPS_HI = 64, + UNW_MIPS_LO = 65, +}; + #endif diff --git a/lib/libunwind/src/AddressSpace.hpp b/lib/libunwind/src/AddressSpace.hpp index 56c89e8dfe8..17145755747 100644 --- a/lib/libunwind/src/AddressSpace.hpp +++ b/lib/libunwind/src/AddressSpace.hpp @@ -18,7 +18,7 @@ #include <stdlib.h> #include <string.h> -#ifndef _LIBUNWIND_IS_BAREMETAL +#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) #include <dlfcn.h> #endif @@ -32,73 +32,137 @@ namespace libunwind { #include "libunwind.h" #include "config.h" #include "dwarf2.h" +#include "EHHeaderParser.hpp" #include "Registers.hpp" -#if _LIBUNWIND_ARM_EHABI -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __APPLE__ -#include <link.h> -typedef void *_Unwind_Ptr; + struct dyld_unwind_sections + { + const struct mach_header* mh; + const void* dwarf_section; + uintptr_t dwarf_section_length; + const void* compact_unwind_section; + uintptr_t compact_unwind_section_length; + }; + #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \ + && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \ + || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) + // In 10.7.0 or later, libSystem.dylib implements this function. + extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *); + #else + // In 10.6.x and earlier, we need to implement this functionality. Note + // that this requires a newer version of libmacho (from cctools) than is + // present in libSystem on 10.6.x (for getsectiondata). + static inline bool _dyld_find_unwind_sections(void* addr, + dyld_unwind_sections* info) { + // Find mach-o image containing address. + Dl_info dlinfo; + if (!dladdr(addr, &dlinfo)) + return false; +#if __LP64__ + const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase; +#else + const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase; +#endif -#elif defined(__linux__) + // Initialize the return struct + info->mh = (const struct mach_header *)mh; + info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length); + info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length); -typedef long unsigned int *_Unwind_Ptr; -extern "C" _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr addr, int *len); + if (!info->dwarf_section) { + info->dwarf_section_length = 0; + } -// Emulate the BSD dl_unwind_find_exidx API when on a GNU libdl system. -#define dl_unwind_find_exidx __gnu_Unwind_Find_exidx + if (!info->compact_unwind_section) { + info->compact_unwind_section_length = 0; + } + + return true; + } + #endif + +#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) -#elif !defined(_LIBUNWIND_IS_BAREMETAL) -#include <link.h> -#else // !defined(_LIBUNWIND_IS_BAREMETAL) // When statically linked on bare-metal, the symbols for the EH table are looked // up without going through the dynamic loader. -struct EHTEntry { - uint32_t functionOffset; - uint32_t unwindOpcodes; -}; -extern EHTEntry __exidx_start; -extern EHTEntry __exidx_end; -#endif // !defined(_LIBUNWIND_IS_BAREMETAL) -#endif // _LIBUNWIND_ARM_EHABI - -#if defined(__CloudABI__) || defined(__FreeBSD__) || defined(__linux__) || \ - defined(__NetBSD__) || defined(__OpenBSD__) -#if _LIBUNWIND_SUPPORT_DWARF_UNWIND && _LIBUNWIND_SUPPORT_DWARF_INDEX + +// The following linker script may be used to produce the necessary sections and symbols. +// Unless the --eh-frame-hdr linker option is provided, the section is not generated +// and does not take space in the output file. +// +// .eh_frame : +// { +// __eh_frame_start = .; +// KEEP(*(.eh_frame)) +// __eh_frame_end = .; +// } +// +// .eh_frame_hdr : +// { +// KEEP(*(.eh_frame_hdr)) +// } +// +// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; +// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; + +extern char __eh_frame_start; +extern char __eh_frame_end; + +#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) +extern char __eh_frame_hdr_start; +extern char __eh_frame_hdr_end; +#endif + +#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) + +// When statically linked on bare-metal, the symbols for the EH table are looked +// up without going through the dynamic loader. +extern char __exidx_start; +extern char __exidx_end; + +#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + +// ELF-based systems may use dl_iterate_phdr() to access sections +// containing unwinding information. The ElfW() macro for pointer-size +// independent ELF header traversal is not provided by <link.h> on some +// systems (e.g., FreeBSD). On these systems the data structures are +// just called Elf_XXX. Define ElfW() locally. +#ifndef _WIN32 #include <link.h> -// Macro for machine-independent access to the ELF program headers. This -// macro is not available on some systems (e.g., FreeBSD). On these -// systems the data structures are just called Elf_XXX. Define ElfW() -// locally. +#else +#include <windows.h> +#include <psapi.h> +#endif #if !defined(ElfW) #define ElfW(type) Elf_##type #endif -#include "EHHeaderParser.hpp" -#endif + #endif namespace libunwind { /// Used by findUnwindSections() to return info about needed sections. struct UnwindInfoSections { -#if _LIBUNWIND_SUPPORT_DWARF_UNWIND || _LIBUNWIND_SUPPORT_DWARF_INDEX || \ - _LIBUNWIND_SUPPORT_COMPACT_UNWIND +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \ + defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) // No dso_base for ARM EHABI. uintptr_t dso_base; #endif -#if _LIBUNWIND_SUPPORT_DWARF_UNWIND +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) uintptr_t dwarf_section; uintptr_t dwarf_section_length; #endif -#if _LIBUNWIND_SUPPORT_DWARF_INDEX +#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) uintptr_t dwarf_index_section; uintptr_t dwarf_index_section_length; #endif -#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND +#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) uintptr_t compact_unwind_section; uintptr_t compact_unwind_section_length; #endif -#if _LIBUNWIND_ARM_EHABI +#if defined(_LIBUNWIND_ARM_EHABI) uintptr_t arm_section; uintptr_t arm_section_length; #endif @@ -110,13 +174,8 @@ struct UnwindInfoSections { /// making local unwinds fast. class __attribute__((visibility("hidden"))) LocalAddressSpace { public: -#ifdef __LP64__ - typedef uint64_t pint_t; - typedef int64_t sint_t; -#else - typedef uint32_t pint_t; - typedef int32_t sint_t; -#endif + typedef uintptr_t pint_t; + typedef intptr_t sint_t; uint8_t get8(pint_t addr) { uint8_t val; memcpy(&val, (void *)addr, sizeof(val)); @@ -162,7 +221,7 @@ public: }; inline uintptr_t LocalAddressSpace::getP(pint_t addr) { -#ifdef __LP64__ +#if __SIZEOF_POINTER__ == 8 return get64(addr); #else return get32(addr); @@ -210,7 +269,7 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { } while (byte & 0x80); // sign extend negative numbers if ((byte & 0x40) != 0) - result |= (-1LL) << bit; + result |= (-1ULL) << bit; addr = (pint_t) p; return result; } @@ -311,55 +370,13 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, return result; } -#ifdef __APPLE__ - struct dyld_unwind_sections - { - const struct mach_header* mh; - const void* dwarf_section; - uintptr_t dwarf_section_length; - const void* compact_unwind_section; - uintptr_t compact_unwind_section_length; - }; - #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \ - && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \ - || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) - // In 10.7.0 or later, libSystem.dylib implements this function. - extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *); - #else - // In 10.6.x and earlier, we need to implement this functionality. - static inline bool _dyld_find_unwind_sections(void* addr, - dyld_unwind_sections* info) { - // Find mach-o image containing address. - Dl_info dlinfo; - if (!dladdr(addr, &dlinfo)) - return false; - const mach_header *mh = (const mach_header *)dlinfo.dli_saddr; - - // Find dwarf unwind section in that image. - unsigned long size; - const uint8_t *p = getsectiondata(mh, "__TEXT", "__eh_frame", &size); - if (!p) - return false; - - // Fill in return struct. - info->mh = mh; - info->dwarf_section = p; - info->dwarf_section_length = size; - info->compact_unwind_section = 0; - info->compact_unwind_section_length = 0; - - return true; - } - #endif -#endif - inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, UnwindInfoSections &info) { #ifdef __APPLE__ dyld_unwind_sections dyldInfo; if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { info.dso_base = (uintptr_t)dyldInfo.mh; - #if _LIBUNWIND_SUPPORT_DWARF_UNWIND + #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section; info.dwarf_section_length = dyldInfo.dwarf_section_length; #endif @@ -367,23 +384,72 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length; return true; } -#elif _LIBUNWIND_ARM_EHABI - #ifdef _LIBUNWIND_IS_BAREMETAL +#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) + // Bare metal is statically linked, so no need to ask the dynamic loader + info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start); + info.dwarf_section = (uintptr_t)(&__eh_frame_start); + _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", + (void *)info.dwarf_section, (void *)info.dwarf_section_length); +#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start); + info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start); + _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p", + (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length); +#endif + if (info.dwarf_section_length) + return true; +#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) // Bare metal is statically linked, so no need to ask the dynamic loader info.arm_section = (uintptr_t)(&__exidx_start); info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start); - #else + _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", + (void *)info.arm_section, (void *)info.arm_section_length); + if (info.arm_section && info.arm_section_length) + return true; +#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) + HMODULE mods[1024]; + HANDLE process = GetCurrentProcess(); + DWORD needed; + + if (!EnumProcessModules(process, mods, sizeof(mods), &needed)) + return false; + + for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) { + PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i]; + PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew); + PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader; + PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh); + bool found_obj = false; + bool found_hdr = false; + + info.dso_base = (uintptr_t)mods[i]; + for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) { + uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i]; + uintptr_t end = begin + pish->Misc.VirtualSize; + if (!strncmp((const char *)pish->Name, ".text", + IMAGE_SIZEOF_SHORT_NAME)) { + if (targetAddr >= begin && targetAddr < end) + found_obj = true; + } else if (!strncmp((const char *)pish->Name, ".eh_frame", + IMAGE_SIZEOF_SHORT_NAME)) { + info.dwarf_section = begin; + info.dwarf_section_length = pish->Misc.VirtualSize; + found_hdr = true; + } + if (found_obj && found_hdr) + return true; + } + } + return false; +#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) && \ + (__ANDROID_API__ < 21) int length = 0; - info.arm_section = (uintptr_t) dl_unwind_find_exidx( - (_Unwind_Ptr) targetAddr, &length); + info.arm_section = + (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); info.arm_section_length = (uintptr_t)length; - #endif - _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x\n", - info.arm_section, info.arm_section_length); if (info.arm_section && info.arm_section_length) return true; -#elif _LIBUNWIND_SUPPORT_DWARF_UNWIND -#if _LIBUNWIND_SUPPORT_DWARF_INDEX +#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) struct dl_iterate_cb_data { LocalAddressSpace *addressSpace; UnwindInfoSections *sects; @@ -394,7 +460,6 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, int found = dl_iterate_phdr( [](struct dl_phdr_info *pinfo, size_t, void *data) -> int { auto cbdata = static_cast<dl_iterate_cb_data *>(data); - size_t object_length; bool found_obj = false; bool found_hdr = false; @@ -411,11 +476,32 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, #if !defined(Elf_Phdr) typedef ElfW(Phdr) Elf_Phdr; #endif +#if !defined(Elf_Addr) && defined(__ANDROID__) + typedef ElfW(Addr) Elf_Addr; +#endif + + #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." + #endif + size_t object_length; +#if defined(__ANDROID__) + Elf_Addr image_base = + pinfo->dlpi_phnum + ? reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) - + reinterpret_cast<const Elf_Phdr *>(pinfo->dlpi_phdr) + ->p_offset + : 0; +#endif for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; if (phdr->p_type == PT_LOAD) { uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; +#if defined(__ANDROID__) + if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base) + begin = begin + image_base; +#endif uintptr_t end = begin + phdr->p_memsz; if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { cbdata->sects->dso_base = begin; @@ -425,6 +511,10 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, } else if (phdr->p_type == PT_GNU_EH_FRAME) { EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr; +#if defined(__ANDROID__) + if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base) + eh_frame_hdr_start = eh_frame_hdr_start + image_base; +#endif cbdata->sects->dwarf_index_section = eh_frame_hdr_start; cbdata->sects->dwarf_index_section_length = phdr->p_memsz; EHHeaderParser<LocalAddressSpace>::decodeEHHdr( @@ -441,12 +531,26 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, } else { return false; } + #else // defined(_LIBUNWIND_ARM_EHABI) + for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { + const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; + if (phdr->p_type == PT_LOAD) { + uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; + uintptr_t end = begin + phdr->p_memsz; + if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) + found_obj = true; + } else if (phdr->p_type == PT_ARM_EXIDX) { + uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr; + cbdata->sects->arm_section = exidx_start; + cbdata->sects->arm_section_length = phdr->p_memsz; + found_hdr = true; + } + } + return found_obj && found_hdr; + #endif }, &cb_data); return static_cast<bool>(found); -#else -#error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." -#endif #endif return false; @@ -467,7 +571,7 @@ inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, size_t bufLen, unw_word_t *offset) { -#ifndef _LIBUNWIND_IS_BAREMETAL +#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) Dl_info dyldInfo; if (dladdr((void *)addr, &dyldInfo)) { if (dyldInfo.dli_sname != NULL) { @@ -484,14 +588,14 @@ inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, #ifdef UNW_REMOTE -/// OtherAddressSpace is used as a template parameter to UnwindCursor when +/// RemoteAddressSpace is used as a template parameter to UnwindCursor when /// unwinding a thread in the another process. The other process can be a /// different endianness and a different pointer size which is handled by /// the P template parameter. template <typename P> -class OtherAddressSpace { +class RemoteAddressSpace { public: - OtherAddressSpace(task_t task) : fTask(task) {} + RemoteAddressSpace(task_t task) : fTask(task) {} typedef typename P::uint_t pint_t; @@ -514,29 +618,29 @@ private: task_t fTask; }; -template <typename P> uint8_t OtherAddressSpace<P>::get8(pint_t addr) { +template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) { return *((uint8_t *)localCopy(addr)); } -template <typename P> uint16_t OtherAddressSpace<P>::get16(pint_t addr) { +template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) { return P::E::get16(*(uint16_t *)localCopy(addr)); } -template <typename P> uint32_t OtherAddressSpace<P>::get32(pint_t addr) { +template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) { return P::E::get32(*(uint32_t *)localCopy(addr)); } -template <typename P> uint64_t OtherAddressSpace<P>::get64(pint_t addr) { +template <typename P> uint64_t RemoteAddressSpace<P>::get64(pint_t addr) { return P::E::get64(*(uint64_t *)localCopy(addr)); } template <typename P> -typename P::uint_t OtherAddressSpace<P>::getP(pint_t addr) { +typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) { return P::getP(*(uint64_t *)localCopy(addr)); } template <typename P> -uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) { +uint64_t RemoteAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) { uintptr_t size = (end - addr); LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); LocalAddressSpace::pint_t sladdr = laddr; @@ -546,7 +650,7 @@ uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) { } template <typename P> -int64_t OtherAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) { +int64_t RemoteAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) { uintptr_t size = (end - addr); LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); LocalAddressSpace::pint_t sladdr = laddr; @@ -555,13 +659,14 @@ int64_t OtherAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) { return result; } -template <typename P> void *OtherAddressSpace<P>::localCopy(pint_t addr) { +template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) { // FIX ME } template <typename P> -bool OtherAddressSpace<P>::findFunctionName(pint_t addr, char *buf, - size_t bufLen, unw_word_t *offset) { +bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf, + size_t bufLen, + unw_word_t *offset) { // FIX ME } @@ -577,7 +682,7 @@ struct unw_addr_space { /// a 32-bit intel process. struct unw_addr_space_i386 : public unw_addr_space { unw_addr_space_i386(task_t task) : oas(task) {} - OtherAddressSpace<Pointer32<LittleEndian> > oas; + RemoteAddressSpace<Pointer32<LittleEndian>> oas; }; /// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t @@ -585,7 +690,7 @@ struct unw_addr_space_i386 : public unw_addr_space { /// a 64-bit intel process. struct unw_addr_space_x86_64 : public unw_addr_space { unw_addr_space_x86_64(task_t task) : oas(task) {} - OtherAddressSpace<Pointer64<LittleEndian> > oas; + RemoteAddressSpace<Pointer64<LittleEndian>> oas; }; /// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points @@ -593,7 +698,14 @@ struct unw_addr_space_x86_64 : public unw_addr_space { /// a 32-bit PowerPC process. struct unw_addr_space_ppc : public unw_addr_space { unw_addr_space_ppc(task_t task) : oas(task) {} - OtherAddressSpace<Pointer32<BigEndian> > oas; + RemoteAddressSpace<Pointer32<BigEndian>> oas; +}; + +/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points +/// to when examining a 64-bit PowerPC process. +struct unw_addr_space_ppc64 : public unw_addr_space { + unw_addr_space_ppc64(task_t task) : oas(task) {} + RemoteAddressSpace<Pointer64<LittleEndian>> oas; }; #endif // UNW_REMOTE diff --git a/lib/libunwind/src/DwarfInstructions.hpp b/lib/libunwind/src/DwarfInstructions.hpp index 7fa62cd7bba..eff054e7a06 100644 --- a/lib/libunwind/src/DwarfInstructions.hpp +++ b/lib/libunwind/src/DwarfInstructions.hpp @@ -6,7 +6,7 @@ // Source Licenses. See LICENSE.TXT for details. // // -// Processor specific interpretation of dwarf unwind info. +// Processor specific interpretation of DWARF unwind info. // //===----------------------------------------------------------------------===// @@ -18,7 +18,6 @@ #include <stdlib.h> #include "dwarf2.h" -#include "AddressSpace.hpp" #include "Registers.hpp" #include "DwarfParser.hpp" #include "config.h" @@ -27,7 +26,7 @@ namespace libunwind { -/// DwarfInstructions maps abtract dwarf unwind instructions to a particular +/// DwarfInstructions maps abtract DWARF unwind instructions to a particular /// architecture template <typename A, typename R> class DwarfInstructions { @@ -87,7 +86,7 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister( case CFI_Parser<A>::kRegisterInCFADecrypt: return addressSpace.getP( - cfa + (pint_t)savedReg.value) ^ registers.getWCookie(); + cfa + (pint_t)savedReg.value) ^ registers.getWCookie(); case CFI_Parser<A>::kRegisterAtExpression: return addressSpace.getP( @@ -170,11 +169,11 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, // get pointer to cfa (architecture specific) pint_t cfa = getCFA(addressSpace, prolog, registers); - // restore registers that dwarf says were saved + // restore registers that DWARF says were saved R newRegisters = registers; pint_t returnAddress = 0; const int lastReg = R::lastDwarfRegNum(); - assert((int)CFI_Parser<A>::kMaxRegisterNumber > lastReg && + assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg && "register range too large"); assert(lastReg >= (int)cieInfo.returnAddressRegister && "register range does not contain return address register"); @@ -486,7 +485,7 @@ DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace, case DW_OP_plus_uconst: // pop stack, add uelb128 constant, push result - *sp += addressSpace.getULEB128(p, expressionEnd); + *sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd)); if (log) fprintf(stderr, "add constant\n"); break; @@ -750,7 +749,7 @@ DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace, case DW_OP_call4: case DW_OP_call_ref: default: - _LIBUNWIND_ABORT("dwarf opcode not implemented"); + _LIBUNWIND_ABORT("DWARF opcode not implemented"); } } diff --git a/lib/libunwind/src/DwarfParser.hpp b/lib/libunwind/src/DwarfParser.hpp index 2f8c2c6d1f9..1911f164d57 100644 --- a/lib/libunwind/src/DwarfParser.hpp +++ b/lib/libunwind/src/DwarfParser.hpp @@ -21,12 +21,12 @@ #include "libunwind.h" #include "dwarf2.h" -#include "AddressSpace.hpp" +#include "config.h" namespace libunwind { /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records. -/// See Dwarf Spec for details: +/// See DWARF Spec for details: /// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html /// template <typename A> @@ -78,7 +78,7 @@ public: int64_t value; }; /// Information about a frame layout and registers saved determined - /// by "running" the dwarf FDE "instructions" + /// by "running" the DWARF FDE "instructions" struct PrologInfo { uint32_t cfaRegister; int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset @@ -87,7 +87,7 @@ public: uint32_t codeOffsetAtStackDecrement; bool registersInOtherRegisters; bool sameValueUsed; - RegisterLocation savedRegisters[kMaxRegisterNumber]; + RegisterLocation savedRegisters[kMaxRegisterNumber + 1]; }; struct PrologInfoStackEntry { @@ -139,23 +139,23 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, if (err != NULL) return err; p += 4; - // parse pc begin and range + // Parse pc begin and range. pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding); pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F); - // parse rest of info + // Parse rest of info. fdeInfo->lsda = 0; - // check for augmentation length + // Check for augmentation length. if (cieInfo->fdesHaveAugmentationData) { pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI); pint_t endOfAug = p + augLen; if (cieInfo->lsdaEncoding != DW_EH_PE_omit) { - // peek at value (without indirection). Zero means no lsda + // Peek at value (without indirection). Zero means no LSDA. pint_t lsdaStart = p; if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) { - // reset pointer and re-parse lsda address + // Reset pointer and re-parse LSDA address. p = lsdaStart; fdeInfo->lsda = addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding); @@ -193,23 +193,23 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, return false; // end marker uint32_t id = addressSpace.get32(p); if (id == 0) { - // skip over CIEs + // Skip over CIEs. p += cfiLength; } else { - // process FDE to see if it covers pc + // Process FDE to see if it covers pc. pint_t nextCFI = p + cfiLength; uint32_t ciePointer = addressSpace.get32(p); pint_t cieStart = p - ciePointer; - // validate pointer to CIE is within section + // Validate pointer to CIE is within section. if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) { if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) { p += 4; - // parse pc begin and range + // Parse pc begin and range. pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding); pint_t pcRange = addressSpace.getEncodedP( p, nextCFI, cieInfo->pointerEncoding & 0x0F); - // test if pc is within the function this FDE covers + // Test if pc is within the function this FDE covers. if ((pcStart < pc) && (pc <= pcStart + pcRange)) { // parse rest of info fdeInfo->lsda = 0; @@ -218,11 +218,11 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI); pint_t endOfAug = p + augLen; if (cieInfo->lsdaEncoding != DW_EH_PE_omit) { - // peek at value (without indirection). Zero means no lsda + // Peek at value (without indirection). Zero means no LSDA. pint_t lsdaStart = p; if (addressSpace.getEncodedP( p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) { - // reset pointer and re-parse lsda address + // Reset pointer and re-parse LSDA address. p = lsdaStart; fdeInfo->lsda = addressSpace .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding); @@ -240,7 +240,7 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, // pc is not in begin/range, skip this FDE } } else { - // malformed CIE, now augmentation describing pc range encoding + // Malformed CIE, now augmentation describing pc range encoding. } } else { // malformed FDE. CIE is bad @@ -339,7 +339,7 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, } -/// "run" the dwarf instructions and create the abstact PrologInfo for an FDE +/// "run" the DWARF instructions and create the abstact PrologInfo for an FDE template <typename A> bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, @@ -358,22 +358,21 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, upToPC - fdeInfo.pcStart, rememberStack, results); } -/// "run" the dwarf instructions +/// "run" the DWARF instructions template <typename A> bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, pint_t instructionsEnd, const CIE_Info &cieInfo, pint_t pcoffset, PrologInfoStackEntry *&rememberStack, PrologInfo *results) { - const bool logDwarf = false; pint_t p = instructions; pint_t codeOffset = 0; PrologInfo initialState = *results; - if (logDwarf) - fprintf(stderr, "parseInstructions(instructions=0x%0" PRIx64 ")\n", - (uint64_t)instructionsEnd); - // see Dwarf Spec, section 6.4.2 for details on unwind opcodes + _LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n", + static_cast<uint64_t>(instructionsEnd)); + + // see DWARF Spec, section 6.4.2 for details on unwind opcodes while ((p < instructionsEnd) && (codeOffset < pcoffset)) { uint64_t reg; uint64_t reg2; @@ -387,81 +386,71 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, ++p; switch (opcode) { case DW_CFA_nop: - if (logDwarf) - fprintf(stderr, "DW_CFA_nop\n"); + _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n"); break; case DW_CFA_set_loc: codeOffset = addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding); - if (logDwarf) - fprintf(stderr, "DW_CFA_set_loc\n"); + _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n"); break; case DW_CFA_advance_loc1: codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor); p += 1; - if (logDwarf) - fprintf(stderr, "DW_CFA_advance_loc1: new offset=%" PRIu64 "\n", - (uint64_t)codeOffset); + _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n", + static_cast<uint64_t>(codeOffset)); break; case DW_CFA_advance_loc2: codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor); p += 2; - if (logDwarf) - fprintf(stderr, "DW_CFA_advance_loc2: new offset=%" PRIu64 "\n", - (uint64_t)codeOffset); + _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n", + static_cast<uint64_t>(codeOffset)); break; case DW_CFA_advance_loc4: codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor); p += 4; - if (logDwarf) - fprintf(stderr, "DW_CFA_advance_loc4: new offset=%" PRIu64 "\n", - (uint64_t)codeOffset); + _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n", + static_cast<uint64_t>(codeOffset)); break; case DW_CFA_offset_extended: reg = addressSpace.getULEB128(p, instructionsEnd); offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_offset_extended dwarf unwind, reg too big\n"); + _LIBUNWIND_LOG0( + "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); return false; } results->savedRegisters[reg].location = kRegisterInCFA; results->savedRegisters[reg].value = offset; - if (logDwarf) - fprintf(stderr, - "DW_CFA_offset_extended(reg=%" PRIu64 ", offset=%" PRId64 ")\n", - reg, offset); + _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", " + "offset=%" PRId64 ")\n", + reg, offset); break; case DW_CFA_restore_extended: reg = addressSpace.getULEB128(p, instructionsEnd); - ; if (reg > kMaxRegisterNumber) { - fprintf( - stderr, - "malformed DW_CFA_restore_extended dwarf unwind, reg too big\n"); + _LIBUNWIND_LOG0( + "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); return false; } results->savedRegisters[reg] = initialState.savedRegisters[reg]; - if (logDwarf) - fprintf(stderr, "DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg); + _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg); break; case DW_CFA_undefined: reg = addressSpace.getULEB128(p, instructionsEnd); if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_undefined dwarf unwind, reg too big\n"); + _LIBUNWIND_LOG0( + "malformed DW_CFA_undefined DWARF unwind, reg too big"); return false; } results->savedRegisters[reg].location = kRegisterUnused; - if (logDwarf) - fprintf(stderr, "DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); + _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); break; case DW_CFA_same_value: reg = addressSpace.getULEB128(p, instructionsEnd); if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_same_value dwarf unwind, reg too big\n"); + _LIBUNWIND_LOG0( + "malformed DW_CFA_same_value DWARF unwind, reg too big"); return false; } // <rdar://problem/8456377> DW_CFA_same_value unsupported @@ -471,29 +460,27 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, results->savedRegisters[reg].location = kRegisterUnused; // set flag to disable conversion to compact unwind results->sameValueUsed = true; - if (logDwarf) - fprintf(stderr, "DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); + _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); break; case DW_CFA_register: reg = addressSpace.getULEB128(p, instructionsEnd); reg2 = addressSpace.getULEB128(p, instructionsEnd); if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_register dwarf unwind, reg too big\n"); + _LIBUNWIND_LOG0( + "malformed DW_CFA_register DWARF unwind, reg too big"); return false; } if (reg2 > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_register dwarf unwind, reg2 too big\n"); + _LIBUNWIND_LOG0( + "malformed DW_CFA_register DWARF unwind, reg2 too big"); return false; } results->savedRegisters[reg].location = kRegisterInRegister; results->savedRegisters[reg].value = (int64_t)reg2; // set flag to disable conversion to compact unwind results->registersInOtherRegisters = true; - if (logDwarf) - fprintf(stderr, "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", - reg, reg2); + _LIBUNWIND_TRACE_DWARF( + "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2); break; #if !defined(_LIBUNWIND_NO_HEAP) case DW_CFA_remember_state: @@ -506,8 +493,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, } else { return false; } - if (logDwarf) - fprintf(stderr, "DW_CFA_remember_state\n"); + _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n"); break; case DW_CFA_restore_state: if (rememberStack != NULL) { @@ -518,214 +504,217 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, } else { return false; } - if (logDwarf) - fprintf(stderr, "DW_CFA_restore_state\n"); + _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n"); break; #endif case DW_CFA_def_cfa: reg = addressSpace.getULEB128(p, instructionsEnd); offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd); if (reg > kMaxRegisterNumber) { - fprintf(stderr, "malformed DW_CFA_def_cfa dwarf unwind, reg too big\n"); + _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big"); return false; } results->cfaRegister = (uint32_t)reg; results->cfaRegisterOffset = (int32_t)offset; - if (logDwarf) - fprintf(stderr, "DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n", - reg, offset); + _LIBUNWIND_TRACE_DWARF( + "DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n", reg, offset); break; case DW_CFA_def_cfa_register: reg = addressSpace.getULEB128(p, instructionsEnd); if (reg > kMaxRegisterNumber) { - fprintf( - stderr, - "malformed DW_CFA_def_cfa_register dwarf unwind, reg too big\n"); + _LIBUNWIND_LOG0( + "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big"); return false; } results->cfaRegister = (uint32_t)reg; - if (logDwarf) - fprintf(stderr, "DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg); + _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg); break; case DW_CFA_def_cfa_offset: results->cfaRegisterOffset = (int32_t) addressSpace.getULEB128(p, instructionsEnd); results->codeOffsetAtStackDecrement = (uint32_t)codeOffset; - if (logDwarf) - fprintf(stderr, "DW_CFA_def_cfa_offset(%d)\n", - results->cfaRegisterOffset); + _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n", + results->cfaRegisterOffset); break; case DW_CFA_def_cfa_expression: results->cfaRegister = 0; results->cfaExpression = (int64_t)p; length = addressSpace.getULEB128(p, instructionsEnd); - p += length; - if (logDwarf) - fprintf(stderr, "DW_CFA_def_cfa_expression(expression=0x%" PRIx64 - ", length=%" PRIu64 ")\n", - results->cfaExpression, length); + assert(length < static_cast<pint_t>(~0) && "pointer overflow"); + p += static_cast<pint_t>(length); + _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64 + ", length=%" PRIu64 ")\n", + results->cfaExpression, length); break; case DW_CFA_expression: reg = addressSpace.getULEB128(p, instructionsEnd); if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_expression dwarf unwind, reg too big\n"); + _LIBUNWIND_LOG0( + "malformed DW_CFA_expression DWARF unwind, reg too big"); return false; } results->savedRegisters[reg].location = kRegisterAtExpression; results->savedRegisters[reg].value = (int64_t)p; length = addressSpace.getULEB128(p, instructionsEnd); - p += length; - if (logDwarf) - fprintf(stderr, "DW_CFA_expression(reg=%" PRIu64 - ", expression=0x%" PRIx64 ", length=%" PRIu64 ")\n", - reg, results->savedRegisters[reg].value, length); + assert(length < static_cast<pint_t>(~0) && "pointer overflow"); + p += static_cast<pint_t>(length); + _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", " + "expression=0x%" PRIx64 ", " + "length=%" PRIu64 ")\n", + reg, results->savedRegisters[reg].value, length); break; case DW_CFA_offset_extended_sf: reg = addressSpace.getULEB128(p, instructionsEnd); if (reg > kMaxRegisterNumber) { - fprintf( - stderr, - "malformed DW_CFA_offset_extended_sf dwarf unwind, reg too big\n"); + _LIBUNWIND_LOG0( + "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big"); return false; } offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; results->savedRegisters[reg].location = kRegisterInCFA; results->savedRegisters[reg].value = offset; - if (logDwarf) - fprintf(stderr, "DW_CFA_offset_extended_sf(reg=%" PRIu64 - ", offset=%" PRId64 ")\n", - reg, offset); + _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", " + "offset=%" PRId64 ")\n", + reg, offset); break; case DW_CFA_def_cfa_sf: reg = addressSpace.getULEB128(p, instructionsEnd); offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_def_cfa_sf dwarf unwind, reg too big\n"); + _LIBUNWIND_LOG0( + "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big"); return false; } results->cfaRegister = (uint32_t)reg; results->cfaRegisterOffset = (int32_t)offset; - if (logDwarf) - fprintf(stderr, - "DW_CFA_def_cfa_sf(reg=%" PRIu64 ", offset=%" PRId64 ")\n", reg, - offset); + _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", " + "offset=%" PRId64 ")\n", + reg, offset); break; case DW_CFA_def_cfa_offset_sf: results->cfaRegisterOffset = (int32_t) (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor); results->codeOffsetAtStackDecrement = (uint32_t)codeOffset; - if (logDwarf) - fprintf(stderr, "DW_CFA_def_cfa_offset_sf(%d)\n", - results->cfaRegisterOffset); + _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n", + results->cfaRegisterOffset); break; case DW_CFA_val_offset: reg = addressSpace.getULEB128(p, instructionsEnd); + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG( + "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64 + ") out of range\n", + reg); + return false; + } offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; results->savedRegisters[reg].location = kRegisterOffsetFromCFA; results->savedRegisters[reg].value = offset; - if (logDwarf) - fprintf(stderr, - "DW_CFA_val_offset(reg=%" PRIu64 ", offset=%" PRId64 "\n", reg, - offset); + _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", " + "offset=%" PRId64 "\n", + reg, offset); break; case DW_CFA_val_offset_sf: reg = addressSpace.getULEB128(p, instructionsEnd); if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_val_offset_sf dwarf unwind, reg too big\n"); + _LIBUNWIND_LOG0( + "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big"); return false; } offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; results->savedRegisters[reg].location = kRegisterOffsetFromCFA; results->savedRegisters[reg].value = offset; - if (logDwarf) - fprintf(stderr, - "DW_CFA_val_offset_sf(reg=%" PRIu64 ", offset=%" PRId64 "\n", - reg, offset); + _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", " + "offset=%" PRId64 "\n", + reg, offset); break; case DW_CFA_val_expression: reg = addressSpace.getULEB128(p, instructionsEnd); if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_val_expression dwarf unwind, reg too big\n"); + _LIBUNWIND_LOG0( + "malformed DW_CFA_val_expression DWARF unwind, reg too big"); return false; } results->savedRegisters[reg].location = kRegisterIsExpression; results->savedRegisters[reg].value = (int64_t)p; length = addressSpace.getULEB128(p, instructionsEnd); - p += length; - if (logDwarf) - fprintf(stderr, "DW_CFA_val_expression(reg=%" PRIu64 - ", expression=0x%" PRIx64 ", length=%" PRIu64 ")\n", - reg, results->savedRegisters[reg].value, length); + assert(length < static_cast<pint_t>(~0) && "pointer overflow"); + p += static_cast<pint_t>(length); + _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", " + "expression=0x%" PRIx64 ", length=%" PRIu64 ")\n", + reg, results->savedRegisters[reg].value, length); break; case DW_CFA_GNU_window_save: // Hardcodes windowed registers for SPARC for (reg = 16; reg < 32; reg++) { - if (reg == 31) - results->savedRegisters[reg].location = kRegisterInCFADecrypt; - else - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = (reg - 16) * sizeof(pint_t); + if (reg == 31) + results->savedRegisters[reg].location = kRegisterInCFADecrypt; + else + results->savedRegisters[reg].location = kRegisterInCFA; + results->savedRegisters[reg].value = (reg - 16) * sizeof(pint_t); } - if (logDwarf) - fprintf(stderr, "DW_CGA_GNU_window_save\n"); + _LIBUNWIND_LOG0("DW_CGA_GNU_window_save"); break; case DW_CFA_GNU_args_size: length = addressSpace.getULEB128(p, instructionsEnd); results->spExtraArgSize = (uint32_t)length; - if (logDwarf) - fprintf(stderr, "DW_CFA_GNU_args_size(%" PRIu64 ")\n", length); + _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length); break; case DW_CFA_GNU_negative_offset_extended: reg = addressSpace.getULEB128(p, instructionsEnd); if (reg > kMaxRegisterNumber) { - fprintf(stderr, "malformed DW_CFA_GNU_negative_offset_extended dwarf " - "unwind, reg too big\n"); + _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF " + "unwind, reg too big"); return false; } offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; results->savedRegisters[reg].location = kRegisterInCFA; results->savedRegisters[reg].value = -offset; - if (logDwarf) - fprintf(stderr, "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", - offset); + _LIBUNWIND_TRACE_DWARF( + "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); break; default: operand = opcode & 0x3F; switch (opcode & 0xC0) { case DW_CFA_offset: reg = operand; + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64 + ") out of range", + reg); + return false; + } offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; results->savedRegisters[reg].location = kRegisterInCFA; results->savedRegisters[reg].value = offset; - if (logDwarf) - fprintf(stderr, "DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", - operand, offset); + _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", + operand, offset); break; case DW_CFA_advance_loc: codeOffset += operand * cieInfo.codeAlignFactor; - if (logDwarf) - fprintf(stderr, "DW_CFA_advance_loc: new offset=%" PRIu64 "\n", - (uint64_t)codeOffset); + _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n", + static_cast<uint64_t>(codeOffset)); break; case DW_CFA_restore: reg = operand; + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG("malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64 + ") out of range", + reg); + return false; + } results->savedRegisters[reg] = initialState.savedRegisters[reg]; - if (logDwarf) - fprintf(stderr, "DW_CFA_restore(reg=%" PRIu64 ")\n", reg); + _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n", + static_cast<uint64_t>(operand)); break; default: - if (logDwarf) - fprintf(stderr, "unknown CFA opcode 0x%02X\n", opcode); + _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode); return false; } } diff --git a/lib/libunwind/src/EHHeaderParser.hpp b/lib/libunwind/src/EHHeaderParser.hpp index 1bf6bb313b0..d6f4e1259a6 100644 --- a/lib/libunwind/src/EHHeaderParser.hpp +++ b/lib/libunwind/src/EHHeaderParser.hpp @@ -15,7 +15,6 @@ #include "libunwind.h" -#include "AddressSpace.hpp" #include "DwarfParser.hpp" namespace libunwind { @@ -68,7 +67,9 @@ void EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart, ehHdrInfo.eh_frame_ptr = addressSpace.getEncodedP(p, ehHdrEnd, eh_frame_ptr_enc, ehHdrStart); ehHdrInfo.fde_count = - addressSpace.getEncodedP(p, ehHdrEnd, fde_count_enc, ehHdrStart); + fde_count_enc == DW_EH_PE_omit + ? 0 + : addressSpace.getEncodedP(p, ehHdrEnd, fde_count_enc, ehHdrStart); ehHdrInfo.table = p; } @@ -85,7 +86,7 @@ bool EHHeaderParser<A>::decodeTableEntry( const char *message = CFI_Parser<A>::decodeFDE(addressSpace, fde, fdeInfo, cieInfo); if (message != NULL) { - _LIBUNWIND_DEBUG_LOG("EHHeaderParser::decodeTableEntry: bad fde: %s\n", + _LIBUNWIND_DEBUG_LOG("EHHeaderParser::decodeTableEntry: bad fde: %s", message); return false; } diff --git a/lib/libunwind/src/Registers.hpp b/lib/libunwind/src/Registers.hpp index 1a98d929e10..888d07be5b2 100644 --- a/lib/libunwind/src/Registers.hpp +++ b/lib/libunwind/src/Registers.hpp @@ -44,7 +44,7 @@ public: void setVectorRegister(int num, v128 value); const char *getRegisterName(int num); void jumpto(); - static int lastDwarfRegNum() { return 8; } + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; } uint32_t getSP() const { return _registers.__esp; } void setSP(uint32_t value) { _registers.__esp = value; } @@ -123,9 +123,17 @@ inline uint32_t Registers_x86::getRegister(int regNum) const { return _registers.__edx; case UNW_X86_EBX: return _registers.__ebx; +#if !defined(__APPLE__) + case UNW_X86_ESP: +#else case UNW_X86_EBP: +#endif return _registers.__ebp; +#if !defined(__APPLE__) + case UNW_X86_EBP: +#else case UNW_X86_ESP: +#endif return _registers.__esp; case UNW_X86_ESI: return _registers.__esi; @@ -155,10 +163,18 @@ inline void Registers_x86::setRegister(int regNum, uint32_t value) { case UNW_X86_EBX: _registers.__ebx = value; return; +#if !defined(__APPLE__) + case UNW_X86_ESP: +#else case UNW_X86_EBP: +#endif _registers.__ebp = value; return; +#if !defined(__APPLE__) + case UNW_X86_EBP: +#else case UNW_X86_ESP: +#endif _registers.__esp = value; return; case UNW_X86_ESI: @@ -230,12 +246,12 @@ public: bool validFloatRegister(int) const { return false; } double getFloatRegister(int num) const; void setFloatRegister(int num, double value); - bool validVectorRegister(int) const { return false; } + bool validVectorRegister(int) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); const char *getRegisterName(int num); void jumpto(); - static int lastDwarfRegNum() { return 16; } + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; } uint64_t getSP() const { return _registers.__rsp; } void setSP(uint64_t value) { _registers.__rsp = value; } @@ -278,8 +294,14 @@ private: uint64_t __cs; uint64_t __fs; uint64_t __gs; +#if defined(_WIN64) + uint64_t __padding; // 16-byte align +#endif }; GPRs _registers; +#if defined(_WIN64) + v128 _xmm[16]; +#endif }; inline Registers_x86_64::Registers_x86_64(const void *registers) { @@ -444,6 +466,38 @@ inline const char *Registers_x86_64::getRegisterName(int regNum) { return "r14"; case UNW_X86_64_R15: return "r15"; + case UNW_X86_64_XMM0: + return "xmm0"; + case UNW_X86_64_XMM1: + return "xmm1"; + case UNW_X86_64_XMM2: + return "xmm2"; + case UNW_X86_64_XMM3: + return "xmm3"; + case UNW_X86_64_XMM4: + return "xmm4"; + case UNW_X86_64_XMM5: + return "xmm5"; + case UNW_X86_64_XMM6: + return "xmm6"; + case UNW_X86_64_XMM7: + return "xmm7"; + case UNW_X86_64_XMM8: + return "xmm8"; + case UNW_X86_64_XMM9: + return "xmm9"; + case UNW_X86_64_XMM10: + return "xmm10"; + case UNW_X86_64_XMM11: + return "xmm11"; + case UNW_X86_64_XMM12: + return "xmm12"; + case UNW_X86_64_XMM13: + return "xmm13"; + case UNW_X86_64_XMM14: + return "xmm14"; + case UNW_X86_64_XMM15: + return "xmm15"; default: return "unknown register"; } @@ -457,12 +511,34 @@ inline void Registers_x86_64::setFloatRegister(int, double) { _LIBUNWIND_ABORT("no x86_64 float registers"); } -inline v128 Registers_x86_64::getVectorRegister(int) const { +inline bool Registers_x86_64::validVectorRegister(int regNum) const { +#if defined(_WIN64) + if (regNum < UNW_X86_64_XMM0) + return false; + if (regNum > UNW_X86_64_XMM15) + return false; + return true; +#else + return false; +#endif +} + +inline v128 Registers_x86_64::getVectorRegister(int regNum) const { +#if defined(_WIN64) + assert(validVectorRegister(regNum)); + return _xmm[regNum - UNW_X86_64_XMM0]; +#else _LIBUNWIND_ABORT("no x86_64 vector registers"); +#endif } -inline void Registers_x86_64::setVectorRegister(int, v128) { +inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) { +#if defined(_WIN64) + assert(validVectorRegister(regNum)); + _xmm[regNum - UNW_X86_64_XMM0] = value; +#else _LIBUNWIND_ABORT("no x86_64 vector registers"); +#endif } #endif // _LIBUNWIND_TARGET_X86_64 @@ -486,7 +562,7 @@ public: void setVectorRegister(int num, v128 value); const char *getRegisterName(int num); void jumpto(); - static int lastDwarfRegNum() { return 112; } + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; } uint64_t getSP() const { return _registers.__r1; } void setSP(uint32_t value) { _registers.__r1 = value; } @@ -1033,6 +1109,583 @@ inline const char *Registers_ppc::getRegisterName(int regNum) { } #endif // _LIBUNWIND_TARGET_PPC +#if defined(_LIBUNWIND_TARGET_PPC64) +/// Registers_ppc holds the register state of a thread in a 64-bit PowerPC +/// process. +class _LIBUNWIND_HIDDEN Registers_ppc64 { +public: + Registers_ppc64(); + Registers_ppc64(const void *registers); + + bool validRegister(int num) const; + uint64_t getRegister(int num) const; + void setRegister(int num, uint64_t value); + bool validFloatRegister(int num) const; + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int num) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; } + + uint64_t getSP() const { return _registers.__r1; } + void setSP(uint64_t value) { _registers.__r1 = value; } + uint64_t getIP() const { return _registers.__srr0; } + void setIP(uint64_t value) { _registers.__srr0 = value; } + +private: + struct ppc64_thread_state_t { + uint64_t __srr0; /* Instruction address register (PC) */ + uint64_t __srr1; /* Machine state register (supervisor) */ + uint64_t __r0; + uint64_t __r1; + uint64_t __r2; + uint64_t __r3; + uint64_t __r4; + uint64_t __r5; + uint64_t __r6; + uint64_t __r7; + uint64_t __r8; + uint64_t __r9; + uint64_t __r10; + uint64_t __r11; + uint64_t __r12; + uint64_t __r13; + uint64_t __r14; + uint64_t __r15; + uint64_t __r16; + uint64_t __r17; + uint64_t __r18; + uint64_t __r19; + uint64_t __r20; + uint64_t __r21; + uint64_t __r22; + uint64_t __r23; + uint64_t __r24; + uint64_t __r25; + uint64_t __r26; + uint64_t __r27; + uint64_t __r28; + uint64_t __r29; + uint64_t __r30; + uint64_t __r31; + uint64_t __cr; /* Condition register */ + uint64_t __xer; /* User's integer exception register */ + uint64_t __lr; /* Link register */ + uint64_t __ctr; /* Count register */ + uint64_t __vrsave; /* Vector Save Register */ + }; + + struct ppc64_float_state_t { + double __fpregs[32]; + uint64_t __fpscr; /* floating point status register */ + }; + + ppc64_thread_state_t _registers; + ppc64_float_state_t _floatRegisters; + v128 _vectorRegisters[32]; +}; + +inline Registers_ppc64::Registers_ppc64(const void *registers) { + static_assert((check_fit<Registers_ppc64, unw_context_t>::does_fit), + "ppc64 registers do not fit into unw_context_t"); + memcpy(&_registers, static_cast<const uint8_t *>(registers), + sizeof(_registers)); + static_assert(sizeof(ppc64_thread_state_t) == 312, + "expected float register offset to be 312"); + memcpy(&_floatRegisters, + static_cast<const uint8_t *>(registers) + sizeof(ppc64_thread_state_t), + sizeof(_floatRegisters)); + static_assert(sizeof(ppc64_thread_state_t) + sizeof(ppc64_float_state_t) == 576, + "expected vector register offset to be 576 bytes"); + memcpy(_vectorRegisters, + static_cast<const uint8_t *>(registers) + sizeof(ppc64_thread_state_t) + + sizeof(ppc64_float_state_t), + sizeof(_vectorRegisters)); +} + +inline Registers_ppc64::Registers_ppc64() { + memset(&_registers, 0, sizeof(_registers)); + memset(&_floatRegisters, 0, sizeof(_floatRegisters)); + memset(&_vectorRegisters, 0, sizeof(_vectorRegisters)); +} + +inline bool Registers_ppc64::validRegister(int regNum) const { + switch (regNum) { + case UNW_REG_IP: + case UNW_REG_SP: + case UNW_PPC64_VRSAVE: + case UNW_PPC64_LR: + case UNW_PPC64_CTR: + return true; + } + + if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31) + return true; + if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7) + return true; + + return false; +} + +inline uint64_t Registers_ppc64::getRegister(int regNum) const { + switch (regNum) { + case UNW_REG_IP: + return _registers.__srr0; + case UNW_REG_SP: + return _registers.__r1; + case UNW_PPC64_R0: + return _registers.__r0; + case UNW_PPC64_R1: + return _registers.__r1; + case UNW_PPC64_R2: + return _registers.__r2; + case UNW_PPC64_R3: + return _registers.__r3; + case UNW_PPC64_R4: + return _registers.__r4; + case UNW_PPC64_R5: + return _registers.__r5; + case UNW_PPC64_R6: + return _registers.__r6; + case UNW_PPC64_R7: + return _registers.__r7; + case UNW_PPC64_R8: + return _registers.__r8; + case UNW_PPC64_R9: + return _registers.__r9; + case UNW_PPC64_R10: + return _registers.__r10; + case UNW_PPC64_R11: + return _registers.__r11; + case UNW_PPC64_R12: + return _registers.__r12; + case UNW_PPC64_R13: + return _registers.__r13; + case UNW_PPC64_R14: + return _registers.__r14; + case UNW_PPC64_R15: + return _registers.__r15; + case UNW_PPC64_R16: + return _registers.__r16; + case UNW_PPC64_R17: + return _registers.__r17; + case UNW_PPC64_R18: + return _registers.__r18; + case UNW_PPC64_R19: + return _registers.__r19; + case UNW_PPC64_R20: + return _registers.__r20; + case UNW_PPC64_R21: + return _registers.__r21; + case UNW_PPC64_R22: + return _registers.__r22; + case UNW_PPC64_R23: + return _registers.__r23; + case UNW_PPC64_R24: + return _registers.__r24; + case UNW_PPC64_R25: + return _registers.__r25; + case UNW_PPC64_R26: + return _registers.__r26; + case UNW_PPC64_R27: + return _registers.__r27; + case UNW_PPC64_R28: + return _registers.__r28; + case UNW_PPC64_R29: + return _registers.__r29; + case UNW_PPC64_R30: + return _registers.__r30; + case UNW_PPC64_R31: + return _registers.__r31; + case UNW_PPC64_LR: + return _registers.__lr; + case UNW_PPC64_CTR: + return _registers.__ctr; + case UNW_PPC64_CR0: + return (_registers.__cr & 0xF0000000); + case UNW_PPC64_CR1: + return (_registers.__cr & 0x0F000000); + case UNW_PPC64_CR2: + return (_registers.__cr & 0x00F00000); + case UNW_PPC64_CR3: + return (_registers.__cr & 0x000F0000); + case UNW_PPC64_CR4: + return (_registers.__cr & 0x0000F000); + case UNW_PPC64_CR5: + return (_registers.__cr & 0x00000F00); + case UNW_PPC64_CR6: + return (_registers.__cr & 0x000000F0); + case UNW_PPC64_CR7: + return (_registers.__cr & 0x0000000F); + case UNW_PPC64_VRSAVE: + return _registers.__vrsave; + case UNW_PPC64_FPSCR: + return _floatRegisters.__fpscr; + } + _LIBUNWIND_ABORT("unsupported ppc64 register"); +} + +inline void Registers_ppc64::setRegister(int regNum, uint64_t value) { + switch (regNum) { + case UNW_REG_IP: + _registers.__srr0 = value; + return; + case UNW_REG_SP: + _registers.__r1 = value; + return; + case UNW_PPC64_R0: + _registers.__r0 = value; + return; + case UNW_PPC64_R1: + _registers.__r1 = value; + return; + case UNW_PPC64_R2: + _registers.__r2 = value; + return; + case UNW_PPC64_R3: + _registers.__r3 = value; + return; + case UNW_PPC64_R4: + _registers.__r4 = value; + return; + case UNW_PPC64_R5: + _registers.__r5 = value; + return; + case UNW_PPC64_R6: + _registers.__r6 = value; + return; + case UNW_PPC64_R7: + _registers.__r7 = value; + return; + case UNW_PPC64_R8: + _registers.__r8 = value; + return; + case UNW_PPC64_R9: + _registers.__r9 = value; + return; + case UNW_PPC64_R10: + _registers.__r10 = value; + return; + case UNW_PPC64_R11: + _registers.__r11 = value; + return; + case UNW_PPC64_R12: + _registers.__r12 = value; + return; + case UNW_PPC64_R13: + _registers.__r13 = value; + return; + case UNW_PPC64_R14: + _registers.__r14 = value; + return; + case UNW_PPC64_R15: + _registers.__r15 = value; + return; + case UNW_PPC64_R16: + _registers.__r16 = value; + return; + case UNW_PPC64_R17: + _registers.__r17 = value; + return; + case UNW_PPC64_R18: + _registers.__r18 = value; + return; + case UNW_PPC64_R19: + _registers.__r19 = value; + return; + case UNW_PPC64_R20: + _registers.__r20 = value; + return; + case UNW_PPC64_R21: + _registers.__r21 = value; + return; + case UNW_PPC64_R22: + _registers.__r22 = value; + return; + case UNW_PPC64_R23: + _registers.__r23 = value; + return; + case UNW_PPC64_R24: + _registers.__r24 = value; + return; + case UNW_PPC64_R25: + _registers.__r25 = value; + return; + case UNW_PPC64_R26: + _registers.__r26 = value; + return; + case UNW_PPC64_R27: + _registers.__r27 = value; + return; + case UNW_PPC64_R28: + _registers.__r28 = value; + return; + case UNW_PPC64_R29: + _registers.__r29 = value; + return; + case UNW_PPC64_R30: + _registers.__r30 = value; + return; + case UNW_PPC64_R31: + _registers.__r31 = value; + return; + case UNW_PPC64_LR: + _registers.__lr = value; + return; + case UNW_PPC64_CTR: + _registers.__ctr = value; + return; + case UNW_PPC64_CR0: + _registers.__cr &= 0x0FFFFFFF; + _registers.__cr |= (value & 0xF0000000); + return; + case UNW_PPC64_CR1: + _registers.__cr &= 0xF0FFFFFF; + _registers.__cr |= (value & 0x0F000000); + return; + case UNW_PPC64_CR2: + _registers.__cr &= 0xFF0FFFFF; + _registers.__cr |= (value & 0x00F00000); + return; + case UNW_PPC64_CR3: + _registers.__cr &= 0xFFF0FFFF; + _registers.__cr |= (value & 0x000F0000); + return; + case UNW_PPC64_CR4: + _registers.__cr &= 0xFFFF0FFF; + _registers.__cr |= (value & 0x0000F000); + return; + case UNW_PPC64_CR5: + _registers.__cr &= 0xFFFFF0FF; + _registers.__cr |= (value & 0x00000F00); + return; + case UNW_PPC64_CR6: + _registers.__cr &= 0xFFFFFF0F; + _registers.__cr |= (value & 0x000000F0); + return; + case UNW_PPC64_CR7: + _registers.__cr &= 0xFFFFFFF0; + _registers.__cr |= (value & 0x0000000F); + return; + case UNW_PPC64_VRSAVE: + _registers.__vrsave = value; + return; + case UNW_PPC64_XER: + _registers.__xer = value; + return; + case UNW_PPC64_VSCR: + // not saved + return; + } + _LIBUNWIND_ABORT("unsupported ppc64 register"); +} + +inline bool Registers_ppc64::validFloatRegister(int regNum) const { + if (regNum < UNW_PPC64_F0) + return false; + if (regNum > UNW_PPC64_F31) + return false; + return true; +} + +inline double Registers_ppc64::getFloatRegister(int regNum) const { + assert(validFloatRegister(regNum)); + return _floatRegisters.__fpregs[regNum - UNW_PPC64_F0]; +} + +inline void Registers_ppc64::setFloatRegister(int regNum, double value) { + assert(validFloatRegister(regNum)); + _floatRegisters.__fpregs[regNum - UNW_PPC64_F0] = value; +} + +inline bool Registers_ppc64::validVectorRegister(int regNum) const { + if (regNum < UNW_PPC64_V0) + return false; + if (regNum > UNW_PPC64_V31) + return false; + return true; +} + +inline v128 Registers_ppc64::getVectorRegister(int regNum) const { + assert(validVectorRegister(regNum)); + v128 result = _vectorRegisters[regNum - UNW_PPC64_V0]; + return result; +} + +inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) { + assert(validVectorRegister(regNum)); + _vectorRegisters[regNum - UNW_PPC64_V0] = value; +} + +inline const char *Registers_ppc64::getRegisterName(int regNum) { + switch (regNum) { + case UNW_REG_IP: + return "ip"; + case UNW_REG_SP: + return "sp"; + case UNW_PPC64_R0: + return "r0"; + case UNW_PPC64_R1: + return "r1"; + case UNW_PPC64_R2: + return "r2"; + case UNW_PPC64_R3: + return "r3"; + case UNW_PPC64_R4: + return "r4"; + case UNW_PPC64_R5: + return "r5"; + case UNW_PPC64_R6: + return "r6"; + case UNW_PPC64_R7: + return "r7"; + case UNW_PPC64_R8: + return "r8"; + case UNW_PPC64_R9: + return "r9"; + case UNW_PPC64_R10: + return "r10"; + case UNW_PPC64_R11: + return "r11"; + case UNW_PPC64_R12: + return "r12"; + case UNW_PPC64_R13: + return "r13"; + case UNW_PPC64_R14: + return "r14"; + case UNW_PPC64_R15: + return "r15"; + case UNW_PPC64_R16: + return "r16"; + case UNW_PPC64_R17: + return "r17"; + case UNW_PPC64_R18: + return "r18"; + case UNW_PPC64_R19: + return "r19"; + case UNW_PPC64_R20: + return "r20"; + case UNW_PPC64_R21: + return "r21"; + case UNW_PPC64_R22: + return "r22"; + case UNW_PPC64_R23: + return "r23"; + case UNW_PPC64_R24: + return "r24"; + case UNW_PPC64_R25: + return "r25"; + case UNW_PPC64_R26: + return "r26"; + case UNW_PPC64_R27: + return "r27"; + case UNW_PPC64_R28: + return "r28"; + case UNW_PPC64_R29: + return "r29"; + case UNW_PPC64_R30: + return "r30"; + case UNW_PPC64_R31: + return "r31"; + case UNW_PPC64_F0: + return "fp0"; + case UNW_PPC64_F1: + return "fp1"; + case UNW_PPC64_F2: + return "fp2"; + case UNW_PPC64_F3: + return "fp3"; + case UNW_PPC64_F4: + return "fp4"; + case UNW_PPC64_F5: + return "fp5"; + case UNW_PPC64_F6: + return "fp6"; + case UNW_PPC64_F7: + return "fp7"; + case UNW_PPC64_F8: + return "fp8"; + case UNW_PPC64_F9: + return "fp9"; + case UNW_PPC64_F10: + return "fp10"; + case UNW_PPC64_F11: + return "fp11"; + case UNW_PPC64_F12: + return "fp12"; + case UNW_PPC64_F13: + return "fp13"; + case UNW_PPC64_F14: + return "fp14"; + case UNW_PPC64_F15: + return "fp15"; + case UNW_PPC64_F16: + return "fp16"; + case UNW_PPC64_F17: + return "fp17"; + case UNW_PPC64_F18: + return "fp18"; + case UNW_PPC64_F19: + return "fp19"; + case UNW_PPC64_F20: + return "fp20"; + case UNW_PPC64_F21: + return "fp21"; + case UNW_PPC64_F22: + return "fp22"; + case UNW_PPC64_F23: + return "fp23"; + case UNW_PPC64_F24: + return "fp24"; + case UNW_PPC64_F25: + return "fp25"; + case UNW_PPC64_F26: + return "fp26"; + case UNW_PPC64_F27: + return "fp27"; + case UNW_PPC64_F28: + return "fp28"; + case UNW_PPC64_F29: + return "fp29"; + case UNW_PPC64_F30: + return "fp30"; + case UNW_PPC64_F31: + return "fp31"; + case UNW_PPC64_LR: + return "lr"; + case UNW_PPC64_CTR: + return "ctr"; + case UNW_PPC64_CR0: + return "cr0"; + case UNW_PPC64_CR1: + return "cr1"; + case UNW_PPC64_CR2: + return "cr2"; + case UNW_PPC64_CR3: + return "cr3"; + case UNW_PPC64_CR4: + return "cr4"; + case UNW_PPC64_CR5: + return "cr5"; + case UNW_PPC64_CR6: + return "cr6"; + case UNW_PPC64_CR7: + return "cr7"; + case UNW_PPC64_XER: + return "xer"; + case UNW_PPC64_VRSAVE: + return "vrsave"; + case UNW_PPC64_FPSCR: + return "fpscr"; + default: + return "unknown register"; + } +} +#endif // _LIBUNWIND_TARGET_PPC64 + #if defined(_LIBUNWIND_TARGET_AARCH64) /// Registers_arm64 holds the register state of a thread in a 64-bit arm @@ -1053,7 +1706,7 @@ public: void setVectorRegister(int num, v128 value); const char *getRegisterName(int num); void jumpto(); - static int lastDwarfRegNum() { return 95; } + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } uint64_t getSP() const { return _registers.__sp; } void setSP(uint64_t value) { _registers.__sp = value; } @@ -1314,7 +1967,7 @@ public: Registers_arm(const void *registers); bool validRegister(int num) const; - uint32_t getRegister(int num); + uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; unw_fpreg_t getFloatRegister(int num); @@ -1327,6 +1980,7 @@ public: restoreSavedFloatRegisters(); restoreCoreAndJumpTo(); } + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; } uint32_t getSP() const { return _registers.__sp; } void setSP(uint32_t value) { _registers.__sp = value; } @@ -1401,11 +2055,11 @@ private: // Whether iWMMX data registers are saved. bool _saved_iwmmx; // Whether iWMMX control registers are saved. - bool _saved_iwmmx_control; + mutable bool _saved_iwmmx_control; // iWMMX registers unw_fpreg_t _iwmmx[16]; // iWMMX control registers - uint32_t _iwmmx_control[4]; + mutable uint32_t _iwmmx_control[4]; #endif }; @@ -1462,7 +2116,7 @@ inline bool Registers_arm::validRegister(int regNum) const { return false; } -inline uint32_t Registers_arm::getRegister(int regNum) { +inline uint32_t Registers_arm::getRegister(int regNum) const { if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) return _registers.__sp; @@ -1804,7 +2458,7 @@ public: void setVectorRegister(int num, v128 value); const char *getRegisterName(int num); void jumpto(); - static int lastDwarfRegNum() { return 31; } + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; } uint64_t getSP() const { return _registers.__r[1]; } void setSP(uint32_t value) { _registers.__r[1] = value; } @@ -1971,7 +2625,6 @@ inline const char *Registers_or1k::getRegisterName(int regNum) { } #endif // _LIBUNWIND_TARGET_OR1K - #if defined(_LIBUNWIND_TARGET_SPARC64) /// Registers_sparc64 holds the register state of a thread in a 64-bit /// sparc process. @@ -2017,7 +2670,7 @@ inline Registers_sparc64::Registers_sparc64(const void *registers) { memcpy(&_registers, static_cast<const uint8_t *>(registers), sizeof(_registers)); memcpy(&_wcookie, static_cast<const uint8_t *>(registers) + sizeof(GPRs), - sizeof(_wcookie)); + sizeof(_wcookie)); } inline Registers_sparc64::Registers_sparc64() { @@ -2114,6 +2767,418 @@ inline const char *Registers_sparc64::getRegisterName(int regNum) { } #endif // _LIBUNWIND_TARGET_SPARC64 + +#if defined(_LIBUNWIND_TARGET_MIPS_O32) +/// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS +/// process. +class _LIBUNWIND_HIDDEN Registers_mips_o32 { +public: + Registers_mips_o32(); + Registers_mips_o32(const void *registers); + + bool validRegister(int num) const; + uint32_t getRegister(int num) const; + void setRegister(int num, uint32_t value); + bool validFloatRegister(int num) const; + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int num) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } + + uint32_t getSP() const { return _registers.__r[29]; } + void setSP(uint32_t value) { _registers.__r[29] = value; } + uint32_t getIP() const { return _registers.__pc; } + void setIP(uint32_t value) { _registers.__pc = value; } + +private: + struct mips_o32_thread_state_t { + uint32_t __r[32]; + uint32_t __pc; + uint32_t __hi; + uint32_t __lo; + }; + + mips_o32_thread_state_t _registers; +}; + +inline Registers_mips_o32::Registers_mips_o32(const void *registers) { + static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit), + "mips_o32 registers do not fit into unw_context_t"); + memcpy(&_registers, static_cast<const uint8_t *>(registers), + sizeof(_registers)); +} + +inline Registers_mips_o32::Registers_mips_o32() { + memset(&_registers, 0, sizeof(_registers)); +} + +inline bool Registers_mips_o32::validRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return true; + if (regNum == UNW_REG_SP) + return true; + if (regNum < 0) + return false; + if (regNum <= UNW_MIPS_R31) + return true; + if (regNum == UNW_MIPS_HI) + return true; + if (regNum == UNW_MIPS_LO) + return true; + // FIXME: Hard float, DSP accumulator registers, MSA registers + return false; +} + +inline uint32_t Registers_mips_o32::getRegister(int regNum) const { + if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) + return _registers.__r[regNum - UNW_MIPS_R0]; + + switch (regNum) { + case UNW_REG_IP: + return _registers.__pc; + case UNW_REG_SP: + return _registers.__r[29]; + case UNW_MIPS_HI: + return _registers.__hi; + case UNW_MIPS_LO: + return _registers.__lo; + } + _LIBUNWIND_ABORT("unsupported mips_o32 register"); +} + +inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) { + if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) { + _registers.__r[regNum - UNW_MIPS_R0] = value; + return; + } + + switch (regNum) { + case UNW_REG_IP: + _registers.__pc = value; + return; + case UNW_REG_SP: + _registers.__r[29] = value; + return; + case UNW_MIPS_HI: + _registers.__hi = value; + return; + case UNW_MIPS_LO: + _registers.__lo = value; + return; + } + _LIBUNWIND_ABORT("unsupported mips_o32 register"); +} + +inline bool Registers_mips_o32::validFloatRegister(int /* regNum */) const { + return false; +} + +inline double Registers_mips_o32::getFloatRegister(int /* regNum */) const { + _LIBUNWIND_ABORT("mips_o32 float support not implemented"); +} + +inline void Registers_mips_o32::setFloatRegister(int /* regNum */, + double /* value */) { + _LIBUNWIND_ABORT("mips_o32 float support not implemented"); +} + +inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const { + return false; +} + +inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const { + _LIBUNWIND_ABORT("mips_o32 vector support not implemented"); +} + +inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) { + _LIBUNWIND_ABORT("mips_o32 vector support not implemented"); +} + +inline const char *Registers_mips_o32::getRegisterName(int regNum) { + switch (regNum) { + case UNW_MIPS_R0: + return "$0"; + case UNW_MIPS_R1: + return "$1"; + case UNW_MIPS_R2: + return "$2"; + case UNW_MIPS_R3: + return "$3"; + case UNW_MIPS_R4: + return "$4"; + case UNW_MIPS_R5: + return "$5"; + case UNW_MIPS_R6: + return "$6"; + case UNW_MIPS_R7: + return "$7"; + case UNW_MIPS_R8: + return "$8"; + case UNW_MIPS_R9: + return "$9"; + case UNW_MIPS_R10: + return "$10"; + case UNW_MIPS_R11: + return "$11"; + case UNW_MIPS_R12: + return "$12"; + case UNW_MIPS_R13: + return "$13"; + case UNW_MIPS_R14: + return "$14"; + case UNW_MIPS_R15: + return "$15"; + case UNW_MIPS_R16: + return "$16"; + case UNW_MIPS_R17: + return "$17"; + case UNW_MIPS_R18: + return "$18"; + case UNW_MIPS_R19: + return "$19"; + case UNW_MIPS_R20: + return "$20"; + case UNW_MIPS_R21: + return "$21"; + case UNW_MIPS_R22: + return "$22"; + case UNW_MIPS_R23: + return "$23"; + case UNW_MIPS_R24: + return "$24"; + case UNW_MIPS_R25: + return "$25"; + case UNW_MIPS_R26: + return "$26"; + case UNW_MIPS_R27: + return "$27"; + case UNW_MIPS_R28: + return "$28"; + case UNW_MIPS_R29: + return "$29"; + case UNW_MIPS_R30: + return "$30"; + case UNW_MIPS_R31: + return "$31"; + case UNW_MIPS_HI: + return "$hi"; + case UNW_MIPS_LO: + return "$lo"; + default: + return "unknown register"; + } +} +#endif // _LIBUNWIND_TARGET_MIPS_O32 + +#if defined(_LIBUNWIND_TARGET_MIPS_N64) +/// Registers_mips_n64 holds the register state of a thread in a 64-bit MIPS +/// process. +class _LIBUNWIND_HIDDEN Registers_mips_n64 { +public: + Registers_mips_n64(); + Registers_mips_n64(const void *registers); + + bool validRegister(int num) const; + uint64_t getRegister(int num) const; + void setRegister(int num, uint64_t value); + bool validFloatRegister(int num) const; + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int num) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } + + uint64_t getSP() const { return _registers.__r[29]; } + void setSP(uint64_t value) { _registers.__r[29] = value; } + uint64_t getIP() const { return _registers.__pc; } + void setIP(uint64_t value) { _registers.__pc = value; } + +private: + struct mips_n64_thread_state_t { + uint64_t __r[32]; + uint64_t __pc; + uint64_t __hi; + uint64_t __lo; + }; + + mips_n64_thread_state_t _registers; +}; + +inline Registers_mips_n64::Registers_mips_n64(const void *registers) { + static_assert((check_fit<Registers_mips_n64, unw_context_t>::does_fit), + "mips_n64 registers do not fit into unw_context_t"); + memcpy(&_registers, static_cast<const uint8_t *>(registers), + sizeof(_registers)); +} + +inline Registers_mips_n64::Registers_mips_n64() { + memset(&_registers, 0, sizeof(_registers)); +} + +inline bool Registers_mips_n64::validRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return true; + if (regNum == UNW_REG_SP) + return true; + if (regNum < 0) + return false; + if (regNum <= UNW_MIPS_R31) + return true; + if (regNum == UNW_MIPS_HI) + return true; + if (regNum == UNW_MIPS_LO) + return true; + // FIXME: Hard float, DSP accumulator registers, MSA registers + return false; +} + +inline uint64_t Registers_mips_n64::getRegister(int regNum) const { + if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) + return _registers.__r[regNum - UNW_MIPS_R0]; + + switch (regNum) { + case UNW_REG_IP: + return _registers.__pc; + case UNW_REG_SP: + return _registers.__r[29]; + case UNW_MIPS_HI: + return _registers.__hi; + case UNW_MIPS_LO: + return _registers.__lo; + } + _LIBUNWIND_ABORT("unsupported mips_n64 register"); +} + +inline void Registers_mips_n64::setRegister(int regNum, uint64_t value) { + if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) { + _registers.__r[regNum - UNW_MIPS_R0] = value; + return; + } + + switch (regNum) { + case UNW_REG_IP: + _registers.__pc = value; + return; + case UNW_REG_SP: + _registers.__r[29] = value; + return; + case UNW_MIPS_HI: + _registers.__hi = value; + return; + case UNW_MIPS_LO: + _registers.__lo = value; + return; + } + _LIBUNWIND_ABORT("unsupported mips_n64 register"); +} + +inline bool Registers_mips_n64::validFloatRegister(int /* regNum */) const { + return false; +} + +inline double Registers_mips_n64::getFloatRegister(int /* regNum */) const { + _LIBUNWIND_ABORT("mips_n64 float support not implemented"); +} + +inline void Registers_mips_n64::setFloatRegister(int /* regNum */, + double /* value */) { + _LIBUNWIND_ABORT("mips_n64 float support not implemented"); +} + +inline bool Registers_mips_n64::validVectorRegister(int /* regNum */) const { + return false; +} + +inline v128 Registers_mips_n64::getVectorRegister(int /* regNum */) const { + _LIBUNWIND_ABORT("mips_n64 vector support not implemented"); +} + +inline void Registers_mips_n64::setVectorRegister(int /* regNum */, v128 /* value */) { + _LIBUNWIND_ABORT("mips_n64 vector support not implemented"); +} + +inline const char *Registers_mips_n64::getRegisterName(int regNum) { + switch (regNum) { + case UNW_MIPS_R0: + return "$0"; + case UNW_MIPS_R1: + return "$1"; + case UNW_MIPS_R2: + return "$2"; + case UNW_MIPS_R3: + return "$3"; + case UNW_MIPS_R4: + return "$4"; + case UNW_MIPS_R5: + return "$5"; + case UNW_MIPS_R6: + return "$6"; + case UNW_MIPS_R7: + return "$7"; + case UNW_MIPS_R8: + return "$8"; + case UNW_MIPS_R9: + return "$9"; + case UNW_MIPS_R10: + return "$10"; + case UNW_MIPS_R11: + return "$11"; + case UNW_MIPS_R12: + return "$12"; + case UNW_MIPS_R13: + return "$13"; + case UNW_MIPS_R14: + return "$14"; + case UNW_MIPS_R15: + return "$15"; + case UNW_MIPS_R16: + return "$16"; + case UNW_MIPS_R17: + return "$17"; + case UNW_MIPS_R18: + return "$18"; + case UNW_MIPS_R19: + return "$19"; + case UNW_MIPS_R20: + return "$20"; + case UNW_MIPS_R21: + return "$21"; + case UNW_MIPS_R22: + return "$22"; + case UNW_MIPS_R23: + return "$23"; + case UNW_MIPS_R24: + return "$24"; + case UNW_MIPS_R25: + return "$25"; + case UNW_MIPS_R26: + return "$26"; + case UNW_MIPS_R27: + return "$27"; + case UNW_MIPS_R28: + return "$28"; + case UNW_MIPS_R29: + return "$29"; + case UNW_MIPS_R30: + return "$30"; + case UNW_MIPS_R31: + return "$31"; + case UNW_MIPS_HI: + return "$hi"; + case UNW_MIPS_LO: + return "$lo"; + default: + return "unknown register"; + } +} +#endif // _LIBUNWIND_TARGET_MIPS_N64 } // namespace libunwind #endif // __REGISTERS_HPP__ diff --git a/lib/libunwind/src/UnwindCursor.hpp b/lib/libunwind/src/UnwindCursor.hpp index 52f3347eb3e..df12a16d5d7 100644 --- a/lib/libunwind/src/UnwindCursor.hpp +++ b/lib/libunwind/src/UnwindCursor.hpp @@ -6,7 +6,7 @@ // Source Licenses. See LICENSE.TXT for details. // // -// C++ interface to lower levels of libuwind +// C++ interface to lower levels of libunwind //===----------------------------------------------------------------------===// #ifndef __UNWINDCURSOR_HPP__ @@ -16,7 +16,6 @@ #include <stdint.h> #include <stdio.h> #include <stdlib.h> -#include <pthread.h> #include <unwind.h> #ifdef __APPLE__ @@ -32,11 +31,12 @@ #include "EHHeaderParser.hpp" #include "libunwind.h" #include "Registers.hpp" +#include "RWMutex.hpp" #include "Unwind-EHABI.h" namespace libunwind { -#if _LIBUNWIND_SUPPORT_DWARF_UNWIND +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) /// Cache of recently found FDEs. template <typename A> class _LIBUNWIND_HIDDEN DwarfFDECache { @@ -60,7 +60,7 @@ private: // These fields are all static to avoid needing an initializer. // There is only one instance of this class per process. - static pthread_rwlock_t _lock; + static RWMutex _lock; #ifdef __APPLE__ static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide); static bool _registeredForDyldUnloads; @@ -88,7 +88,7 @@ template <typename A> typename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64]; template <typename A> -pthread_rwlock_t DwarfFDECache<A>::_lock = PTHREAD_RWLOCK_INITIALIZER; +RWMutex DwarfFDECache<A>::_lock; #ifdef __APPLE__ template <typename A> @@ -98,7 +98,7 @@ bool DwarfFDECache<A>::_registeredForDyldUnloads = false; template <typename A> typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) { pint_t result = 0; - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_rdlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); for (entry *p = _buffer; p < _bufferUsed; ++p) { if ((mh == p->mh) || (mh == 0)) { if ((p->ip_start <= pc) && (pc < p->ip_end)) { @@ -107,7 +107,7 @@ typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) { } } } - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared()); return result; } @@ -115,7 +115,7 @@ template <typename A> void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde) { #if !defined(_LIBUNWIND_NO_HEAP) - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); if (_bufferUsed >= _bufferEnd) { size_t oldSize = (size_t)(_bufferEnd - _buffer); size_t newSize = oldSize * 4; @@ -139,13 +139,13 @@ void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end, _registeredForDyldUnloads = true; } #endif - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); #endif } template <typename A> void DwarfFDECache<A>::removeAllIn(pint_t mh) { - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); entry *d = _buffer; for (const entry *s = _buffer; s < _bufferUsed; ++s) { if (s->mh != mh) { @@ -155,7 +155,7 @@ void DwarfFDECache<A>::removeAllIn(pint_t mh) { } } _bufferUsed = d; - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); } #ifdef __APPLE__ @@ -168,18 +168,18 @@ void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header *mh, intptr_t ) { template <typename A> void DwarfFDECache<A>::iterateCacheEntries(void (*func)( unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); for (entry *p = _buffer; p < _bufferUsed; ++p) { (*func)(p->ip_start, p->ip_end, p->fde, p->mh); } - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); } -#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND +#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) #define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field)) -#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND +#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) template <typename A> class UnwindSectionHeader { public: UnwindSectionHeader(A &addressSpace, typename A::pint_t addr) @@ -367,7 +367,7 @@ private: A &_addressSpace; typename A::pint_t _addr; }; -#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND +#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) class _LIBUNWIND_HIDDEN AbstractUnwindCursor { public: @@ -440,7 +440,7 @@ public: private: -#if _LIBUNWIND_ARM_EHABI +#if defined(_LIBUNWIND_ARM_EHABI) bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections §s); int stepWithEHABI() { @@ -458,7 +458,7 @@ private: } #endif -#if _LIBUNWIND_SUPPORT_DWARF_UNWIND +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections §s, uint32_t fdeSectionOffsetHint=0); int stepWithDwarfFDE() { @@ -469,11 +469,11 @@ private: } #endif -#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND +#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) bool getInfoFromCompactEncodingSection(pint_t pc, const UnwindInfoSections §s); int stepWithCompactEncoding() { - #if _LIBUNWIND_SUPPORT_DWARF_UNWIND + #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) if ( compactSaysUseDwarf() ) return stepWithDwarfFDE(); #endif @@ -501,6 +501,13 @@ private: } #endif +#if defined(_LIBUNWIND_TARGET_PPC64) + int stepWithCompactEncoding(Registers_ppc64 &) { + return UNW_EINVAL; + } +#endif + + #if defined(_LIBUNWIND_TARGET_AARCH64) int stepWithCompactEncoding(Registers_arm64 &) { return CompactUnwinder_arm64<A>::stepWithCompactEncoding( @@ -508,6 +515,18 @@ private: } #endif +#if defined(_LIBUNWIND_TARGET_MIPS_O32) + int stepWithCompactEncoding(Registers_mips_o32 &) { + return UNW_EINVAL; + } +#endif + +#if defined(_LIBUNWIND_TARGET_MIPS_N64) + int stepWithCompactEncoding(Registers_mips_n64 &) { + return UNW_EINVAL; + } +#endif + bool compactSaysUseDwarf(uint32_t *offset=NULL) const { R dummy; return compactSaysUseDwarf(dummy, offset); @@ -541,6 +560,12 @@ private: } #endif +#if defined(_LIBUNWIND_TARGET_PPC64) + bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const { + return true; + } +#endif + #if defined(_LIBUNWIND_TARGET_AARCH64) bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const { if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) { @@ -551,9 +576,21 @@ private: return false; } #endif -#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND -#if _LIBUNWIND_SUPPORT_DWARF_UNWIND +#if defined(_LIBUNWIND_TARGET_MIPS_O32) + bool compactSaysUseDwarf(Registers_mips_o32 &, uint32_t *) const { + return true; + } +#endif + +#if defined(_LIBUNWIND_TARGET_MIPS_N64) + bool compactSaysUseDwarf(Registers_mips_n64 &, uint32_t *) const { + return true; + } +#endif +#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) + +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) compact_unwind_encoding_t dwarfEncoding() const { R dummy; return dwarfEncoding(dummy); @@ -577,24 +614,48 @@ private: } #endif +#if defined(_LIBUNWIND_TARGET_PPC64) + compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const { + return 0; + } +#endif + #if defined(_LIBUNWIND_TARGET_AARCH64) compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const { return UNWIND_ARM64_MODE_DWARF; } #endif +#if defined(_LIBUNWIND_TARGET_ARM) + compact_unwind_encoding_t dwarfEncoding(Registers_arm &) const { + return 0; + } +#endif + #if defined (_LIBUNWIND_TARGET_OR1K) compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const { return 0; } #endif +#if defined (_LIBUNWIND_TARGET_MIPS_O32) + compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const { + return 0; + } +#endif + +#if defined (_LIBUNWIND_TARGET_MIPS_N64) + compact_unwind_encoding_t dwarfEncoding(Registers_mips_n64 &) const { + return 0; + } +#endif + #if defined (_LIBUNWIND_TARGET_SPARC64) compact_unwind_encoding_t dwarfEncoding(Registers_sparc64 &) const { return 0; } #endif -#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND +#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) A &_addressSpace; @@ -672,7 +733,7 @@ template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() { return _isSignalFrame; } -#if _LIBUNWIND_ARM_EHABI +#if defined(_LIBUNWIND_ARM_EHABI) struct EHABIIndexEntry { uint32_t functionOffset; uint32_t data; @@ -693,7 +754,8 @@ struct EHABISectionIterator { return _Self(addressSpace, sects, 0); } static _Self end(A& addressSpace, const UnwindInfoSections& sects) { - return _Self(addressSpace, sects, sects.arm_section_length); + return _Self(addressSpace, sects, + sects.arm_section_length / sizeof(EHABIIndexEntry)); } EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i) @@ -743,14 +805,21 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( EHABISectionIterator<A>::begin(_addressSpace, sects); EHABISectionIterator<A> end = EHABISectionIterator<A>::end(_addressSpace, sects); + if (begin == end) + return false; EHABISectionIterator<A> itNextPC = std::upper_bound(begin, end, pc); - if (itNextPC == begin || itNextPC == end) + if (itNextPC == begin) return false; EHABISectionIterator<A> itThisPC = itNextPC - 1; pint_t thisPC = itThisPC.functionAddress(); - pint_t nextPC = itNextPC.functionAddress(); + // If an exception is thrown from a function, corresponding to the last entry + // in the table, we don't really know the function extent and have to choose a + // value for nextPC. Choosing max() will allow the range check during trace to + // succeed. + pint_t nextPC = (itNextPC == end) ? std::numeric_limits<pint_t>::max() + : itNextPC.functionAddress(); pint_t indexDataAddr = itThisPC.dataAddress(); if (indexDataAddr == 0) @@ -867,7 +936,7 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( } #endif -#if _LIBUNWIND_SUPPORT_DWARF_UNWIND +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) template <typename A, typename R> bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections §s, @@ -883,7 +952,7 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, sects.dwarf_section + fdeSectionOffsetHint, &fdeInfo, &cieInfo); } -#if _LIBUNWIND_SUPPORT_DWARF_INDEX +#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) if (!foundFDE && (sects.dwarf_index_section != 0)) { foundFDE = EHHeaderParser<A>::findFDE( _addressSpace, pc, sects.dwarf_index_section, @@ -926,7 +995,7 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, // Add to cache (to make next lookup faster) if we had no hint // and there was no index. if (!foundInCache && (fdeSectionOffsetHint == 0)) { - #if _LIBUNWIND_SUPPORT_DWARF_INDEX + #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) if (sects.dwarf_index_section == 0) #endif DwarfFDECache<A>::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd, @@ -935,13 +1004,13 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, return true; } } - //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX\n", (uint64_t)pc); + //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc); return false; } -#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND +#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) -#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND +#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) template <typename A, typename R> bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, const UnwindInfoSections §s) { @@ -1092,13 +1161,13 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base; if (pc < funcStart) { _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " - "level compressed unwind table. funcStart=0x%llX\n", + "level compressed unwind table. funcStart=0x%llX", (uint64_t) pc, (uint64_t) funcStart); return false; } if (pc > funcEnd) { _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " - "level compressed unwind table. funcEnd=0x%llX\n", + "level compressed unwind table. funcEnd=0x%llX", (uint64_t) pc, (uint64_t) funcEnd); return false; } @@ -1119,7 +1188,7 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, } } else { _LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second " - "level page\n", + "level page", (uint64_t) sects.compact_unwind_section); return false; } @@ -1149,7 +1218,7 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, } if (lsda == 0) { _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for " - "pc=0x%0llX, but lsda table has no entry\n", + "pc=0x%0llX, but lsda table has no entry", encoding, (uint64_t) pc); return false; } @@ -1162,7 +1231,7 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, --personalityIndex; // change 1-based to zero-based index if (personalityIndex > sectionHeader.personalityArrayCount()) { _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, " - "but personality table has only %d entires\n", + "but personality table has only %d entires", encoding, personalityIndex, sectionHeader.personalityArrayCount()); return false; @@ -1195,13 +1264,13 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, _info.extra = sects.dso_base; return true; } -#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND +#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) template <typename A, typename R> void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { pint_t pc = (pint_t)this->getReg(UNW_REG_IP); -#if _LIBUNWIND_ARM_EHABI +#if defined(_LIBUNWIND_ARM_EHABI) // Remove the thumb bit so the IP represents the actual instruction address. // This matches the behaviour of _Unwind_GetIP on arm. pc &= (pint_t)~0x1; @@ -1218,11 +1287,11 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { // Ask address space object to find unwind sections for this pc. UnwindInfoSections sects; if (_addressSpace.findUnwindSections(pc, sects)) { -#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND +#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) // If there is a compact unwind encoding table, look there first. if (sects.compact_unwind_section != 0) { if (this->getInfoFromCompactEncodingSection(pc, sects)) { - #if _LIBUNWIND_SUPPORT_DWARF_UNWIND + #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) // Found info in table, done unless encoding says to use dwarf. uint32_t dwarfOffset; if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) { @@ -1239,9 +1308,9 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { return; } } -#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND +#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) -#if _LIBUNWIND_SUPPORT_DWARF_UNWIND +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) // If there is dwarf unwind info, look there next. if (sects.dwarf_section != 0) { if (this->getInfoFromDwarfSection(pc, sects)) { @@ -1251,14 +1320,14 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { } #endif -#if _LIBUNWIND_ARM_EHABI +#if defined(_LIBUNWIND_ARM_EHABI) // If there is ARM EHABI unwind info, look there next. if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects)) return; #endif } -#if _LIBUNWIND_SUPPORT_DWARF_UNWIND +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) // There is no static unwind info for this pc. Look to see if an FDE was // dynamically registered for it. pint_t cachedFDE = DwarfFDECache<A>::findFDE(0, pc); @@ -1317,7 +1386,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { } } } -#endif // #if _LIBUNWIND_SUPPORT_DWARF_UNWIND +#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) // no unwind info, flag that we can't reliably unwind _unwindInfoMissing = true; @@ -1331,11 +1400,11 @@ int UnwindCursor<A, R>::step() { // Use unwinding info to modify register set as if function returned. int result; -#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND +#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) result = this->stepWithCompactEncoding(); -#elif _LIBUNWIND_SUPPORT_DWARF_UNWIND +#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) result = this->stepWithDwarfFDE(); -#elif _LIBUNWIND_ARM_EHABI +#elif defined(_LIBUNWIND_ARM_EHABI) result = this->stepWithEHABI(); #else #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \ diff --git a/lib/libunwind/src/UnwindRegistersRestore.S b/lib/libunwind/src/UnwindRegistersRestore.S index 3b185aa3e10..94141de2eb5 100644 --- a/lib/libunwind/src/UnwindRegistersRestore.S +++ b/lib/libunwind/src/UnwindRegistersRestore.S @@ -11,11 +11,17 @@ .text +#if !defined(__USING_SJLJ_EXCEPTIONS__) + #if defined(__i386__) DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) # # void libunwind::Registers_x86::jumpto() # +#if defined(_WIN32) +# On windows, the 'this' pointer is passed in ecx instead of on the stack + movl %ecx, %eax +#else # On entry: # + + # +-----------------------+ @@ -25,6 +31,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) # +-----------------------+ <-- SP # + + movl 4(%esp), %eax +#endif # set up eax and ret on new stack location movl 28(%eax), %edx # edx holds new stack pointer subl $8,%edx @@ -58,7 +65,16 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv) # # void libunwind::Registers_x86_64::jumpto() # +#if defined(_WIN64) +# On entry, thread_state pointer is in rcx; move it into rdi +# to share restore code below. Since this routine restores and +# overwrites all registers, we can use the same registers for +# pointers and temporaries as on unix even though win64 normally +# mustn't clobber some of them. + movq %rcx, %rdi +#else # On entry, thread_state pointer is in rdi +#endif movq 56(%rdi), %rax # rax holds new stack pointer subq $16, %rax @@ -88,11 +104,125 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv) # skip cs # skip fs # skip gs + +#if defined(_WIN64) + movdqu 176(%rdi),%xmm0 + movdqu 192(%rdi),%xmm1 + movdqu 208(%rdi),%xmm2 + movdqu 224(%rdi),%xmm3 + movdqu 240(%rdi),%xmm4 + movdqu 256(%rdi),%xmm5 + movdqu 272(%rdi),%xmm6 + movdqu 288(%rdi),%xmm7 + movdqu 304(%rdi),%xmm8 + movdqu 320(%rdi),%xmm9 + movdqu 336(%rdi),%xmm10 + movdqu 352(%rdi),%xmm11 + movdqu 368(%rdi),%xmm12 + movdqu 384(%rdi),%xmm13 + movdqu 400(%rdi),%xmm14 + movdqu 416(%rdi),%xmm15 +#endif movq 56(%rdi), %rsp # cut back rsp to new location pop %rdi # rdi was saved here earlier ret # rip was saved here +#elif defined(__powerpc64__) + +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) +// +// void libunwind::Registers_ppc64::jumpto() +// +// On entry: +// thread_state pointer is in r3 +// + + // restore integral registers + // skip r0 for now + // skip r1 for now + ld %r2, 32(%r3) + // skip r3 for now + // skip r4 for now + // skip r5 for now + ld %r6, 64(%r3) + ld %r7, 72(%r3) + ld %r8, 80(%r3) + ld %r9, 88(%r3) + ld %r10, 96(%r3) + ld %r11, 104(%r3) + ld %r12, 112(%r3) + ld %r13, 120(%r3) + ld %r14, 128(%r3) + ld %r15, 136(%r3) + ld %r16, 144(%r3) + ld %r17, 152(%r3) + ld %r18, 160(%r3) + ld %r19, 168(%r3) + ld %r20, 176(%r3) + ld %r21, 184(%r3) + ld %r22, 192(%r3) + ld %r23, 200(%r3) + ld %r24, 208(%r3) + ld %r25, 216(%r3) + ld %r26, 224(%r3) + ld %r27, 232(%r3) + ld %r28, 240(%r3) + ld %r29, 248(%r3) + ld %r30, 256(%r3) + ld %r31, 264(%r3) + + //restore float registers + lfd %f0, 312(%r3) + lfd %f1, 320(%r3) + lfd %f2, 328(%r3) + lfd %f3, 336(%r3) + lfd %f4, 344(%r3) + lfd %f5, 352(%r3) + lfd %f6, 360(%r3) + lfd %f7, 368(%r3) + lfd %f8, 376(%r3) + lfd %f9, 384(%r3) + lfd %f10, 392(%r3) + lfd %f11, 400(%r3) + lfd %f12, 408(%r3) + lfd %f13, 416(%r3) + lfd %f14, 424(%r3) + lfd %f15, 432(%r3) + lfd %f16, 440(%r3) + lfd %f17, 448(%r3) + lfd %f18, 456(%r3) + lfd %f19, 464(%r3) + lfd %f20, 472(%r3) + lfd %f21, 480(%r3) + lfd %f22, 488(%r3) + lfd %f23, 496(%r3) + lfd %f24, 504(%r3) + lfd %f25, 512(%r3) + lfd %f26, 520(%r3) + lfd %f27, 528(%r3) + lfd %f28, 536(%r3) + lfd %f29, 544(%r3) + lfd %f30, 552(%r3) + lfd %f31, 560(%r3) + + //TODO: restore vector registers + + // Lnovec: + ld %r0, 272(%r3) // __cr + mtcr %r0 + ld %r0, 296(%r3) // __ctr + mtctr %r0 + ld %r0, 0(%r3) // __ssr0 + mtctr %r0 + + ld %r0, 16(%r3) + ld %r5, 56(%r3) + ld %r4, 48(%r3) + ld %r1, 24(%r3) + ld %r3, 40(%r3) + bctr + #elif defined(__ppc__) DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) @@ -322,9 +452,18 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) @ .p2align 2 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv) -#if !defined(__ARM_ARCH_ISA_ARM) - ldr r2, [r0, #52] - ldr r3, [r0, #60] +#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1 + @ r8-r11: ldm into r1-r4, then mov to r8-r11 + adds r0, #0x20 + ldm r0!, {r1-r4} + subs r0, #0x30 + mov r8, r1 + mov r9, r2 + mov r10, r3 + mov r11, r4 + @ r12 does not need loading, it it the intra-procedure-call scratch register + ldr r2, [r0, #0x34] + ldr r3, [r0, #0x3c] mov sp, r2 mov lr, r3 @ restore pc into lr ldm r0, {r0-r7} @@ -347,7 +486,9 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJu @ values pointer is in r0 @ .p2align 2 +#if defined(__ELF__) .fpu vfpv3-d16 +#endif DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPy) @ VFP and iwMMX instructions are only available when compiling with the flags @ that enable them. We do not want to do that in the library (because we do not @@ -366,7 +507,9 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFL @ values pointer is in r0 @ .p2align 2 +#if defined(__ELF__) .fpu vfpv3-d16 +#endif DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPy) vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia JMP(lr) @@ -378,7 +521,9 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFL @ values pointer is in r0 @ .p2align 2 +#if defined(__ELF__) .fpu vfpv3 +#endif DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy) vldmia r0, {d16-d31} JMP(lr) @@ -392,6 +537,9 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy) @ values pointer is in r0 @ .p2align 2 +#if defined(__ELF__) + .arch armv5te +#endif DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy) ldcl p1, cr0, [r0], #8 @ wldrd wR0, [r0], #8 ldcl p1, cr1, [r0], #8 @ wldrd wR1, [r0], #8 @@ -418,6 +566,9 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy) @ values pointer is in r0 @ .p2align 2 +#if defined(__ELF__) + .arch armv5te +#endif DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj) ldc2 p1, cr8, [r0], #4 @ wldrw wCGR0, [r0], #4 ldc2 p1, cr9, [r0], #4 @ wldrw wCGR1, [r0], #4 @@ -488,40 +639,154 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind17Registers_sparc646jumptoEv) # thread_state pointer is in %o0 # flushw - ldx [%o0 + 0x08], %g1 - ldx [%o0 + 0x10], %g2 - ldx [%o0 + 0x18], %g3 - ldx [%o0 + 0x20], %g4 - ldx [%o0 + 0x28], %g5 - ldx [%o0 + 0x30], %g6 - ldx [%o0 + 0x38], %g7 - ldx [%o0 + 0x48], %o1 - ldx [%o0 + 0x50], %o2 - ldx [%o0 + 0x58], %o3 - ldx [%o0 + 0x60], %o4 - ldx [%o0 + 0x68], %o5 - ldx [%o0 + 0x70], %o6 - ldx [%o0 + 0x78], %o7 - ldx [%o0 + 0x80], %l0 - ldx [%o0 + 0x88], %l1 - ldx [%o0 + 0x90], %l2 - ldx [%o0 + 0x98], %l3 - ldx [%o0 + 0xa0], %l4 - ldx [%o0 + 0xa8], %l5 - ldx [%o0 + 0xb0], %l6 - ldx [%o0 + 0xb8], %l7 - ldx [%o0 + 0xc0], %i0 - ldx [%o0 + 0xc8], %i1 - ldx [%o0 + 0xd0], %i2 - ldx [%o0 + 0xd8], %i3 - ldx [%o0 + 0xe0], %i4 - ldx [%o0 + 0xe8], %i5 - ldx [%o0 + 0xf0], %i6 - ldx [%o0 + 0xf8], %i7 - jmpl %o7, %g0 - ldx [%o0 + 0x40], %o0 + ldx [%o0 + 0x08], %g1 + ldx [%o0 + 0x10], %g2 + ldx [%o0 + 0x18], %g3 + ldx [%o0 + 0x20], %g4 + ldx [%o0 + 0x28], %g5 + ldx [%o0 + 0x30], %g6 + ldx [%o0 + 0x38], %g7 + ldx [%o0 + 0x48], %o1 + ldx [%o0 + 0x50], %o2 + ldx [%o0 + 0x58], %o3 + ldx [%o0 + 0x60], %o4 + ldx [%o0 + 0x68], %o5 + ldx [%o0 + 0x70], %o6 + ldx [%o0 + 0x78], %o7 + ldx [%o0 + 0x80], %l0 + ldx [%o0 + 0x88], %l1 + ldx [%o0 + 0x90], %l2 + ldx [%o0 + 0x98], %l3 + ldx [%o0 + 0xa0], %l4 + ldx [%o0 + 0xa8], %l5 + ldx [%o0 + 0xb0], %l6 + ldx [%o0 + 0xb8], %l7 + ldx [%o0 + 0xc0], %i0 + ldx [%o0 + 0xc8], %i1 + ldx [%o0 + 0xd0], %i2 + ldx [%o0 + 0xd8], %i3 + ldx [%o0 + 0xe0], %i4 + ldx [%o0 + 0xe8], %i5 + ldx [%o0 + 0xf0], %i6 + ldx [%o0 + 0xf8], %i7 + jmpl %o7, %g0 + ldx [%o0 + 0x40], %o0 + +#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float) + +// +// void libunwind::Registers_mips_o32::jumpto() +// +// On entry: +// thread state pointer is in a0 ($4) +// +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) + .set push + .set noat + .set noreorder + .set nomacro + // restore hi and lo + lw $8, (4 * 33)($4) + mthi $8 + lw $8, (4 * 34)($4) + mtlo $8 + // r0 is zero + lw $1, (4 * 1)($4) + lw $2, (4 * 2)($4) + lw $3, (4 * 3)($4) + // skip a0 for now + lw $5, (4 * 5)($4) + lw $6, (4 * 6)($4) + lw $7, (4 * 7)($4) + lw $8, (4 * 8)($4) + lw $9, (4 * 9)($4) + lw $10, (4 * 10)($4) + lw $11, (4 * 11)($4) + lw $12, (4 * 12)($4) + lw $13, (4 * 13)($4) + lw $14, (4 * 14)($4) + lw $15, (4 * 15)($4) + lw $16, (4 * 16)($4) + lw $17, (4 * 17)($4) + lw $18, (4 * 18)($4) + lw $19, (4 * 19)($4) + lw $20, (4 * 20)($4) + lw $21, (4 * 21)($4) + lw $22, (4 * 22)($4) + lw $23, (4 * 23)($4) + lw $24, (4 * 24)($4) + lw $25, (4 * 25)($4) + lw $26, (4 * 26)($4) + lw $27, (4 * 27)($4) + lw $28, (4 * 28)($4) + lw $29, (4 * 29)($4) + lw $30, (4 * 30)($4) + // load new pc into ra + lw $31, (4 * 32)($4) + // jump to ra, load a0 in the delay slot + jr $31 + lw $4, (4 * 4)($4) + .set pop + +#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float) + +// +// void libunwind::Registers_mips_n64::jumpto() +// +// On entry: +// thread state pointer is in a0 ($4) +// +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_n646jumptoEv) + .set push + .set noat + .set noreorder + .set nomacro + // restore hi and lo + ld $8, (8 * 33)($4) + mthi $8 + ld $8, (8 * 34)($4) + mtlo $8 + // r0 is zero + ld $1, (8 * 1)($4) + ld $2, (8 * 2)($4) + ld $3, (8 * 3)($4) + // skip a0 for now + ld $5, (8 * 5)($4) + ld $6, (8 * 6)($4) + ld $7, (8 * 7)($4) + ld $8, (8 * 8)($4) + ld $9, (8 * 9)($4) + ld $10, (8 * 10)($4) + ld $11, (8 * 11)($4) + ld $12, (8 * 12)($4) + ld $13, (8 * 13)($4) + ld $14, (8 * 14)($4) + ld $15, (8 * 15)($4) + ld $16, (8 * 16)($4) + ld $17, (8 * 17)($4) + ld $18, (8 * 18)($4) + ld $19, (8 * 19)($4) + ld $20, (8 * 20)($4) + ld $21, (8 * 21)($4) + ld $22, (8 * 22)($4) + ld $23, (8 * 23)($4) + ld $24, (8 * 24)($4) + ld $25, (8 * 25)($4) + ld $26, (8 * 26)($4) + ld $27, (8 * 27)($4) + ld $28, (8 * 28)($4) + ld $29, (8 * 29)($4) + ld $30, (8 * 30)($4) + // load new pc into ra + ld $31, (8 * 32)($4) + // jump to ra, load a0 in the delay slot + jr $31 + ld $4, (8 * 4)($4) + .set pop #endif +#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ + NO_EXEC_STACK_DIRECTIVE diff --git a/lib/libunwind/src/UnwindRegistersSave.S b/lib/libunwind/src/UnwindRegistersSave.S index f24c5398cbb..81d413c4874 100644 --- a/lib/libunwind/src/UnwindRegistersSave.S +++ b/lib/libunwind/src/UnwindRegistersSave.S @@ -11,6 +11,8 @@ .text +#if !defined(__USING_SJLJ_EXCEPTIONS__) + #if defined(__i386__) # @@ -61,32 +63,171 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) # thread_state pointer is in rdi # DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - movq %rax, (%rdi) - movq %rbx, 8(%rdi) - movq %rcx, 16(%rdi) - movq %rdx, 24(%rdi) - movq %rdi, 32(%rdi) - movq %rsi, 40(%rdi) - movq %rbp, 48(%rdi) - movq %rsp, 56(%rdi) - addq $8, 56(%rdi) - movq %r8, 64(%rdi) - movq %r9, 72(%rdi) - movq %r10, 80(%rdi) - movq %r11, 88(%rdi) - movq %r12, 96(%rdi) - movq %r13,104(%rdi) - movq %r14,112(%rdi) - movq %r15,120(%rdi) - movq (%rsp),%rsi - movq %rsi,128(%rdi) # store return address as rip +#if defined(_WIN64) +#define PTR %rcx +#define TMP %rdx +#else +#define PTR %rdi +#define TMP %rsi +#endif + + movq %rax, (PTR) + movq %rbx, 8(PTR) + movq %rcx, 16(PTR) + movq %rdx, 24(PTR) + movq %rdi, 32(PTR) + movq %rsi, 40(PTR) + movq %rbp, 48(PTR) + movq %rsp, 56(PTR) + addq $8, 56(PTR) + movq %r8, 64(PTR) + movq %r9, 72(PTR) + movq %r10, 80(PTR) + movq %r11, 88(PTR) + movq %r12, 96(PTR) + movq %r13,104(PTR) + movq %r14,112(PTR) + movq %r15,120(PTR) + movq (%rsp),TMP + movq TMP,128(PTR) # store return address as rip # skip rflags # skip cs # skip fs # skip gs + +#if defined(_WIN64) + movdqu %xmm0,176(PTR) + movdqu %xmm1,192(PTR) + movdqu %xmm2,208(PTR) + movdqu %xmm3,224(PTR) + movdqu %xmm4,240(PTR) + movdqu %xmm5,256(PTR) + movdqu %xmm6,272(PTR) + movdqu %xmm7,288(PTR) + movdqu %xmm8,304(PTR) + movdqu %xmm9,320(PTR) + movdqu %xmm10,336(PTR) + movdqu %xmm11,352(PTR) + movdqu %xmm12,368(PTR) + movdqu %xmm13,384(PTR) + movdqu %xmm14,400(PTR) + movdqu %xmm15,416(PTR) +#endif xorl %eax, %eax # return UNW_ESUCCESS ret +#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float) + +# +# extern int unw_getcontext(unw_context_t* thread_state) +# +# On entry: +# thread_state pointer is in a0 ($4) +# +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + .set push + .set noat + .set noreorder + .set nomacro + sw $1, (4 * 1)($4) + sw $2, (4 * 2)($4) + sw $3, (4 * 3)($4) + sw $4, (4 * 4)($4) + sw $5, (4 * 5)($4) + sw $6, (4 * 6)($4) + sw $7, (4 * 7)($4) + sw $8, (4 * 8)($4) + sw $9, (4 * 9)($4) + sw $10, (4 * 10)($4) + sw $11, (4 * 11)($4) + sw $12, (4 * 12)($4) + sw $13, (4 * 13)($4) + sw $14, (4 * 14)($4) + sw $15, (4 * 15)($4) + sw $16, (4 * 16)($4) + sw $17, (4 * 17)($4) + sw $18, (4 * 18)($4) + sw $19, (4 * 19)($4) + sw $20, (4 * 20)($4) + sw $21, (4 * 21)($4) + sw $22, (4 * 22)($4) + sw $23, (4 * 23)($4) + sw $24, (4 * 24)($4) + sw $25, (4 * 25)($4) + sw $26, (4 * 26)($4) + sw $27, (4 * 27)($4) + sw $28, (4 * 28)($4) + sw $29, (4 * 29)($4) + sw $30, (4 * 30)($4) + sw $31, (4 * 31)($4) + # Store return address to pc + sw $31, (4 * 32)($4) + # hi and lo + mfhi $8 + sw $8, (4 * 33)($4) + mflo $8 + sw $8, (4 * 34)($4) + jr $31 + # return UNW_ESUCCESS + or $2, $0, $0 + .set pop + +#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float) + +# +# extern int unw_getcontext(unw_context_t* thread_state) +# +# On entry: +# thread_state pointer is in a0 ($4) +# +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + .set push + .set noat + .set noreorder + .set nomacro + sd $1, (8 * 1)($4) + sd $2, (8 * 2)($4) + sd $3, (8 * 3)($4) + sd $4, (8 * 4)($4) + sd $5, (8 * 5)($4) + sd $6, (8 * 6)($4) + sd $7, (8 * 7)($4) + sd $8, (8 * 8)($4) + sd $9, (8 * 9)($4) + sd $10, (8 * 10)($4) + sd $11, (8 * 11)($4) + sd $12, (8 * 12)($4) + sd $13, (8 * 13)($4) + sd $14, (8 * 14)($4) + sd $15, (8 * 15)($4) + sd $16, (8 * 16)($4) + sd $17, (8 * 17)($4) + sd $18, (8 * 18)($4) + sd $19, (8 * 19)($4) + sd $20, (8 * 20)($4) + sd $21, (8 * 21)($4) + sd $22, (8 * 22)($4) + sd $23, (8 * 23)($4) + sd $24, (8 * 24)($4) + sd $25, (8 * 25)($4) + sd $26, (8 * 26)($4) + sd $27, (8 * 27)($4) + sd $28, (8 * 28)($4) + sd $29, (8 * 29)($4) + sd $30, (8 * 30)($4) + sd $31, (8 * 31)($4) + # Store return address to pc + sd $31, (8 * 32)($4) + # hi and lo + mfhi $8 + sd $8, (8 * 33)($4) + mflo $8 + sd $8, (8 * 34)($4) + jr $31 + # return UNW_ESUCCESS + or $2, $0, $0 + .set pop + # elif defined(__mips__) # @@ -96,6 +237,109 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) teq $0, $0 +#elif defined(__powerpc64__) + +// +// extern int unw_getcontext(unw_context_t* thread_state) +// +// On entry: +// thread_state pointer is in r3 +// +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + std %r0, 16(%r3) + mflr %r0 + std %r0, 0(%r3) // store lr as ssr0 + std %r1, 24(%r3) + std %r2, 32(%r3) + std %r3, 40(%r3) + std %r4, 48(%r3) + std %r5, 56(%r3) + std %r6, 64(%r3) + std %r7, 72(%r3) + std %r8, 80(%r3) + std %r9, 88(%r3) + std %r10, 96(%r3) + std %r11, 104(%r3) + std %r12, 112(%r3) + std %r13, 120(%r3) + std %r14, 128(%r3) + std %r15, 136(%r3) + std %r16, 144(%r3) + std %r17, 152(%r3) + std %r18, 160(%r3) + std %r19, 168(%r3) + std %r20, 176(%r3) + std %r21, 184(%r3) + std %r22, 192(%r3) + std %r23, 200(%r3) + std %r24, 208(%r3) + std %r25, 216(%r3) + std %r26, 224(%r3) + std %r27, 232(%r3) + std %r28, 240(%r3) + std %r29, 248(%r3) + std %r30, 256(%r3) + std %r31, 264(%r3) + + mfcr %r0 + std %r0, 272(%r3) + + mfxer %r0 + std %r0, 280(%r3) + + mflr %r0 + std %r0, 288(%r3) + + mfctr %r0 + std %r0, 296(%r3) + + mfvrsave %r0 + std %r0, 304(%r3) + + // save float registers + stfd %f0, 312(%r3) + stfd %f1, 320(%r3) + stfd %f2, 328(%r3) + stfd %f3, 336(%r3) + stfd %f4, 344(%r3) + stfd %f5, 352(%r3) + stfd %f6, 360(%r3) + stfd %f7, 368(%r3) + stfd %f8, 376(%r3) + stfd %f9, 384(%r3) + stfd %f10, 392(%r3) + stfd %f11, 400(%r3) + stfd %f12, 408(%r3) + stfd %f13, 416(%r3) + stfd %f14, 424(%r3) + stfd %f15, 432(%r3) + stfd %f16, 440(%r3) + stfd %f17, 448(%r3) + stfd %f18, 456(%r3) + stfd %f19, 464(%r3) + stfd %f20, 472(%r3) + stfd %f21, 480(%r3) + stfd %f22, 488(%r3) + stfd %f23, 496(%r3) + stfd %f24, 504(%r3) + stfd %f25, 512(%r3) + stfd %f26, 520(%r3) + stfd %f27, 528(%r3) + stfd %f28, 536(%r3) + stfd %f29, 544(%r3) + stfd %f30, 552(%r3) + stfd %f31, 560(%r3) + + mffs %f0 + stfd %f0, 568(%r3) + + //TODO: save vector registers + + + li %r3, 0 // return UNW_ESUCCESS + blr + + #elif defined(__ppc__) ; @@ -309,13 +553,24 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) @ .p2align 2 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) -#if !defined(__ARM_ARCH_ISA_ARM) - stm r0, {r0-r7} +#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1 + stm r0!, {r0-r7} + mov r1, r8 + mov r2, r9 + mov r3, r10 + stm r0!, {r1-r3} + mov r1, r11 mov r2, sp mov r3, lr - str r2, [r0, #52] - str r3, [r0, #56] - str r3, [r0, #60] @ store return address as pc + str r1, [r0, #0] @ r11 + @ r12 does not need storing, it it the intra-procedure-call scratch register + str r2, [r0, #8] @ sp + str r3, [r0, #12] @ lr + str r3, [r0, #16] @ store return address as pc + @ T1 does not have a non-cpsr-clobbering register-zeroing instruction. + @ It is safe to use here though because we are about to return, and cpsr is + @ not expected to be preserved. + movs r0, #0 @ return UNW_ESUCCESS #else @ 32bit thumb-2 restrictions for stm: @ . the sp (r13) cannot be in the list @@ -324,13 +579,6 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) str sp, [r0, #52] str lr, [r0, #56] str lr, [r0, #60] @ store return address as pc -#endif -#if __ARM_ARCH_ISA_THUMB == 1 - @ T1 does not have a non-cpsr-clobbering register-zeroing instruction. - @ It is safe to use here though because we are about to return, and cpsr is - @ not expected to be preserved. - movs r0, #0 @ return UNW_ESUCCESS -#else mov r0, #0 @ return UNW_ESUCCESS #endif JMP(lr) @@ -342,7 +590,9 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) @ values pointer is in r0 @ .p2align 2 +#if defined(__ELF__) .fpu vfpv3-d16 +#endif DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy) vstmia r0, {d0-d15} JMP(lr) @@ -354,7 +604,9 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMD @ values pointer is in r0 @ .p2align 2 +#if defined(__ELF__) .fpu vfpv3-d16 +#endif DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy) vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia JMP(lr) @@ -366,7 +618,9 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMX @ values pointer is in r0 @ .p2align 2 +#if defined(__ELF__) .fpu vfpv3 +#endif DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy) @ VFP and iwMMX instructions are only available when compiling with the flags @ that enable them. We do not want to do that in the library (because we do not @@ -387,6 +641,9 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy) @ values pointer is in r0 @ .p2align 2 +#if defined(__ELF__) + .arch armv5te +#endif DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy) stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8 stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8 @@ -413,6 +670,9 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy) @ values pointer is in r0 @ .p2align 2 +#if defined(__ELF__) + .arch armv5te +#endif DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj) stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4 stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4 @@ -465,7 +725,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) l.sw 124(r3), r31 #elif defined(__sparc__) && defined(__arch64__) - + # # extern int unw_getcontext(unw_context_t* thread_state) # @@ -473,50 +733,52 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) # thread_state pointer is in %o0 # DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - stx %g1, [%o0 + 0x08] - stx %g2, [%o0 + 0x10] - stx %g3, [%o0 + 0x18] - stx %g4, [%o0 + 0x20] - stx %g5, [%o0 + 0x28] - stx %g6, [%o0 + 0x30] - stx %g7, [%o0 + 0x38] - stx %o0, [%o0 + 0x40] - stx %o1, [%o0 + 0x48] - stx %o2, [%o0 + 0x50] - stx %o3, [%o0 + 0x58] - stx %o4, [%o0 + 0x60] - stx %o5, [%o0 + 0x68] - stx %o6, [%o0 + 0x70] - stx %o7, [%o0 + 0x78] - stx %l0, [%o0 + 0x80] - stx %l1, [%o0 + 0x88] - stx %l2, [%o0 + 0x90] - stx %l3, [%o0 + 0x98] - stx %l4, [%o0 + 0xa0] - stx %l5, [%o0 + 0xa8] - stx %l6, [%o0 + 0xb0] - stx %l7, [%o0 + 0xb8] - stx %i0, [%o0 + 0xc0] - stx %i1, [%o0 + 0xc8] - stx %i2, [%o0 + 0xd0] - stx %i3, [%o0 + 0xd8] - stx %i4, [%o0 + 0xe0] - stx %i5, [%o0 + 0xe8] - stx %i6, [%o0 + 0xf0] - stx %i7, [%o0 + 0xf8] + stx %g1, [%o0 + 0x08] + stx %g2, [%o0 + 0x10] + stx %g3, [%o0 + 0x18] + stx %g4, [%o0 + 0x20] + stx %g5, [%o0 + 0x28] + stx %g6, [%o0 + 0x30] + stx %g7, [%o0 + 0x38] + stx %o0, [%o0 + 0x40] + stx %o1, [%o0 + 0x48] + stx %o2, [%o0 + 0x50] + stx %o3, [%o0 + 0x58] + stx %o4, [%o0 + 0x60] + stx %o5, [%o0 + 0x68] + stx %o6, [%o0 + 0x70] + stx %o7, [%o0 + 0x78] + stx %l0, [%o0 + 0x80] + stx %l1, [%o0 + 0x88] + stx %l2, [%o0 + 0x90] + stx %l3, [%o0 + 0x98] + stx %l4, [%o0 + 0xa0] + stx %l5, [%o0 + 0xa8] + stx %l6, [%o0 + 0xb0] + stx %l7, [%o0 + 0xb8] + stx %i0, [%o0 + 0xc0] + stx %i1, [%o0 + 0xc8] + stx %i2, [%o0 + 0xd0] + stx %i3, [%o0 + 0xd8] + stx %i4, [%o0 + 0xe0] + stx %i5, [%o0 + 0xe8] + stx %i6, [%o0 + 0xf0] + stx %i7, [%o0 + 0xf8] # save StackGhost cookie - add %i7, %g0, %g4 - save %sp, -176, %sp + add %i7, %g0, %g4 + save %sp, -176, %sp # register window flush necessary even without StackGhost flushw restore - ldx [%sp + 2047 + 0x78], %g5 - xor %g4, %g5, %g4 + ldx [%sp + 2047 + 0x78], %g5 + xor %g4, %g5, %g4 retl - stx %g4, [%o0 + 0x100] + stx %g4, [%o0 + 0x100] #endif +#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ + NO_EXEC_STACK_DIRECTIVE diff --git a/lib/libunwind/src/libunwind.cpp b/lib/libunwind/src/libunwind.cpp index 46b26fedc28..d94c8cfb955 100644 --- a/lib/libunwind/src/libunwind.cpp +++ b/lib/libunwind/src/libunwind.cpp @@ -1,4 +1,4 @@ -//===--------------------------- libuwind.cpp -----------------------------===// +//===--------------------------- libunwind.cpp ----------------------------===// // // The LLVM Compiler Infrastructure // @@ -24,6 +24,8 @@ #include <stdlib.h> +#if !defined(__USING_SJLJ_EXCEPTIONS__) +#include "AddressSpace.hpp" #include "UnwindCursor.hpp" using namespace libunwind; @@ -42,25 +44,31 @@ extern int unw_getcontext(unw_context_t *); /// unw_getcontext(). _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor, unw_context_t *context) { - _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)\n", + _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)", static_cast<void *>(cursor), static_cast<void *>(context)); #if defined(__i386__) # define REGISTER_KIND Registers_x86 #elif defined(__x86_64__) # define REGISTER_KIND Registers_x86_64 +#elif defined(__powerpc64__) +# define REGISTER_KIND Registers_ppc64 #elif defined(__ppc__) # define REGISTER_KIND Registers_ppc #elif defined(__aarch64__) # define REGISTER_KIND Registers_arm64 -#elif _LIBUNWIND_ARM_EHABI +#elif defined(__arm__) # define REGISTER_KIND Registers_arm #elif defined(__or1k__) # define REGISTER_KIND Registers_or1k +#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float) +# define REGISTER_KIND Registers_mips_o32 +#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float) +# define REGISTER_KIND Registers_mips_n64 +#elif defined(__mips__) +# warning The MIPS architecture is not supported with this ABI and environment! #elif defined(__sparc__) && defined(__arch64__) # define REGISTER_KIND Registers_sparc64 -#elif defined(__mips__) -# warning The MIPS architecture is not supported. #else # error Architecture not supported #endif @@ -87,18 +95,18 @@ _LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor, switch (as->cpuType) { case CPU_TYPE_I386: new ((void *)cursor) - UnwindCursor<OtherAddressSpace<Pointer32<LittleEndian> >, + UnwindCursor<RemoteAddressSpace<Pointer32<LittleEndian>>, Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg); break; case CPU_TYPE_X86_64: - new ((void *)cursor) UnwindCursor< - OtherAddressSpace<Pointer64<LittleEndian> >, Registers_x86_64>( - ((unw_addr_space_x86_64 *)as)->oas, arg); + new ((void *)cursor) + UnwindCursor<RemoteAddressSpace<Pointer64<LittleEndian>>, + Registers_x86_64>(((unw_addr_space_x86_64 *)as)->oas, arg); break; case CPU_TYPE_POWERPC: new ((void *)cursor) - UnwindCursor<OtherAddressSpace<Pointer32<BigEndian> >, Registers_ppc>( - ((unw_addr_space_ppc *)as)->oas, arg); + UnwindCursor<RemoteAddressSpace<Pointer32<BigEndian>>, + Registers_ppc>(((unw_addr_space_ppc *)as)->oas, arg); break; default: return UNW_EUNSPEC; @@ -159,7 +167,7 @@ _LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) { /// Get value of specified register at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_word_t *value) { - _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)\n", + _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)", static_cast<void *>(cursor), regNum, static_cast<void *>(value)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; @@ -174,8 +182,8 @@ _LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum, /// Set value of specified register at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_word_t value) { - _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)\n", - static_cast<void *>(cursor), regNum, (long long)value); + _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%" PRIxPTR ")", + static_cast<void *>(cursor), regNum, value); typedef LocalAddressSpace::pint_t pint_t; AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validReg(regNum)) { @@ -193,7 +201,7 @@ _LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, /// Get value of specified float register at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_fpreg_t *value) { - _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)\n", + _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)", static_cast<void *>(cursor), regNum, static_cast<void *>(value)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; @@ -208,11 +216,11 @@ _LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, /// Set value of specified float register at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_fpreg_t value) { -#if _LIBUNWIND_ARM_EHABI - _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)\n", +#if defined(_LIBUNWIND_ARM_EHABI) + _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)", static_cast<void *>(cursor), regNum, value); #else - _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)\n", + _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)", static_cast<void *>(cursor), regNum, value); #endif AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; @@ -226,7 +234,7 @@ _LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, /// Move cursor to next frame. _LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_step(cursor=%p)\n", static_cast<void *>(cursor)); + _LIBUNWIND_TRACE_API("unw_step(cursor=%p)", static_cast<void *>(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->step(); } @@ -235,7 +243,7 @@ _LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) { /// Get unwind info at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor, unw_proc_info_t *info) { - _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)\n", + _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)", static_cast<void *>(cursor), static_cast<void *>(info)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; co->getInfo(info); @@ -248,7 +256,7 @@ _LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor, /// Resume execution at cursor position (aka longjump). _LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)\n", static_cast<void *>(cursor)); + _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)", static_cast<void *>(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; co->jumpto(); return UNW_EUNSPEC; @@ -258,7 +266,7 @@ _LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) { /// Get name of function at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf, size_t bufLen, unw_word_t *offset) { - _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)\n", + _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)", static_cast<void *>(cursor), static_cast<void *>(buf), static_cast<unsigned long>(bufLen)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; @@ -271,7 +279,7 @@ _LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf, /// Checks if a register is a floating-point register. _LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) { - _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)\n", + _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)", static_cast<void *>(cursor), regNum); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->validFloatReg(regNum); @@ -281,7 +289,7 @@ _LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) { /// Checks if a register is a floating-point register. _LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor, unw_regnum_t regNum) { - _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)\n", + _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)", static_cast<void *>(cursor), regNum); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->getRegisterName(regNum); @@ -290,7 +298,7 @@ _LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor, /// Checks if current frame is signal trampoline. _LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)\n", + _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)", static_cast<void *>(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->isSignalFrame(); @@ -299,7 +307,7 @@ _LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) { #ifdef __arm__ // Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD _LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)\n", + _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)", static_cast<void *>(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->saveVFPAsX(); @@ -307,11 +315,11 @@ _LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) { #endif -#if _LIBUNWIND_SUPPORT_DWARF_UNWIND -/// SPI: walks cached dwarf entries +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) +/// SPI: walks cached DWARF entries _LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)( unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { - _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)\n", + _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)", reinterpret_cast<void *>(func)); DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func); } @@ -341,7 +349,8 @@ void _unw_remove_dynamic_fde(unw_word_t fde) { // fde is own mh_group DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde); } -#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND +#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) +#endif // !defined(__USING_SJLJ_EXCEPTIONS__) @@ -373,5 +382,17 @@ bool logUnwinding() { return log; } +_LIBUNWIND_HIDDEN +bool logDWARF() { + // do manual lock to avoid use of _cxa_guard_acquire or initializers + static bool checked = false; + static bool log = false; + if (!checked) { + log = (getenv("LIBUNWIND_PRINT_DWARF") != NULL); + checked = true; + } + return log; +} + #endif // NDEBUG diff --git a/lib/libunwind/src/unwind_ext.h b/lib/libunwind/src/unwind_ext.h deleted file mode 100644 index c40ce6a1610..00000000000 --- a/lib/libunwind/src/unwind_ext.h +++ /dev/null @@ -1,37 +0,0 @@ -//===-------------------------- unwind_ext.h ------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Extensions to unwind API. -// -//===----------------------------------------------------------------------===// - -#ifndef __UNWIND_EXT__ -#define __UNWIND_EXT__ - -#include "unwind.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// These platform specific functions to get and set the top context are -// implemented elsewhere. - -extern struct _Unwind_FunctionContext * -__Unwind_SjLj_GetTopOfFunctionStack(); - -extern void -__Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc); - -#ifdef __cplusplus -} -#endif - -#endif // __UNWIND_EXT__ - - |