Commit 1e66ac5755

Jakub Konka <kubkon@jakubkonka.com>
2020-12-16 11:48:54
Update libunwind
llvm commit b2851aea80e5a8f0cfd6c3c5a56a6b00fb28c6b6
1 parent 8612dac
lib/libunwind/include/libunwind.h
@@ -43,6 +43,12 @@
   #define LIBUNWIND_AVAIL
 #endif
 
+#if defined(_WIN32) && defined(__SEH__)
+  #define LIBUNWIND_CURSOR_ALIGNMENT_ATTR __attribute__((__aligned__(16)))
+#else
+  #define LIBUNWIND_CURSOR_ALIGNMENT_ATTR
+#endif
+
 /* error codes */
 enum {
   UNW_ESUCCESS      = 0,     /* no error */
@@ -68,7 +74,7 @@ typedef struct unw_context_t unw_context_t;
 
 struct unw_cursor_t {
   uint64_t data[_LIBUNWIND_CURSOR_SIZE];
-};
+} LIBUNWIND_CURSOR_ALIGNMENT_ATTR;
 typedef struct unw_cursor_t unw_cursor_t;
 
 typedef struct unw_addr_space *unw_addr_space_t;
lib/libunwind/src/AddressSpace.hpp
@@ -17,6 +17,12 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "libunwind.h"
+#include "config.h"
+#include "dwarf2.h"
+#include "EHHeaderParser.hpp"
+#include "Registers.hpp"
+
 #ifndef _LIBUNWIND_USE_DLADDR
   #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
     #define _LIBUNWIND_USE_DLADDR 1
@@ -39,19 +45,6 @@ struct EHABIIndexEntry {
 };
 #endif
 
-#ifdef __APPLE__
-#include <mach-o/getsect.h>
-namespace libunwind {
-   bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde);
-}
-#endif
-
-#include "libunwind.h"
-#include "config.h"
-#include "dwarf2.h"
-#include "EHHeaderParser.hpp"
-#include "Registers.hpp"
-
 #ifdef __APPLE__
 
   struct dyld_unwind_sections
@@ -62,43 +55,9 @@ namespace libunwind {
     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
 
-      // 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);
-
-      if (!info->dwarf_section) {
-        info->dwarf_section_length = 0;
-      }
-
-      if (!info->compact_unwind_section) {
-        info->compact_unwind_section_length = 0;
-      }
-
-      return true;
-    }
-  #endif
+  // In 10.7.0 or later, libSystem.dylib implements this function.
+  extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
 
 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
 
@@ -139,22 +98,15 @@ extern char __eh_frame_hdr_end;
 extern char __exidx_start;
 extern char __exidx_end;
 
-#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
 
-// 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>
-#else
 #include <windows.h>
 #include <psapi.h>
-#endif
-#if !defined(ElfW)
-#define ElfW(type) Elf_##type
-#endif
+
+#elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) ||                               \
+      defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX)
+
+#include <link.h>
 
 #endif
 
@@ -162,11 +114,15 @@ namespace libunwind {
 
 /// Used by findUnwindSections() to return info about needed sections.
 struct UnwindInfoSections {
-#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) ||       \
-    defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
-  // No dso_base for SEH or ARM EHABI.
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) ||                                \
+    defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) ||                              \
+    defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
+  // No dso_base for SEH.
   uintptr_t       dso_base;
 #endif
+#if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
+  uintptr_t       text_segment_length;
+#endif
 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
   uintptr_t       dwarf_section;
   uintptr_t       dwarf_section_length;
@@ -290,11 +246,11 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
     if (p == pend)
       _LIBUNWIND_ABORT("truncated sleb128 expression");
     byte = *p++;
-    result |= ((byte & 0x7f) << bit);
+    result |= (uint64_t)(byte & 0x7f) << bit;
     bit += 7;
   } while (byte & 0x80);
   // sign extend negative numbers
-  if ((byte & 0x40) != 0)
+  if ((byte & 0x40) != 0 && bit < 64)
     result |= (-1ULL) << bit;
   addr = (pint_t) p;
   return result;
@@ -392,23 +348,14 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
   return result;
 }
 
-#ifdef __APPLE__
-#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
-#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
-#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
-#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
-#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__)
-// Code inside findUnwindSections handles all these cases.
-//
-// Although the above ifdef chain is ugly, there doesn't seem to be a cleaner
-// way to handle it. The generalized boolean expression is:
-//
-//  A OR (B AND C) OR (D AND C) OR (B AND E) OR (F AND E) OR (D AND G)
-//
-// Running it through various boolean expression simplifiers gives expressions
-// that don't help at all.
-#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+#if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
 
+// 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.
+#if !defined(ElfW)
+  #define ElfW(type) Elf_##type
+#endif
 #if !defined(Elf_Half)
   typedef ElfW(Half) Elf_Half;
 #endif
@@ -447,16 +394,12 @@ struct _LIBUNWIND_HIDDEN dl_iterate_cb_data {
   uintptr_t targetAddr;
 };
 
-#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
-
 #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE)
 #include "FrameHeaderCache.hpp"
 
-// There should be just one of these per process.
-static FrameHeaderCache ProcessFrameHeaderCache;
+// Typically there is one cache per process, but when libunwind is built as a
+// hermetic static library, then each shared object may have its own cache.
+static FrameHeaderCache TheFrameHeaderCache;
 #endif
 
 static bool checkAddrInSegment(const Elf_Phdr *phdr, size_t image_base,
@@ -466,95 +409,93 @@ static bool checkAddrInSegment(const Elf_Phdr *phdr, size_t image_base,
     uintptr_t end = begin + phdr->p_memsz;
     if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) {
       cbdata->sects->dso_base = begin;
-      cbdata->sects->dwarf_section_length = phdr->p_memsz;
+      cbdata->sects->text_segment_length = phdr->p_memsz;
       return true;
     }
   }
   return false;
 }
 
