merge libunwind 6.0.0; ok patrick@, kettenis@
authorrobert <robert@openbsd.org>
Tue, 11 Sep 2018 18:03:05 +0000 (18:03 +0000)
committerrobert <robert@openbsd.org>
Tue, 11 Sep 2018 18:03:05 +0000 (18:03 +0000)
13 files changed:
lib/libunwind/include/__libunwind_config.h
lib/libunwind/include/libunwind.h
lib/libunwind/include/mach-o/compact_unwind_encoding.h
lib/libunwind/src/AddressSpace.hpp
lib/libunwind/src/DwarfInstructions.hpp
lib/libunwind/src/DwarfParser.hpp
lib/libunwind/src/EHHeaderParser.hpp
lib/libunwind/src/Registers.hpp
lib/libunwind/src/UnwindCursor.hpp
lib/libunwind/src/UnwindRegistersRestore.S
lib/libunwind/src/UnwindRegistersSave.S
lib/libunwind/src/libunwind.cpp
lib/libunwind/src/unwind_ext.h [deleted file]

index 112ff25..95632e0 100644 (file)
 
 #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
 #  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__
index 5c8b2ac..29cf62e 100644 (file)
@@ -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
 //
 //===----------------------------------------------------------------------===//
 #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
index de14fd5..b71c2c8 100644 (file)
@@ -6,7 +6,7 @@
 // Source Licenses. See LICENSE.TXT for details.
 //
 //
-// Darwin's alternative to DWARF based unwind encodings.
+// Darwin's alternative to dwarf based unwind encodings.
 //
 //===----------------------------------------------------------------------===//
 
@@ -17,7 +17,7 @@
 #include <stdint.h>
 
 //
-// Compilers can emit standard DWARF FDEs in the __TEXT,__eh_frame section
+// Compilers can emit standard Dwarf FDEs in the __TEXT,__eh_frame section
 // of object files. Or compilers can emit compact unwind information in
 // the __LD,__compact_unwind section.
 //
 // runtime to access unwind info for any given function.  If the compiler
 // emitted compact unwind info for the function, that compact unwind info will
 // be encoded in the __TEXT,__unwind_info section. If the compiler emitted
-// DWARF unwind info, the __TEXT,__unwind_info section will contain the offset
+// dwarf unwind info, the __TEXT,__unwind_info section will contain the offset
 // of the FDE in the __TEXT,__eh_frame section in the final linked image.
 //
-// Note: Previously, the linker would transform some DWARF unwind infos into
+// Note: Previously, the linker would transform some dwarf unwind infos into
 //       compact unwind info.  But that is fragile and no longer done.
 
 
@@ -58,7 +58,7 @@ enum {
 // 1-bit: has lsda
 // 2-bit: personality index
 //
-// 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=DWARF
+// 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=dwarf
 //  ebp based:
 //        15-bits (5*3-bits per reg) register permutation
 //        8-bits for stack offset
@@ -128,9 +128,9 @@ enum {
 //    UNWIND_X86_FRAMELESS_STACK_SIZE.  
 // UNWIND_X86_MODE_DWARF:
 //    No compact unwind encoding is available.  Instead the low 24-bits of the
-//    compact encoding is the offset of the DWARF FDE in the __eh_frame section.
+//    compact encoding is the offset of the dwarf FDE in the __eh_frame section.
 //    This mode is never used in object files.  It is only generated by the 
-//    linker in final linked images which have only DWARF unwind info for a
+//    linker in final linked images which have only dwarf unwind info for a
 //    function.
 //
 // The permutation encoding is a Lehmer code sequence encoded into a
@@ -193,7 +193,7 @@ enum {
 // 1-bit: has lsda
 // 2-bit: personality index
 //
-// 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=DWARF
+// 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=dwarf
 //  rbp based:
 //        15-bits (5*3-bits per reg) register permutation
 //        8-bits for stack offset
@@ -262,9 +262,9 @@ enum {
 //    UNWIND_X86_64_FRAMELESS_STACK_SIZE.  
 // UNWIND_X86_64_MODE_DWARF:
 //    No compact unwind encoding is available.  Instead the low 24-bits of the
-//    compact encoding is the offset of the DWARF FDE in the __eh_frame section.
+//    compact encoding is the offset of the dwarf FDE in the __eh_frame section.
 //    This mode is never used in object files.  It is only generated by the 
-//    linker in final linked images which have only DWARF unwind info for a
+//    linker in final linked images which have only dwarf unwind info for a
 //    function.
 //
 
@@ -275,14 +275,14 @@ enum {
 // 1-bit: has lsda
 // 2-bit: personality index
 //
-// 4-bits: 4=frame-based, 3=DWARF, 2=frameless
+// 4-bits: 4=frame-based, 3=dwarf, 2=frameless
 //  frameless:
 //        12-bits of stack size
 //  frame-based:
 //        4-bits D reg pairs saved
 //        5-bits X reg pairs saved
-//  DWARF:
-//        24-bits offset of DWARF FDE in __eh_frame section
+//  dwarf:
+//        24-bits offset of dwarf FDE in __eh_frame section
 //
 enum {
     UNWIND_ARM64_MODE_MASK                     = 0x0F000000,
@@ -320,9 +320,9 @@ enum {
 //    UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK.
 // UNWIND_ARM64_MODE_DWARF:
 //    No compact unwind encoding is available.  Instead the low 24-bits of the
-//    compact encoding is the offset of the DWARF FDE in the __eh_frame section.
+//    compact encoding is the offset of the dwarf FDE in the __eh_frame section.
 //    This mode is never used in object files.  It is only generated by the 
-//    linker in final linked images which have only DWARF unwind info for a
+//    linker in final linked images which have only dwarf unwind info for a
 //    function.
 //
 
@@ -385,7 +385,7 @@ enum {
 // saved at that range of the function.
 //
 // If a particular function is so wacky that there is no compact unwind way
-// to encode it, then the compiler can emit traditional DWARF unwind info.  
+// to encode it, then the compiler can emit traditional dwarf unwind info.  
 // The runtime will use which ever is available.
 //
 // Runtime support for compact unwind encodings are only available on 10.6 
index 56c89e8..1714575 100644 (file)
@@ -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
index 7fa62cd..eff054e 100644 (file)
@@ -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");
     }
 
   }
index 2f8c2c6..1911f16 100644 (file)
 #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;
       }
     }
index 1bf6bb3..d6f4e12 100644 (file)
@@ -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;
   }
index 1a98d92..888d07b 100644 (file)
@@ -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__
index 52f3347..df12a16 100644 (file)
@@ -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__
 #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 &sects);
 
   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 &sects,
                                             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 &sects);
   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 &sects,
@@ -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 &sects) {
@@ -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 \
index 3b185aa..94141de 100644 (file)
 
   .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
 
index f24c539..81d413c 100644 (file)
@@ -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
 
index 46b26fe..d94c8cf 100644 (file)
@@ -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 (file)
index c40ce6a..0000000
+++ /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__
-
-