+static bool checkForUnwindInfoSegment(const Elf_Phdr *phdr, size_t image_base,
+                                      dl_iterate_cb_data *cbdata) {
+#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
+  if (phdr->p_type == PT_GNU_EH_FRAME) {
+    EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
+    uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr;
+    cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
+    cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
+    if (EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
+            *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
+            hdrInfo)) {
+      // .eh_frame_hdr records the start of .eh_frame, but not its size.
+      // Rely on a zero terminator to find the end of the section.
+      cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
+      cbdata->sects->dwarf_section_length = UINTPTR_MAX;
+      return true;
+    }
+  }
+  return false;
+#elif defined(_LIBUNWIND_ARM_EHABI)
+  if (phdr->p_type == PT_ARM_EXIDX) {
+    uintptr_t exidx_start = image_base + phdr->p_vaddr;
+    cbdata->sects->arm_section = exidx_start;
+    cbdata->sects->arm_section_length = phdr->p_memsz;
+    return true;
+  }
+  return false;
+#else
+#error Need one of _LIBUNWIND_SUPPORT_DWARF_INDEX or _LIBUNWIND_ARM_EHABI
+#endif
+}
+
 static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo,
                                     size_t pinfo_size, void *data) {
   auto cbdata = static_cast<dl_iterate_cb_data *>(data);
   if (pinfo->dlpi_phnum == 0 || cbdata->targetAddr < pinfo->dlpi_addr)
     return 0;
 #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE)
-  if (ProcessFrameHeaderCache.find(pinfo, pinfo_size, data))
+  if (TheFrameHeaderCache.find(pinfo, pinfo_size, data))
     return 1;
+#else
+  // Avoid warning about unused variable.
+  (void)pinfo_size;
 #endif
 
   Elf_Addr image_base = calculateImageBase(pinfo);
-  bool found_obj = false;
-  bool found_hdr = false;
 
-  // Third phdr is usually the executable phdr.
-  if (pinfo->dlpi_phnum > 2)
-    found_obj = checkAddrInSegment(&pinfo->dlpi_phdr[2], image_base, cbdata);
+  // Most shared objects seen in this callback function likely don't contain the
+  // target address, so optimize for that. Scan for a matching PT_LOAD segment
+  // first and bail when it isn't found.
+  bool found_text = false;
+  for (Elf_Half i = 0; i < pinfo->dlpi_phnum; ++i) {
+    if (checkAddrInSegment(&pinfo->dlpi_phdr[i], image_base, cbdata)) {
+      found_text = true;
+      break;
+    }
+  }
+  if (!found_text)
+    return 0;
 
-  // PT_GNU_EH_FRAME is usually near the end. Iterate backward. We already know
-  // that there is one or more phdrs.
+  // PT_GNU_EH_FRAME and PT_ARM_EXIDX are usually near the end. Iterate
+  // backward.
+  bool found_unwind = false;
   for (Elf_Half i = pinfo->dlpi_phnum; i > 0; i--) {
     const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i - 1];
-    if (!found_hdr && phdr->p_type == PT_GNU_EH_FRAME) {
-      EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
-      uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr;
-      cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
-      cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
-      found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
-          *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
-          hdrInfo);
-      if (found_hdr)
-        cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
-    } else if (!found_obj) {
-      found_obj = checkAddrInSegment(phdr, image_base, cbdata);
-    }
-    if (found_obj && found_hdr) {
-#if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE)
-      ProcessFrameHeaderCache.add(cbdata->sects);
-#endif
-      return 1;
+    if (checkForUnwindInfoSegment(phdr, image_base, cbdata)) {
+      found_unwind = true;
+      break;
     }
   }
-  cbdata->sects->dwarf_section_length = 0;
-  return 0;
-}
-
-#else  // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND)
-// Given all the #ifdef's above, the code here is for
-// defined(LIBUNWIND_ARM_EHABI)
-
-static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t,
-                                    void *data) {
-  auto *cbdata = static_cast<dl_iterate_cb_data *>(data);
-  bool found_obj = false;
-  bool found_hdr = false;
-
-  assert(cbdata);
-  assert(cbdata->sects);
-
-  if (cbdata->targetAddr < pinfo->dlpi_addr)
+  if (!found_unwind)
     return 0;
 
-  Elf_Addr image_base = calculateImageBase(pinfo);
-
-  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 = image_base + 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 = image_base + 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;
+#if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE)
+  TheFrameHeaderCache.add(cbdata->sects);
+#endif
+  return 1;
 }
-#endif  // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND)
-#endif  // defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+
+#endif  // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
 
 
 inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
@@ -572,6 +513,7 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
     return true;
   }
 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
+  info.dso_base = 0;
   // 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);
@@ -638,16 +580,14 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
   (void)targetAddr;
   (void)info;
   return true;
-#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__)
-  // For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After
-  // API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster.
+#elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX)
   int length = 0;
   info.arm_section =
       (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length);
   info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry);
   if (info.arm_section && info.arm_section_length)
     return true;
-#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+#elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
   dl_iterate_cb_data cb_data = {this, &info, targetAddr};
   int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data);
   return static_cast<bool>(found);
@@ -658,14 +598,10 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
 
 
 inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
-#ifdef __APPLE__
-  return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde));
-#else
   // TO DO: if OS has way to dynamically register FDEs, check that.
   (void)targetAddr;
   (void)fde;
   return false;
-#endif
 }
 
 inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
lib/libunwind/src/assembly.h
@@ -25,9 +25,6 @@
 #define PPC64_OFFS_VRSAVE 304
 #define PPC64_OFFS_FP     312
 #define PPC64_OFFS_V      824
-#ifdef _ARCH_PWR8
-#define PPC64_HAS_VMX
-#endif
 #elif defined(__APPLE__) && defined(__aarch64__)
 #define SEPARATOR %%
 #else
@@ -48,6 +45,24 @@
 #define PPC64_OPD2
 #endif
 
+#if defined(__ARM_FEATURE_BTI_DEFAULT)
+  .pushsection ".note.gnu.property", "a" SEPARATOR                             \
+  .balign 8 SEPARATOR                                                          \
+  .long 4 SEPARATOR                                                            \
+  .long 0x10 SEPARATOR                                                         \
+  .long 0x5 SEPARATOR                                                          \
+  .asciz "GNU" SEPARATOR                                                       \
+  .long 0xc0000000 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */          \
+  .long 4 SEPARATOR                                                            \
+  .long 3 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_BTI AND */               \
+                    /* GNU_PROPERTY_AARCH64_FEATURE_1_PAC */                   \
+  .long 0 SEPARATOR                                                            \
+  .popsection SEPARATOR
+#define AARCH64_BTI  bti c
+#else
+#define AARCH64_BTI
+#endif
+
 #define GLUE2(a, b) a ## b
 #define GLUE(a, b) GLUE2(a, b)
 #define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
@@ -144,7 +159,8 @@
   SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
   PPC64_OPD1                                                                   \
   SYMBOL_NAME(name):                                                           \
-  PPC64_OPD2
+  PPC64_OPD2                                                                   \
+  AARCH64_BTI
 
 #if defined(__arm__)
 #if !defined(__ARM_ARCH)
lib/libunwind/src/config.h
@@ -18,23 +18,15 @@
 #include <stdint.h>
 #include <stdlib.h>
 
-// Define static_assert() unless already defined by compiler.
-#ifndef __has_feature
-  #define __has_feature(__x) 0
-#endif
-#if !(__has_feature(cxx_static_assert)) && !defined(static_assert)
-  #define static_assert(__b, __m) \
-      extern int compile_time_assert_failed[ ( __b ) ? 1 : -1 ]  \
-                                                  __attribute__( ( unused ) );
-#endif
+#include <__libunwind_config.h>
 
 // Platform specific configuration defines.
 #ifdef __APPLE__
   #if defined(FOR_DYLD)
-    #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND
+    #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1
   #else
-    #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND
-    #define _LIBUNWIND_SUPPORT_DWARF_UNWIND   1
+    #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1
+    #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
   #endif
 #elif defined(_WIN32)
   #ifdef __SEH__
@@ -42,8 +34,19 @@
   #else
     #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
   #endif
+#elif defined(_LIBUNWIND_IS_BAREMETAL)
+  #if !defined(_LIBUNWIND_ARM_EHABI)
+    #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
+    #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1
+  #endif
+#elif defined(__BIONIC__) && defined(_LIBUNWIND_ARM_EHABI)
+  // For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After
+  // API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster.
+  #define _LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX 1
 #else
-  #if defined(__ARM_DWARF_EH__) || !defined(__arm__)
+  // Assume an ELF system with a dl_iterate_phdr function.
+  #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1
+  #if !defined(_LIBUNWIND_ARM_EHABI)
     #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
     #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1
   #endif
@@ -91,6 +94,8 @@
 #error Unsupported target
 #endif
 
+// Apple/armv7k defaults to DWARF/Compact unwinding, but its libunwind also
+// needs to include the SJLJ APIs.
 #if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__)
 #define _LIBUNWIND_BUILD_SJLJ_APIS
 #endif
@@ -111,8 +116,27 @@
 #endif
 #endif
 
-#if defined(__powerpc64__) && defined(_ARCH_PWR8)
-#define PPC64_HAS_VMX
+#ifndef _LIBUNWIND_REMEMBER_HEAP_ALLOC
+#if defined(_LIBUNWIND_REMEMBER_STACK_ALLOC) || defined(__APPLE__) ||          \
+    defined(__linux__) || defined(__ANDROID__) || defined(__MINGW32__) ||      \
+    defined(_LIBUNWIND_IS_BAREMETAL)
+#define _LIBUNWIND_REMEMBER_ALLOC(_size) alloca(_size)
+#define _LIBUNWIND_REMEMBER_FREE(_ptr)                                         \
+  do {                                                                         \
+  } while (0)
+#elif defined(_WIN32)
+#define _LIBUNWIND_REMEMBER_ALLOC(_size) _malloca(_size)
+#define _LIBUNWIND_REMEMBER_FREE(_ptr) _freea(_ptr)
+#define _LIBUNWIND_REMEMBER_CLEANUP_NEEDED
+#else
+#define _LIBUNWIND_REMEMBER_ALLOC(_size) malloc(_size)
+#define _LIBUNWIND_REMEMBER_FREE(_ptr) free(_ptr)
+#define _LIBUNWIND_REMEMBER_CLEANUP_NEEDED
+#endif
+#else /* _LIBUNWIND_REMEMBER_HEAP_ALLOC */
+#define _LIBUNWIND_REMEMBER_ALLOC(_size) malloc(_size)
+#define _LIBUNWIND_REMEMBER_FREE(_ptr) free(_ptr)
+#define _LIBUNWIND_REMEMBER_CLEANUP_NEEDED
 #endif
 
 #if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL)
lib/libunwind/src/DwarfInstructions.hpp
@@ -93,7 +93,8 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
 
   case CFI_Parser<A>::kRegisterInRegister:
     return registers.getRegister((int)savedReg.value);
-
+  case CFI_Parser<A>::kRegisterUndefined:
+    return 0;
   case CFI_Parser<A>::kRegisterUnused:
   case CFI_Parser<A>::kRegisterOffsetFromCFA:
     // FIX ME
@@ -117,6 +118,7 @@ double DwarfInstructions<A, R>::getSavedFloatRegister(
 
   case CFI_Parser<A>::kRegisterIsExpression:
   case CFI_Parser<A>::kRegisterUnused:
+  case CFI_Parser<A>::kRegisterUndefined:
   case CFI_Parser<A>::kRegisterOffsetFromCFA:
   case CFI_Parser<A>::kRegisterInRegister:
     // FIX ME
@@ -140,6 +142,7 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister(
 
   case CFI_Parser<A>::kRegisterIsExpression:
   case CFI_Parser<A>::kRegisterUnused:
+  case CFI_Parser<A>::kRegisterUndefined:
   case CFI_Parser<A>::kRegisterOffsetFromCFA:
   case CFI_Parser<A>::kRegisterInRegister:
     // FIX ME
@@ -190,6 +193,10 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
                                     prolog.savedRegisters[i]));
           else
             return UNW_EBADREG;
+        } else if (i == (int)cieInfo.returnAddressRegister) {
+            // Leaf function keeps the return address in register and there is no
+            // explicit intructions how to restore it.
+            returnAddress = registers.getRegister(cieInfo.returnAddressRegister);
         }
       }
 
lib/libunwind/src/DwarfParser.hpp
@@ -69,6 +69,7 @@ public:
   };
   enum RegisterSavedWhere {
     kRegisterUnused,
+    kRegisterUndefined,
     kRegisterInCFA,
     kRegisterOffsetFromCFA,
     kRegisterInRegister,
@@ -87,9 +88,6 @@ public:
     int32_t           cfaRegisterOffset;  // CFA = (cfaRegister)+cfaRegisterOffset
     int64_t           cfaExpression;      // CFA = expression
     uint32_t          spExtraArgSize;
-    uint32_t          codeOffsetAtStackDecrement;
-    bool              registersInOtherRegisters;
-    bool              sameValueUsed;
     RegisterLocation  savedRegisters[kMaxRegisterNumber + 1];
     enum class InitializeTime { kLazy, kNormal };
 
@@ -134,8 +132,26 @@ public:
     PrologInfo info;
   };
 
+  struct RememberStack {
+    PrologInfoStackEntry *entry;
+    RememberStack() : entry(nullptr) {}
+    ~RememberStack() {
+#if defined(_LIBUNWIND_REMEMBER_CLEANUP_NEEDED)
+      // Clean up rememberStack. Even in the case where every
+      // DW_CFA_remember_state is paired with a DW_CFA_restore_state,
+      // parseInstructions can skip restore opcodes if it reaches the target PC
+      // and stops interpreting, so we have to make sure we don't leak memory.
+      while (entry) {
+        PrologInfoStackEntry *next = entry->next;
+        _LIBUNWIND_REMEMBER_FREE(entry);
+        entry = next;
+      }
+#endif
+    }
+  };
+
   static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
-                      uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
+                      uintptr_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
                       CIE_Info *cieInfo);
   static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
                                FDE_Info *fdeInfo, CIE_Info *cieInfo);
@@ -144,13 +160,6 @@ public:
                                    int arch, PrologInfo *results);
 
   static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
-
-private:
-  static bool parseInstructions(A &addressSpace, pint_t instructions,
-                                pint_t instructionsEnd, const CIE_Info &cieInfo,
-                                pint_t pcoffset,
-                                PrologInfoStackEntry *&rememberStack, int arch,
-                                PrologInfo *results);
 };
 
 /// Parse a FDE into a CIE_Info and an FDE_Info
@@ -166,7 +175,7 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
     p += 8;
   }
   if (cfiLength == 0)
-    return "FDE has zero length"; // end marker
+    return "FDE has zero length"; // zero terminator
   uint32_t ciePointer = addressSpace.get32(p);
   if (ciePointer == 0)
     return "FDE is really a CIE"; // this is a CIE not an FDE
@@ -211,11 +220,13 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
 /// Scan an eh_frame section to find an FDE for a pc
 template <typename A>
 bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
-                            uint32_t sectionLength, pint_t fdeHint,
+                            uintptr_t sectionLength, pint_t fdeHint,
                             FDE_Info *fdeInfo, CIE_Info *cieInfo) {
   //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
   pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
-  const pint_t ehSectionEnd = p + sectionLength;
+  const pint_t ehSectionEnd = (sectionLength == UINTPTR_MAX)
+                                  ? static_cast<pint_t>(-1)
+                                  : (ehSectionStart + sectionLength);
   while (p < ehSectionEnd) {
     pint_t currentCFI = p;
     //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
@@ -227,7 +238,7 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
       p += 8;
     }
     if (cfiLength == 0)
-      return false; // end marker
+      return false; // zero terminator
     uint32_t id = addressSpace.get32(p);
     if (id == 0) {
       // Skip over CIEs.
@@ -336,7 +347,8 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
   // parse data alignment factor
   cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd);
   // parse return address register
-  uint64_t raReg = addressSpace.getULEB128(p, cieContentEnd);
+  uint64_t raReg = (version == 1) ? addressSpace.get8(p++)
+                                  : addressSpace.getULEB128(p, cieContentEnd);
   assert(raReg < 255 && "return address register too large");
   cieInfo->returnAddressRegister = (uint8_t)raReg;
   // parse augmentation data based on augmentation string
@@ -390,418 +402,409 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
                                          const FDE_Info &fdeInfo,
                                          const CIE_Info &cieInfo, pint_t upToPC,
                                          int arch, PrologInfo *results) {
-  PrologInfoStackEntry *rememberStack = NULL;
-
-  // parse CIE then FDE instructions
-  bool returnValue =
-      parseInstructions(addressSpace, cieInfo.cieInstructions,
-                        cieInfo.cieStart + cieInfo.cieLength, cieInfo,
-                        (pint_t)(-1), rememberStack, arch, results) &&
-      parseInstructions(addressSpace, fdeInfo.fdeInstructions,
-                        fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
-                        upToPC - fdeInfo.pcStart, rememberStack, arch, results);
-
-#if !defined(_LIBUNWIND_NO_HEAP)
-  // Clean up rememberStack. Even in the case where every DW_CFA_remember_state
-  // is paired with a DW_CFA_restore_state, parseInstructions can skip restore
-  // opcodes if it reaches the target PC and stops interpreting, so we have to
-  // make sure we don't leak memory.
-  while (rememberStack) {
-    PrologInfoStackEntry *next = rememberStack->next;
-    free(rememberStack);
-    rememberStack = next;
-  }
-#endif
-
-  return returnValue;
-}
+  // Alloca is used for the allocation of the rememberStack entries. It removes
+  // the dependency on new/malloc but the below for loop can not be refactored
+  // into functions. Entry could be saved during the processing of a CIE and
+  // restored by an FDE.
+  RememberStack rememberStack;
+
+  struct ParseInfo {
+    pint_t instructions;
+    pint_t instructionsEnd;
+    pint_t pcoffset;
+  };
 
-/// "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,
-                                      int arch, PrologInfo *results) {
-  pint_t p = instructions;
-  pint_t codeOffset = 0;
-  // initialState initialized as registers in results are modified. Use
-  // PrologInfo accessor functions to avoid reading uninitialized data.
-  PrologInfo initialState(PrologInfo::InitializeTime::kLazy);
-
-  _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;
-    int64_t offset;
-    uint64_t length;
-    uint8_t opcode = addressSpace.get8(p);
-    uint8_t operand;
-#if !defined(_LIBUNWIND_NO_HEAP)
-    PrologInfoStackEntry *entry;
-#endif
-    ++p;
-    switch (opcode) {
-    case DW_CFA_nop:
-      _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n");
-      break;
-    case DW_CFA_set_loc:
-      codeOffset =
-          addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
-      _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n");
-      break;
-    case DW_CFA_advance_loc1:
-      codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
-      p += 1;
-      _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;
-      _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;
-      _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) {
-        _LIBUNWIND_LOG0(
-                "malformed DW_CFA_offset_extended DWARF unwind, reg too big");
-        return false;
-      }
-      results->setRegister(reg, kRegisterInCFA, offset, initialState);
-      _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) {
-        _LIBUNWIND_LOG0(
-            "malformed DW_CFA_restore_extended DWARF unwind, reg too big");
-        return false;
-      }
-      results->restoreRegisterToInitialState(reg, initialState);
-      _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg);
-      break;
-    case DW_CFA_undefined:
-      reg = addressSpace.getULEB128(p, instructionsEnd);
-      if (reg > kMaxRegisterNumber) {
-        _LIBUNWIND_LOG0(
-                "malformed DW_CFA_undefined DWARF unwind, reg too big");
-        return false;
-      }
-      results->setRegisterLocation(reg, kRegisterUnused, initialState);
-      _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg);
-      break;
-    case DW_CFA_same_value:
-      reg = addressSpace.getULEB128(p, instructionsEnd);
-      if (reg > kMaxRegisterNumber) {
-        _LIBUNWIND_LOG0(
-                "malformed DW_CFA_same_value DWARF unwind, reg too big");
-        return false;
-      }
-      // <rdar://problem/8456377> DW_CFA_same_value unsupported
-      // "same value" means register was stored in frame, but its current
-      // value has not changed, so no need to restore from frame.
-      // We model this as if the register was never saved.
-      results->setRegisterLocation(reg, kRegisterUnused, initialState);
-      // set flag to disable conversion to compact unwind
-      results->sameValueUsed = true;
-      _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) {
-        _LIBUNWIND_LOG0(
-                "malformed DW_CFA_register DWARF unwind, reg too big");
-        return false;
-      }
-      if (reg2 > kMaxRegisterNumber) {
-        _LIBUNWIND_LOG0(
-                "malformed DW_CFA_register DWARF unwind, reg2 too big");
-        return false;
-      }
-      results->setRegister(reg, kRegisterInRegister, (int64_t)reg2,
-                           initialState);
-      // set flag to disable conversion to compact unwind
-      results->registersInOtherRegisters = true;
-      _LIBUNWIND_TRACE_DWARF(
-          "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2);
-      break;
-#if !defined(_LIBUNWIND_NO_HEAP)
-    case DW_CFA_remember_state:
-      // avoid operator new, because that would be an upward dependency
-      entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
-      if (entry != NULL) {
-        entry->next = rememberStack;
-        entry->info = *results;
-        rememberStack = entry;
-      } else {
-        return false;
-      }
-      _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n");
-      break;
-    case DW_CFA_restore_state:
-      if (rememberStack != NULL) {
-        PrologInfoStackEntry *top = rememberStack;
-        *results = top->info;
-        rememberStack = top->next;
-        free((char *)top);
-      } else {
-        return false;
-      }
-      _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) {
-        _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big");
-        return false;
-      }
-      results->cfaRegister = (uint32_t)reg;
-      results->cfaRegisterOffset = (int32_t)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) {
-        _LIBUNWIND_LOG0(
-            "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big");
-        return false;
-      }
-      results->cfaRegister = (uint32_t)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;
-      _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);
-      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) {
-        _LIBUNWIND_LOG0(
-                "malformed DW_CFA_expression DWARF unwind, reg too big");
-        return false;
-      }
-      results->setRegister(reg, kRegisterAtExpression, (int64_t)p,
-                           initialState);
-      length = addressSpace.getULEB128(p, instructionsEnd);
-      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) {
-        _LIBUNWIND_LOG0(
-            "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big");
-        return false;
-      }
-      offset =
-          addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
-      results->setRegister(reg, kRegisterInCFA, offset, initialState);
-      _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) {
-        _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;
-      _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;
-      _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->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState);
-      _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) {
-        _LIBUNWIND_LOG0(
-                "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big");
-        return false;
-      }
-      offset =
-          addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
-      results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState);
-      _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) {
-        _LIBUNWIND_LOG0(
-                "malformed DW_CFA_val_expression DWARF unwind, reg too big");
-        return false;
-      }
-      results->setRegister(reg, kRegisterIsExpression, (int64_t)p,
-                           initialState);
-      length = addressSpace.getULEB128(p, instructionsEnd);
-      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_args_size:
-      length = addressSpace.getULEB128(p, instructionsEnd);
-      results->spExtraArgSize = (uint32_t)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) {
-        _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF "
-                        "unwind, reg too big");
-        return false;
+  ParseInfo parseInfoArray[] = {
+      {cieInfo.cieInstructions, cieInfo.cieStart + cieInfo.cieLength,
+       (pint_t)(-1)},
+      {fdeInfo.fdeInstructions, fdeInfo.fdeStart + fdeInfo.fdeLength,
+       upToPC - fdeInfo.pcStart}};
+
+  for (const auto &info : parseInfoArray) {
+    pint_t p = info.instructions;
+    pint_t instructionsEnd = info.instructionsEnd;
+    pint_t pcoffset = info.pcoffset;
+    pint_t codeOffset = 0;
+
+    // initialState initialized as registers in results are modified. Use
+    // PrologInfo accessor functions to avoid reading uninitialized data.
+    PrologInfo initialState(PrologInfo::InitializeTime::kLazy);
+
+    _LIBUNWIND_TRACE_DWARF("parseFDEInstructions(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;
+      int64_t offset;
+      uint64_t length;
+      uint8_t opcode = addressSpace.get8(p);
+      uint8_t operand;
+
+      ++p;
+      switch (opcode) {
+      case DW_CFA_nop:
+        _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n");
+        break;
+      case DW_CFA_set_loc:
+        codeOffset = addressSpace.getEncodedP(p, instructionsEnd,
+                                              cieInfo.pointerEncoding);
+        _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n");
+        break;
+      case DW_CFA_advance_loc1:
+        codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
+        p += 1;
+        _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;
+        _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;
+        _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) {
+          _LIBUNWIND_LOG0(
+              "malformed DW_CFA_offset_extended DWARF unwind, reg too big");
+          return false;
+        }
+        results->setRegister(reg, kRegisterInCFA, offset, initialState);
+        _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) {
+          _LIBUNWIND_LOG0(
+              "malformed DW_CFA_restore_extended DWARF unwind, reg too big");
+          return false;
+        }
+        results->restoreRegisterToInitialState(reg, initialState);
+        _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n",
+                               reg);
+        break;
+      case DW_CFA_undefined:
+        reg = addressSpace.getULEB128(p, instructionsEnd);
+        if (reg > kMaxRegisterNumber) {
+          _LIBUNWIND_LOG0(
+              "malformed DW_CFA_undefined DWARF unwind, reg too big");
+          return false;
+        }
+        results->setRegisterLocation(reg, kRegisterUndefined, initialState);
+        _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg);
+        break;
+      case DW_CFA_same_value:
+        reg = addressSpace.getULEB128(p, instructionsEnd);
+        if (reg > kMaxRegisterNumber) {
+          _LIBUNWIND_LOG0(
+              "malformed DW_CFA_same_value DWARF unwind, reg too big");
+          return false;
+        }
+        // <rdar://problem/8456377> DW_CFA_same_value unsupported
+        // "same value" means register was stored in frame, but its current
+        // value has not changed, so no need to restore from frame.
+        // We model this as if the register was never saved.
+        results->setRegisterLocation(reg, kRegisterUnused, initialState);
+        _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) {
+          _LIBUNWIND_LOG0(
+              "malformed DW_CFA_register DWARF unwind, reg too big");
+          return false;
+        }
+        if (reg2 > kMaxRegisterNumber) {
+          _LIBUNWIND_LOG0(
+              "malformed DW_CFA_register DWARF unwind, reg2 too big");
+          return false;
+        }
+        results->setRegister(reg, kRegisterInRegister, (int64_t)reg2,
+                             initialState);
+        _LIBUNWIND_TRACE_DWARF(
+            "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2);
+        break;
+      case DW_CFA_remember_state: {
+        // Avoid operator new because that would be an upward dependency.
+        // Avoid malloc because it needs heap allocation.
+        PrologInfoStackEntry *entry =
+            (PrologInfoStackEntry *)_LIBUNWIND_REMEMBER_ALLOC(
+                sizeof(PrologInfoStackEntry));
+        if (entry != NULL) {
+          entry->next = rememberStack.entry;
+          entry->info = *results;
+          rememberStack.entry = entry;
+        } else {
+          return false;
+        }
+        _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n");
+        break;
       }
-      offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
-                                                    * cieInfo.dataAlignFactor;
-      results->setRegister(reg, kRegisterInCFA, -offset, initialState);
-      _LIBUNWIND_TRACE_DWARF(
-          "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset);
-      break;
+      case DW_CFA_restore_state:
+        if (rememberStack.entry != NULL) {
+          PrologInfoStackEntry *top = rememberStack.entry;
+          *results = top->info;
+          rememberStack.entry = top->next;
+          _LIBUNWIND_REMEMBER_FREE(top);
+        } else {
+          return false;
+        }
+        _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n");
+        break;
+      case DW_CFA_def_cfa:
+        reg = addressSpace.getULEB128(p, instructionsEnd);
+        offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
+        if (reg > kMaxRegisterNumber) {
+          _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big");
+          return false;
+        }
+        results->cfaRegister = (uint32_t)reg;
+        results->cfaRegisterOffset = (int32_t)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) {
+          _LIBUNWIND_LOG0(
+              "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big");
+          return false;
+        }
+        results->cfaRegister = (uint32_t)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);
+        _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);
+        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) {
+          _LIBUNWIND_LOG0(
+              "malformed DW_CFA_expression DWARF unwind, reg too big");
+          return false;
+        }
+        results->setRegister(reg, kRegisterAtExpression, (int64_t)p,
+                             initialState);
+        length = addressSpace.getULEB128(p, instructionsEnd);
+        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) {
+          _LIBUNWIND_LOG0(
+              "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big");
+          return false;
+        }
+        offset = addressSpace.getSLEB128(p, instructionsEnd) *
+                 cieInfo.dataAlignFactor;
+        results->setRegister(reg, kRegisterInCFA, offset, initialState);
+        _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) {
+          _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;
+        _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);
+        _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->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState);
+        _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) {
+          _LIBUNWIND_LOG0(
+              "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big");
+          return false;
+        }
+        offset = addressSpace.getSLEB128(p, instructionsEnd) *
+                 cieInfo.dataAlignFactor;
+        results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState);
+        _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) {
+          _LIBUNWIND_LOG0(
+              "malformed DW_CFA_val_expression DWARF unwind, reg too big");
+          return false;
+        }
+        results->setRegister(reg, kRegisterIsExpression, (int64_t)p,
+                             initialState);
+        length = addressSpace.getULEB128(p, instructionsEnd);
+        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_args_size:
+        length = addressSpace.getULEB128(p, instructionsEnd);
+        results->spExtraArgSize = (uint32_t)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) {
+          _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->setRegister(reg, kRegisterInCFA, -offset, initialState);
+        _LIBUNWIND_TRACE_DWARF(
+            "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset);
+        break;
 
 #if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC)
-    // The same constant is used to represent different instructions on
-    // AArch64 (negate_ra_state) and SPARC (window_save).
-    static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save,
-                  "uses the same constant");
-    case DW_CFA_AARCH64_negate_ra_state:
-      switch (arch) {
+        // The same constant is used to represent different instructions on
+        // AArch64 (negate_ra_state) and SPARC (window_save).
+        static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save,
+                      "uses the same constant");
+      case DW_CFA_AARCH64_negate_ra_state:
+        switch (arch) {
 #if defined(_LIBUNWIND_TARGET_AARCH64)
         case REGISTERS_ARM64: {
           int64_t value =
               results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^ 0x1;
-          results->setRegisterValue(UNW_ARM64_RA_SIGN_STATE, value, initialState);
+          results->setRegisterValue(UNW_ARM64_RA_SIGN_STATE, value,
+                                    initialState);
           _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n");
         } break;
 #endif
 
 #if defined(_LIBUNWIND_TARGET_SPARC)
-      // case DW_CFA_GNU_window_save:
-      case REGISTERS_SPARC:
-        _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n");
-        for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) {
-          results->setRegister(reg, kRegisterInRegister,
-                               ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0,
-                               initialState);
-        }
+        // case DW_CFA_GNU_window_save:
+        case REGISTERS_SPARC:
+          _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n");
+          for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) {
+            results->setRegister(reg, kRegisterInRegister,
+                                 ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0,
+                                 initialState);
+          }
 
-        for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) {
-          results->setRegister(reg, kRegisterInCFA,
-                               ((int64_t)reg - UNW_SPARC_L0) * 4, initialState);
+          for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) {
+            results->setRegister(reg, kRegisterInCFA,
+                                 ((int64_t)reg - UNW_SPARC_L0) * 4,
+                                 initialState);
+          }
+          break;
+#endif
         }
         break;
-#endif
-      }
-      break;
 #else
-      (void)arch;
+        (void)arch;
 #endif
 
-    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->setRegister(reg, kRegisterInCFA, offset, initialState);
-        _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n",
-                               operand, offset);
-        break;
-      case DW_CFA_advance_loc:
-        codeOffset += operand * cieInfo.codeAlignFactor;
-        _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);
+      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->setRegister(reg, kRegisterInCFA, offset, initialState);
+          _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n",
+                                 operand, offset);
+          break;
+        case DW_CFA_advance_loc:
+          codeOffset += operand * cieInfo.codeAlignFactor;
+          _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->restoreRegisterToInitialState(reg, initialState);
+          _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n",
+                                 static_cast<uint64_t>(operand));
+          break;
+        default:
+          _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode);
           return false;
         }
-        results->restoreRegisterToInitialState(reg, initialState);
-        _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n",
-                               static_cast<uint64_t>(operand));
-        break;
-      default:
-        _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode);
-        return false;
       }
     }
   }
-
   return true;
 }
 
lib/libunwind/src/FrameHeaderCache.hpp
@@ -32,7 +32,7 @@
 class _LIBUNWIND_HIDDEN FrameHeaderCache {
   struct CacheEntry {
     uintptr_t LowPC() { return Info.dso_base; };
-    uintptr_t HighPC() { return Info.dso_base + Info.dwarf_section_length; };
+    uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; };
     UnwindInfoSections Info;
     CacheEntry *Next;
   };
lib/libunwind/src/Registers.hpp
@@ -39,6 +39,8 @@ enum {
 };
 
 #if defined(_LIBUNWIND_TARGET_I386)
+class _LIBUNWIND_HIDDEN Registers_x86;
+extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);
 /// Registers_x86 holds the register state of a thread in a 32-bit intel
 /// process.
 class _LIBUNWIND_HIDDEN Registers_x86 {
@@ -56,7 +58,7 @@ public:
   v128        getVectorRegister(int num) const;
   void        setVectorRegister(int num, v128 value);
   static const char *getRegisterName(int num);
-  void        jumpto();
+  void        jumpto() { __libunwind_Registers_x86_jumpto(this); }
   static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; }
   static int  getArch() { return REGISTERS_X86; }
 
@@ -248,6 +250,8 @@ inline void Registers_x86::setVectorRegister(int, v128) {
 #if defined(_LIBUNWIND_TARGET_X86_64)
 /// Registers_x86_64  holds the register state of a thread in a 64-bit intel
 /// process.
+class _LIBUNWIND_HIDDEN Registers_x86_64;
+extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *);
 class _LIBUNWIND_HIDDEN Registers_x86_64 {
 public:
   Registers_x86_64();
@@ -263,7 +267,7 @@ public:
   v128        getVectorRegister(int num) const;
   void        setVectorRegister(int num, v128 value);
   static const char *getRegisterName(int num);
-  void        jumpto();
+  void        jumpto() { __libunwind_Registers_x86_64_jumpto(this); }
   static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; }
   static int  getArch() { return REGISTERS_X86_64; }
 
@@ -1510,12 +1514,12 @@ inline void Registers_ppc64::setFloatRegister(int regNum, double value) {
 }
 
 inline bool Registers_ppc64::validVectorRegister(int regNum) const {
-#ifdef PPC64_HAS_VMX
+#if defined(__VSX__)
   if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31)
     return true;
   if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)
     return true;
-#else
+#elif defined(__ALTIVEC__)
   if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)
     return true;
 #endif
@@ -1771,6 +1775,8 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) {
 #if defined(_LIBUNWIND_TARGET_AARCH64)
 /// Registers_arm64  holds the register state of a thread in a 64-bit arm
 /// process.
+class _LIBUNWIND_HIDDEN Registers_arm64;
+extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
 class _LIBUNWIND_HIDDEN Registers_arm64 {
 public:
   Registers_arm64();
@@ -1786,7 +1792,7 @@ public:
   v128        getVectorRegister(int num) const;
   void        setVectorRegister(int num, v128 value);
   static const char *getRegisterName(int num);
-  void        jumpto();
+  void        jumpto() { __libunwind_Registers_arm64_jumpto(this); }
   static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; }
   static int  getArch() { return REGISTERS_ARM64; }
 
lib/libunwind/src/Unwind-seh.cpp
@@ -46,18 +46,6 @@ using namespace libunwind;
 /// handling.
 #define STATUS_GCC_UNWIND MAKE_GCC_EXCEPTION(1) // 0x21474343
 
-/// Class of foreign exceptions based on unrecognized SEH exceptions.
-static const uint64_t kSEHExceptionClass = 0x434C4E4753454800; // CLNGSEH\0
-
-/// Exception cleanup routine used by \c _GCC_specific_handler to
-/// free foreign exceptions.
-static void seh_exc_cleanup(_Unwind_Reason_Code urc, _Unwind_Exception *exc) {
-  (void)urc;
-  if (exc->exception_class != kSEHExceptionClass)
-    _LIBUNWIND_ABORT("SEH cleanup called on non-SEH exception");
-  free(exc);
-}
-
 static int __unw_init_seh(unw_cursor_t *cursor, CONTEXT *ctx);
 static DISPATCHER_CONTEXT *__unw_seh_get_disp_ctx(unw_cursor_t *cursor);
 static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor,
@@ -108,10 +96,10 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
     }
   } else {
     // Foreign exception.
-    exc = (_Unwind_Exception *)malloc(sizeof(_Unwind_Exception));
-    exc->exception_class = kSEHExceptionClass;
-    exc->exception_cleanup = seh_exc_cleanup;
-    memset(exc->private_, 0, sizeof(exc->private_));
+    // We can't interact with them (we don't know the original target frame
+    // that we should pass on to RtlUnwindEx in _Unwind_Resume), so just
+    // pass without calling our destructors here.
+    return ExceptionContinueSearch;
   }
   if (!ctx) {
     __unw_init_seh(&cursor, disp->ContextRecord);
lib/libunwind/src/Unwind_AppleExtras.cpp
@@ -8,35 +8,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "config.h"
-#include "AddressSpace.hpp"
-#include "DwarfParser.hpp"
-
-
-// private keymgr stuff
-#define KEYMGR_GCC3_DW2_OBJ_LIST 302
-extern "C" {
- extern void _keymgr_set_and_unlock_processwide_ptr(int key, void *ptr);
- extern void *_keymgr_get_and_lock_processwide_ptr(int key);
-}
-
-// undocumented libgcc "struct object"
-struct libgcc_object {
-  void          *start;
-  void          *unused1;
-  void          *unused2;
-  void          *fde;
-  unsigned long  encoding;
-  void          *fde_end;
-  libgcc_object *next;
-};
-
-// undocumented libgcc "struct km_object_info" referenced by
-// KEYMGR_GCC3_DW2_OBJ_LIST
-struct libgcc_object_info {
-  libgcc_object   *seen_objects;
-  libgcc_object   *unseen_objects;
-  unsigned         spare[2];
-};
 
 
 // static linker symbols to prevent wrong two level namespace for _Unwind symbols
@@ -140,44 +111,3 @@ NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow)
 NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister)
 
 #endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS)
-
-
-namespace libunwind {
-
-_LIBUNWIND_HIDDEN
-bool checkKeyMgrRegisteredFDEs(uintptr_t pc, void *&fde) {
-#if __MAC_OS_X_VERSION_MIN_REQUIRED
-  // lastly check for old style keymgr registration of dynamically generated
-  // FDEs acquire exclusive access to libgcc_object_info
-  libgcc_object_info *head = (libgcc_object_info *)
-                _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST);
-  if (head != NULL) {
-    // look at each FDE in keymgr
-    for (libgcc_object *ob = head->unseen_objects; ob != NULL; ob = ob->next) {
-      CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
-      CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
-      const char *msg = CFI_Parser<LocalAddressSpace>::decodeFDE(
-                                      LocalAddressSpace::sThisAddressSpace,
-                                      (uintptr_t)ob->fde, &fdeInfo, &cieInfo);
-      if (msg == NULL) {
-        // Check if this FDE is for a function that includes the pc
-        if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) {
-          fde = (void*)fdeInfo.pcStart;
-          _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST,
-                                                 head);
-          return true;
-        }
-      }
-    }
-  }
-  // release libgcc_object_info
-  _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head);
-#else
-  (void)pc;
-  (void)fde;
-#endif
-  return false;
-}
-
-}
-
lib/libunwind/src/UnwindCursor.hpp
@@ -81,6 +81,7 @@ template <typename A>
 class _LIBUNWIND_HIDDEN DwarfFDECache {
   typedef typename A::pint_t pint_t;
 public:
+  static constexpr pint_t kSearchAll = static_cast<pint_t>(-1);
   static pint_t findFDE(pint_t mh, pint_t pc);
   static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
   static void removeAllIn(pint_t mh);
@@ -138,7 +139,7 @@ typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) {
   pint_t result = 0;
   _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared());
   for (entry *p = _buffer; p < _bufferUsed; ++p) {
-    if ((mh == p->mh) || (mh == 0)) {
+    if ((mh == p->mh) || (mh == kSearchAll)) {
       if ((p->ip_start <= pc) && (pc < p->ip_end)) {
         result = p->fde;
         break;
@@ -530,6 +531,8 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
     : _addressSpace(as), _unwindInfoMissing(false) {
   static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
                 "UnwindCursor<> does not fit in unw_cursor_t");
+  static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),
+                "UnwindCursor<> requires more alignment than unw_cursor_t");
   memset(&_info, 0, sizeof(_info));
   memset(&_histTable, 0, sizeof(_histTable));
   _dispContext.ContextRecord = &_msContext;
@@ -923,6 +926,9 @@ private:
 #endif
 
 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+  bool getInfoFromFdeCie(const typename CFI_Parser<A>::FDE_Info &fdeInfo,
+                         const typename CFI_Parser<A>::CIE_Info &cieInfo,
+                         pint_t pc, uintptr_t dso_base);
   bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects,
                                             uint32_t fdeSectionOffsetHint=0);
   int stepWithDwarfFDE() {
@@ -1182,6 +1188,8 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
       _isSignalFrame(false) {
   static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
                 "UnwindCursor<> does not fit in unw_cursor_t");
+  static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),
+                "UnwindCursor<> requires more alignment than unw_cursor_t");
   memset(&_info, 0, sizeof(_info));
 }
 
@@ -1472,6 +1480,32 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection(
 #endif
 
 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+template <typename A, typename R>
+bool UnwindCursor<A, R>::getInfoFromFdeCie(
+    const typename CFI_Parser<A>::FDE_Info &fdeInfo,
+    const typename CFI_Parser<A>::CIE_Info &cieInfo, pint_t pc,
+    uintptr_t dso_base) {
+  typename CFI_Parser<A>::PrologInfo prolog;
+  if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,
+                                          R::getArch(), &prolog)) {
+    // Save off parsed FDE info
+    _info.start_ip          = fdeInfo.pcStart;
+    _info.end_ip            = fdeInfo.pcEnd;
+    _info.lsda              = fdeInfo.lsda;
+    _info.handler           = cieInfo.personality;
+    // Some frameless functions need SP altered when resuming in function, so
+    // propagate spExtraArgSize.
+    _info.gp                = prolog.spExtraArgSize;
+    _info.flags             = 0;
+    _info.format            = dwarfEncoding();
+    _info.unwind_info       = fdeInfo.fdeStart;
+    _info.unwind_info_size  = static_cast<uint32_t>(fdeInfo.fdeLength);
+    _info.extra             = static_cast<unw_word_t>(dso_base);
+    return true;
+  }
+  return false;
+}
+
 template <typename A, typename R>
 bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
                                                 const UnwindInfoSections &sects,
@@ -1483,7 +1517,7 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
   // If compact encoding table gave offset into dwarf section, go directly there
   if (fdeSectionOffsetHint != 0) {
     foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
-                                    (uint32_t)sects.dwarf_section_length,
+                                    sects.dwarf_section_length,
                                     sects.dwarf_section + fdeSectionOffsetHint,
                                     &fdeInfo, &cieInfo);
   }
@@ -1500,7 +1534,7 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
     if (cachedFDE != 0) {
       foundFDE =
           CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
-                                 (uint32_t)sects.dwarf_section_length,
+                                 sects.dwarf_section_length,
                                  cachedFDE, &fdeInfo, &cieInfo);
       foundInCache = foundFDE;
     }
@@ -1508,25 +1542,11 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
   if (!foundFDE) {
     // Still not found, do full scan of __eh_frame section.
     foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
-                                      (uint32_t)sects.dwarf_section_length, 0,
+                                      sects.dwarf_section_length, 0,
                                       &fdeInfo, &cieInfo);
   }
   if (foundFDE) {
-    typename CFI_Parser<A>::PrologInfo prolog;
-    if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,
-                                            R::getArch(), &prolog)) {
-      // Save off parsed FDE info
-      _info.start_ip          = fdeInfo.pcStart;
-      _info.end_ip            = fdeInfo.pcEnd;
-      _info.lsda              = fdeInfo.lsda;
-      _info.handler           = cieInfo.personality;
-      _info.gp                = prolog.spExtraArgSize;
-      _info.flags             = 0;
-      _info.format            = dwarfEncoding();
-      _info.unwind_info       = fdeInfo.fdeStart;
-      _info.unwind_info_size  = (uint32_t)fdeInfo.fdeLength;
-      _info.extra             = (unw_word_t) sects.dso_base;
-
+    if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) {
       // Add to cache (to make next lookup faster) if we had no hint
       // and there was no index.
       if (!foundInCache && (fdeSectionOffsetHint == 0)) {
@@ -1759,12 +1779,12 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
     }
   }
 
-  // extact personality routine, if encoding says function has one
+  // extract personality routine, if encoding says function has one
   uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >>
                               (__builtin_ctz(UNWIND_PERSONALITY_MASK));
   if (personalityIndex != 0) {
     --personalityIndex; // change 1-based to zero-based index
-    if (personalityIndex > sectionHeader.personalityArrayCount()) {
+    if (personalityIndex >= sectionHeader.personalityArrayCount()) {
       _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d,  "
                             "but personality table has only %d entries",
                             encoding, personalityIndex,
@@ -1926,60 +1946,27 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
 #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);
+  pint_t cachedFDE = DwarfFDECache<A>::findFDE(DwarfFDECache<A>::kSearchAll,
+                                               pc);
   if (cachedFDE != 0) {
-    CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
-    CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
-    const char *msg = CFI_Parser<A>::decodeFDE(_addressSpace,
-                                                cachedFDE, &fdeInfo, &cieInfo);
-    if (msg == NULL) {
-      typename CFI_Parser<A>::PrologInfo prolog;
-      if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
-                                              pc, R::getArch(), &prolog)) {
-        // save off parsed FDE info
-        _info.start_ip         = fdeInfo.pcStart;
-        _info.end_ip           = fdeInfo.pcEnd;
-        _info.lsda             = fdeInfo.lsda;
-        _info.handler          = cieInfo.personality;
-        _info.gp               = prolog.spExtraArgSize;
-                                  // Some frameless functions need SP
-                                  // altered when resuming in function.
-        _info.flags            = 0;
-        _info.format           = dwarfEncoding();
-        _info.unwind_info      = fdeInfo.fdeStart;
-        _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
-        _info.extra            = 0;
+    typename CFI_Parser<A>::FDE_Info fdeInfo;
+    typename CFI_Parser<A>::CIE_Info cieInfo;
+    if (!CFI_Parser<A>::decodeFDE(_addressSpace, cachedFDE, &fdeInfo, &cieInfo))
+      if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, 0))
         return;
-      }
-    }
   }
 
   // Lastly, ask AddressSpace object about platform specific ways to locate
   // other FDEs.
   pint_t fde;
   if (_addressSpace.findOtherFDE(pc, fde)) {
-    CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
-    CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
+    typename CFI_Parser<A>::FDE_Info fdeInfo;
+    typename CFI_Parser<A>::CIE_Info cieInfo;
     if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) {
       // Double check this FDE is for a function that includes the pc.
-      if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) {
-        typename CFI_Parser<A>::PrologInfo prolog;
-        if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
-                                                pc, R::getArch(), &prolog)) {
-          // save off parsed FDE info
-          _info.start_ip         = fdeInfo.pcStart;
-          _info.end_ip           = fdeInfo.pcEnd;
-          _info.lsda             = fdeInfo.lsda;
-          _info.handler          = cieInfo.personality;
-          _info.gp               = prolog.spExtraArgSize;
-          _info.flags            = 0;
-          _info.format           = dwarfEncoding();
-          _info.unwind_info      = fdeInfo.fdeStart;
-          _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
-          _info.extra            = 0;
+      if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd))
+        if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, 0))
           return;
-        }
-      }
     }
   }
 #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
lib/libunwind/src/UnwindLevel1.c
@@ -39,8 +39,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
   __unw_init_local(cursor, uc);
 
   // Walk each frame looking for a place to stop.
-  bool handlerNotFound = true;
-  while (handlerNotFound) {
+  while (true) {
     // Ask libunwind to get next frame (skip over first which is
     // _Unwind_RaiseException).
     int stepResult = __unw_step(cursor);
@@ -102,7 +101,6 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
       case _URC_HANDLER_FOUND:
         // found a catch clause or locals that need destructing in this frame
         // stop search and remember stack pointer at the frame
-        handlerNotFound = false;
         __unw_get_reg(cursor, UNW_REG_SP, &sp);
         exception_object->private_2 = (uintptr_t)sp;
         _LIBUNWIND_TRACE_UNWINDING(
lib/libunwind/src/UnwindRegistersRestore.S
@@ -13,14 +13,10 @@
 #if !defined(__USING_SJLJ_EXCEPTIONS__)
 
 #if defined(__i386__)
-DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv)
+DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto)
 #
-# void libunwind::Registers_x86::jumpto()
+# extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);
 #
-#if defined(_WIN32)
-# On windows, the 'this' pointer is passed in ecx instead of on the stack
-  movl   %ecx, %eax
-#else
 # On entry:
 #  +                       +
 #  +-----------------------+
@@ -30,7 +26,6 @@ DEFINE_LIBUNWIND_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
@@ -60,9 +55,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv)
 
 #elif defined(__x86_64__)
 
-DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv)
+DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto)
 #
-# void libunwind::Registers_x86_64::jumpto()
+# extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *);
 #
 #if defined(_WIN64)
 # On entry, thread_state pointer is in rcx; move it into rdi
@@ -175,7 +170,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
   PPC64_LR(30)
   PPC64_LR(31)
 
-#ifdef PPC64_HAS_VMX
+#if defined(__VSX__)
 
   // restore VS registers
   // (note that this also restores floating point registers and V registers,
@@ -317,6 +312,7 @@ PPC64_CLVS_BOTTOM(n)
   PPC64_LF(30)
   PPC64_LF(31)
 
+#if defined(__ALTIVEC__)
   // restore vector registers if any are in use
   ld    %r5, PPC64_OFFS_VRSAVE(%r3)   // test VRsave
   cmpwi %r5, 0
@@ -378,6 +374,7 @@ PPC64_CLV_UNALIGNED_BOTTOM(n)
   PPC64_CLV_UNALIGNEDh(31)
 
 #endif
+#endif
 
 Lnovec:
   ld    %r0, PPC64_OFFS_CR(%r3)
@@ -436,6 +433,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
   lwz     %r30,128(%r3)
   lwz     %r31,132(%r3)
 
+#ifndef __NO_FPRS__
   // restore float registers
   lfd     %f0, 160(%r3)
   lfd     %f1, 168(%r3)
@@ -469,7 +467,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
   lfd     %f29,392(%r3)
   lfd     %f30,400(%r3)
   lfd     %f31,408(%r3)
+#endif
 
+#if defined(__ALTIVEC__)
   // restore vector registers if any are in use
   lwz     %r5, 156(%r3)       // test VRsave
   cmpwi   %r5, 0
@@ -542,6 +542,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
   LOAD_VECTOR_UNALIGNEDh(29)
   LOAD_VECTOR_UNALIGNEDh(30)
   LOAD_VECTOR_UNALIGNEDh(31)
+#endif
 
 Lnovec:
   lwz     %r0, 136(%r3)   // __cr
@@ -560,13 +561,13 @@ Lnovec:
 #elif defined(__aarch64__)
 
 //
-// void libunwind::Registers_arm64::jumpto()
+// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
 //
 // On entry:
 //  thread_state pointer is in x0
 //
   .p2align 2
-DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
+DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
   // skip restore of x0,x1 for now
   ldp    x2, x3,  [x0, #0x010]
   ldp    x4, x5,  [x0, #0x020]
lib/libunwind/src/UnwindRegistersSave.S
@@ -384,7 +384,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   mfvrsave    %r0
   std   %r0,  PPC64_OFFS_VRSAVE(%r3)
 
-#ifdef PPC64_HAS_VMX
+#if defined(__VSX__)
   // save VS registers
   // (note that this also saves floating point registers and V registers,
   // because part of VS is mapped to these registers)
@@ -501,6 +501,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   PPC64_STF(30)
   PPC64_STF(31)
 
+#if defined(__ALTIVEC__)
   // save vector registers
 
   // Use 16-bytes below the stack pointer as an
@@ -548,6 +549,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   PPC64_STV_UNALIGNED(30)
   PPC64_STV_UNALIGNED(31)
 
+#endif
 #endif
 
   li    %r3,  0   // return UNW_ESUCCESS
@@ -608,6 +610,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   mfctr   %r0
   stw     %r0, 148(%r3)
 
+#if !defined(__NO_FPRS__)
   // save float registers
   stfd    %f0, 160(%r3)
   stfd    %f1, 168(%r3)
@@ -641,8 +644,9 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   stfd    %f29,392(%r3)
   stfd    %f30,400(%r3)
   stfd    %f31,408(%r3)
+#endif
 
-
+#if defined(__ALTIVEC__)
   // save vector registers
 
   subi    %r4, %r1, 16
@@ -692,6 +696,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   SAVE_VECTOR_UNALIGNED(%v29, 424+0x1D0)
   SAVE_VECTOR_UNALIGNED(%v30, 424+0x1E0)
   SAVE_VECTOR_UNALIGNED(%v31, 424+0x1F0)
+#endif
 
   li      %r3, 0  // return UNW_ESUCCESS
   blr