Merge to upstream r355142. am: cc3148bd34
am: 4041d10e89

Change-Id: I68203fc12df36bce7c4199a5986bfb72431b0a87
diff --git a/.arcconfig b/.arcconfig
index 97a4bf1..78ee8d3 100644
--- a/.arcconfig
+++ b/.arcconfig
@@ -1,4 +1,4 @@
 {
-  "project_id" : "libunwind",
+  "repository.callsign" : "UNW",
   "conduit_uri" : "https://reviews.llvm.org/"
 }
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b28e4d0..debc847 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -59,27 +59,31 @@
       OUTPUT_VARIABLE CONFIG_OUTPUT
       ERROR_QUIET)
     if(NOT HAD_ERROR)
-      string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH)
+      string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH_FROM_LLVM_CONFIG)
+      file(TO_CMAKE_PATH "${LLVM_CMAKE_PATH_FROM_LLVM_CONFIG}" LLVM_CMAKE_PATH)
     else()
-      set(LLVM_CMAKE_PATH
-          "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
+      file(TO_CMAKE_PATH "${LLVM_BINARY_DIR}" LLVM_BINARY_DIR_CMAKE_STYLE)
+      set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
     endif()
   else()
-    message(FATAL_ERROR "llvm-config not found and LLVM_MAIN_SRC_DIR not defined. "
-                        "Reconfigure with -DLLVM_CONFIG=path/to/llvm-config "
-                        "or -DLLVM_PATH=path/to/llvm-source-root.")
+    message(WARNING "UNSUPPORTED LIBUNWIND CONFIGURATION DETECTED: "
+                    "llvm-config not found and LLVM_MAIN_SRC_DIR not defined. "
+                    "Reconfigure with -DLLVM_CONFIG=path/to/llvm-config "
+                    "or -DLLVM_PATH=path/to/llvm-source-root.")
   endif()
 
   if (EXISTS ${LLVM_CMAKE_PATH})
+    # Enable warnings, otherwise -w gets added to the cflags by HandleLLVMOptions.
+    set(LLVM_ENABLE_WARNINGS ON)
     list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
     include("${LLVM_CMAKE_PATH}/AddLLVM.cmake")
     include("${LLVM_CMAKE_PATH}/HandleLLVMOptions.cmake")
   else()
-    message(FATAL_ERROR "Not found: ${LLVM_CMAKE_PATH}")
+    message(WARNING "Not found: ${LLVM_CMAKE_PATH}")
   endif()
 
   set(PACKAGE_NAME libunwind)
-  set(PACKAGE_VERSION 5.0.0svn)
+  set(PACKAGE_VERSION 9.0.0svn)
   set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
   set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org")
 
@@ -111,13 +115,13 @@
   set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX})
   set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX})
 else()
-  set(LLVM_MAIN_SRC_DIR "${CMAKE_SOURCE_DIR}" CACHE PATH "Path to LLVM source tree")
   set(LLVM_LIT "${CMAKE_SOURCE_DIR}/utils/lit/lit.py")
 endif()
 
 #===============================================================================
 # Setup CMake Options
 #===============================================================================
+include(CMakeDependentOption)
 include(HandleCompilerRT)
 
 # Define options.
@@ -136,9 +140,19 @@
 set(LIBUNWIND_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING
     "Define suffix of library directory name (32/64)")
 option(LIBUNWIND_INSTALL_LIBRARY "Install the libunwind library." ON)
+cmake_dependent_option(LIBUNWIND_INSTALL_STATIC_LIBRARY
+  "Install the static libunwind library." ON
+  "LIBUNWIND_ENABLE_STATIC;LIBUNWIND_INSTALL_LIBRARY" OFF)
+cmake_dependent_option(LIBUNWIND_INSTALL_SHARED_LIBRARY
+  "Install the shared libunwind library." ON
+  "LIBUNWIND_ENABLE_SHARED;LIBUNWIND_INSTALL_LIBRARY" OFF)
 set(LIBUNWIND_TARGET_TRIPLE "" CACHE STRING "Target triple for cross compiling.")
 set(LIBUNWIND_GCC_TOOLCHAIN "" CACHE PATH "GCC toolchain for cross compiling.")
 set(LIBUNWIND_SYSROOT "" CACHE PATH "Sysroot for cross compiling.")
+set(LIBUNWIND_TEST_LINKER_FLAGS "" CACHE STRING
+    "Additional linker flags for test programs.")
+set(LIBUNWIND_TEST_COMPILER_FLAGS "" CACHE STRING
+    "Additional compiler flags for test programs.")
 
 if (NOT LIBUNWIND_ENABLE_SHARED AND NOT LIBUNWIND_ENABLE_STATIC)
   message(FATAL_ERROR "libunwind must be built as either a shared or static library.")
@@ -153,6 +167,9 @@
   message(FATAL_ERROR "LIBUNWIND_BUILD_32_BITS=ON is not supported on this platform.")
 endif()
 
+option(LIBUNWIND_HERMETIC_STATIC_LIBRARY
+  "Do not export any symbols from the static library." OFF)
+
 #===============================================================================
 # Configure System
 #===============================================================================
@@ -165,7 +182,14 @@
 set(LIBUNWIND_COMPILER    ${CMAKE_CXX_COMPILER})
 set(LIBUNWIND_SOURCE_DIR  ${CMAKE_CURRENT_SOURCE_DIR})
 set(LIBUNWIND_BINARY_DIR  ${CMAKE_CURRENT_BINARY_DIR})
-if (LLVM_LIBRARY_OUTPUT_INTDIR)
+
+string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION
+       ${PACKAGE_VERSION})
+
+if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
+  set(DEFAULT_INSTALL_PREFIX lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/${LLVM_DEFAULT_TARGET_TRIPLE}/)
+  set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}/${LLVM_DEFAULT_TARGET_TRIPLE}/lib${LIBUNWIND_LIBDIR_SUFFIX})
+elseif(LLVM_LIBRARY_OUTPUT_INTDIR)
   set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
 else()
   set(LIBUNWIND_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBUNWIND_LIBDIR_SUFFIX})
@@ -175,41 +199,53 @@
 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBUNWIND_LIBRARY_DIR})
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBUNWIND_LIBRARY_DIR})
 
-set(LIBUNWIND_INSTALL_PREFIX "" CACHE STRING
+set(LIBUNWIND_INSTALL_PREFIX ${DEFAULT_INSTALL_PREFIX} CACHE STRING
     "Define libunwind destination prefix.")
 
-if (NOT LIBUNWIND_INSTALL_PREFIX MATCHES "^$|.*/")
-  message(FATAL_ERROR "LIBUNWIND_INSTALL_PREFIX has to end with \"/\".")
-endif()
-
 set(LIBUNWIND_C_FLAGS "")
 set(LIBUNWIND_CXX_FLAGS "")
 set(LIBUNWIND_COMPILE_FLAGS "")
 set(LIBUNWIND_LINK_FLAGS "")
 
 # Get required flags.
-macro(append_if list condition var)
+macro(unwind_append_if list condition var)
   if (${condition})
     list(APPEND ${list} ${var})
   endif()
 endmacro()
 
-macro(add_target_flags_if condition var)
+macro(add_target_flags)
+  foreach(value ${ARGN})
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${value}")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${value}")
+    list(APPEND LIBUNWIND_COMPILE_FLAGS ${value})
+    list(APPEND LIBUNWIND_LINK_FLAGS ${value})
+  endforeach()
+endmacro()
+
+macro(add_target_flags_if condition)
   if (${condition})
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${var}")
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${var}")
-    list(APPEND LIBUNWIND_COMPILE_FLAGS ${var})
-    list(APPEND LIBUNWIND_LINK_FLAGS ${var})
+    add_target_flags(${ARGN})
   endif()
 endmacro()
 
 add_target_flags_if(LIBUNWIND_BUILD_32_BITS "-m32")
-add_target_flags_if(LIBUNWIND_TARGET_TRIPLE
-          "--target=${LIBUNWIND_TARGET_TRIPLE}")
-add_target_flags_if(LIBUNWIND_GCC_TOOLCHAIN
-          "--gcc-toolchain=${LIBUNWIND_GCC_TOOLCHAIN}")
-add_target_flags_if(LIBUNWIND_SYSROOT
-          "--sysroot=${LIBUNWIND_SYSROOT}")
+
+if(LIBUNWIND_TARGET_TRIPLE)
+  add_target_flags("--target=${LIBUNWIND_TARGET_TRIPLE}")
+elseif(CMAKE_CXX_COMPILER_TARGET)
+  set(LIBUNWIND_TARGET_TRIPLE "${CMAKE_CXX_COMPILER_TARGET}")
+endif()
+if(LIBUNWIND_GCC_TOOLCHAIN)
+  add_target_flags("--gcc-toolchain=${LIBUNWIND_GCC_TOOLCHAIN}")
+elseif(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN)
+  set(LIBUNWIND_GCC_TOOLCHAIN "${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}")
+endif()
+if(LIBUNWIND_SYSROOT)
+  add_target_flags("--sysroot=${LIBUNWIND_SYSROOT}")
+elseif(CMAKE_SYSROOT)
+  set(LIBUNWIND_SYSROOT "${CMAKE_SYSROOT}")
+endif()
 
 if (LIBUNWIND_TARGET_TRIPLE)
   set(TARGET_TRIPLE "${LIBUNWIND_TARGET_TRIPLE}")
@@ -218,7 +254,7 @@
 # Configure compiler.
 include(config-ix)
 
-if (LIBUNWIND_USE_COMPILER_RT)
+if (LIBUNWIND_USE_COMPILER_RT AND NOT LIBUNWIND_HAS_NODEFAULTLIBS_FLAG)
   list(APPEND LIBUNWIND_LINK_FLAGS "-rtlib=compiler-rt")
 endif()
 
@@ -226,48 +262,51 @@
 # Setup Compiler Flags
 #===============================================================================
 
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WERROR_FLAG -Werror=return-type)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WERROR_FLAG -Werror=return-type)
 
 # Get warning flags
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_W_FLAG -W)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WALL_FLAG -Wall)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WCHAR_SUBSCRIPTS_FLAG -Wchar-subscripts)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WCONVERSION_FLAG -Wconversion)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WMISMATCHED_TAGS_FLAG -Wmismatched-tags)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WMISSING_BRACES_FLAG -Wmissing-braces)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WNEWLINE_EOF_FLAG -Wnewline-eof)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WNO_UNUSED_FUNCTION_FLAG -Wno-unused-function)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSHADOW_FLAG -Wshadow)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSHORTEN_64_TO_32_FLAG -Wshorten-64-to-32)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSIGN_COMPARE_FLAG -Wsign-compare)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSIGN_CONVERSION_FLAG -Wsign-conversion)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSTRICT_ALIASING_FLAG -Wstrict-aliasing=2)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSTRICT_OVERFLOW_FLAG -Wstrict-overflow=4)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WUNUSED_PARAMETER_FLAG -Wunused-parameter)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WUNUSED_VARIABLE_FLAG -Wunused-variable)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WWRITE_STRINGS_FLAG -Wwrite-strings)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WUNDEF_FLAG -Wundef)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_W_FLAG -W)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WALL_FLAG -Wall)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WCHAR_SUBSCRIPTS_FLAG -Wchar-subscripts)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WCONVERSION_FLAG -Wconversion)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WMISMATCHED_TAGS_FLAG -Wmismatched-tags)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WMISSING_BRACES_FLAG -Wmissing-braces)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WNEWLINE_EOF_FLAG -Wnewline-eof)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WNO_UNUSED_FUNCTION_FLAG -Wno-unused-function)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSHADOW_FLAG -Wshadow)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSHORTEN_64_TO_32_FLAG -Wshorten-64-to-32)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSIGN_COMPARE_FLAG -Wsign-compare)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSIGN_CONVERSION_FLAG -Wsign-conversion)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSTRICT_ALIASING_FLAG -Wstrict-aliasing=2)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSTRICT_OVERFLOW_FLAG -Wstrict-overflow=4)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WUNUSED_PARAMETER_FLAG -Wunused-parameter)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WUNUSED_VARIABLE_FLAG -Wunused-variable)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WWRITE_STRINGS_FLAG -Wwrite-strings)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WUNDEF_FLAG -Wundef)
 
 if (LIBUNWIND_ENABLE_WERROR)
-  append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WERROR_FLAG -Werror)
-  append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WX_FLAG -WX)
+  unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WERROR_FLAG -Werror)
+  unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WX_FLAG -WX)
 else()
-  append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WNO_ERROR_FLAG -Wno-error)
-  append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_NO_WX_FLAG -WX-)
+  unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WNO_ERROR_FLAG -Wno-error)
+  unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_NO_WX_FLAG -WX-)
 endif()
 
 if (LIBUNWIND_ENABLE_PEDANTIC)
-  append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_PEDANTIC_FLAG -pedantic)
+  unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_PEDANTIC_FLAG -pedantic)
 endif()
 
 # Get feature flags.
 # Exceptions
 # Catches C++ exceptions only and tells the compiler to assume that extern C
 # functions never throw a C++ exception.
-append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_FSTRICT_ALIASING_FLAG -fstrict-aliasing)
-append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_EHSC_FLAG -EHsc)
+unwind_append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_FSTRICT_ALIASING_FLAG -fstrict-aliasing)
+unwind_append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_EHSC_FLAG -EHsc)
 
-append_if(LIBUNWIND_C_FLAGS LIBUNWIND_HAS_FUNWIND_TABLES -funwind-tables)
+unwind_append_if(LIBUNWIND_C_FLAGS LIBUNWIND_HAS_FUNWIND_TABLES -funwind-tables)
+
+# Ensure that we don't depend on C++ standard library.
+unwind_append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_NOSTDINCXX_FLAG -nostdinc++)
 
 # Assert
 string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
@@ -323,30 +362,12 @@
 
 include_directories(include)
 
-find_path(
-  LIBUNWIND_LIBCXX_INCLUDES_INTERNAL
-  __libcpp_version
-  PATHS ${LLVM_MAIN_SRC_DIR}/projects/libcxx/include
-        ${LLVM_MAIN_SRC_DIR}/runtimes/libcxx/include
-  NO_DEFAULT_PATH
-)
-if ((NOT LIBUNWIND_STANDALONE_BUILD OR HAVE_LIBCXX) AND
-    IS_DIRECTORY "${LIBUNWIND_LIBCXX_INCLUDES_INTERNAL}")
-  set(LIBUNWIND_CXX_INCLUDE_PATHS_DEFAULT "${LIBUNWIND_LIBCXX_INCLUDES_INTERNAL}")
-endif()
-
-set(LIBUNWIND_CXX_INCLUDE_PATHS "${LIBUNWIND_CXX_INCLUDE_PATHS_DEFAULT}" CACHE PATH
-    "Paths to C++ header directories separated by ';'.")
-
-if (NOT LIBUNWIND_CXX_INCLUDE_PATHS STREQUAL "")
-  list(APPEND LIBUNWIND_CXX_FLAGS -nostdinc++)
-  include_directories("${LIBUNWIND_CXX_INCLUDE_PATHS}")
-endif()
-
 add_subdirectory(src)
 
 if (LIBUNWIND_INCLUDE_DOCS)
   add_subdirectory(docs)
 endif()
 
-add_subdirectory(test)
+if (EXISTS ${LLVM_CMAKE_PATH})
+  add_subdirectory(test)
+endif()
diff --git a/LICENSE.TXT b/LICENSE.TXT
index fb77e1b..1e31206 100644
--- a/LICENSE.TXT
+++ b/LICENSE.TXT
@@ -1,5 +1,240 @@
 ==============================================================================
-libunwind License
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+==============================================================================
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+    1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+    2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+    3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+    4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+    5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+    6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+    7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+    8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+    9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+    END OF TERMS AND CONDITIONS
+
+    APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+    Copyright [yyyy] [name of copyright owner]
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+==============================================================================
+Software from third parties included in the LLVM Project:
+==============================================================================
+The LLVM Project contains third party software which is under different license
+terms. All such code will be identified clearly using at least one of two
+mechanisms:
+1) It will be in a separate directory tree with its own `LICENSE.txt` or
+   `LICENSE` file at the top containing the specific license and restrictions
+   which apply to that software, or
+2) It will contain specific license and restriction terms at the top of every
+   file.
+
+==============================================================================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
 ==============================================================================
 
 The libunwind library is dual licensed under both the University of Illinois
@@ -14,7 +249,7 @@
 University of Illinois/NCSA
 Open Source License
 
-Copyright (c) 2009-2017 by the contributors listed in CREDITS.TXT
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
 
 All rights reserved.
 
diff --git a/cmake/Modules/HandleCompilerRT.cmake b/cmake/Modules/HandleCompilerRT.cmake
index 9bf88bb..77168e5 100644
--- a/cmake/Modules/HandleCompilerRT.cmake
+++ b/cmake/Modules/HandleCompilerRT.cmake
@@ -8,12 +8,16 @@
   if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND CMAKE_CXX_COMPILER_TARGET)
     list(APPEND CLANG_COMMAND "--target=${CMAKE_CXX_COMPILER_TARGET}")
   endif()
+  get_property(LIBUNWIND_CXX_FLAGS CACHE CMAKE_CXX_FLAGS PROPERTY VALUE)
+  string(REPLACE " " ";" LIBUNWIND_CXX_FLAGS "${LIBUNWIND_CXX_FLAGS}")
+  list(APPEND CLANG_COMMAND ${LIBUNWIND_CXX_FLAGS})
   execute_process(
       COMMAND ${CLANG_COMMAND}
       RESULT_VARIABLE HAD_ERROR
       OUTPUT_VARIABLE LIBRARY_FILE
   )
   string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE)
+  file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE)
   string(REPLACE "builtins" "${name}" LIBRARY_FILE "${LIBRARY_FILE}")
   if (NOT HAD_ERROR AND EXISTS "${LIBRARY_FILE}")
     message(STATUS "Found compiler-rt library: ${LIBRARY_FILE}")
@@ -37,6 +41,7 @@
         OUTPUT_VARIABLE LIBRARY_DIR
     )
     string(STRIP "${LIBRARY_DIR}" LIBRARY_DIR)
+    file(TO_CMAKE_PATH "${LIBRARY_DIR}" LIBRARY_DIR)
     set(LIBRARY_DIR "${LIBRARY_DIR}/darwin")
   else()
     set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBUNWIND_COMPILE_FLAGS}
@@ -47,6 +52,7 @@
         OUTPUT_VARIABLE LIBRARY_FILE
     )
     string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE)
+    file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE)
     get_filename_component(LIBRARY_DIR "${LIBRARY_FILE}" DIRECTORY)
   endif()
   if (NOT HAD_ERROR AND EXISTS "${LIBRARY_DIR}")
diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake
index 2d4da64..670c31f 100644
--- a/cmake/config-ix.cmake
+++ b/cmake/config-ix.cmake
@@ -7,6 +7,7 @@
 
 if (NOT LIBUNWIND_USE_COMPILER_RT)
   check_library_exists(gcc_s __gcc_personality_v0 "" LIBUNWIND_HAS_GCC_S_LIB)
+  check_library_exists(gcc __absvdi2 "" LIBUNWIND_HAS_GCC_LIB)
 endif()
 
 # libunwind is built with -nodefaultlibs, so we want all our checks to also
@@ -23,11 +24,15 @@
     list(APPEND CMAKE_REQUIRED_LIBRARIES c)
   endif ()
   if (LIBUNWIND_USE_COMPILER_RT)
-    list(APPEND CMAKE_REQUIRED_FLAGS -rtlib=compiler-rt)
     find_compiler_rt_library(builtins LIBUNWIND_BUILTINS_LIBRARY)
     list(APPEND CMAKE_REQUIRED_LIBRARIES "${LIBUNWIND_BUILTINS_LIBRARY}")
-  elseif (LIBUNWIND_HAS_GCC_S_LIB)
-    list(APPEND CMAKE_REQUIRED_LIBRARIES gcc_s)
+  else ()
+    if (LIBUNWIND_HAS_GCC_S_LIB)
+      list(APPEND CMAKE_REQUIRED_LIBRARIES gcc_s)
+    endif ()
+    if (LIBUNWIND_HAS_GCC_LIB)
+      list(APPEND CMAKE_REQUIRED_LIBRARIES gcc)
+    endif ()
   endif ()
   if (MINGW)
     # Mingw64 requires quite a few "C" runtime libraries in order for basic
diff --git a/docs/BuildingLibunwind.rst b/docs/BuildingLibunwind.rst
index 6aa4556..7f42133 100644
--- a/docs/BuildingLibunwind.rst
+++ b/docs/BuildingLibunwind.rst
@@ -18,16 +18,10 @@
 
 The basic steps needed to build libc++ are:
 
-#. Checkout LLVM:
+#. Checkout LLVM, libunwind, and related projects:
 
    * ``cd where-you-want-llvm-to-live``
-   * ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm``
-
-#. Checkout libunwind:
-
-   * ``cd where-you-want-llvm-to-live``
-   * ``cd llvm/runtimes``
-   * ``svn co http://llvm.org/svn/llvm-project/libunwind/trunk libunwind``
+   * ``git clone https://github.com/llvm/llvm-project.git``
 
 #. Configure and build libunwind:
 
@@ -38,7 +32,7 @@
    * ``cd where you want to build llvm``
    * ``mkdir build``
    * ``cd build``
-   * ``cmake -G <generator> [options] <path to llvm sources>``
+   * ``cmake -G <generator> -DLLVM_ENABLE_PROJECTS=libunwind [options] <path to llvm sources>``
 
    For more information about configuring libunwind see :ref:`CMake Options`.
 
diff --git a/docs/conf.py b/docs/conf.py
index 29c95f3..704a1d0 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -11,6 +11,7 @@
 # serve to show the default.
 
 import sys, os
+from datetime import date
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
@@ -40,16 +41,16 @@
 
 # General information about the project.
 project = u'libunwind'
-copyright = u'2011-2017, LLVM Project'
+copyright = u'2011-%d, LLVM Project' % date.today().year
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # The short X.Y version.
-version = '6.0'
+version = '9.0'
 # The full version, including alpha/beta/rc tags.
-release = '6.0'
+release = '9.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/docs/index.rst b/docs/index.rst
index 7e7277e..9e53b41 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -101,5 +101,4 @@
 * `LLVM Bugzilla <https://bugs.llvm.org/>`_
 * `cfe-commits Mailing List`_
 * `cfe-dev Mailing List`_
-* `Browse libunwind -- SVN <http://llvm.org/svn/llvm-project/libunwind/trunk/>`_
-* `Browse libunwind -- ViewVC <http://llvm.org/viewvc/llvm-project/libunwind/trunk/>`_
+* `Browse libunwind Sources <https://github.com/llvm/llvm-project/blob/master/libunwind/>`_
diff --git a/include/__libunwind_config.h b/include/__libunwind_config.h
index 69a4996..6e7e5e6 100644
--- a/include/__libunwind_config.h
+++ b/include/__libunwind_config.h
@@ -1,9 +1,8 @@
 //===------------------------- __libunwind_config.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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 
@@ -18,10 +17,12 @@
 #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     116
 #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_OR1K      32
 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS      65
+#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC     31
 
 #if defined(_LIBUNWIND_IS_NATIVE_ONLY)
 # if defined(__i386__)
@@ -33,12 +34,21 @@
 #  define _LIBUNWIND_TARGET_X86_64 1
 #  if defined(_WIN64)
 #    define _LIBUNWIND_CONTEXT_SIZE 54
-#    define _LIBUNWIND_CURSOR_SIZE 66
+#    ifdef __SEH__
+#      define _LIBUNWIND_CURSOR_SIZE 204
+#    else
+#      define _LIBUNWIND_CURSOR_SIZE 66
+#    endif
 #  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 167
+#  define _LIBUNWIND_CURSOR_SIZE 179
+#  define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64
 # elif defined(__ppc__)
 #  define _LIBUNWIND_TARGET_PPC 1
 #  define _LIBUNWIND_CONTEXT_SIZE 117
@@ -47,11 +57,18 @@
 # elif defined(__aarch64__)
 #  define _LIBUNWIND_TARGET_AARCH64 1
 #  define _LIBUNWIND_CONTEXT_SIZE 66
-#  define _LIBUNWIND_CURSOR_SIZE 78
+#  if defined(__SEH__)
+#    define _LIBUNWIND_CURSOR_SIZE 164
+#  else
+#    define _LIBUNWIND_CURSOR_SIZE 78
+#  endif
 #  define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64
 # elif defined(__arm__)
 #  define _LIBUNWIND_TARGET_ARM 1
-#  if defined(__ARM_WMMX)
+#  if defined(__SEH__)
+#    define _LIBUNWIND_CONTEXT_SIZE 42
+#    define _LIBUNWIND_CURSOR_SIZE 80
+#  elif defined(__ARM_WMMX)
 #    define _LIBUNWIND_CONTEXT_SIZE 61
 #    define _LIBUNWIND_CURSOR_SIZE 68
 #  else
@@ -65,18 +82,42 @@
 #  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)
+#  if defined(_ABIO32) && _MIPS_SIM == _ABIO32
 #    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
+#    if defined(__mips_hard_float)
+#      define _LIBUNWIND_CONTEXT_SIZE 50
+#      define _LIBUNWIND_CURSOR_SIZE 57
+#    else
+#      define _LIBUNWIND_CONTEXT_SIZE 18
+#      define _LIBUNWIND_CURSOR_SIZE 24
+#    endif
+#  elif defined(_ABIN32) && _MIPS_SIM == _ABIN32
+#    define _LIBUNWIND_TARGET_MIPS_NEWABI 1
+#    if defined(__mips_hard_float)
+#      define _LIBUNWIND_CONTEXT_SIZE 67
+#      define _LIBUNWIND_CURSOR_SIZE 74
+#    else
+#      define _LIBUNWIND_CONTEXT_SIZE 35
+#      define _LIBUNWIND_CURSOR_SIZE 42
+#    endif
+#  elif defined(_ABI64) && _MIPS_SIM == _ABI64
+#    define _LIBUNWIND_TARGET_MIPS_NEWABI 1
+#    if defined(__mips_hard_float)
+#      define _LIBUNWIND_CONTEXT_SIZE 67
+#      define _LIBUNWIND_CURSOR_SIZE 79
+#    else
+#      define _LIBUNWIND_CONTEXT_SIZE 35
+#      define _LIBUNWIND_CURSOR_SIZE 47
+#    endif
 #  else
 #    error "Unsupported MIPS ABI and/or environment"
 #  endif
 #  define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS
+# elif defined(__sparc__)
+  #define _LIBUNWIND_TARGET_SPARC 1
+  #define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC
+  #define _LIBUNWIND_CONTEXT_SIZE 16
+  #define _LIBUNWIND_CURSOR_SIZE 23
 # else
 #  error "Unsupported architecture."
 # endif
@@ -84,13 +125,15 @@
 # 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_TARGET_MIPS_O32 1
-# define _LIBUNWIND_TARGET_MIPS_N64 1
-# define _LIBUNWIND_CONTEXT_SIZE 128
-# define _LIBUNWIND_CURSOR_SIZE 140
+# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
+# define _LIBUNWIND_TARGET_SPARC 1
+# define _LIBUNWIND_CONTEXT_SIZE 167
+# define _LIBUNWIND_CURSOR_SIZE 179
 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
 #endif // _LIBUNWIND_IS_NATIVE_ONLY
 
diff --git a/include/libunwind.h b/include/libunwind.h
index 9011d55..d06724d 100644
--- a/include/libunwind.h
+++ b/include/libunwind.h
@@ -1,9 +1,8 @@
 //===---------------------------- libunwind.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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 // Compatible with libunwind API documented at:
@@ -57,6 +56,9 @@
   UNW_EINVAL        = -6547, /* unsupported operation or bad value */
   UNW_EBADVERSION   = -6548, /* unwind info has unsupported version */
   UNW_ENOINFO       = -6549  /* no unwind info found */
+#if defined(_LIBUNWIND_TARGET_AARCH64) && !defined(_LIBUNWIND_IS_NATIVE_ONLY)
+  , UNW_ECROSSRASIGNING = -6550 /* cross unwind with return address signing */
+#endif
 };
 
 struct unw_context_t {
@@ -73,7 +75,7 @@
 
 typedef int unw_regnum_t;
 typedef uintptr_t unw_word_t;
-#if defined(__arm__)
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
 typedef uint64_t unw_fpreg_t;
 #else
 typedef double unw_fpreg_t;
@@ -122,32 +124,6 @@
 
 extern unw_addr_space_t unw_local_addr_space;
 
-#ifdef UNW_REMOTE
-/*
- * Mac OS X "remote" API for unwinding other processes on same machine
- *
- */
-extern unw_addr_space_t unw_create_addr_space_for_task(task_t);
-extern void unw_destroy_addr_space(unw_addr_space_t);
-extern int unw_init_remote_thread(unw_cursor_t *, unw_addr_space_t, thread_t *);
-#endif /* UNW_REMOTE */
-
-/*
- * traditional libunwind "remote" API
- *   NOT IMPLEMENTED on Mac OS X
- *
- * extern int               unw_init_remote(unw_cursor_t*, unw_addr_space_t,
- *                                          thread_t*);
- * extern unw_accessors_t   unw_get_accessors(unw_addr_space_t);
- * extern unw_addr_space_t  unw_create_addr_space(unw_accessors_t, int);
- * extern void              unw_flush_cache(unw_addr_space_t, unw_word_t,
- *                                          unw_word_t);
- * extern int               unw_set_caching_policy(unw_addr_space_t,
- *                                                 unw_caching_policy_t);
- * extern void              _U_dyn_register(unw_dyn_info_t*);
- * extern void              _U_dyn_cancel(unw_dyn_info_t*);
- */
-
 #ifdef __cplusplus
 }
 #endif
@@ -325,6 +301,190 @@
   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,
+  // 64: reserved
+  UNW_PPC64_LR      = 65,
+  UNW_PPC64_CTR     = 66,
+  // 67: reserved
+  UNW_PPC64_CR0     = 68,
+  UNW_PPC64_CR1     = 69,
+  UNW_PPC64_CR2     = 70,
+  UNW_PPC64_CR3     = 71,
+  UNW_PPC64_CR4     = 72,
+  UNW_PPC64_CR5     = 73,
+  UNW_PPC64_CR6     = 74,
+  UNW_PPC64_CR7     = 75,
+  UNW_PPC64_XER     = 76,
+  UNW_PPC64_V0      = 77,
+  UNW_PPC64_V1      = 78,
+  UNW_PPC64_V2      = 79,
+  UNW_PPC64_V3      = 80,
+  UNW_PPC64_V4      = 81,
+  UNW_PPC64_V5      = 82,
+  UNW_PPC64_V6      = 83,
+  UNW_PPC64_V7      = 84,
+  UNW_PPC64_V8      = 85,
+  UNW_PPC64_V9      = 86,
+  UNW_PPC64_V10     = 87,
+  UNW_PPC64_V11     = 88,
+  UNW_PPC64_V12     = 89,
+  UNW_PPC64_V13     = 90,
+  UNW_PPC64_V14     = 91,
+  UNW_PPC64_V15     = 92,
+  UNW_PPC64_V16     = 93,
+  UNW_PPC64_V17     = 94,
+  UNW_PPC64_V18     = 95,
+  UNW_PPC64_V19     = 96,
+  UNW_PPC64_V20     = 97,
+  UNW_PPC64_V21     = 98,
+  UNW_PPC64_V22     = 99,
+  UNW_PPC64_V23     = 100,
+  UNW_PPC64_V24     = 101,
+  UNW_PPC64_V25     = 102,
+  UNW_PPC64_V26     = 103,
+  UNW_PPC64_V27     = 104,
+  UNW_PPC64_V28     = 105,
+  UNW_PPC64_V29     = 106,
+  UNW_PPC64_V30     = 107,
+  UNW_PPC64_V31     = 108,
+  // 109, 111-113: OpenPOWER ELF V2 ABI: reserved
+  // Borrowing VRSAVE number from PPC32.
+  UNW_PPC64_VRSAVE  = 109,
+  UNW_PPC64_VSCR    = 110,
+  UNW_PPC64_TFHAR   = 114,
+  UNW_PPC64_TFIAR   = 115,
+  UNW_PPC64_TEXASR  = 116,
+  UNW_PPC64_VS0     = UNW_PPC64_F0,
+  UNW_PPC64_VS1     = UNW_PPC64_F1,
+  UNW_PPC64_VS2     = UNW_PPC64_F2,
+  UNW_PPC64_VS3     = UNW_PPC64_F3,
+  UNW_PPC64_VS4     = UNW_PPC64_F4,
+  UNW_PPC64_VS5     = UNW_PPC64_F5,
+  UNW_PPC64_VS6     = UNW_PPC64_F6,
+  UNW_PPC64_VS7     = UNW_PPC64_F7,
+  UNW_PPC64_VS8     = UNW_PPC64_F8,
+  UNW_PPC64_VS9     = UNW_PPC64_F9,
+  UNW_PPC64_VS10    = UNW_PPC64_F10,
+  UNW_PPC64_VS11    = UNW_PPC64_F11,
+  UNW_PPC64_VS12    = UNW_PPC64_F12,
+  UNW_PPC64_VS13    = UNW_PPC64_F13,
+  UNW_PPC64_VS14    = UNW_PPC64_F14,
+  UNW_PPC64_VS15    = UNW_PPC64_F15,
+  UNW_PPC64_VS16    = UNW_PPC64_F16,
+  UNW_PPC64_VS17    = UNW_PPC64_F17,
+  UNW_PPC64_VS18    = UNW_PPC64_F18,
+  UNW_PPC64_VS19    = UNW_PPC64_F19,
+  UNW_PPC64_VS20    = UNW_PPC64_F20,
+  UNW_PPC64_VS21    = UNW_PPC64_F21,
+  UNW_PPC64_VS22    = UNW_PPC64_F22,
+  UNW_PPC64_VS23    = UNW_PPC64_F23,
+  UNW_PPC64_VS24    = UNW_PPC64_F24,
+  UNW_PPC64_VS25    = UNW_PPC64_F25,
+  UNW_PPC64_VS26    = UNW_PPC64_F26,
+  UNW_PPC64_VS27    = UNW_PPC64_F27,
+  UNW_PPC64_VS28    = UNW_PPC64_F28,
+  UNW_PPC64_VS29    = UNW_PPC64_F29,
+  UNW_PPC64_VS30    = UNW_PPC64_F30,
+  UNW_PPC64_VS31    = UNW_PPC64_F31,
+  UNW_PPC64_VS32    = UNW_PPC64_V0,
+  UNW_PPC64_VS33    = UNW_PPC64_V1,
+  UNW_PPC64_VS34    = UNW_PPC64_V2,
+  UNW_PPC64_VS35    = UNW_PPC64_V3,
+  UNW_PPC64_VS36    = UNW_PPC64_V4,
+  UNW_PPC64_VS37    = UNW_PPC64_V5,
+  UNW_PPC64_VS38    = UNW_PPC64_V6,
+  UNW_PPC64_VS39    = UNW_PPC64_V7,
+  UNW_PPC64_VS40    = UNW_PPC64_V8,
+  UNW_PPC64_VS41    = UNW_PPC64_V9,
+  UNW_PPC64_VS42    = UNW_PPC64_V10,
+  UNW_PPC64_VS43    = UNW_PPC64_V11,
+  UNW_PPC64_VS44    = UNW_PPC64_V12,
+  UNW_PPC64_VS45    = UNW_PPC64_V13,
+  UNW_PPC64_VS46    = UNW_PPC64_V14,
+  UNW_PPC64_VS47    = UNW_PPC64_V15,
+  UNW_PPC64_VS48    = UNW_PPC64_V16,
+  UNW_PPC64_VS49    = UNW_PPC64_V17,
+  UNW_PPC64_VS50    = UNW_PPC64_V18,
+  UNW_PPC64_VS51    = UNW_PPC64_V19,
+  UNW_PPC64_VS52    = UNW_PPC64_V20,
+  UNW_PPC64_VS53    = UNW_PPC64_V21,
+  UNW_PPC64_VS54    = UNW_PPC64_V22,
+  UNW_PPC64_VS55    = UNW_PPC64_V23,
+  UNW_PPC64_VS56    = UNW_PPC64_V24,
+  UNW_PPC64_VS57    = UNW_PPC64_V25,
+  UNW_PPC64_VS58    = UNW_PPC64_V26,
+  UNW_PPC64_VS59    = UNW_PPC64_V27,
+  UNW_PPC64_VS60    = UNW_PPC64_V28,
+  UNW_PPC64_VS61    = UNW_PPC64_V29,
+  UNW_PPC64_VS62    = UNW_PPC64_V30,
+  UNW_PPC64_VS63    = UNW_PPC64_V31
+};
+
 // 64-bit ARM64 registers
 enum {
   UNW_ARM64_X0  = 0,
@@ -363,6 +523,8 @@
   UNW_ARM64_X31 = 31,
   UNW_ARM64_SP  = 31,
   // reserved block
+  UNW_ARM64_RA_SIGN_STATE = 34,
+  // reserved block
   UNW_ARM64_D0  = 64,
   UNW_ARM64_D1  = 65,
   UNW_ARM64_D2  = 66,
@@ -561,6 +723,7 @@
   UNW_OR1K_R29 = 29,
   UNW_OR1K_R30 = 30,
   UNW_OR1K_R31 = 31,
+  UNW_OR1K_EPCR = 32,
 };
 
 // MIPS registers
@@ -597,8 +760,76 @@
   UNW_MIPS_R29 = 29,
   UNW_MIPS_R30 = 30,
   UNW_MIPS_R31 = 31,
+  UNW_MIPS_F0  = 32,
+  UNW_MIPS_F1  = 33,
+  UNW_MIPS_F2  = 34,
+  UNW_MIPS_F3  = 35,
+  UNW_MIPS_F4  = 36,
+  UNW_MIPS_F5  = 37,
+  UNW_MIPS_F6  = 38,
+  UNW_MIPS_F7  = 39,
+  UNW_MIPS_F8  = 40,
+  UNW_MIPS_F9  = 41,
+  UNW_MIPS_F10 = 42,
+  UNW_MIPS_F11 = 43,
+  UNW_MIPS_F12 = 44,
+  UNW_MIPS_F13 = 45,
+  UNW_MIPS_F14 = 46,
+  UNW_MIPS_F15 = 47,
+  UNW_MIPS_F16 = 48,
+  UNW_MIPS_F17 = 49,
+  UNW_MIPS_F18 = 50,
+  UNW_MIPS_F19 = 51,
+  UNW_MIPS_F20 = 52,
+  UNW_MIPS_F21 = 53,
+  UNW_MIPS_F22 = 54,
+  UNW_MIPS_F23 = 55,
+  UNW_MIPS_F24 = 56,
+  UNW_MIPS_F25 = 57,
+  UNW_MIPS_F26 = 58,
+  UNW_MIPS_F27 = 59,
+  UNW_MIPS_F28 = 60,
+  UNW_MIPS_F29 = 61,
+  UNW_MIPS_F30 = 62,
+  UNW_MIPS_F31 = 63,
   UNW_MIPS_HI = 64,
   UNW_MIPS_LO = 65,
 };
 
+// SPARC registers
+enum {
+  UNW_SPARC_G0 = 0,
+  UNW_SPARC_G1 = 1,
+  UNW_SPARC_G2 = 2,
+  UNW_SPARC_G3 = 3,
+  UNW_SPARC_G4 = 4,
+  UNW_SPARC_G5 = 5,
+  UNW_SPARC_G6 = 6,
+  UNW_SPARC_G7 = 7,
+  UNW_SPARC_O0 = 8,
+  UNW_SPARC_O1 = 9,
+  UNW_SPARC_O2 = 10,
+  UNW_SPARC_O3 = 11,
+  UNW_SPARC_O4 = 12,
+  UNW_SPARC_O5 = 13,
+  UNW_SPARC_O6 = 14,
+  UNW_SPARC_O7 = 15,
+  UNW_SPARC_L0 = 16,
+  UNW_SPARC_L1 = 17,
+  UNW_SPARC_L2 = 18,
+  UNW_SPARC_L3 = 19,
+  UNW_SPARC_L4 = 20,
+  UNW_SPARC_L5 = 21,
+  UNW_SPARC_L6 = 22,
+  UNW_SPARC_L7 = 23,
+  UNW_SPARC_I0 = 24,
+  UNW_SPARC_I1 = 25,
+  UNW_SPARC_I2 = 26,
+  UNW_SPARC_I3 = 27,
+  UNW_SPARC_I4 = 28,
+  UNW_SPARC_I5 = 29,
+  UNW_SPARC_I6 = 30,
+  UNW_SPARC_I7 = 31,
+};
+
 #endif
diff --git a/include/mach-o/compact_unwind_encoding.h b/include/mach-o/compact_unwind_encoding.h
index de14fd5..5301b10 100644
--- a/include/mach-o/compact_unwind_encoding.h
+++ b/include/mach-o/compact_unwind_encoding.h
@@ -1,9 +1,8 @@
 //===------------------ mach-o/compact_unwind_encoding.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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 // Darwin's alternative to DWARF based unwind encodings.
diff --git a/include/unwind.h b/include/unwind.h
index 0ab87dd..122b57b 100644
--- a/include/unwind.h
+++ b/include/unwind.h
@@ -1,9 +1,8 @@
 //===------------------------------- unwind.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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 // C++ ABI Level 1 ABI documented at:
@@ -19,6 +18,11 @@
 #include <stdint.h>
 #include <stddef.h>
 
+#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) && defined(_WIN32)
+#include <windows.h>
+#include <ntverp.h>
+#endif
+
 #if defined(__APPLE__)
 #define LIBUNWIND_UNAVAIL __attribute__ (( unavailable ))
 #else
@@ -120,13 +124,17 @@
   uint64_t exception_class;
   void (*exception_cleanup)(_Unwind_Reason_Code reason,
                             _Unwind_Exception *exc);
+#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+  uintptr_t private_[6];
+#else
   uintptr_t private_1; // non-zero means forced unwind
   uintptr_t private_2; // holds sp that phase1 found for phase2 to use
+#endif
 #if __SIZEOF_POINTER__ == 4
   // The implementation of _Unwind_Exception uses an attribute mode on the
   // above fields which has the side effect of causing this whole struct to
-  // round up to 32 bytes in size. To be more explicit, we add pad fields
-  // added for binary compatibility.
+  // round up to 32 bytes in size (48 with SEH). To be more explicit, we add
+  // pad fields added for binary compatibility.
   uint32_t reserved[3];
 #endif
   // The Itanium ABI requires that _Unwind_Exception objects are "double-word
@@ -369,6 +377,22 @@
 extern void *__deregister_frame_info_bases(const void *fde)
     LIBUNWIND_UNAVAIL;
 
+#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+#ifndef _WIN32
+typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD;
+typedef struct _CONTEXT CONTEXT;
+typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT;
+#elif !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
+typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT;
+#endif
+// This is the common wrapper for GCC-style personality functions with SEH.
+extern EXCEPTION_DISPOSITION _GCC_specific_handler(EXCEPTION_RECORD *exc,
+                                                   void *frame,
+                                                   CONTEXT *ctx,
+                                                   DISPATCHER_CONTEXT *disp,
+                                                   __personality_routine pers);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/AddressSpace.hpp b/src/AddressSpace.hpp
index 2be16af..fb370ad 100644
--- a/src/AddressSpace.hpp
+++ b/src/AddressSpace.hpp
@@ -1,9 +1,8 @@
 //===------------------------- AddressSpace.hpp ---------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 // Abstracts accessing local vs remote address spaces.
@@ -18,7 +17,15 @@
 #include <stdlib.h>
 #include <string.h>
 
-#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
+#ifndef _LIBUNWIND_USE_DLADDR
+  #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
+    #define _LIBUNWIND_USE_DLADDR 1
+  #else
+    #define _LIBUNWIND_USE_DLADDR 0
+  #endif
+#endif
+
+#if _LIBUNWIND_USE_DLADDR
 #include <dlfcn.h>
 #endif
 
@@ -83,6 +90,38 @@
     }
   #endif
 
+#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && 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.
+
+// 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
@@ -115,7 +154,7 @@
 struct UnwindInfoSections {
 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) ||       \
     defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
-  // No dso_base for ARM EHABI.
+  // No dso_base for SEH or ARM EHABI.
   uintptr_t       dso_base;
 #endif
 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
@@ -140,7 +179,7 @@
 /// LocalAddressSpace is used as a template parameter to UnwindCursor when
 /// unwinding a thread in the same process.  The wrappers compile away,
 /// making local unwinds fast.
-class __attribute__((visibility("hidden"))) LocalAddressSpace {
+class _LIBUNWIND_HIDDEN LocalAddressSpace {
 public:
   typedef uintptr_t pint_t;
   typedef intptr_t  sint_t;
@@ -175,6 +214,7 @@
     return val;
   }
   uintptr_t       getP(pint_t addr);
+  uint64_t        getRegister(pint_t addr);
   static uint64_t getULEB128(pint_t &addr, pint_t end);
   static int64_t  getSLEB128(pint_t &addr, pint_t end);
 
@@ -196,6 +236,14 @@
 #endif
 }
 
+inline uint64_t LocalAddressSpace::getRegister(pint_t addr) {
+#if __SIZEOF_POINTER__ == 8 || defined(__mips64)
+  return get64(addr);
+#else
+  return get32(addr);
+#endif
+}
+
 /// Read a ULEB128 into a 64-bit word.
 inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
   const uint8_t *p = (uint8_t *)addr;
@@ -348,12 +396,26 @@
     info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
     return true;
   }
+#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);
-  _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x",
-                             info.arm_section, info.arm_section_length);
+  _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)
@@ -391,6 +453,12 @@
     }
   }
   return false;
+#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
+  // Don't even bother, since Windows has functions that do all this stuff
+  // for us.
+  (void)targetAddr;
+  (void)info;
+  return true;
 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) &&                  \
     (__ANDROID_API__ < 21)
   int length = 0;
@@ -467,11 +535,11 @@
 #endif
             cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
             cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
-            EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
+            found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
                 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
                 hdrInfo);
-            cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
-            found_hdr = true;
+            if (found_hdr)
+              cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
           }
         }
 
@@ -521,7 +589,7 @@
 inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
                                                 size_t bufLen,
                                                 unw_word_t *offset) {
-#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
+#if _LIBUNWIND_USE_DLADDR
   Dl_info dyldInfo;
   if (dladdr((void *)addr, &dyldInfo)) {
     if (dyldInfo.dli_sname != NULL) {
@@ -530,129 +598,15 @@
       return true;
     }
   }
+#else
+  (void)addr;
+  (void)buf;
+  (void)bufLen;
+  (void)offset;
 #endif
   return false;
 }
 
-
-
-#ifdef UNW_REMOTE
-
-/// 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 RemoteAddressSpace {
-public:
-  RemoteAddressSpace(task_t task) : fTask(task) {}
-
-  typedef typename P::uint_t pint_t;
-
-  uint8_t   get8(pint_t addr);
-  uint16_t  get16(pint_t addr);
-  uint32_t  get32(pint_t addr);
-  uint64_t  get64(pint_t addr);
-  pint_t    getP(pint_t addr);
-  uint64_t  getULEB128(pint_t &addr, pint_t end);
-  int64_t   getSLEB128(pint_t &addr, pint_t end);
-  pint_t    getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
-                        pint_t datarelBase = 0);
-  bool      findFunctionName(pint_t addr, char *buf, size_t bufLen,
-                        unw_word_t *offset);
-  bool      findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
-  bool      findOtherFDE(pint_t targetAddr, pint_t &fde);
-private:
-  void *localCopy(pint_t addr);
-
-  task_t fTask;
-};
-
-template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) {
-  return *((uint8_t *)localCopy(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 RemoteAddressSpace<P>::get32(pint_t addr) {
-  return P::E::get32(*(uint32_t *)localCopy(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 RemoteAddressSpace<P>::getP(pint_t addr) {
-  return P::getP(*(uint64_t *)localCopy(addr));
-}
-
-template <typename P>
-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;
-  uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size);
-  addr += (laddr - sladdr);
-  return result;
-}
-
-template <typename P>
-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;
-  uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size);
-  addr += (laddr - sladdr);
-  return result;
-}
-
-template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) {
-  // FIX ME
-}
-
-template <typename P>
-bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
-                                             size_t bufLen,
-                                             unw_word_t *offset) {
-  // FIX ME
-}
-
-/// unw_addr_space is the base class that abstract unw_addr_space_t type in
-/// libunwind.h points to.
-struct unw_addr_space {
-  cpu_type_t cpuType;
-  task_t taskPort;
-};
-
-/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points
-/// to when examining
-/// a 32-bit intel process.
-struct unw_addr_space_i386 : public unw_addr_space {
-  unw_addr_space_i386(task_t task) : oas(task) {}
-  RemoteAddressSpace<Pointer32<LittleEndian>> oas;
-};
-
-/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
-/// points to when examining
-/// 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) {}
-  RemoteAddressSpace<Pointer64<LittleEndian>> oas;
-};
-
-/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
-/// to when examining
-/// a 32-bit PowerPC process.
-struct unw_addr_space_ppc : public unw_addr_space {
-  unw_addr_space_ppc(task_t task) : oas(task) {}
-  RemoteAddressSpace<Pointer32<BigEndian>> oas;
-};
-
-#endif // UNW_REMOTE
-
 } // namespace libunwind
 
 #endif // __ADDRESSSPACE_HPP__
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2d2ec13..2928a14 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,8 +2,9 @@
 
 set(LIBUNWIND_CXX_SOURCES
     libunwind.cpp
-    Unwind-EHABI.cpp)
-append_if(LIBUNWIND_CXX_SOURCES APPLE Unwind_AppleExtras.cpp)
+    Unwind-EHABI.cpp
+    Unwind-seh.cpp)
+unwind_append_if(LIBUNWIND_CXX_SOURCES APPLE Unwind_AppleExtras.cpp)
 
 set(LIBUNWIND_C_SOURCES
     UnwindLevel1.c
@@ -35,7 +36,7 @@
     ${CMAKE_CURRENT_SOURCE_DIR}/../include/libunwind.h
     ${CMAKE_CURRENT_SOURCE_DIR}/../include/unwind.h)
 
-append_if(LIBUNWIND_HEADERS APPLE
+unwind_append_if(LIBUNWIND_HEADERS APPLE
           "${CMAKE_CURRENT_SOURCE_DIR}/../include/mach-o/compact_unwind_encoding.h")
 
 if (MSVC_IDE)
@@ -50,17 +51,26 @@
     ${LIBUNWIND_ASM_SOURCES})
 
 # Generate library list.
-set(libraries ${LIBUNWINDCXX_ABI_LIBRARIES})
-append_if(libraries LIBUNWIND_HAS_C_LIB c)
-append_if(libraries LIBUNWIND_HAS_DL_LIB dl)
+set(libraries)
+unwind_append_if(libraries LIBUNWIND_HAS_C_LIB c)
+if (LIBUNWIND_USE_COMPILER_RT)
+  list(APPEND libraries "${LIBUNWIND_BUILTINS_LIBRARY}")
+else()
+  unwind_append_if(libraries LIBUNWIND_HAS_GCC_S_LIB gcc_s)
+  unwind_append_if(libraries LIBUNWIND_HAS_GCC_LIB gcc)
+endif()
+unwind_append_if(libraries LIBUNWIND_HAS_DL_LIB dl)
 if (LIBUNWIND_ENABLE_THREADS)
-  append_if(libraries LIBUNWIND_HAS_PTHREAD_LIB pthread)
+  unwind_append_if(libraries LIBUNWIND_HAS_PTHREAD_LIB pthread)
 endif()
 
 # Setup flags.
-append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_NO_RTTI_FLAG -fno-rtti)
+unwind_append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_NO_RTTI_FLAG -fno-rtti)
 
-append_if(LIBUNWIND_LINK_FLAGS LIBUNWIND_HAS_NODEFAULTLIBS_FLAG -nodefaultlibs)
+unwind_append_if(LIBUNWIND_LINK_FLAGS LIBUNWIND_HAS_NODEFAULTLIBS_FLAG -nodefaultlibs)
+
+# MINGW_LIBRARIES is defined in config-ix.cmake
+unwind_append_if(libraries MINGW "${MINGW_LIBRARIES}")
 
 if (LIBUNWIND_HAS_NO_EXCEPTIONS_FLAG AND LIBUNWIND_HAS_FUNWIND_TABLES)
   list(APPEND LIBUNWIND_COMPILE_FLAGS -fno-exceptions)
@@ -91,49 +101,83 @@
 string(REPLACE ";" " " LIBUNWIND_LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}")
 
 set_property(SOURCE ${LIBUNWIND_CXX_SOURCES}
-             APPEND_STRING PROPERTY COMPILE_FLAGS " ${CMAKE_CXX_FLAGS} ${LIBUNWIND_CXX_FLAGS}")
+             APPEND_STRING PROPERTY COMPILE_FLAGS " ${LIBUNWIND_CXX_FLAGS}")
 set_property(SOURCE ${LIBUNWIND_C_SOURCES}
-             APPEND_STRING PROPERTY COMPILE_FLAGS " ${CMAKE_C_FLAGS} ${LIBUNWIND_C_FLAGS}")
+             APPEND_STRING PROPERTY COMPILE_FLAGS " ${LIBUNWIND_C_FLAGS}")
+
+macro(unwind_object_library name)
+  cmake_parse_arguments(ARGS "" "" "DEFINES;FLAGS" ${ARGN})
 
 # Add a object library that contains the compiled source files.
-add_library(unwind_objects OBJECT ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
+  add_library(${name} OBJECT ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
 
-set_target_properties(unwind_objects
-                      PROPERTIES
-                        COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}"
-                        POSITION_INDEPENDENT_CODE ON)
+  if(ARGS_DEFINES)
+    target_compile_definitions(${name} PRIVATE ${ARGS_DEFINES})
+  endif()
 
-set(LIBUNWIND_TARGETS)
+  set_target_properties(${name}
+                        PROPERTIES
+                          COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}"
+                          POSITION_INDEPENDENT_CODE ON)
+
+  if(ARGS_FLAGS)
+    target_compile_options(${name} PRIVATE ${ARGS_FLAGS})
+  endif()
+endmacro()
+
+if(LIBUNWIND_HERMETIC_STATIC_LIBRARY)
+  append_flags_if_supported(UNWIND_STATIC_OBJECTS_FLAGS -fvisibility=hidden)
+  append_flags_if_supported(UNWIND_STATIC_OBJECTS_FLAGS -fvisibility-global-new-delete-hidden)
+  unwind_object_library(unwind_static_objects
+    DEFINES _LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS
+    FLAGS ${UNWIND_STATIC_OBJECTS_FLAGS})
+  unwind_object_library(unwind_shared_objects)
+  set(unwind_static_sources $<TARGET_OBJECTS:unwind_static_objects>)
+  set(unwind_shared_sources $<TARGET_OBJECTS:unwind_shared_objects>)
+else()
+  unwind_object_library(unwind_objects)
+  set(unwind_static_sources $<TARGET_OBJECTS:unwind_objects>)
+  set(unwind_shared_sources $<TARGET_OBJECTS:unwind_objects>)
+endif()
 
 # Build the shared library.
 if (LIBUNWIND_ENABLE_SHARED)
-  add_library(unwind_shared SHARED $<TARGET_OBJECTS:unwind_objects>)
-  target_link_libraries(unwind_shared ${libraries})
+  add_library(unwind_shared SHARED ${unwind_shared_sources})
+  if(COMMAND llvm_setup_rpath)
+    llvm_setup_rpath(unwind_shared)
+  endif()
+  target_link_libraries(unwind_shared PRIVATE ${libraries})
   set_target_properties(unwind_shared
                         PROPERTIES
                           LINK_FLAGS    "${LIBUNWIND_LINK_FLAGS}"
                           OUTPUT_NAME   "unwind"
                           VERSION       "1.0"
                           SOVERSION     "1")
-  list(APPEND LIBUNWIND_TARGETS "unwind_shared")
+  list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_shared")
+  if (LIBUNWIND_INSTALL_SHARED_LIBRARY)
+    list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_shared")
+  endif()
 endif()
 
 # Build the static library.
 if (LIBUNWIND_ENABLE_STATIC)
-  add_library(unwind_static STATIC $<TARGET_OBJECTS:unwind_objects>)
-  target_link_libraries(unwind_static ${libraries})
+  add_library(unwind_static STATIC ${unwind_static_sources})
+  target_link_libraries(unwind_static PRIVATE ${libraries})
   set_target_properties(unwind_static
                         PROPERTIES
                           LINK_FLAGS    "${LIBUNWIND_LINK_FLAGS}"
                           OUTPUT_NAME   "unwind")
-  list(APPEND LIBUNWIND_TARGETS "unwind_static")
+  list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_static")
+  if (LIBUNWIND_INSTALL_STATIC_LIBRARY)
+    list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_static")
+  endif()
 endif()
 
 # Add a meta-target for both libraries.
-add_custom_target(unwind DEPENDS ${LIBUNWIND_TARGETS})
+add_custom_target(unwind DEPENDS ${LIBUNWIND_BUILD_TARGETS})
 
 if (LIBUNWIND_INSTALL_LIBRARY)
-  install(TARGETS ${LIBUNWIND_TARGETS}
+  install(TARGETS ${LIBUNWIND_INSTALL_TARGETS}
     LIBRARY DESTINATION ${LIBUNWIND_INSTALL_PREFIX}lib${LIBUNWIND_LIBDIR_SUFFIX} COMPONENT unwind
     ARCHIVE DESTINATION ${LIBUNWIND_INSTALL_PREFIX}lib${LIBUNWIND_LIBDIR_SUFFIX} COMPONENT unwind)
 endif()
diff --git a/src/CompactUnwinder.hpp b/src/CompactUnwinder.hpp
index 7b97bf8..1c3175d 100644
--- a/src/CompactUnwinder.hpp
+++ b/src/CompactUnwinder.hpp
@@ -1,9 +1,8 @@
 //===-------------------------- CompactUnwinder.hpp -----------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 //  Does runtime stack unwinding using compact unwind encodings.
diff --git a/src/DwarfInstructions.hpp b/src/DwarfInstructions.hpp
index bd1448b..4f5f821 100644
--- a/src/DwarfInstructions.hpp
+++ b/src/DwarfInstructions.hpp
@@ -1,9 +1,8 @@
 //===-------------------------- DwarfInstructions.hpp ---------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 //  Processor specific interpretation of DWARF unwind info.
@@ -82,12 +81,11 @@
     const RegisterLocation &savedReg) {
   switch (savedReg.location) {
   case CFI_Parser<A>::kRegisterInCFA:
-    return addressSpace.getP(cfa + (pint_t)savedReg.value);
+    return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);
 
   case CFI_Parser<A>::kRegisterAtExpression:
-    return addressSpace.getP(
-        evaluateExpression((pint_t)savedReg.value, addressSpace,
-                            registers, cfa));
+    return (pint_t)addressSpace.getRegister(evaluateExpression(
+        (pint_t)savedReg.value, addressSpace, registers, cfa));
 
   case CFI_Parser<A>::kRegisterIsExpression:
     return evaluateExpression((pint_t)savedReg.value, addressSpace,
@@ -159,7 +157,7 @@
                                &cieInfo) == NULL) {
     PrologInfo prolog;
     if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
-                                            &prolog)) {
+                                            R::getArch(), &prolog)) {
       // get pointer to cfa (architecture specific)
       pint_t cfa = getCFA(addressSpace, prolog, registers);
 
@@ -198,6 +196,42 @@
       // restoring SP means setting it to CFA.
       newRegisters.setSP(cfa);
 
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+      // If the target is aarch64 then the return address may have been signed
+      // using the v8.3 pointer authentication extensions. The original
+      // return address needs to be authenticated before the return address is
+      // restored. autia1716 is used instead of autia as autia1716 assembles
+      // to a NOP on pre-v8.3a architectures.
+      if ((R::getArch() == REGISTERS_ARM64) &&
+          prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) {
+#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
+        return UNW_ECROSSRASIGNING;
+#else
+        register unsigned long long x17 __asm("x17") = returnAddress;
+        register unsigned long long x16 __asm("x16") = cfa;
+
+        // These are the autia1716/autib1716 instructions. The hint instructions
+        // are used here as gcc does not assemble autia1716/autib1716 for pre
+        // armv8.3a targets.
+        if (cieInfo.addressesSignedWithBKey)
+          asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716
+        else
+          asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716
+        returnAddress = x17;
+#endif
+      }
+#endif
+
+#if defined(_LIBUNWIND_TARGET_SPARC)
+      if (R::getArch() == REGISTERS_SPARC) {
+        // Skip call site instruction and delay slot
+        returnAddress += 8;
+        // Skip unimp instruction if function returns a struct
+        if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)
+          returnAddress += 4;
+      }
+#endif
+
       // Return address is address after call site instruction, so setting IP to
       // that does simualates a return.
       newRegisters.setIP(returnAddress);
diff --git a/src/DwarfParser.hpp b/src/DwarfParser.hpp
index 95af7a6..df69c2a 100644
--- a/src/DwarfParser.hpp
+++ b/src/DwarfParser.hpp
@@ -1,9 +1,8 @@
 //===--------------------------- DwarfParser.hpp --------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 //  Parses DWARF CFIs (FDEs and CIEs).
@@ -17,10 +16,10 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <limits>
 
 #include "libunwind.h"
 #include "dwarf2.h"
+#include "Registers.hpp"
 
 #include "config.h"
 
@@ -50,6 +49,9 @@
     bool      isSignalFrame;
     bool      fdesHaveAugmentationData;
     uint8_t   returnAddressRegister;
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+    bool      addressesSignedWithBKey;
+#endif
   };
 
   /// Information about an FDE (Frame Description Entry)
@@ -104,7 +106,7 @@
                                FDE_Info *fdeInfo, CIE_Info *cieInfo);
   static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
                                    const CIE_Info &cieInfo, pint_t upToPC,
-                                   PrologInfo *results);
+                                   int arch, PrologInfo *results);
 
   static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
 
@@ -112,7 +114,7 @@
   static bool parseInstructions(A &addressSpace, pint_t instructions,
                                 pint_t instructionsEnd, const CIE_Info &cieInfo,
                                 pint_t pcoffset,
-                                PrologInfoStackEntry *&rememberStack,
+                                PrologInfoStackEntry *&rememberStack, int arch,
                                 PrologInfo *results);
 };
 
@@ -264,6 +266,9 @@
   cieInfo->dataAlignFactor = 0;
   cieInfo->isSignalFrame = false;
   cieInfo->fdesHaveAugmentationData = false;
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+  cieInfo->addressesSignedWithBKey = false;
+#endif
   cieInfo->cieStart = cie;
   pint_t p = cie;
   pint_t cieLength = (pint_t)addressSpace.get32(p);
@@ -327,6 +332,11 @@
       case 'S':
         cieInfo->isSignalFrame = true;
         break;
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+      case 'B':
+        cieInfo->addressesSignedWithBKey = true;
+        break;
+#endif
       default:
         // ignore unknown letters
         break;
@@ -344,7 +354,7 @@
 bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
                                          const FDE_Info &fdeInfo,
                                          const CIE_Info &cieInfo, pint_t upToPC,
-                                         PrologInfo *results) {
+                                         int arch, PrologInfo *results) {
   // clear results
   memset(results, '\0', sizeof(PrologInfo));
   PrologInfoStackEntry *rememberStack = NULL;
@@ -352,10 +362,11 @@
   // parse CIE then FDE instructions
   return parseInstructions(addressSpace, cieInfo.cieInstructions,
                            cieInfo.cieStart + cieInfo.cieLength, cieInfo,
-                           (pint_t)(-1), rememberStack, results) &&
+                           (pint_t)(-1), rememberStack, arch, results) &&
          parseInstructions(addressSpace, fdeInfo.fdeInstructions,
                            fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
-                           upToPC - fdeInfo.pcStart, rememberStack, results);
+                           upToPC - fdeInfo.pcStart, rememberStack, arch,
+                           results);
 }
 
 /// "run" the DWARF instructions
@@ -364,7 +375,7 @@
                                       pint_t instructionsEnd,
                                       const CIE_Info &cieInfo, pint_t pcoffset,
                                       PrologInfoStackEntry *&rememberStack,
-                                      PrologInfo *results) {
+                                      int arch, PrologInfo *results) {
   pint_t p = instructions;
   pint_t codeOffset = 0;
   PrologInfo initialState = *results;
@@ -416,8 +427,8 @@
       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;
@@ -429,9 +440,8 @@
     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];
@@ -440,8 +450,8 @@
     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;
@@ -450,8 +460,8 @@
     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
@@ -467,13 +477,13 @@
       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;
@@ -512,7 +522,7 @@
       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;
@@ -523,9 +533,8 @@
     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;
@@ -542,7 +551,7 @@
       results->cfaRegister = 0;
       results->cfaExpression = (int64_t)p;
       length = addressSpace.getULEB128(p, instructionsEnd);
-      assert(length < std::numeric_limits<pint_t>::max() && "pointer overflow");
+      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",
@@ -551,14 +560,14 @@
     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);
-      assert(length < std::numeric_limits<pint_t>::max() && "pointer overflow");
+      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 ", "
@@ -568,9 +577,8 @@
     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 =
@@ -586,8 +594,8 @@
       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;
@@ -606,7 +614,7 @@
     case DW_CFA_val_offset:
       reg = addressSpace.getULEB128(p, instructionsEnd);
       if (reg > kMaxRegisterNumber) {
-        fprintf(stderr,
+        _LIBUNWIND_LOG(
                 "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64
                 ") out of range\n",
                 reg);
@@ -623,8 +631,8 @@
     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 =
@@ -638,14 +646,14 @@
     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);
-      assert(length < std::numeric_limits<pint_t>::max() && "pointer overflow");
+      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",
@@ -659,8 +667,8 @@
     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)
@@ -670,14 +678,51 @@
       _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) {
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+      case REGISTERS_ARM64:
+        results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^= 0x1;
+        _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->savedRegisters[reg].location = kRegisterInRegister;
+          results->savedRegisters[reg].value =
+              ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0;
+        }
+
+        for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) {
+          results->savedRegisters[reg].location = kRegisterInCFA;
+          results->savedRegisters[reg].value =
+              ((int64_t)reg - UNW_SPARC_L0) * 4;
+        }
+        break;
+#endif
+      }
+      break;
+#else
+      (void)arch;
+#endif
+
     default:
       operand = opcode & 0x3F;
       switch (opcode & 0xC0) {
       case DW_CFA_offset:
         reg = operand;
         if (reg > kMaxRegisterNumber) {
-          fprintf(stderr, "malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64
-                          ") out of range\n",
+          _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64
+                         ") out of range",
                   reg);
           return false;
         }
@@ -696,8 +741,8 @@
       case DW_CFA_restore:
         reg = operand;
         if (reg > kMaxRegisterNumber) {
-          fprintf(stderr, "malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64
-                          ") out of range\n",
+          _LIBUNWIND_LOG("malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64
+                         ") out of range",
                   reg);
           return false;
         }
diff --git a/src/EHHeaderParser.hpp b/src/EHHeaderParser.hpp
index 9bdaf55..0101835 100644
--- a/src/EHHeaderParser.hpp
+++ b/src/EHHeaderParser.hpp
@@ -1,9 +1,8 @@
 //===------------------------- EHHeaderParser.hpp -------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 //  Parses ELF .eh_frame_hdr sections.
@@ -36,7 +35,7 @@
     uint8_t table_enc;
   };
 
-  static void decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd,
+  static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd,
                           EHHeaderInfo &ehHdrInfo);
   static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,
                       uint32_t sectionLength,
@@ -53,12 +52,14 @@
 };
 
 template <typename A>
-void EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
+bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
                                     pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {
   pint_t p = ehHdrStart;
   uint8_t version = addressSpace.get8(p++);
-  if (version != 1)
-    _LIBUNWIND_ABORT("Unsupported .eh_frame_hdr version");
+  if (version != 1) {
+    _LIBUNWIND_LOG0("Unsupported .eh_frame_hdr version");
+    return false;
+  }
 
   uint8_t eh_frame_ptr_enc = addressSpace.get8(p++);
   uint8_t fde_count_enc = addressSpace.get8(p++);
@@ -71,6 +72,8 @@
           ? 0
           : addressSpace.getEncodedP(p, ehHdrEnd, fde_count_enc, ehHdrStart);
   ehHdrInfo.table = p;
+
+  return true;
 }
 
 template <typename A>
@@ -102,7 +105,9 @@
   pint_t ehHdrEnd = ehHdrStart + sectionLength;
 
   EHHeaderParser<A>::EHHeaderInfo hdrInfo;
-  EHHeaderParser<A>::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd, hdrInfo);
+  if (!EHHeaderParser<A>::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd,
+                                      hdrInfo))
+    return false;
 
   size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc);
   pint_t tableEntry;
diff --git a/src/RWMutex.hpp b/src/RWMutex.hpp
index 50a78a5..92c8db3 100644
--- a/src/RWMutex.hpp
+++ b/src/RWMutex.hpp
@@ -1,9 +1,8 @@
 //===----------------------------- Registers.hpp --------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 // Abstract interface to shared reader/writer log, hiding platform and
diff --git a/src/Registers.hpp b/src/Registers.hpp
index d881e20..e88ba51 100644
--- a/src/Registers.hpp
+++ b/src/Registers.hpp
@@ -1,9 +1,8 @@
 //===----------------------------- Registers.hpp --------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 //  Models register sets for supported processors.
@@ -24,6 +23,18 @@
 // For emulating 128-bit registers
 struct v128 { uint32_t vec[4]; };
 
+enum {
+  REGISTERS_X86,
+  REGISTERS_X86_64,
+  REGISTERS_PPC,
+  REGISTERS_PPC64,
+  REGISTERS_ARM64,
+  REGISTERS_ARM,
+  REGISTERS_OR1K,
+  REGISTERS_MIPS_O32,
+  REGISTERS_MIPS_NEWABI,
+  REGISTERS_SPARC,
+};
 
 #if defined(_LIBUNWIND_TARGET_I386)
 /// Registers_x86 holds the register state of a thread in a 32-bit intel
@@ -42,9 +53,10 @@
   bool        validVectorRegister(int) const { return false; }
   v128        getVectorRegister(int num) const;
   void        setVectorRegister(int num, v128 value);
-  const char *getRegisterName(int num);
+  static const char *getRegisterName(int num);
   void        jumpto();
   static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; }
+  static int  getArch() { return REGISTERS_X86; }
 
   uint32_t  getSP() const          { return _registers.__esp; }
   void      setSP(uint32_t value)  { _registers.__esp = value; }
@@ -248,9 +260,10 @@
   bool        validVectorRegister(int) const;
   v128        getVectorRegister(int num) const;
   void        setVectorRegister(int num, v128 value);
-  const char *getRegisterName(int num);
+  static const char *getRegisterName(int num);
   void        jumpto();
   static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; }
+  static int  getArch() { return REGISTERS_X86_64; }
 
   uint64_t  getSP() const          { return _registers.__rsp; }
   void      setSP(uint64_t value)  { _registers.__rsp = value; }
@@ -517,6 +530,7 @@
     return false;
   return true;
 #else
+  (void)regNum; // suppress unused parameter warning
   return false;
 #endif
 }
@@ -526,6 +540,7 @@
   assert(validVectorRegister(regNum));
   return _xmm[regNum - UNW_X86_64_XMM0];
 #else
+  (void)regNum; // suppress unused parameter warning
   _LIBUNWIND_ABORT("no x86_64 vector registers");
 #endif
 }
@@ -535,6 +550,7 @@
   assert(validVectorRegister(regNum));
   _xmm[regNum - UNW_X86_64_XMM0] = value;
 #else
+  (void)regNum; (void)value; // suppress unused parameter warnings
   _LIBUNWIND_ABORT("no x86_64 vector registers");
 #endif
 }
@@ -558,9 +574,10 @@
   bool        validVectorRegister(int num) const;
   v128        getVectorRegister(int num) const;
   void        setVectorRegister(int num, v128 value);
-  const char *getRegisterName(int num);
+  static const char *getRegisterName(int num);
   void        jumpto();
   static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; }
+  static int  getArch() { return REGISTERS_PPC; }
 
   uint64_t  getSP() const         { return _registers.__r1; }
   void      setSP(uint32_t value) { _registers.__r1 = value; }
@@ -1106,6 +1123,648 @@
 }
 #endif // _LIBUNWIND_TARGET_PPC
 
+#if defined(_LIBUNWIND_TARGET_PPC64)
+/// Registers_ppc64 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);
+  static const char *getRegisterName(int num);
+  void        jumpto();
+  static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; }
+  static int  getArch() { return REGISTERS_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
+  };
+
+  union ppc64_vsr_t {
+    struct asfloat_s {
+      double f;
+      uint64_t v2;
+    } asfloat;
+    v128 v;
+  };
+
+  ppc64_thread_state_t _registers;
+  ppc64_vsr_t          _vectorScalarRegisters[64];
+
+  static int getVectorRegNum(int num);
+};
+
+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(_registers) == 312,
+                "expected vector scalar register offset to be 312");
+  memcpy(&_vectorScalarRegisters,
+         static_cast<const uint8_t *>(registers) + sizeof(_registers),
+         sizeof(_vectorScalarRegisters));
+  static_assert(sizeof(_registers) +
+                sizeof(_vectorScalarRegisters) == 1336,
+                "expected vector register offset to be 1336 bytes");
+}
+
+inline Registers_ppc64::Registers_ppc64() {
+  memset(&_registers, 0, sizeof(_registers));
+  memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters));
+}
+
+inline bool Registers_ppc64::validRegister(int regNum) const {
+  switch (regNum) {
+  case UNW_REG_IP:
+  case UNW_REG_SP:
+  case UNW_PPC64_XER:
+  case UNW_PPC64_LR:
+  case UNW_PPC64_CTR:
+  case UNW_PPC64_VRSAVE:
+      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_PPC64_R0:
+    return _registers.__r0;
+  case UNW_PPC64_R1:
+  case UNW_REG_SP:
+    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_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_XER:
+    return _registers.__xer;
+  case UNW_PPC64_LR:
+    return _registers.__lr;
+  case UNW_PPC64_CTR:
+    return _registers.__ctr;
+  case UNW_PPC64_VRSAVE:
+    return _registers.__vrsave;
+  }
+  _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_PPC64_R0:
+    _registers.__r0 = value;
+    return;
+  case UNW_PPC64_R1:
+  case UNW_REG_SP:
+    _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_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_XER:
+    _registers.__xer = value;
+    return;
+  case UNW_PPC64_LR:
+    _registers.__lr = value;
+    return;
+  case UNW_PPC64_CTR:
+    _registers.__ctr = value;
+    return;
+  case UNW_PPC64_VRSAVE:
+    _registers.__vrsave = value;
+    return;
+  }
+  _LIBUNWIND_ABORT("unsupported ppc64 register");
+}
+
+inline bool Registers_ppc64::validFloatRegister(int regNum) const {
+  return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31;
+}
+
+inline double Registers_ppc64::getFloatRegister(int regNum) const {
+  assert(validFloatRegister(regNum));
+  return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f;
+}
+
+inline void Registers_ppc64::setFloatRegister(int regNum, double value) {
+  assert(validFloatRegister(regNum));
+  _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value;
+}
+
+inline bool Registers_ppc64::validVectorRegister(int regNum) const {
+#ifdef PPC64_HAS_VMX
+  if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31)
+    return true;
+  if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)
+    return true;
+#else
+  if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)
+    return true;
+#endif
+  return false;
+}
+
+inline int Registers_ppc64::getVectorRegNum(int num)
+{
+  if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31)
+    return num - UNW_PPC64_VS0;
+  else
+    return num - UNW_PPC64_VS32 + 32;
+}
+
+inline v128 Registers_ppc64::getVectorRegister(int regNum) const {
+  assert(validVectorRegister(regNum));
+  return _vectorScalarRegisters[getVectorRegNum(regNum)].v;
+}
+
+inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) {
+  assert(validVectorRegister(regNum));
+  _vectorScalarRegisters[getVectorRegNum(regNum)].v = 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_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_LR:
+    return "lr";
+  case UNW_PPC64_CTR:
+    return "ctr";
+  case UNW_PPC64_VRSAVE:
+    return "vrsave";
+  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_V0:
+    return "v0";
+  case UNW_PPC64_V1:
+    return "v1";
+  case UNW_PPC64_V2:
+    return "v2";
+  case UNW_PPC64_V3:
+    return "v3";
+  case UNW_PPC64_V4:
+    return "v4";
+  case UNW_PPC64_V5:
+    return "v5";
+  case UNW_PPC64_V6:
+    return "v6";
+  case UNW_PPC64_V7:
+    return "v7";
+  case UNW_PPC64_V8:
+    return "v8";
+  case UNW_PPC64_V9:
+    return "v9";
+  case UNW_PPC64_V10:
+    return "v10";
+  case UNW_PPC64_V11:
+    return "v11";
+  case UNW_PPC64_V12:
+    return "v12";
+  case UNW_PPC64_V13:
+    return "v13";
+  case UNW_PPC64_V14:
+    return "v14";
+  case UNW_PPC64_V15:
+    return "v15";
+  case UNW_PPC64_V16:
+    return "v16";
+  case UNW_PPC64_V17:
+    return "v17";
+  case UNW_PPC64_V18:
+    return "v18";
+  case UNW_PPC64_V19:
+    return "v19";
+  case UNW_PPC64_V20:
+    return "v20";
+  case UNW_PPC64_V21:
+    return "v21";
+  case UNW_PPC64_V22:
+    return "v22";
+  case UNW_PPC64_V23:
+    return "v23";
+  case UNW_PPC64_V24:
+    return "v24";
+  case UNW_PPC64_V25:
+    return "v25";
+  case UNW_PPC64_V26:
+    return "v26";
+  case UNW_PPC64_V27:
+    return "v27";
+  case UNW_PPC64_V28:
+    return "v28";
+  case UNW_PPC64_V29:
+    return "v29";
+  case UNW_PPC64_V30:
+    return "v30";
+  case UNW_PPC64_V31:
+    return "v31";
+  }
+  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
@@ -1124,9 +1783,10 @@
   bool        validVectorRegister(int num) const;
   v128        getVectorRegister(int num) const;
   void        setVectorRegister(int num, v128 value);
-  const char *getRegisterName(int num);
+  static const char *getRegisterName(int num);
   void        jumpto();
   static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; }
+  static int  getArch() { return REGISTERS_ARM64; }
 
   uint64_t  getSP() const         { return _registers.__sp; }
   void      setSP(uint64_t value) { _registers.__sp = value; }
@@ -1142,7 +1802,7 @@
     uint64_t __lr;    // Link register x30
     uint64_t __sp;    // Stack pointer x31
     uint64_t __pc;    // Program counter
-    uint64_t padding; // 16-byte align
+    uint64_t __ra_sign_state; // RA sign state register
   };
 
   GPRs    _registers;
@@ -1178,6 +1838,8 @@
     return false;
   if (regNum > 95)
     return false;
+  if (regNum == UNW_ARM64_RA_SIGN_STATE)
+    return true;
   if ((regNum > 31) && (regNum < 64))
     return false;
   return true;
@@ -1188,6 +1850,8 @@
     return _registers.__pc;
   if (regNum == UNW_REG_SP)
     return _registers.__sp;
+  if (regNum == UNW_ARM64_RA_SIGN_STATE)
+    return _registers.__ra_sign_state;
   if ((regNum >= 0) && (regNum < 32))
     return _registers.__x[regNum];
   _LIBUNWIND_ABORT("unsupported arm64 register");
@@ -1198,6 +1862,8 @@
     _registers.__pc = value;
   else if (regNum == UNW_REG_SP)
     _registers.__sp = value;
+  else if (regNum == UNW_ARM64_RA_SIGN_STATE)
+    _registers.__ra_sign_state = value;
   else if ((regNum >= 0) && (regNum < 32))
     _registers.__x[regNum] = value;
   else
@@ -1394,12 +2060,13 @@
   bool        validVectorRegister(int num) const;
   v128        getVectorRegister(int num) const;
   void        setVectorRegister(int num, v128 value);
-  const char *getRegisterName(int num);
+  static const char *getRegisterName(int num);
   void        jumpto() {
     restoreSavedFloatRegisters();
     restoreCoreAndJumpTo();
   }
   static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; }
+  static int  getArch() { return REGISTERS_ARM; }
 
   uint32_t  getSP() const         { return _registers.__sp; }
   void      setSP(uint32_t value) { _registers.__sp = value; }
@@ -1436,16 +2103,16 @@
     uint32_t __pc;    // Program counter r15
   };
 
-  static void saveVFPWithFSTMD(unw_fpreg_t*);
-  static void saveVFPWithFSTMX(unw_fpreg_t*);
-  static void saveVFPv3(unw_fpreg_t*);
-  static void restoreVFPWithFLDMD(unw_fpreg_t*);
-  static void restoreVFPWithFLDMX(unw_fpreg_t*);
-  static void restoreVFPv3(unw_fpreg_t*);
+  static void saveVFPWithFSTMD(void*);
+  static void saveVFPWithFSTMX(void*);
+  static void saveVFPv3(void*);
+  static void restoreVFPWithFLDMD(void*);
+  static void restoreVFPWithFLDMX(void*);
+  static void restoreVFPv3(void*);
 #if defined(__ARM_WMMX)
-  static void saveiWMMX(unw_fpreg_t*);
+  static void saveiWMMX(void*);
   static void saveiWMMXControl(uint32_t*);
-  static void restoreiWMMX(unw_fpreg_t*);
+  static void restoreiWMMX(void*);
   static void restoreiWMMXControl(uint32_t*);
 #endif
   void restoreCoreAndJumpTo();
@@ -1508,7 +2175,7 @@
   memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
 #if defined(__ARM_WMMX)
   _saved_iwmmx = false;
-  _saved_iwmmx_control = false;  
+  _saved_iwmmx_control = false;
   memset(&_iwmmx, 0, sizeof(_iwmmx));
   memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
 #endif
@@ -1874,18 +2541,21 @@
   bool        validVectorRegister(int num) const;
   v128        getVectorRegister(int num) const;
   void        setVectorRegister(int num, v128 value);
-  const char *getRegisterName(int num);
+  static const char *getRegisterName(int num);
   void        jumpto();
   static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; }
+  static int  getArch() { return REGISTERS_OR1K; }
 
   uint64_t  getSP() const         { return _registers.__r[1]; }
   void      setSP(uint32_t value) { _registers.__r[1] = value; }
-  uint64_t  getIP() const         { return _registers.__r[9]; }
-  void      setIP(uint32_t value) { _registers.__r[9] = value; }
+  uint64_t  getIP() const         { return _registers.__pc; }
+  void      setIP(uint32_t value) { _registers.__pc = value; }
 
 private:
   struct or1k_thread_state_t {
-    unsigned int __r[32];
+    unsigned int __r[32]; // r0-r31
+    unsigned int __pc;    // Program counter
+    unsigned int __epcr;  // Program counter at exception
   };
 
   or1k_thread_state_t _registers;
@@ -1911,6 +2581,8 @@
     return false;
   if (regNum <= UNW_OR1K_R31)
     return true;
+  if (regNum == UNW_OR1K_EPCR)
+    return true;
   return false;
 }
 
@@ -1920,9 +2592,11 @@
 
   switch (regNum) {
   case UNW_REG_IP:
-    return _registers.__r[9];
+    return _registers.__pc;
   case UNW_REG_SP:
     return _registers.__r[1];
+  case UNW_OR1K_EPCR:
+    return _registers.__epcr;
   }
   _LIBUNWIND_ABORT("unsupported or1k register");
 }
@@ -1935,11 +2609,14 @@
 
   switch (regNum) {
   case UNW_REG_IP:
-    _registers.__r[9] = value;
+    _registers.__pc = value;
     return;
   case UNW_REG_SP:
     _registers.__r[1] = value;
     return;
+  case UNW_OR1K_EPCR:
+    _registers.__epcr = value;
+    return;
   }
   _LIBUNWIND_ABORT("unsupported or1k register");
 }
@@ -2035,6 +2712,8 @@
     return "r30";
   case UNW_OR1K_R31:
     return "r31";
+  case UNW_OR1K_EPCR:
+    return "EPCR";
   default:
     return "unknown register";
   }
@@ -2059,9 +2738,10 @@
   bool        validVectorRegister(int num) const;
   v128        getVectorRegister(int num) const;
   void        setVectorRegister(int num, v128 value);
-  const char *getRegisterName(int num);
+  static const char *getRegisterName(int num);
   void        jumpto();
   static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
+  static int  getArch() { return REGISTERS_MIPS_O32; }
 
   uint32_t  getSP() const         { return _registers.__r[29]; }
   void      setSP(uint32_t value) { _registers.__r[29] = value; }
@@ -2077,6 +2757,14 @@
   };
 
   mips_o32_thread_state_t _registers;
+#ifdef __mips_hard_float
+  /// O32 with 32-bit floating point registers only uses half of this
+  /// space.  However, using the same layout for 32-bit vs 64-bit
+  /// floating point registers results in a single context size for
+  /// O32 with hard float.
+  uint32_t _padding;
+  double _floats[32];
+#endif
 };
 
 inline Registers_mips_o32::Registers_mips_o32(const void *registers) {
@@ -2099,17 +2787,34 @@
     return false;
   if (regNum <= UNW_MIPS_R31)
     return true;
+#if __mips_isa_rev != 6
   if (regNum == UNW_MIPS_HI)
     return true;
   if (regNum == UNW_MIPS_LO)
     return true;
-  // FIXME: Hard float, DSP accumulator registers, MSA registers
+#endif
+#if defined(__mips_hard_float) && __mips_fpr == 32
+  if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
+    return true;
+#endif
+  // FIXME: 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];
+#if defined(__mips_hard_float) && __mips_fpr == 32
+  if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
+    uint32_t *p;
+
+    if (regNum % 2 == 0)
+      p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
+    else
+      p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
+    return *p;
+  }
+#endif
 
   switch (regNum) {
   case UNW_REG_IP:
@@ -2129,6 +2834,18 @@
     _registers.__r[regNum - UNW_MIPS_R0] = value;
     return;
   }
+#if defined(__mips_hard_float) && __mips_fpr == 32
+  if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
+    uint32_t *p;
+
+    if (regNum % 2 == 0)
+      p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
+    else
+      p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
+    *p = value;
+    return;
+  }
+#endif
 
   switch (regNum) {
   case UNW_REG_IP:
@@ -2147,17 +2864,31 @@
   _LIBUNWIND_ABORT("unsupported mips_o32 register");
 }
 
-inline bool Registers_mips_o32::validFloatRegister(int /* regNum */) const {
+inline bool Registers_mips_o32::validFloatRegister(int regNum) const {
+#if defined(__mips_hard_float) && __mips_fpr == 64
+  if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
+    return true;
+#endif
   return false;
 }
 
-inline double Registers_mips_o32::getFloatRegister(int /* regNum */) const {
+inline double Registers_mips_o32::getFloatRegister(int regNum) const {
+#if defined(__mips_hard_float) && __mips_fpr == 64
+  assert(validFloatRegister(regNum));
+  return _floats[regNum - UNW_MIPS_F0];
+#else
   _LIBUNWIND_ABORT("mips_o32 float support not implemented");
+#endif
 }
 
-inline void Registers_mips_o32::setFloatRegister(int /* regNum */,
-                                                 double /* value */) {
+inline void Registers_mips_o32::setFloatRegister(int regNum,
+                                                 double value) {
+#if defined(__mips_hard_float) && __mips_fpr == 64
+  assert(validFloatRegister(regNum));
+  _floats[regNum - UNW_MIPS_F0] = value;
+#else
   _LIBUNWIND_ABORT("mips_o32 float support not implemented");
+#endif
 }
 
 inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
@@ -2238,6 +2969,70 @@
     return "$30";
   case UNW_MIPS_R31:
     return "$31";
+  case UNW_MIPS_F0:
+    return "$f0";
+  case UNW_MIPS_F1:
+    return "$f1";
+  case UNW_MIPS_F2:
+    return "$f2";
+  case UNW_MIPS_F3:
+    return "$f3";
+  case UNW_MIPS_F4:
+    return "$f4";
+  case UNW_MIPS_F5:
+    return "$f5";
+  case UNW_MIPS_F6:
+    return "$f6";
+  case UNW_MIPS_F7:
+    return "$f7";
+  case UNW_MIPS_F8:
+    return "$f8";
+  case UNW_MIPS_F9:
+    return "$f9";
+  case UNW_MIPS_F10:
+    return "$f10";
+  case UNW_MIPS_F11:
+    return "$f11";
+  case UNW_MIPS_F12:
+    return "$f12";
+  case UNW_MIPS_F13:
+    return "$f13";
+  case UNW_MIPS_F14:
+    return "$f14";
+  case UNW_MIPS_F15:
+    return "$f15";
+  case UNW_MIPS_F16:
+    return "$f16";
+  case UNW_MIPS_F17:
+    return "$f17";
+  case UNW_MIPS_F18:
+    return "$f18";
+  case UNW_MIPS_F19:
+    return "$f19";
+  case UNW_MIPS_F20:
+    return "$f20";
+  case UNW_MIPS_F21:
+    return "$f21";
+  case UNW_MIPS_F22:
+    return "$f22";
+  case UNW_MIPS_F23:
+    return "$f23";
+  case UNW_MIPS_F24:
+    return "$f24";
+  case UNW_MIPS_F25:
+    return "$f25";
+  case UNW_MIPS_F26:
+    return "$f26";
+  case UNW_MIPS_F27:
+    return "$f27";
+  case UNW_MIPS_F28:
+    return "$f28";
+  case UNW_MIPS_F29:
+    return "$f29";
+  case UNW_MIPS_F30:
+    return "$f30";
+  case UNW_MIPS_F31:
+    return "$f31";
   case UNW_MIPS_HI:
     return "$hi";
   case UNW_MIPS_LO:
@@ -2248,13 +3043,13 @@
 }
 #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 {
+#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
+/// Registers_mips_newabi holds the register state of a thread in a
+/// MIPS process using NEWABI (the N32 or N64 ABIs).
+class _LIBUNWIND_HIDDEN Registers_mips_newabi {
 public:
-  Registers_mips_n64();
-  Registers_mips_n64(const void *registers);
+  Registers_mips_newabi();
+  Registers_mips_newabi(const void *registers);
 
   bool        validRegister(int num) const;
   uint64_t    getRegister(int num) const;
@@ -2265,9 +3060,10 @@
   bool        validVectorRegister(int num) const;
   v128        getVectorRegister(int num) const;
   void        setVectorRegister(int num, v128 value);
-  const char *getRegisterName(int num);
+  static const char *getRegisterName(int num);
   void        jumpto();
   static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
+  static int  getArch() { return REGISTERS_MIPS_NEWABI; }
 
   uint64_t  getSP() const         { return _registers.__r[29]; }
   void      setSP(uint64_t value) { _registers.__r[29] = value; }
@@ -2275,28 +3071,31 @@
   void      setIP(uint64_t value) { _registers.__pc = value; }
 
 private:
-  struct mips_n64_thread_state_t {
+  struct mips_newabi_thread_state_t {
     uint64_t __r[32];
     uint64_t __pc;
     uint64_t __hi;
     uint64_t __lo;
   };
 
-  mips_n64_thread_state_t _registers;
+  mips_newabi_thread_state_t _registers;
+#ifdef __mips_hard_float
+  double _floats[32];
+#endif
 };
 
-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");
+inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) {
+  static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit),
+                "mips_newabi 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() {
+inline Registers_mips_newabi::Registers_mips_newabi() {
   memset(&_registers, 0, sizeof(_registers));
 }
 
-inline bool Registers_mips_n64::validRegister(int regNum) const {
+inline bool Registers_mips_newabi::validRegister(int regNum) const {
   if (regNum == UNW_REG_IP)
     return true;
   if (regNum == UNW_REG_SP)
@@ -2305,15 +3104,17 @@
     return false;
   if (regNum <= UNW_MIPS_R31)
     return true;
+#if __mips_isa_rev != 6
   if (regNum == UNW_MIPS_HI)
     return true;
   if (regNum == UNW_MIPS_LO)
     return true;
+#endif
   // FIXME: Hard float, DSP accumulator registers, MSA registers
   return false;
 }
 
-inline uint64_t Registers_mips_n64::getRegister(int regNum) const {
+inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
   if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
     return _registers.__r[regNum - UNW_MIPS_R0];
 
@@ -2327,10 +3128,10 @@
   case UNW_MIPS_LO:
     return _registers.__lo;
   }
-  _LIBUNWIND_ABORT("unsupported mips_n64 register");
+  _LIBUNWIND_ABORT("unsupported mips_newabi register");
 }
 
-inline void Registers_mips_n64::setRegister(int regNum, uint64_t value) {
+inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
   if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
     _registers.__r[regNum - UNW_MIPS_R0] = value;
     return;
@@ -2350,35 +3151,49 @@
     _registers.__lo = value;
     return;
   }
-  _LIBUNWIND_ABORT("unsupported mips_n64 register");
+  _LIBUNWIND_ABORT("unsupported mips_newabi register");
 }
 
-inline bool Registers_mips_n64::validFloatRegister(int /* regNum */) const {
+inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {
+#ifdef __mips_hard_float
+  if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
+    return true;
+#endif
   return false;
 }
 
-inline double Registers_mips_n64::getFloatRegister(int /* regNum */) const {
-  _LIBUNWIND_ABORT("mips_n64 float support not implemented");
+inline double Registers_mips_newabi::getFloatRegister(int regNum) const {
+#ifdef __mips_hard_float
+  assert(validFloatRegister(regNum));
+  return _floats[regNum - UNW_MIPS_F0];
+#else
+  _LIBUNWIND_ABORT("mips_newabi float support not implemented");
+#endif
 }
 
-inline void Registers_mips_n64::setFloatRegister(int /* regNum */,
-                                                 double /* value */) {
-  _LIBUNWIND_ABORT("mips_n64 float support not implemented");
+inline void Registers_mips_newabi::setFloatRegister(int regNum,
+                                                    double value) {
+#ifdef __mips_hard_float
+  assert(validFloatRegister(regNum));
+  _floats[regNum - UNW_MIPS_F0] = value;
+#else
+  _LIBUNWIND_ABORT("mips_newabi float support not implemented");
+#endif
 }
 
-inline bool Registers_mips_n64::validVectorRegister(int /* regNum */) const {
+inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
   return false;
 }
 
-inline v128 Registers_mips_n64::getVectorRegister(int /* regNum */) const {
-  _LIBUNWIND_ABORT("mips_n64 vector support not implemented");
+inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
+  _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
 }
 
-inline void Registers_mips_n64::setVectorRegister(int /* regNum */, v128 /* value */) {
-  _LIBUNWIND_ABORT("mips_n64 vector support not implemented");
+inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) {
+  _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
 }
 
-inline const char *Registers_mips_n64::getRegisterName(int regNum) {
+inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
   switch (regNum) {
   case UNW_MIPS_R0:
     return "$0";
@@ -2444,6 +3259,70 @@
     return "$30";
   case UNW_MIPS_R31:
     return "$31";
+  case UNW_MIPS_F0:
+    return "$f0";
+  case UNW_MIPS_F1:
+    return "$f1";
+  case UNW_MIPS_F2:
+    return "$f2";
+  case UNW_MIPS_F3:
+    return "$f3";
+  case UNW_MIPS_F4:
+    return "$f4";
+  case UNW_MIPS_F5:
+    return "$f5";
+  case UNW_MIPS_F6:
+    return "$f6";
+  case UNW_MIPS_F7:
+    return "$f7";
+  case UNW_MIPS_F8:
+    return "$f8";
+  case UNW_MIPS_F9:
+    return "$f9";
+  case UNW_MIPS_F10:
+    return "$f10";
+  case UNW_MIPS_F11:
+    return "$f11";
+  case UNW_MIPS_F12:
+    return "$f12";
+  case UNW_MIPS_F13:
+    return "$f13";
+  case UNW_MIPS_F14:
+    return "$f14";
+  case UNW_MIPS_F15:
+    return "$f15";
+  case UNW_MIPS_F16:
+    return "$f16";
+  case UNW_MIPS_F17:
+    return "$f17";
+  case UNW_MIPS_F18:
+    return "$f18";
+  case UNW_MIPS_F19:
+    return "$f19";
+  case UNW_MIPS_F20:
+    return "$f20";
+  case UNW_MIPS_F21:
+    return "$f21";
+  case UNW_MIPS_F22:
+    return "$f22";
+  case UNW_MIPS_F23:
+    return "$f23";
+  case UNW_MIPS_F24:
+    return "$f24";
+  case UNW_MIPS_F25:
+    return "$f25";
+  case UNW_MIPS_F26:
+    return "$f26";
+  case UNW_MIPS_F27:
+    return "$f27";
+  case UNW_MIPS_F28:
+    return "$f28";
+  case UNW_MIPS_F29:
+    return "$f29";
+  case UNW_MIPS_F30:
+    return "$f30";
+  case UNW_MIPS_F31:
+    return "$f31";
   case UNW_MIPS_HI:
     return "$hi";
   case UNW_MIPS_LO:
@@ -2452,7 +3331,192 @@
     return "unknown register";
   }
 }
-#endif // _LIBUNWIND_TARGET_MIPS_N64
+#endif // _LIBUNWIND_TARGET_MIPS_NEWABI
+
+#if defined(_LIBUNWIND_TARGET_SPARC)
+/// Registers_sparc holds the register state of a thread in a 32-bit Sparc
+/// process.
+class _LIBUNWIND_HIDDEN Registers_sparc {
+public:
+  Registers_sparc();
+  Registers_sparc(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);
+  static const char *getRegisterName(int num);
+  void        jumpto();
+  static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC; }
+  static int  getArch() { return REGISTERS_SPARC; }
+
+  uint64_t  getSP() const         { return _registers.__regs[UNW_SPARC_O6]; }
+  void      setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; }
+  uint64_t  getIP() const         { return _registers.__regs[UNW_SPARC_O7]; }
+  void      setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
+
+private:
+  struct sparc_thread_state_t {
+    unsigned int __regs[32];
+  };
+
+  sparc_thread_state_t _registers;
+};
+
+inline Registers_sparc::Registers_sparc(const void *registers) {
+  static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit),
+                "sparc registers do not fit into unw_context_t");
+  memcpy(&_registers, static_cast<const uint8_t *>(registers),
+         sizeof(_registers));
+}
+
+inline Registers_sparc::Registers_sparc() {
+  memset(&_registers, 0, sizeof(_registers));
+}
+
+inline bool Registers_sparc::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_SPARC_I7)
+    return true;
+  return false;
+}
+
+inline uint32_t Registers_sparc::getRegister(int regNum) const {
+  if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
+    return _registers.__regs[regNum];
+  }
+
+  switch (regNum) {
+  case UNW_REG_IP:
+    return _registers.__regs[UNW_SPARC_O7];
+  case UNW_REG_SP:
+    return _registers.__regs[UNW_SPARC_O6];
+  }
+  _LIBUNWIND_ABORT("unsupported sparc register");
+}
+
+inline void Registers_sparc::setRegister(int regNum, uint32_t value) {
+  if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
+    _registers.__regs[regNum] = value;
+    return;
+  }
+
+  switch (regNum) {
+  case UNW_REG_IP:
+    _registers.__regs[UNW_SPARC_O7] = value;
+    return;
+  case UNW_REG_SP:
+    _registers.__regs[UNW_SPARC_O6] = value;
+    return;
+  }
+  _LIBUNWIND_ABORT("unsupported sparc register");
+}
+
+inline bool Registers_sparc::validFloatRegister(int) const { return false; }
+
+inline double Registers_sparc::getFloatRegister(int) const {
+  _LIBUNWIND_ABORT("no Sparc float registers");
+}
+
+inline void Registers_sparc::setFloatRegister(int, double) {
+  _LIBUNWIND_ABORT("no Sparc float registers");
+}
+
+inline bool Registers_sparc::validVectorRegister(int) const { return false; }
+
+inline v128 Registers_sparc::getVectorRegister(int) const {
+  _LIBUNWIND_ABORT("no Sparc vector registers");
+}
+
+inline void Registers_sparc::setVectorRegister(int, v128) {
+  _LIBUNWIND_ABORT("no Sparc vector registers");
+}
+
+inline const char *Registers_sparc::getRegisterName(int regNum) {
+  switch (regNum) {
+  case UNW_REG_IP:
+    return "pc";
+  case UNW_SPARC_G0:
+    return "g0";
+  case UNW_SPARC_G1:
+    return "g1";
+  case UNW_SPARC_G2:
+    return "g2";
+  case UNW_SPARC_G3:
+    return "g3";
+  case UNW_SPARC_G4:
+    return "g4";
+  case UNW_SPARC_G5:
+    return "g5";
+  case UNW_SPARC_G6:
+    return "g6";
+  case UNW_SPARC_G7:
+    return "g7";
+  case UNW_SPARC_O0:
+    return "o0";
+  case UNW_SPARC_O1:
+    return "o1";
+  case UNW_SPARC_O2:
+    return "o2";
+  case UNW_SPARC_O3:
+    return "o3";
+  case UNW_SPARC_O4:
+    return "o4";
+  case UNW_SPARC_O5:
+    return "o5";
+  case UNW_REG_SP:
+  case UNW_SPARC_O6:
+    return "sp";
+  case UNW_SPARC_O7:
+    return "o7";
+  case UNW_SPARC_L0:
+    return "l0";
+  case UNW_SPARC_L1:
+    return "l1";
+  case UNW_SPARC_L2:
+    return "l2";
+  case UNW_SPARC_L3:
+    return "l3";
+  case UNW_SPARC_L4:
+    return "l4";
+  case UNW_SPARC_L5:
+    return "l5";
+  case UNW_SPARC_L6:
+    return "l6";
+  case UNW_SPARC_L7:
+    return "l7";
+  case UNW_SPARC_I0:
+    return "i0";
+  case UNW_SPARC_I1:
+    return "i1";
+  case UNW_SPARC_I2:
+    return "i2";
+  case UNW_SPARC_I3:
+    return "i3";
+  case UNW_SPARC_I4:
+    return "i4";
+  case UNW_SPARC_I5:
+    return "i5";
+  case UNW_SPARC_I6:
+    return "fp";
+  case UNW_SPARC_I7:
+    return "i7";
+  default:
+    return "unknown register";
+  }
+}
+#endif // _LIBUNWIND_TARGET_SPARC
+
 } // namespace libunwind
 
 #endif // __REGISTERS_HPP__
diff --git a/src/Unwind-EHABI.cpp b/src/Unwind-EHABI.cpp
index f37732c..c64ca12 100644
--- a/src/Unwind-EHABI.cpp
+++ b/src/Unwind-EHABI.cpp
@@ -1,9 +1,8 @@
 //===--------------------------- Unwind-EHABI.cpp -------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 //  Implements ARM zero-cost C++ exceptions
@@ -21,8 +20,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <type_traits>
-
 #include "config.h"
 #include "libunwind.h"
 #include "libunwind_ext.h"
diff --git a/src/Unwind-EHABI.h b/src/Unwind-EHABI.h
index fe164ff..6897082 100644
--- a/src/Unwind-EHABI.h
+++ b/src/Unwind-EHABI.h
@@ -1,9 +1,8 @@
 //===------------------------- Unwind-EHABI.hpp ---------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 //===----------------------------------------------------------------------===//
diff --git a/src/Unwind-seh.cpp b/src/Unwind-seh.cpp
new file mode 100644
index 0000000..8b4b7d5
--- /dev/null
+++ b/src/Unwind-seh.cpp
@@ -0,0 +1,500 @@
+//===--------------------------- Unwind-seh.cpp ---------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  Implements SEH-based Itanium C++ exceptions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "config.h"
+
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+
+#include <unwind.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <windef.h>
+#include <excpt.h>
+#include <winnt.h>
+#include <ntstatus.h>
+
+#include "libunwind_ext.h"
+#include "UnwindCursor.hpp"
+
+using namespace libunwind;
+
+#define STATUS_USER_DEFINED (1u << 29)
+
+#define STATUS_GCC_MAGIC  (('G' << 16) | ('C' << 8) | 'C')
+
+#define MAKE_CUSTOM_STATUS(s, c) \
+  ((NTSTATUS)(((s) << 30) | STATUS_USER_DEFINED | (c)))
+#define MAKE_GCC_EXCEPTION(c) \
+  MAKE_CUSTOM_STATUS(STATUS_SEVERITY_SUCCESS, STATUS_GCC_MAGIC | ((c) << 24))
+
+/// SEH exception raised by libunwind when the program calls
+/// \c _Unwind_RaiseException.
+#define STATUS_GCC_THROW MAKE_GCC_EXCEPTION(0) // 0x20474343
+/// SEH exception raised by libunwind to initiate phase 2 of exception
+/// 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, DISPATCHER_CONTEXT *disp);
+
+/// Common implementation of SEH-style handler functions used by Itanium-
+/// style frames.  Depending on how and why it was called, it may do one of:
+///  a) Delegate to the given Itanium-style personality function; or
+///  b) Initiate a collided unwind to halt unwinding.
+_LIBUNWIND_EXPORT EXCEPTION_DISPOSITION
+_GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
+                      DISPATCHER_CONTEXT *disp, __personality_routine pers) {
+  unw_cursor_t cursor;
+  _Unwind_Exception *exc;
+  _Unwind_Action action;
+  struct _Unwind_Context *ctx = nullptr;
+  _Unwind_Reason_Code urc;
+  uintptr_t retval, target;
+  bool ours = false;
+
+  _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler(%#010lx(%lx), %p)",
+                             ms_exc->ExceptionCode, ms_exc->ExceptionFlags,
+                             (void *)frame);
+  if (ms_exc->ExceptionCode == STATUS_GCC_UNWIND) {
+    if (IS_TARGET_UNWIND(ms_exc->ExceptionFlags)) {
+      // Set up the upper return value (the lower one and the target PC
+      // were set in the call to RtlUnwindEx()) for the landing pad.
+#ifdef __x86_64__
+      disp->ContextRecord->Rdx = ms_exc->ExceptionInformation[3];
+#elif defined(__arm__)
+      disp->ContextRecord->R1 = ms_exc->ExceptionInformation[3];
+#elif defined(__aarch64__)
+      disp->ContextRecord->X1 = ms_exc->ExceptionInformation[3];
+#endif
+    }
+    // This is the collided unwind to the landing pad. Nothing to do.
+    return ExceptionContinueSearch;
+  }
+
+  if (ms_exc->ExceptionCode == STATUS_GCC_THROW) {
+    // This is (probably) a libunwind-controlled exception/unwind. Recover the
+    // parameters which we set below, and pass them to the personality function.
+    ours = true;
+    exc = (_Unwind_Exception *)ms_exc->ExceptionInformation[0];
+    if (!IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) {
+      ctx = (struct _Unwind_Context *)ms_exc->ExceptionInformation[1];
+      action = (_Unwind_Action)ms_exc->ExceptionInformation[2];
+    }
+  } 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_));
+  }
+  if (!ctx) {
+    _unw_init_seh(&cursor, disp->ContextRecord);
+    _unw_seh_set_disp_ctx(&cursor, disp);
+    unw_set_reg(&cursor, UNW_REG_IP, disp->ControlPc-1);
+    ctx = (struct _Unwind_Context *)&cursor;
+
+    if (!IS_UNWINDING(ms_exc->ExceptionFlags)) {
+      if (ours && ms_exc->NumberParameters > 1)
+        action =  (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_FORCE_UNWIND);
+      else
+        action = _UA_SEARCH_PHASE;
+    } else {
+      if (ours && ms_exc->ExceptionInformation[1] == (ULONG_PTR)frame)
+        action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
+      else
+        action = _UA_CLEANUP_PHASE;
+    }
+  }
+
+  _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() calling personality "
+                             "function %p(1, %d, %llx, %p, %p)",
+                             (void *)pers, action, exc->exception_class,
+                             (void *)exc, (void *)ctx);
+  urc = pers(1, action, exc->exception_class, exc, ctx);
+  _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() personality returned %d", urc);
+  switch (urc) {
+  case _URC_CONTINUE_UNWIND:
+    // If we're in phase 2, and the personality routine said to continue
+    // at the target frame, we're in real trouble.
+    if (action & _UA_HANDLER_FRAME)
+      _LIBUNWIND_ABORT("Personality continued unwind at the target frame!");
+    return ExceptionContinueSearch;
+  case _URC_HANDLER_FOUND:
+    // If we were called by __libunwind_seh_personality(), indicate that
+    // a handler was found; otherwise, initiate phase 2 by unwinding.
+    if (ours && ms_exc->NumberParameters > 1)
+      return 4 /* ExecptionExecuteHandler in mingw */;
+    // This should never happen in phase 2.
+    if (IS_UNWINDING(ms_exc->ExceptionFlags))
+      _LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!");
+    exc->private_[1] = (ULONG_PTR)frame;
+    if (ours) {
+      ms_exc->NumberParameters = 4;
+      ms_exc->ExceptionInformation[1] = (ULONG_PTR)frame;
+    }
+    // FIXME: Indicate target frame in foreign case!
+    // phase 2: the clean up phase
+    RtlUnwindEx(frame, (PVOID)disp->ControlPc, ms_exc, exc, ms_ctx, disp->HistoryTable);
+    _LIBUNWIND_ABORT("RtlUnwindEx() failed");
+  case _URC_INSTALL_CONTEXT: {
+    // If we were called by __libunwind_seh_personality(), indicate that
+    // a handler was found; otherwise, it's time to initiate a collided
+    // unwind to the target.
+    if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1)
+      return 4 /* ExecptionExecuteHandler in mingw */;
+    // This should never happen in phase 1.
+    if (!IS_UNWINDING(ms_exc->ExceptionFlags))
+      _LIBUNWIND_ABORT("Personality installed context during phase 1!");
+#ifdef __x86_64__
+    exc->private_[2] = disp->TargetIp;
+    unw_get_reg(&cursor, UNW_X86_64_RAX, &retval);
+    unw_get_reg(&cursor, UNW_X86_64_RDX, &exc->private_[3]);
+#elif defined(__arm__)
+    exc->private_[2] = disp->TargetPc;
+    unw_get_reg(&cursor, UNW_ARM_R0, &retval);
+    unw_get_reg(&cursor, UNW_ARM_R1, &exc->private_[3]);
+#elif defined(__aarch64__)
+    exc->private_[2] = disp->TargetPc;
+    unw_get_reg(&cursor, UNW_ARM64_X0, &retval);
+    unw_get_reg(&cursor, UNW_ARM64_X1, &exc->private_[3]);
+#endif
+    unw_get_reg(&cursor, UNW_REG_IP, &target);
+    ms_exc->ExceptionCode = STATUS_GCC_UNWIND;
+#ifdef __x86_64__
+    ms_exc->ExceptionInformation[2] = disp->TargetIp;
+#elif defined(__arm__) || defined(__aarch64__)
+    ms_exc->ExceptionInformation[2] = disp->TargetPc;
+#endif
+    ms_exc->ExceptionInformation[3] = exc->private_[3];
+    // Give NTRTL some scratch space to keep track of the collided unwind.
+    // Don't use the one that was passed in; we don't want to overwrite the
+    // context in the DISPATCHER_CONTEXT.
+    CONTEXT new_ctx;
+    RtlUnwindEx(frame, (PVOID)target, ms_exc, (PVOID)retval, &new_ctx, disp->HistoryTable);
+    _LIBUNWIND_ABORT("RtlUnwindEx() failed");
+  }
+  // Anything else indicates a serious problem.
+  default: return ExceptionContinueExecution;
+  }
+}
+
+/// Personality function returned by \c unw_get_proc_info() in SEH contexts.
+/// This is a wrapper that calls the real SEH handler function, which in
+/// turn (at least, for Itanium-style frames) calls the real Itanium
+/// personality function (see \c _GCC_specific_handler()).
+extern "C" _Unwind_Reason_Code
+__libunwind_seh_personality(int version, _Unwind_Action state,
+                            uint64_t klass, _Unwind_Exception *exc,
+                            struct _Unwind_Context *context) {
+  (void)version;
+  (void)klass;
+  EXCEPTION_RECORD ms_exc;
+  bool phase2 = (state & (_UA_SEARCH_PHASE|_UA_CLEANUP_PHASE)) == _UA_CLEANUP_PHASE;
+  ms_exc.ExceptionCode = STATUS_GCC_THROW;
+  ms_exc.ExceptionFlags = 0;
+  ms_exc.NumberParameters = 3;
+  ms_exc.ExceptionInformation[0] = (ULONG_PTR)exc;
+  ms_exc.ExceptionInformation[1] = (ULONG_PTR)context;
+  ms_exc.ExceptionInformation[2] = state;
+  DISPATCHER_CONTEXT *disp_ctx = _unw_seh_get_disp_ctx((unw_cursor_t *)context);
+  EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc,
+                                                           (PVOID)disp_ctx->EstablisherFrame,
+                                                           disp_ctx->ContextRecord,
+                                                           disp_ctx);
+  switch (ms_act) {
+  case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND;
+  case 4 /*ExceptionExecuteHandler*/:
+    return phase2 ? _URC_INSTALL_CONTEXT : _URC_HANDLER_FOUND;
+  default:
+    return phase2 ? _URC_FATAL_PHASE2_ERROR : _URC_FATAL_PHASE1_ERROR;
+  }
+}
+
+static _Unwind_Reason_Code
+unwind_phase2_forced(unw_context_t *uc,
+                     _Unwind_Exception *exception_object,
+                     _Unwind_Stop_Fn stop, void *stop_parameter) {
+  unw_cursor_t cursor2;
+  unw_init_local(&cursor2, uc);
+
+  // Walk each frame until we reach where search phase said to stop
+  while (unw_step(&cursor2) > 0) {
+
+    // Update info about this frame.
+    unw_proc_info_t frameInfo;
+    if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
+      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step "
+                                 "failed => _URC_END_OF_STACK",
+                                 (void *)exception_object);
+      return _URC_FATAL_PHASE2_ERROR;
+    }
+
+    // When tracing, print state information.
+    if (_LIBUNWIND_TRACING_UNWINDING) {
+      char functionBuf[512];
+      const char *functionName = functionBuf;
+      unw_word_t offset;
+      if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
+                             &offset) != UNW_ESUCCESS) ||
+          (frameInfo.start_ip + offset > frameInfo.end_ip))
+        functionName = ".anonymous.";
+      _LIBUNWIND_TRACE_UNWINDING(
+          "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64
+          ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64,
+          (void *)exception_object, frameInfo.start_ip, functionName,
+          frameInfo.lsda, frameInfo.handler);
+    }
+
+    // Call stop function at each frame.
+    _Unwind_Action action =
+        (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
+    _Unwind_Reason_Code stopResult =
+        (*stop)(1, action, exception_object->exception_class, exception_object,
+                (struct _Unwind_Context *)(&cursor2), stop_parameter);
+    _LIBUNWIND_TRACE_UNWINDING(
+        "unwind_phase2_forced(ex_ojb=%p): stop function returned %d",
+        (void *)exception_object, stopResult);
+    if (stopResult != _URC_NO_REASON) {
+      _LIBUNWIND_TRACE_UNWINDING(
+          "unwind_phase2_forced(ex_ojb=%p): stopped by stop function",
+          (void *)exception_object);
+      return _URC_FATAL_PHASE2_ERROR;
+    }
+
+    // If there is a personality routine, tell it we are unwinding.
+    if (frameInfo.handler != 0) {
+      __personality_routine p =
+          (__personality_routine)(intptr_t)(frameInfo.handler);
+      _LIBUNWIND_TRACE_UNWINDING(
+          "unwind_phase2_forced(ex_ojb=%p): calling personality function %p",
+          (void *)exception_object, (void *)(uintptr_t)p);
+      _Unwind_Reason_Code personalityResult =
+          (*p)(1, action, exception_object->exception_class, exception_object,
+               (struct _Unwind_Context *)(&cursor2));
+      switch (personalityResult) {
+      case _URC_CONTINUE_UNWIND:
+        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+                                   "personality returned "
+                                   "_URC_CONTINUE_UNWIND",
+                                   (void *)exception_object);
+        // Destructors called, continue unwinding
+        break;
+      case _URC_INSTALL_CONTEXT:
+        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+                                   "personality returned "
+                                   "_URC_INSTALL_CONTEXT",
+                                   (void *)exception_object);
+        // We may get control back if landing pad calls _Unwind_Resume().
+        unw_resume(&cursor2);
+        break;
+      default:
+        // Personality routine returned an unknown result code.
+        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+                                   "personality returned %d, "
+                                   "_URC_FATAL_PHASE2_ERROR",
+                                   (void *)exception_object, personalityResult);
+        return _URC_FATAL_PHASE2_ERROR;
+      }
+    }
+  }
+
+  // Call stop function one last time and tell it we've reached the end
+  // of the stack.
+  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
+                             "function with _UA_END_OF_STACK",
+                             (void *)exception_object);
+  _Unwind_Action lastAction =
+      (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
+  (*stop)(1, lastAction, exception_object->exception_class, exception_object,
+          (struct _Unwind_Context *)(&cursor2), stop_parameter);
+
+  // Clean up phase did not resume at the frame that the search phase said it
+  // would.
+  return _URC_FATAL_PHASE2_ERROR;
+}
+
+/// Called by \c __cxa_throw().  Only returns if there is a fatal error.
+_LIBUNWIND_EXPORT _Unwind_Reason_Code
+_Unwind_RaiseException(_Unwind_Exception *exception_object) {
+  _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",
+                       (void *)exception_object);
+
+  // Mark that this is a non-forced unwind, so _Unwind_Resume()
+  // can do the right thing.
+  memset(exception_object->private_, 0, sizeof(exception_object->private_));
+
+  // phase 1: the search phase
+  // We'll let the system do that for us.
+  RaiseException(STATUS_GCC_THROW, 0, 1, (ULONG_PTR *)&exception_object);
+
+  // If we get here, either something went horribly wrong or we reached the
+  // top of the stack. Either way, let libc++abi call std::terminate().
+  return _URC_END_OF_STACK;
+}
+
+/// When \c _Unwind_RaiseException() is in phase2, it hands control
+/// to the personality function at each frame.  The personality
+/// may force a jump to a landing pad in that function; the landing
+/// pad code may then call \c _Unwind_Resume() to continue with the
+/// unwinding.  Note: the call to \c _Unwind_Resume() is from compiler
+/// geneated user code.  All other \c _Unwind_* routines are called
+/// by the C++ runtime \c __cxa_* routines.
+///
+/// Note: re-throwing an exception (as opposed to continuing the unwind)
+/// is implemented by having the code call \c __cxa_rethrow() which
+/// in turn calls \c _Unwind_Resume_or_Rethrow().
+_LIBUNWIND_EXPORT void
+_Unwind_Resume(_Unwind_Exception *exception_object) {
+  _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object);
+
+  if (exception_object->private_[0] != 0) {
+    unw_context_t uc;
+
+    unw_getcontext(&uc);
+    unwind_phase2_forced(&uc, exception_object,
+                         (_Unwind_Stop_Fn) exception_object->private_[0],
+                         (void *)exception_object->private_[4]);
+  } else {
+    // Recover the parameters for the unwind from the exception object
+    // so we can start unwinding again.
+    EXCEPTION_RECORD ms_exc;
+    CONTEXT ms_ctx;
+    UNWIND_HISTORY_TABLE hist;
+
+    memset(&ms_exc, 0, sizeof(ms_exc));
+    memset(&hist, 0, sizeof(hist));
+    ms_exc.ExceptionCode = STATUS_GCC_THROW;
+    ms_exc.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+    ms_exc.NumberParameters = 4;
+    ms_exc.ExceptionInformation[0] = (ULONG_PTR)exception_object;
+    ms_exc.ExceptionInformation[1] = exception_object->private_[1];
+    ms_exc.ExceptionInformation[2] = exception_object->private_[2];
+    ms_exc.ExceptionInformation[3] = exception_object->private_[3];
+    RtlUnwindEx((PVOID)exception_object->private_[1],
+                (PVOID)exception_object->private_[2], &ms_exc,
+                exception_object, &ms_ctx, &hist);
+  }
+
+  // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
+  _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
+}
+
+/// Not used by C++.
+/// Unwinds stack, calling "stop" function at each frame.
+/// Could be used to implement \c longjmp().
+_LIBUNWIND_EXPORT _Unwind_Reason_Code
+_Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
+                     _Unwind_Stop_Fn stop, void *stop_parameter) {
+  _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",
+                       (void *)exception_object, (void *)(uintptr_t)stop);
+  unw_context_t uc;
+  unw_getcontext(&uc);
+
+  // Mark that this is a forced unwind, so _Unwind_Resume() can do
+  // the right thing.
+  exception_object->private_[0] = (uintptr_t) stop;
+  exception_object->private_[4] = (uintptr_t) stop_parameter;
+
+  // do it
+  return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter);
+}
+
+/// Called by personality handler during phase 2 to get LSDA for current frame.
+_LIBUNWIND_EXPORT uintptr_t
+_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
+  uintptr_t result = (uintptr_t)_unw_seh_get_disp_ctx((unw_cursor_t *)context)->HandlerData;
+  _LIBUNWIND_TRACE_API(
+      "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,
+      (void *)context, result);
+  return result;
+}
+
+/// Called by personality handler during phase 2 to find the start of the
+/// function.
+_LIBUNWIND_EXPORT uintptr_t
+_Unwind_GetRegionStart(struct _Unwind_Context *context) {
+  DISPATCHER_CONTEXT *disp = _unw_seh_get_disp_ctx((unw_cursor_t *)context);
+  uintptr_t result = (uintptr_t)disp->FunctionEntry->BeginAddress + disp->ImageBase;
+  _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR,
+                       (void *)context, result);
+  return result;
+}
+
+static int
+_unw_init_seh(unw_cursor_t *cursor, CONTEXT *context) {
+#ifdef _LIBUNWIND_TARGET_X86_64
+  new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor))
+      UnwindCursor<LocalAddressSpace, Registers_x86_64>(
+          context, LocalAddressSpace::sThisAddressSpace);
+  auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
+  co->setInfoBasedOnIPRegister();
+  return UNW_ESUCCESS;
+#elif defined(_LIBUNWIND_TARGET_ARM)
+  new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor))
+      UnwindCursor<LocalAddressSpace, Registers_arm>(
+          context, LocalAddressSpace::sThisAddressSpace);
+  auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
+  co->setInfoBasedOnIPRegister();
+  return UNW_ESUCCESS;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+  new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor))
+      UnwindCursor<LocalAddressSpace, Registers_arm64>(
+          context, LocalAddressSpace::sThisAddressSpace);
+  auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
+  co->setInfoBasedOnIPRegister();
+  return UNW_ESUCCESS;
+#else
+  return UNW_EINVAL;
+#endif
+}
+
+static DISPATCHER_CONTEXT *
+_unw_seh_get_disp_ctx(unw_cursor_t *cursor) {
+#ifdef _LIBUNWIND_TARGET_X86_64
+  return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->getDispatcherContext();
+#elif defined(_LIBUNWIND_TARGET_ARM)
+  return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor)->getDispatcherContext();
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+  return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor)->getDispatcherContext();
+#else
+  return nullptr;
+#endif
+}
+
+static void
+_unw_seh_set_disp_ctx(unw_cursor_t *cursor, DISPATCHER_CONTEXT *disp) {
+#ifdef _LIBUNWIND_TARGET_X86_64
+  reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->setDispatcherContext(disp);
+#elif defined(_LIBUNWIND_TARGET_ARM)
+  reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor)->setDispatcherContext(disp);
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+  reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor)->setDispatcherContext(disp);
+#endif
+}
+
+#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
diff --git a/src/Unwind-sjlj.c b/src/Unwind-sjlj.c
index 90cac3f..2204161 100644
--- a/src/Unwind-sjlj.c
+++ b/src/Unwind-sjlj.c
@@ -1,9 +1,8 @@
 //===--------------------------- Unwind-sjlj.c ----------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 //  Implements setjump-longjump based C++ exceptions
@@ -12,6 +11,7 @@
 
 #include <unwind.h>
 
+#include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
 #include <stdlib.h>
@@ -52,7 +52,7 @@
 #else
 # if __STDC_VERSION__ >= 201112L
 #  define _LIBUNWIND_THREAD_LOCAL _Thread_local
-# elif defined(_WIN32)
+# elif defined(_MSC_VER)
 #  define _LIBUNWIND_THREAD_LOCAL __declspec(thread)
 # elif defined(__GNUC__) || defined(__clang__)
 #  define _LIBUNWIND_THREAD_LOCAL __thread
@@ -108,7 +108,8 @@
 static _Unwind_Reason_Code
 unwind_phase1(struct _Unwind_Exception *exception_object) {
   _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
-  _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p", c);
+  _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p",
+                             (void *)c);
 
   // walk each frame looking for a place to stop
   for (bool handlerNotFound = true; handlerNotFound; c = c->prev) {
@@ -117,17 +118,18 @@
     if (c == NULL) {
       _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): reached "
                                  "bottom => _URC_END_OF_STACK",
-                                  exception_object);
+                                 (void *)exception_object);
       return _URC_END_OF_STACK;
     }
 
-    _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", c);
+    _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", (void *)c);
     // if there is a personality routine, ask it if it will want to stop at this
     // frame
     if (c->personality != NULL) {
       _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): calling "
-                                "personality function %p",
-                                 exception_object, c->personality);
+                                 "personality function %p",
+                                 (void *)exception_object,
+                                 (void *)c->personality);
       _Unwind_Reason_Code personalityResult = (*c->personality)(
           1, _UA_SEARCH_PHASE, exception_object->exception_class,
           exception_object, (struct _Unwind_Context *)c);
@@ -138,12 +140,14 @@
         handlerNotFound = false;
         exception_object->private_2 = (uintptr_t) c;
         _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
-                                   "_URC_HANDLER_FOUND", exception_object);
+                                   "_URC_HANDLER_FOUND",
+                                   (void *)exception_object);
         return _URC_NO_REASON;
 
       case _URC_CONTINUE_UNWIND:
         _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
-                                   "_URC_CONTINUE_UNWIND", exception_object);
+                                   "_URC_CONTINUE_UNWIND",
+                                   (void *)exception_object);
         // continue unwinding
         break;
 
@@ -151,7 +155,7 @@
         // something went wrong
         _LIBUNWIND_TRACE_UNWINDING(
             "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
-            exception_object);
+            (void *)exception_object);
         return _URC_FATAL_PHASE1_ERROR;
       }
     }
@@ -162,19 +166,20 @@
 
 static _Unwind_Reason_Code
 unwind_phase2(struct _Unwind_Exception *exception_object) {
-  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", exception_object);
+  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
+                             (void *)exception_object);
 
   // walk each frame until we reach where search phase said to stop
   _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
   while (true) {
     _LIBUNWIND_TRACE_UNWINDING("unwind_phase2s(ex_ojb=%p): context=%p",
-                              exception_object, c);
+                               (void *)exception_object, (void *)c);
 
     // check for no more frames
     if (c == NULL) {
       _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
-                                "bottom => _URC_END_OF_STACK",
-                                 exception_object);
+                                 "bottom => _URC_END_OF_STACK",
+                                 (void *)exception_object);
       return _URC_END_OF_STACK;
     }
 
@@ -194,7 +199,7 @@
         // continue unwinding
         _LIBUNWIND_TRACE_UNWINDING(
             "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
-            exception_object);
+            (void *)exception_object);
         if ((uintptr_t) c == exception_object->private_2) {
           // phase 1 said we would stop at this frame, but we did not...
           _LIBUNWIND_ABORT("during phase1 personality function said it would "
@@ -203,9 +208,9 @@
         break;
       case _URC_INSTALL_CONTEXT:
         _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): "
-                                  "_URC_INSTALL_CONTEXT, will resume at "
-                                  "landing pad %p",
-                                  exception_object, c->jbuf[1]);
+                                   "_URC_INSTALL_CONTEXT, will resume at "
+                                   "landing pad %p",
+                                   (void *)exception_object, c->jbuf[1]);
         // personality routine says to transfer control to landing pad
         // we may get control back if landing pad calls _Unwind_Resume()
         __Unwind_SjLj_SetTopOfFunctionStack(c);
@@ -239,7 +244,7 @@
     if (c == NULL) {
       _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
                                  "bottom => _URC_END_OF_STACK",
-                                 exception_object);
+                                 (void *)exception_object);
       return _URC_END_OF_STACK;
     }
 
@@ -251,11 +256,11 @@
                 (struct _Unwind_Context *)c, stop_parameter);
     _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
                                "stop function returned %d",
-                                exception_object, stopResult);
+                               (void *)exception_object, stopResult);
     if (stopResult != _URC_NO_REASON) {
       _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
                                  "stopped by stop function",
-                                  exception_object);
+                                 (void *)exception_object);
       return _URC_FATAL_PHASE2_ERROR;
     }
 
@@ -264,7 +269,7 @@
       __personality_routine p = (__personality_routine) c->personality;
       _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
                                  "calling personality function %p",
-                                  exception_object, p);
+                                 (void *)exception_object, (void *)p);
       _Unwind_Reason_Code personalityResult =
           (*p)(1, action, exception_object->exception_class, exception_object,
                (struct _Unwind_Context *)c);
@@ -272,13 +277,13 @@
       case _URC_CONTINUE_UNWIND:
         _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p):  "
                                    "personality returned _URC_CONTINUE_UNWIND",
-                                    exception_object);
+                                   (void *)exception_object);
         // destructors called, continue unwinding
         break;
       case _URC_INSTALL_CONTEXT:
         _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
                                    "personality returned _URC_INSTALL_CONTEXT",
-                                    exception_object);
+                                   (void *)exception_object);
         // we may get control back if landing pad calls _Unwind_Resume()
         __Unwind_SjLj_SetTopOfFunctionStack(c);
         __builtin_longjmp(c->jbuf, 1);
@@ -288,7 +293,7 @@
         _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
                                    "personality returned %d, "
                                    "_URC_FATAL_PHASE2_ERROR",
-                                    exception_object, personalityResult);
+                                   (void *)exception_object, personalityResult);
         return _URC_FATAL_PHASE2_ERROR;
       }
     }
@@ -298,8 +303,8 @@
   // call stop function one last time and tell it we've reached the end of the
   // stack
   _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
-                        "function with _UA_END_OF_STACK",
-                        exception_object);
+                             "function with _UA_END_OF_STACK",
+                             (void *)exception_object);
   _Unwind_Action lastAction =
       (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
   (*stop)(1, lastAction, exception_object->exception_class, exception_object,
@@ -314,7 +319,8 @@
 /// Called by __cxa_throw.  Only returns if there is a fatal error
 _LIBUNWIND_EXPORT _Unwind_Reason_Code
 _Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) {
-  _LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)", exception_object);
+  _LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)",
+                       (void *)exception_object);
 
   // mark that this is a non-forced unwind, so _Unwind_Resume() can do the right
   // thing
@@ -344,7 +350,8 @@
 /// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow()
 _LIBUNWIND_EXPORT void
 _Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) {
-  _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)", exception_object);
+  _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)",
+                       (void *)exception_object);
 
   if (exception_object->private_1 != 0)
     unwind_phase2_forced(exception_object,
@@ -362,8 +369,8 @@
 _LIBUNWIND_EXPORT _Unwind_Reason_Code
 _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) {
   _LIBUNWIND_TRACE_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), "
-                             "private_1=%ld",
-                              exception_object, exception_object->private_1);
+                       "private_1=%" PRIuPTR,
+                       (void *)exception_object, exception_object->private_1);
   // If this is non-forced and a stopping place was found, then this is a
   // re-throw.
   // Call _Unwind_RaiseException() as if this was a new exception.
@@ -386,7 +393,8 @@
 _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
   _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
   _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) "
-                             "=> 0x%0lX",  context, ufc->lsda);
+                       "=> 0x%" PRIuPTR,
+                       (void *)context, ufc->lsda);
   return ufc->lsda;
 }
 
@@ -394,8 +402,8 @@
 /// Called by personality handler during phase 2 to get register values.
 _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
                                           int index) {
-  _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)",
-                             context, index);
+  _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)", (void *)context,
+                       index);
   _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
   return ufc->resumeParameters[index];
 }
@@ -404,8 +412,9 @@
 /// Called by personality handler during phase 2 to alter register values.
 _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
                                      uintptr_t new_value) {
-  _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)"
-                            , context, index, new_value);
+  _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIuPTR
+                       ")",
+                       (void *)context, index, new_value);
   _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
   ufc->resumeParameters[index] = new_value;
 }
@@ -414,8 +423,8 @@
 /// Called by personality handler during phase 2 to get instruction pointer.
 _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
   _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
-  _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%lX", context,
-                  ufc->resumeLocation + 1);
+  _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIu32,
+                       (void *)context, ufc->resumeLocation + 1);
   return ufc->resumeLocation + 1;
 }
 
@@ -427,8 +436,9 @@
                                               int *ipBefore) {
   _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
   *ipBefore = 0;
-  _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX",
-                             context, ipBefore, ufc->resumeLocation + 1);
+  _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIu32,
+                       (void *)context, (void *)ipBefore,
+                       ufc->resumeLocation + 1);
   return ufc->resumeLocation + 1;
 }
 
@@ -436,8 +446,8 @@
 /// Called by personality handler during phase 2 to alter instruction pointer.
 _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
                                      uintptr_t new_value) {
-  _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0lX)",
-                             context, new_value);
+  _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIuPTR ")",
+                       (void *)context, new_value);
   _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
   ufc->resumeLocation = new_value - 1;
 }
@@ -449,7 +459,7 @@
 _Unwind_GetRegionStart(struct _Unwind_Context *context) {
   // Not supported or needed for sjlj based unwinding
   (void)context;
-  _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)", context);
+  _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)", (void *)context);
   return 0;
 }
 
@@ -459,7 +469,7 @@
 _LIBUNWIND_EXPORT void
 _Unwind_DeleteException(struct _Unwind_Exception *exception_object) {
   _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
-                              exception_object);
+                       (void *)exception_object);
   if (exception_object->exception_cleanup != NULL)
     (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
                                            exception_object);
@@ -473,7 +483,7 @@
 _Unwind_GetDataRelBase(struct _Unwind_Context *context) {
   // Not supported or needed for sjlj based unwinding
   (void)context;
-  _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", context);
+  _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context);
   _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
 }
 
@@ -484,14 +494,14 @@
 _Unwind_GetTextRelBase(struct _Unwind_Context *context) {
   // Not supported or needed for sjlj based unwinding
   (void)context;
-  _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", context);
+  _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", (void *)context);
   _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented");
 }
 
 
 /// Called by personality handler to get "Call Frame Area" for current frame.
 _LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
-  _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)", context);
+  _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)", (void *)context);
   if (context != NULL) {
     _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
     // Setjmp/longjmp based exceptions don't have a true CFA.
diff --git a/src/UnwindCursor.hpp b/src/UnwindCursor.hpp
index f09bd23..836de38 100644
--- a/src/UnwindCursor.hpp
+++ b/src/UnwindCursor.hpp
@@ -1,9 +1,8 @@
 //===------------------------- UnwindCursor.hpp ---------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 // C++ interface to lower levels of libunwind
@@ -12,16 +11,56 @@
 #ifndef __UNWINDCURSOR_HPP__
 #define __UNWINDCURSOR_HPP__
 
-#include <algorithm>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unwind.h>
 
+#ifdef _WIN32
+  #include <windows.h>
+  #include <ntverp.h>
+#endif
 #ifdef __APPLE__
   #include <mach-o/dyld.h>
 #endif
 
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+// Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and
+// earlier) SDKs.
+// MinGW-w64 has always provided this struct.
+  #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \
+      !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
+struct _DISPATCHER_CONTEXT {
+  ULONG64 ControlPc;
+  ULONG64 ImageBase;
+  PRUNTIME_FUNCTION FunctionEntry;
+  ULONG64 EstablisherFrame;
+  ULONG64 TargetIp;
+  PCONTEXT ContextRecord;
+  PEXCEPTION_ROUTINE LanguageHandler;
+  PVOID HandlerData;
+  PUNWIND_HISTORY_TABLE HistoryTable;
+  ULONG ScopeIndex;
+  ULONG Fill0;
+};
+  #endif
+
+struct UNWIND_INFO {
+  uint8_t Version : 3;
+  uint8_t Flags : 5;
+  uint8_t SizeOfProlog;
+  uint8_t CountOfCodes;
+  uint8_t FrameRegister : 4;
+  uint8_t FrameOffset : 4;
+  uint16_t UnwindCodes[2];
+};
+
+extern "C" _Unwind_Reason_Code __libunwind_seh_personality(
+    int, _Unwind_Action, uint64_t, _Unwind_Exception *,
+    struct _Unwind_Context *);
+
+#endif
+
 #include "config.h"
 
 #include "AddressSpace.hpp"
@@ -65,7 +104,6 @@
   static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide);
   static bool _registeredForDyldUnloads;
 #endif
-  // Can't use std::vector<> here because this code is below libc++.
   static entry *_buffer;
   static entry *_bufferUsed;
   static entry *_bufferEnd;
@@ -412,6 +450,428 @@
 #endif
 };
 
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
+
+/// \c UnwindCursor contains all state (including all register values) during
+/// an unwind.  This is normally stack-allocated inside a unw_cursor_t.
+template <typename A, typename R>
+class UnwindCursor : public AbstractUnwindCursor {
+  typedef typename A::pint_t pint_t;
+public:
+                      UnwindCursor(unw_context_t *context, A &as);
+                      UnwindCursor(CONTEXT *context, A &as);
+                      UnwindCursor(A &as, void *threadArg);
+  virtual             ~UnwindCursor() {}
+  virtual bool        validReg(int);
+  virtual unw_word_t  getReg(int);
+  virtual void        setReg(int, unw_word_t);
+  virtual bool        validFloatReg(int);
+  virtual unw_fpreg_t getFloatReg(int);
+  virtual void        setFloatReg(int, unw_fpreg_t);
+  virtual int         step();
+  virtual void        getInfo(unw_proc_info_t *);
+  virtual void        jumpto();
+  virtual bool        isSignalFrame();
+  virtual bool        getFunctionName(char *buf, size_t len, unw_word_t *off);
+  virtual void        setInfoBasedOnIPRegister(bool isReturnAddress = false);
+  virtual const char *getRegisterName(int num);
+#ifdef __arm__
+  virtual void        saveVFPAsX();
+#endif
+
+  DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; }
+  void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; }
+
+  // libunwind does not and should not depend on C++ library which means that we
+  // need our own defition of inline placement new.
+  static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
+
+private:
+
+  pint_t getLastPC() const { return _dispContext.ControlPc; }
+  void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; }
+  RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
+    _dispContext.FunctionEntry = RtlLookupFunctionEntry(pc,
+                                                        &_dispContext.ImageBase,
+                                                        _dispContext.HistoryTable);
+    *base = _dispContext.ImageBase;
+    return _dispContext.FunctionEntry;
+  }
+  bool getInfoFromSEH(pint_t pc);
+  int stepWithSEHData() {
+    _dispContext.LanguageHandler = RtlVirtualUnwind(UNW_FLAG_UHANDLER,
+                                                    _dispContext.ImageBase,
+                                                    _dispContext.ControlPc,
+                                                    _dispContext.FunctionEntry,
+                                                    _dispContext.ContextRecord,
+                                                    &_dispContext.HandlerData,
+                                                    &_dispContext.EstablisherFrame,
+                                                    NULL);
+    // Update some fields of the unwind info now, since we have them.
+    _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
+    if (_dispContext.LanguageHandler) {
+      _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
+    } else
+      _info.handler = 0;
+    return UNW_STEP_SUCCESS;
+  }
+
+  A                   &_addressSpace;
+  unw_proc_info_t      _info;
+  DISPATCHER_CONTEXT   _dispContext;
+  CONTEXT              _msContext;
+  UNWIND_HISTORY_TABLE _histTable;
+  bool                 _unwindInfoMissing;
+};
+
+
+template <typename A, typename R>
+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");
+  memset(&_info, 0, sizeof(_info));
+  memset(&_histTable, 0, sizeof(_histTable));
+  _dispContext.ContextRecord = &_msContext;
+  _dispContext.HistoryTable = &_histTable;
+  // Initialize MS context from ours.
+  R r(context);
+  _msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT;
+#if defined(_LIBUNWIND_TARGET_X86_64)
+  _msContext.Rax = r.getRegister(UNW_X86_64_RAX);
+  _msContext.Rcx = r.getRegister(UNW_X86_64_RCX);
+  _msContext.Rdx = r.getRegister(UNW_X86_64_RDX);
+  _msContext.Rbx = r.getRegister(UNW_X86_64_RBX);
+  _msContext.Rsp = r.getRegister(UNW_X86_64_RSP);
+  _msContext.Rbp = r.getRegister(UNW_X86_64_RBP);
+  _msContext.Rsi = r.getRegister(UNW_X86_64_RSI);
+  _msContext.Rdi = r.getRegister(UNW_X86_64_RDI);
+  _msContext.R8 = r.getRegister(UNW_X86_64_R8);
+  _msContext.R9 = r.getRegister(UNW_X86_64_R9);
+  _msContext.R10 = r.getRegister(UNW_X86_64_R10);
+  _msContext.R11 = r.getRegister(UNW_X86_64_R11);
+  _msContext.R12 = r.getRegister(UNW_X86_64_R12);
+  _msContext.R13 = r.getRegister(UNW_X86_64_R13);
+  _msContext.R14 = r.getRegister(UNW_X86_64_R14);
+  _msContext.R15 = r.getRegister(UNW_X86_64_R15);
+  _msContext.Rip = r.getRegister(UNW_REG_IP);
+  union {
+    v128 v;
+    M128A m;
+  } t;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM0);
+  _msContext.Xmm0 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM1);
+  _msContext.Xmm1 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM2);
+  _msContext.Xmm2 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM3);
+  _msContext.Xmm3 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM4);
+  _msContext.Xmm4 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM5);
+  _msContext.Xmm5 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM6);
+  _msContext.Xmm6 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM7);
+  _msContext.Xmm7 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM8);
+  _msContext.Xmm8 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM9);
+  _msContext.Xmm9 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM10);
+  _msContext.Xmm10 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM11);
+  _msContext.Xmm11 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM12);
+  _msContext.Xmm12 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM13);
+  _msContext.Xmm13 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM14);
+  _msContext.Xmm14 = t.m;
+  t.v = r.getVectorRegister(UNW_X86_64_XMM15);
+  _msContext.Xmm15 = t.m;
+#elif defined(_LIBUNWIND_TARGET_ARM)
+  _msContext.R0 = r.getRegister(UNW_ARM_R0);
+  _msContext.R1 = r.getRegister(UNW_ARM_R1);
+  _msContext.R2 = r.getRegister(UNW_ARM_R2);
+  _msContext.R3 = r.getRegister(UNW_ARM_R3);
+  _msContext.R4 = r.getRegister(UNW_ARM_R4);
+  _msContext.R5 = r.getRegister(UNW_ARM_R5);
+  _msContext.R6 = r.getRegister(UNW_ARM_R6);
+  _msContext.R7 = r.getRegister(UNW_ARM_R7);
+  _msContext.R8 = r.getRegister(UNW_ARM_R8);
+  _msContext.R9 = r.getRegister(UNW_ARM_R9);
+  _msContext.R10 = r.getRegister(UNW_ARM_R10);
+  _msContext.R11 = r.getRegister(UNW_ARM_R11);
+  _msContext.R12 = r.getRegister(UNW_ARM_R12);
+  _msContext.Sp = r.getRegister(UNW_ARM_SP);
+  _msContext.Lr = r.getRegister(UNW_ARM_LR);
+  _msContext.Pc = r.getRegister(UNW_ARM_IP);
+  for (int i = UNW_ARM_D0; i <= UNW_ARM_D31; ++i) {
+    union {
+      uint64_t w;
+      double d;
+    } d;
+    d.d = r.getFloatRegister(i);
+    _msContext.D[i - UNW_ARM_D0] = d.w;
+  }
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+  for (int i = UNW_ARM64_X0; i <= UNW_ARM64_X30; ++i)
+    _msContext.X[i - UNW_ARM64_X0] = r.getRegister(i);
+  _msContext.Sp = r.getRegister(UNW_REG_SP);
+  _msContext.Pc = r.getRegister(UNW_REG_IP);
+  for (int i = UNW_ARM64_D0; i <= UNW_ARM64_D31; ++i)
+    _msContext.V[i - UNW_ARM64_D0].D[0] = r.getFloatRegister(i);
+#endif
+}
+
+template <typename A, typename R>
+UnwindCursor<A, R>::UnwindCursor(CONTEXT *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");
+  memset(&_info, 0, sizeof(_info));
+  memset(&_histTable, 0, sizeof(_histTable));
+  _dispContext.ContextRecord = &_msContext;
+  _dispContext.HistoryTable = &_histTable;
+  _msContext = *context;
+}
+
+
+template <typename A, typename R>
+bool UnwindCursor<A, R>::validReg(int regNum) {
+  if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true;
+#if defined(_LIBUNWIND_TARGET_X86_64)
+  if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true;
+#elif defined(_LIBUNWIND_TARGET_ARM)
+  if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) return true;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+  if (regNum >= UNW_ARM64_X0 && regNum <= UNW_ARM64_X30) return true;
+#endif
+  return false;
+}
+
+template <typename A, typename R>
+unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
+  switch (regNum) {
+#if defined(_LIBUNWIND_TARGET_X86_64)
+  case UNW_REG_IP: return _msContext.Rip;
+  case UNW_X86_64_RAX: return _msContext.Rax;
+  case UNW_X86_64_RDX: return _msContext.Rdx;
+  case UNW_X86_64_RCX: return _msContext.Rcx;
+  case UNW_X86_64_RBX: return _msContext.Rbx;
+  case UNW_REG_SP:
+  case UNW_X86_64_RSP: return _msContext.Rsp;
+  case UNW_X86_64_RBP: return _msContext.Rbp;
+  case UNW_X86_64_RSI: return _msContext.Rsi;
+  case UNW_X86_64_RDI: return _msContext.Rdi;
+  case UNW_X86_64_R8: return _msContext.R8;
+  case UNW_X86_64_R9: return _msContext.R9;
+  case UNW_X86_64_R10: return _msContext.R10;
+  case UNW_X86_64_R11: return _msContext.R11;
+  case UNW_X86_64_R12: return _msContext.R12;
+  case UNW_X86_64_R13: return _msContext.R13;
+  case UNW_X86_64_R14: return _msContext.R14;
+  case UNW_X86_64_R15: return _msContext.R15;
+#elif defined(_LIBUNWIND_TARGET_ARM)
+  case UNW_ARM_R0: return _msContext.R0;
+  case UNW_ARM_R1: return _msContext.R1;
+  case UNW_ARM_R2: return _msContext.R2;
+  case UNW_ARM_R3: return _msContext.R3;
+  case UNW_ARM_R4: return _msContext.R4;
+  case UNW_ARM_R5: return _msContext.R5;
+  case UNW_ARM_R6: return _msContext.R6;
+  case UNW_ARM_R7: return _msContext.R7;
+  case UNW_ARM_R8: return _msContext.R8;
+  case UNW_ARM_R9: return _msContext.R9;
+  case UNW_ARM_R10: return _msContext.R10;
+  case UNW_ARM_R11: return _msContext.R11;
+  case UNW_ARM_R12: return _msContext.R12;
+  case UNW_REG_SP:
+  case UNW_ARM_SP: return _msContext.Sp;
+  case UNW_ARM_LR: return _msContext.Lr;
+  case UNW_REG_IP:
+  case UNW_ARM_IP: return _msContext.Pc;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+  case UNW_REG_SP: return _msContext.Sp;
+  case UNW_REG_IP: return _msContext.Pc;
+  default: return _msContext.X[regNum - UNW_ARM64_X0];
+#endif
+  }
+  _LIBUNWIND_ABORT("unsupported register");
+}
+
+template <typename A, typename R>
+void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
+  switch (regNum) {
+#if defined(_LIBUNWIND_TARGET_X86_64)
+  case UNW_REG_IP: _msContext.Rip = value; break;
+  case UNW_X86_64_RAX: _msContext.Rax = value; break;
+  case UNW_X86_64_RDX: _msContext.Rdx = value; break;
+  case UNW_X86_64_RCX: _msContext.Rcx = value; break;
+  case UNW_X86_64_RBX: _msContext.Rbx = value; break;
+  case UNW_REG_SP:
+  case UNW_X86_64_RSP: _msContext.Rsp = value; break;
+  case UNW_X86_64_RBP: _msContext.Rbp = value; break;
+  case UNW_X86_64_RSI: _msContext.Rsi = value; break;
+  case UNW_X86_64_RDI: _msContext.Rdi = value; break;
+  case UNW_X86_64_R8: _msContext.R8 = value; break;
+  case UNW_X86_64_R9: _msContext.R9 = value; break;
+  case UNW_X86_64_R10: _msContext.R10 = value; break;
+  case UNW_X86_64_R11: _msContext.R11 = value; break;
+  case UNW_X86_64_R12: _msContext.R12 = value; break;
+  case UNW_X86_64_R13: _msContext.R13 = value; break;
+  case UNW_X86_64_R14: _msContext.R14 = value; break;
+  case UNW_X86_64_R15: _msContext.R15 = value; break;
+#elif defined(_LIBUNWIND_TARGET_ARM)
+  case UNW_ARM_R0: _msContext.R0 = value; break;
+  case UNW_ARM_R1: _msContext.R1 = value; break;
+  case UNW_ARM_R2: _msContext.R2 = value; break;
+  case UNW_ARM_R3: _msContext.R3 = value; break;
+  case UNW_ARM_R4: _msContext.R4 = value; break;
+  case UNW_ARM_R5: _msContext.R5 = value; break;
+  case UNW_ARM_R6: _msContext.R6 = value; break;
+  case UNW_ARM_R7: _msContext.R7 = value; break;
+  case UNW_ARM_R8: _msContext.R8 = value; break;
+  case UNW_ARM_R9: _msContext.R9 = value; break;
+  case UNW_ARM_R10: _msContext.R10 = value; break;
+  case UNW_ARM_R11: _msContext.R11 = value; break;
+  case UNW_ARM_R12: _msContext.R12 = value; break;
+  case UNW_REG_SP:
+  case UNW_ARM_SP: _msContext.Sp = value; break;
+  case UNW_ARM_LR: _msContext.Lr = value; break;
+  case UNW_REG_IP:
+  case UNW_ARM_IP: _msContext.Pc = value; break;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+  case UNW_REG_SP: _msContext.Sp = value; break;
+  case UNW_REG_IP: _msContext.Pc = value; break;
+  case UNW_ARM64_X0:
+  case UNW_ARM64_X1:
+  case UNW_ARM64_X2:
+  case UNW_ARM64_X3:
+  case UNW_ARM64_X4:
+  case UNW_ARM64_X5:
+  case UNW_ARM64_X6:
+  case UNW_ARM64_X7:
+  case UNW_ARM64_X8:
+  case UNW_ARM64_X9:
+  case UNW_ARM64_X10:
+  case UNW_ARM64_X11:
+  case UNW_ARM64_X12:
+  case UNW_ARM64_X13:
+  case UNW_ARM64_X14:
+  case UNW_ARM64_X15:
+  case UNW_ARM64_X16:
+  case UNW_ARM64_X17:
+  case UNW_ARM64_X18:
+  case UNW_ARM64_X19:
+  case UNW_ARM64_X20:
+  case UNW_ARM64_X21:
+  case UNW_ARM64_X22:
+  case UNW_ARM64_X23:
+  case UNW_ARM64_X24:
+  case UNW_ARM64_X25:
+  case UNW_ARM64_X26:
+  case UNW_ARM64_X27:
+  case UNW_ARM64_X28:
+  case UNW_ARM64_FP:
+  case UNW_ARM64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break;
+#endif
+  default:
+    _LIBUNWIND_ABORT("unsupported register");
+  }
+}
+
+template <typename A, typename R>
+bool UnwindCursor<A, R>::validFloatReg(int regNum) {
+#if defined(_LIBUNWIND_TARGET_ARM)
+  if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true;
+  if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+  if (regNum >= UNW_ARM64_D0 && regNum <= UNW_ARM64_D31) return true;
+#else
+  (void)regNum;
+#endif
+  return false;
+}
+
+template <typename A, typename R>
+unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
+#if defined(_LIBUNWIND_TARGET_ARM)
+  if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
+    union {
+      uint32_t w;
+      float f;
+    } d;
+    d.w = _msContext.S[regNum - UNW_ARM_S0];
+    return d.f;
+  }
+  if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
+    union {
+      uint64_t w;
+      double d;
+    } d;
+    d.w = _msContext.D[regNum - UNW_ARM_D0];
+    return d.d;
+  }
+  _LIBUNWIND_ABORT("unsupported float register");
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+  return _msContext.V[regNum - UNW_ARM64_D0].D[0];
+#else
+  (void)regNum;
+  _LIBUNWIND_ABORT("float registers unimplemented");
+#endif
+}
+
+template <typename A, typename R>
+void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
+#if defined(_LIBUNWIND_TARGET_ARM)
+  if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
+    union {
+      uint32_t w;
+      float f;
+    } d;
+    d.f = value;
+    _msContext.S[regNum - UNW_ARM_S0] = d.w;
+  }
+  if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
+    union {
+      uint64_t w;
+      double d;
+    } d;
+    d.d = value;
+    _msContext.D[regNum - UNW_ARM_D0] = d.w;
+  }
+  _LIBUNWIND_ABORT("unsupported float register");
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+  _msContext.V[regNum - UNW_ARM64_D0].D[0] = value;
+#else
+  (void)regNum;
+  (void)value;
+  _LIBUNWIND_ABORT("float registers unimplemented");
+#endif
+}
+
+template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
+  RtlRestoreContext(&_msContext, nullptr);
+}
+
+#ifdef __arm__
+template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {}
+#endif
+
+template <typename A, typename R>
+const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
+  return R::getRegisterName(regNum);
+}
+
+template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
+  return false;
+}
+
+#else  // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32)
+
 /// UnwindCursor contains all state (including all register values) during
 /// an unwind.  This is normally stack allocated inside a unw_cursor_t.
 template <typename A, typename R>
@@ -438,6 +898,10 @@
   virtual void        saveVFPAsX();
 #endif
 
+  // libunwind does not and should not depend on C++ library which means that we
+  // need our own defition of inline placement new.
+  static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
+
 private:
 
 #if defined(_LIBUNWIND_ARM_EHABI)
@@ -501,6 +965,13 @@
   }
 #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(
@@ -514,12 +985,16 @@
   }
 #endif
 
-#if defined(_LIBUNWIND_TARGET_MIPS_N64)
-  int stepWithCompactEncoding(Registers_mips_n64 &) {
+#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
+  int stepWithCompactEncoding(Registers_mips_newabi &) {
     return UNW_EINVAL;
   }
 #endif
 
+#if defined(_LIBUNWIND_TARGET_SPARC)
+  int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; }
+#endif
+
   bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
     R dummy;
     return compactSaysUseDwarf(dummy, offset);
@@ -553,6 +1028,12 @@
   }
 #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) {
@@ -570,11 +1051,16 @@
   }
 #endif
 
-#if defined(_LIBUNWIND_TARGET_MIPS_N64)
-  bool compactSaysUseDwarf(Registers_mips_n64 &, uint32_t *) const {
+#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
+  bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const {
     return true;
   }
 #endif
+
+#if defined(_LIBUNWIND_TARGET_SPARC)
+  bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; }
+#endif
+
 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
 
 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
@@ -601,6 +1087,12 @@
   }
 #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;
@@ -625,13 +1117,32 @@
   }
 #endif
 
-#if defined (_LIBUNWIND_TARGET_MIPS_N64)
-  compact_unwind_encoding_t dwarfEncoding(Registers_mips_n64 &) const {
+#if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)
+  compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const {
     return 0;
   }
 #endif
+
+#if defined(_LIBUNWIND_TARGET_SPARC)
+  compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; }
+#endif
+
 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
 
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+  // For runtime environments using SEH unwind data without Windows runtime
+  // support.
+  pint_t getLastPC() const { /* FIXME: Implement */ return 0; }
+  void setLastPC(pint_t pc) { /* FIXME: Implement */ }
+  RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
+    /* FIXME: Implement */
+    *base = 0;
+    return nullptr;
+  }
+  bool getInfoFromSEH(pint_t pc);
+  int stepWithSEHData() { /* FIXME: Implement */ return 0; }
+#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+
 
   A               &_addressSpace;
   R                _registers;
@@ -708,6 +1219,8 @@
   return _isSignalFrame;
 }
 
+#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+
 #if defined(_LIBUNWIND_ARM_EHABI)
 struct EHABIIndexEntry {
   uint32_t functionOffset;
@@ -718,7 +1231,6 @@
 struct EHABISectionIterator {
   typedef EHABISectionIterator _Self;
 
-  typedef std::random_access_iterator_tag iterator_category;
   typedef typename A::pint_t value_type;
   typedef typename A::pint_t* pointer;
   typedef typename A::pint_t& reference;
@@ -772,6 +1284,29 @@
   const UnwindInfoSections* _sects;
 };
 
+namespace {
+
+template <typename A>
+EHABISectionIterator<A> EHABISectionUpperBound(
+    EHABISectionIterator<A> first,
+    EHABISectionIterator<A> last,
+    typename A::pint_t value) {
+  size_t len = last - first;
+  while (len > 0) {
+    size_t l2 = len / 2;
+    EHABISectionIterator<A> m = first + l2;
+    if (value < *m) {
+        len = l2;
+    } else {
+        first = ++m;
+        len -= l2 + 1;
+    }
+  }
+  return first;
+}
+
+}
+
 template <typename A, typename R>
 bool UnwindCursor<A, R>::getInfoFromEHABISection(
     pint_t pc,
@@ -783,7 +1318,7 @@
   if (begin == end)
     return false;
 
-  EHABISectionIterator<A> itNextPC = std::upper_bound(begin, end, pc);
+  EHABISectionIterator<A> itNextPC = EHABISectionUpperBound(begin, end, pc);
   if (itNextPC == begin)
     return false;
   EHABISectionIterator<A> itThisPC = itNextPC - 1;
@@ -793,8 +1328,7 @@
   // 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 nextPC = (itNextPC == end) ? UINTPTR_MAX : itNextPC.functionAddress();
   pint_t indexDataAddr = itThisPC.dataAddress();
 
   if (indexDataAddr == 0)
@@ -954,7 +1488,7 @@
   if (foundFDE) {
     typename CFI_Parser<A>::PrologInfo prolog;
     if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,
-                                            &prolog)) {
+                                            R::getArch(), &prolog)) {
       // Save off parsed FDE info
       _info.start_ip          = fdeInfo.pcStart;
       _info.end_ip            = fdeInfo.pcEnd;
@@ -1242,6 +1776,55 @@
 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
 
 
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+template <typename A, typename R>
+bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
+  pint_t base;
+  RUNTIME_FUNCTION *unwindEntry = lookUpSEHUnwindInfo(pc, &base);
+  if (!unwindEntry) {
+    _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc);
+    return false;
+  }
+  _info.gp = 0;
+  _info.flags = 0;
+  _info.format = 0;
+  _info.unwind_info_size = sizeof(RUNTIME_FUNCTION);
+  _info.unwind_info = reinterpret_cast<unw_word_t>(unwindEntry);
+  _info.extra = base;
+  _info.start_ip = base + unwindEntry->BeginAddress;
+#ifdef _LIBUNWIND_TARGET_X86_64
+  _info.end_ip = base + unwindEntry->EndAddress;
+  // Only fill in the handler and LSDA if they're stale.
+  if (pc != getLastPC()) {
+    UNWIND_INFO *xdata = reinterpret_cast<UNWIND_INFO *>(base + unwindEntry->UnwindData);
+    if (xdata->Flags & (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER)) {
+      // The personality is given in the UNWIND_INFO itself. The LSDA immediately
+      // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit
+      // these structures.)
+      // N.B. UNWIND_INFO structs are DWORD-aligned.
+      uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1;
+      const uint32_t *handler = reinterpret_cast<uint32_t *>(&xdata->UnwindCodes[lastcode]);
+      _info.lsda = reinterpret_cast<unw_word_t>(handler+1);
+      if (*handler) {
+        _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
+      } else
+        _info.handler = 0;
+    } else {
+      _info.lsda = 0;
+      _info.handler = 0;
+    }
+  }
+#elif defined(_LIBUNWIND_TARGET_ARM)
+  _info.end_ip = _info.start_ip + unwindEntry->FunctionLength;
+  _info.lsda = 0; // FIXME
+  _info.handler = 0; // FIXME
+#endif
+  setLastPC(pc);
+  return true;
+}
+#endif
+
+
 template <typename A, typename R>
 void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
   pint_t pc = (pint_t)this->getReg(UNW_REG_IP);
@@ -1285,6 +1868,12 @@
     }
 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
 
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+    // If there is SEH unwind info, look there next.
+    if (this->getInfoFromSEH(pc))
+      return;
+#endif
+
 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
     // If there is dwarf unwind info, look there next.
     if (sects.dwarf_section != 0) {
@@ -1314,7 +1903,7 @@
     if (msg == NULL) {
       typename CFI_Parser<A>::PrologInfo prolog;
       if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
-                                                                pc, &prolog)) {
+                                              pc, R::getArch(), &prolog)) {
         // save off parsed FDE info
         _info.start_ip         = fdeInfo.pcStart;
         _info.end_ip           = fdeInfo.pcEnd;
@@ -1343,8 +1932,8 @@
       // 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, &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;
@@ -1377,12 +1966,15 @@
   int result;
 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
   result = this->stepWithCompactEncoding();
+#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+  result = this->stepWithSEHData();
 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
   result = this->stepWithDwarfFDE();
 #elif defined(_LIBUNWIND_ARM_EHABI)
   result = this->stepWithEHABI();
 #else
   #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \
+              _LIBUNWIND_SUPPORT_SEH_UNWIND or \
               _LIBUNWIND_SUPPORT_DWARF_UNWIND or \
               _LIBUNWIND_ARM_EHABI
 #endif
@@ -1392,8 +1984,6 @@
     this->setInfoBasedOnIPRegister(true);
     if (_unwindInfoMissing)
       return UNW_STEP_END;
-    if (_info.gp)
-      setReg(UNW_REG_SP, getReg(UNW_REG_SP) + _info.gp);
   }
 
   return result;
diff --git a/src/UnwindLevel1-gcc-ext.c b/src/UnwindLevel1-gcc-ext.c
index 10619ba..fc303a9 100644
--- a/src/UnwindLevel1-gcc-ext.c
+++ b/src/UnwindLevel1-gcc-ext.c
@@ -1,9 +1,8 @@
 //===--------------------- UnwindLevel1-gcc-ext.c -------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 //  Implements gcc extensions to the C++ ABI Exception Handling Level 1.
@@ -25,6 +24,10 @@
 
 #if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
 
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+#define private_1 private_[0]
+#endif
+
 ///  Called by __cxa_rethrow().
 _LIBUNWIND_EXPORT _Unwind_Reason_Code
 _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {
@@ -33,9 +36,9 @@
                        (void *)exception_object,
                        (long)exception_object->unwinder_cache.reserved1);
 #else
-  _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld",
+  _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%" PRIdPTR,
                        (void *)exception_object,
-                       (long)exception_object->private_1);
+                       (intptr_t)exception_object->private_1);
 #endif
 
 #if defined(_LIBUNWIND_ARM_EHABI)
@@ -92,9 +95,9 @@
   unw_proc_info_t info;
   unw_getcontext(&uc);
   unw_init_local(&cursor, &uc);
-  unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(long) pc);
+  unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t) pc);
   if (unw_get_proc_info(&cursor, &info) == UNW_ESUCCESS)
-    return (void *)(long) info.start_ip;
+    return (void *)(intptr_t) info.start_ip;
   else
     return NULL;
 }
@@ -190,14 +193,14 @@
   unw_proc_info_t info;
   unw_getcontext(&uc);
   unw_init_local(&cursor, &uc);
-  unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(long) pc);
+  unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t) pc);
   unw_get_proc_info(&cursor, &info);
   bases->tbase = (uintptr_t)info.extra;
   bases->dbase = 0; // dbase not used on Mac OS X
   bases->func = (uintptr_t)info.start_ip;
   _LIBUNWIND_TRACE_API("_Unwind_Find_FDE(pc=%p) => %p", pc,
-                  (void *)(long) info.unwind_info);
-  return (void *)(long) info.unwind_info;
+                  (void *)(intptr_t) info.unwind_info);
+  return (void *)(intptr_t) info.unwind_info;
 }
 
 /// Returns the CFA (call frame area, or stack pointer at start of function)
diff --git a/src/UnwindLevel1.c b/src/UnwindLevel1.c
index 518577b..9d4084f 100644
--- a/src/UnwindLevel1.c
+++ b/src/UnwindLevel1.c
@@ -1,9 +1,8 @@
 //===------------------------- UnwindLevel1.c -----------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 // Implements C++ ABI Exception Handling Level 1 as documented at:
@@ -32,6 +31,8 @@
 
 #if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__)
 
+#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND
+
 static _Unwind_Reason_Code
 unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
   unw_init_local(cursor, uc);
@@ -287,7 +288,7 @@
     // If there is a personality routine, tell it we are unwinding.
     if (frameInfo.handler != 0) {
       __personality_routine p =
-          (__personality_routine)(long)(frameInfo.handler);
+          (__personality_routine)(intptr_t)(frameInfo.handler);
       _LIBUNWIND_TRACE_UNWINDING(
           "unwind_phase2_forced(ex_ojb=%p): calling personality function %p",
           (void *)exception_object, (void *)(uintptr_t)p);
@@ -449,6 +450,7 @@
   return result;
 }
 
+#endif // !_LIBUNWIND_SUPPORT_SEH_UNWIND
 
 /// Called by personality handler during phase 2 if a foreign exception
 // is caught.
diff --git a/src/UnwindRegistersRestore.S b/src/UnwindRegistersRestore.S
index bd797f6..ead6454 100644
--- a/src/UnwindRegistersRestore.S
+++ b/src/UnwindRegistersRestore.S
@@ -1,9 +1,8 @@
 //===-------------------- UnwindRegistersRestore.S ------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 
@@ -128,6 +127,271 @@
   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
+//
+
+// load register (GPR)
+#define PPC64_LR(n) \
+  ld    %r##n, (8 * (n + 2))(%r3)
+
+  // restore integral registers
+  // skip r0 for now
+  // skip r1 for now
+  PPC64_LR(2)
+  // skip r3 for now
+  // skip r4 for now
+  // skip r5 for now
+  PPC64_LR(6)
+  PPC64_LR(7)
+  PPC64_LR(8)
+  PPC64_LR(9)
+  PPC64_LR(10)
+  PPC64_LR(11)
+  PPC64_LR(12)
+  PPC64_LR(13)
+  PPC64_LR(14)
+  PPC64_LR(15)
+  PPC64_LR(16)
+  PPC64_LR(17)
+  PPC64_LR(18)
+  PPC64_LR(19)
+  PPC64_LR(20)
+  PPC64_LR(21)
+  PPC64_LR(22)
+  PPC64_LR(23)
+  PPC64_LR(24)
+  PPC64_LR(25)
+  PPC64_LR(26)
+  PPC64_LR(27)
+  PPC64_LR(28)
+  PPC64_LR(29)
+  PPC64_LR(30)
+  PPC64_LR(31)
+
+#ifdef PPC64_HAS_VMX
+
+  // restore VS registers
+  // (note that this also restores floating point registers and V registers,
+  // because part of VS is mapped to these registers)
+
+  addi  %r4, %r3, PPC64_OFFS_FP
+
+// load VS register
+#define PPC64_LVS(n)         \
+  lxvd2x  %vs##n, 0, %r4    ;\
+  addi    %r4, %r4, 16
+
+  // restore the first 32 VS regs (and also all floating point regs)
+  PPC64_LVS(0)
+  PPC64_LVS(1)
+  PPC64_LVS(2)
+  PPC64_LVS(3)
+  PPC64_LVS(4)
+  PPC64_LVS(5)
+  PPC64_LVS(6)
+  PPC64_LVS(7)
+  PPC64_LVS(8)
+  PPC64_LVS(9)
+  PPC64_LVS(10)
+  PPC64_LVS(11)
+  PPC64_LVS(12)
+  PPC64_LVS(13)
+  PPC64_LVS(14)
+  PPC64_LVS(15)
+  PPC64_LVS(16)
+  PPC64_LVS(17)
+  PPC64_LVS(18)
+  PPC64_LVS(19)
+  PPC64_LVS(20)
+  PPC64_LVS(21)
+  PPC64_LVS(22)
+  PPC64_LVS(23)
+  PPC64_LVS(24)
+  PPC64_LVS(25)
+  PPC64_LVS(26)
+  PPC64_LVS(27)
+  PPC64_LVS(28)
+  PPC64_LVS(29)
+  PPC64_LVS(30)
+  PPC64_LVS(31)
+
+  // use VRSAVE to conditionally restore the remaining VS regs,
+  // that are where the V regs are mapped
+
+  ld    %r5, PPC64_OFFS_VRSAVE(%r3)   // test VRsave
+  cmpwi %r5, 0
+  beq   Lnovec
+
+// conditionally load VS
+#define PPC64_CLVS_BOTTOM(n)               \
+  beq    Ldone##n                         ;\
+  addi   %r4, %r3, PPC64_OFFS_FP + n * 16 ;\
+  lxvd2x %vs##n, 0, %r4                   ;\
+Ldone##n:
+
+#define PPC64_CLVSl(n)           \
+  andis. %r0, %r5, (1<<(47-n))  ;\
+PPC64_CLVS_BOTTOM(n)
+
+#define PPC64_CLVSh(n)           \
+  andi.  %r0, %r5, (1<<(63-n))  ;\
+PPC64_CLVS_BOTTOM(n)
+
+  PPC64_CLVSl(32)
+  PPC64_CLVSl(33)
+  PPC64_CLVSl(34)
+  PPC64_CLVSl(35)
+  PPC64_CLVSl(36)
+  PPC64_CLVSl(37)
+  PPC64_CLVSl(38)
+  PPC64_CLVSl(39)
+  PPC64_CLVSl(40)
+  PPC64_CLVSl(41)
+  PPC64_CLVSl(42)
+  PPC64_CLVSl(43)
+  PPC64_CLVSl(44)
+  PPC64_CLVSl(45)
+  PPC64_CLVSl(46)
+  PPC64_CLVSl(47)
+  PPC64_CLVSh(48)
+  PPC64_CLVSh(49)
+  PPC64_CLVSh(50)
+  PPC64_CLVSh(51)
+  PPC64_CLVSh(52)
+  PPC64_CLVSh(53)
+  PPC64_CLVSh(54)
+  PPC64_CLVSh(55)
+  PPC64_CLVSh(56)
+  PPC64_CLVSh(57)
+  PPC64_CLVSh(58)
+  PPC64_CLVSh(59)
+  PPC64_CLVSh(60)
+  PPC64_CLVSh(61)
+  PPC64_CLVSh(62)
+  PPC64_CLVSh(63)
+
+#else
+
+// load FP register
+#define PPC64_LF(n) \
+  lfd   %f##n, (PPC64_OFFS_FP + n * 16)(%r3)
+
+  // restore float registers
+  PPC64_LF(0)
+  PPC64_LF(1)
+  PPC64_LF(2)
+  PPC64_LF(3)
+  PPC64_LF(4)
+  PPC64_LF(5)
+  PPC64_LF(6)
+  PPC64_LF(7)
+  PPC64_LF(8)
+  PPC64_LF(9)
+  PPC64_LF(10)
+  PPC64_LF(11)
+  PPC64_LF(12)
+  PPC64_LF(13)
+  PPC64_LF(14)
+  PPC64_LF(15)
+  PPC64_LF(16)
+  PPC64_LF(17)
+  PPC64_LF(18)
+  PPC64_LF(19)
+  PPC64_LF(20)
+  PPC64_LF(21)
+  PPC64_LF(22)
+  PPC64_LF(23)
+  PPC64_LF(24)
+  PPC64_LF(25)
+  PPC64_LF(26)
+  PPC64_LF(27)
+  PPC64_LF(28)
+  PPC64_LF(29)
+  PPC64_LF(30)
+  PPC64_LF(31)
+
+  // restore vector registers if any are in use
+  ld    %r5, PPC64_OFFS_VRSAVE(%r3)   // test VRsave
+  cmpwi %r5, 0
+  beq   Lnovec
+
+  subi  %r4, %r1, 16
+  // r4 is now a 16-byte aligned pointer into the red zone
+  // the _vectorScalarRegisters may not be 16-byte aligned
+  // so copy via red zone temp buffer
+
+#define PPC64_CLV_UNALIGNED_BOTTOM(n)            \
+  beq    Ldone##n                               ;\
+  ld     %r0, (PPC64_OFFS_V + n * 16)(%r3)      ;\
+  std    %r0, 0(%r4)                            ;\
+  ld     %r0, (PPC64_OFFS_V + n * 16 + 8)(%r3)  ;\
+  std    %r0, 8(%r4)                            ;\
+  lvx    %v##n, 0, %r4                          ;\
+Ldone  ## n:
+
+#define PPC64_CLV_UNALIGNEDl(n)  \
+  andis. %r0, %r5, (1<<(15-n))  ;\
+PPC64_CLV_UNALIGNED_BOTTOM(n)
+
+#define PPC64_CLV_UNALIGNEDh(n)  \
+  andi.  %r0, %r5, (1<<(31-n))  ;\
+PPC64_CLV_UNALIGNED_BOTTOM(n)
+
+  PPC64_CLV_UNALIGNEDl(0)
+  PPC64_CLV_UNALIGNEDl(1)
+  PPC64_CLV_UNALIGNEDl(2)
+  PPC64_CLV_UNALIGNEDl(3)
+  PPC64_CLV_UNALIGNEDl(4)
+  PPC64_CLV_UNALIGNEDl(5)
+  PPC64_CLV_UNALIGNEDl(6)
+  PPC64_CLV_UNALIGNEDl(7)
+  PPC64_CLV_UNALIGNEDl(8)
+  PPC64_CLV_UNALIGNEDl(9)
+  PPC64_CLV_UNALIGNEDl(10)
+  PPC64_CLV_UNALIGNEDl(11)
+  PPC64_CLV_UNALIGNEDl(12)
+  PPC64_CLV_UNALIGNEDl(13)
+  PPC64_CLV_UNALIGNEDl(14)
+  PPC64_CLV_UNALIGNEDl(15)
+  PPC64_CLV_UNALIGNEDh(16)
+  PPC64_CLV_UNALIGNEDh(17)
+  PPC64_CLV_UNALIGNEDh(18)
+  PPC64_CLV_UNALIGNEDh(19)
+  PPC64_CLV_UNALIGNEDh(20)
+  PPC64_CLV_UNALIGNEDh(21)
+  PPC64_CLV_UNALIGNEDh(22)
+  PPC64_CLV_UNALIGNEDh(23)
+  PPC64_CLV_UNALIGNEDh(24)
+  PPC64_CLV_UNALIGNEDh(25)
+  PPC64_CLV_UNALIGNEDh(26)
+  PPC64_CLV_UNALIGNEDh(27)
+  PPC64_CLV_UNALIGNEDh(28)
+  PPC64_CLV_UNALIGNEDh(29)
+  PPC64_CLV_UNALIGNEDh(30)
+  PPC64_CLV_UNALIGNEDh(31)
+
+#endif
+
+Lnovec:
+  ld    %r0, PPC64_OFFS_CR(%r3)
+  mtcr  %r0
+  ld    %r0, PPC64_OFFS_SRR0(%r3)
+  mtctr %r0
+
+  PPC64_LR(0)
+  PPC64_LR(5)
+  PPC64_LR(4)
+  PPC64_LR(1)
+  PPC64_LR(3)
+  bctr
+
 #elif defined(__ppc__)
 
 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
@@ -394,7 +658,7 @@
 #if defined(__ELF__)
   .fpu vfpv3-d16
 #endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPv)
   @ 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
   @ want the compiler to generate instructions that access those) but this is
@@ -415,7 +679,7 @@
 #if defined(__ELF__)
   .fpu vfpv3-d16
 #endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPv)
   vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia
   JMP(lr)
 
@@ -429,7 +693,7 @@
 #if defined(__ELF__)
   .fpu vfpv3
 #endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPv)
   vldmia r0, {d16-d31}
   JMP(lr)
 
@@ -445,7 +709,7 @@
 #if defined(__ELF__)
   .arch armv5te
 #endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPv)
   ldcl p1, cr0, [r0], #8  @ wldrd wR0, [r0], #8
   ldcl p1, cr1, [r0], #8  @ wldrd wR1, [r0], #8
   ldcl p1, cr2, [r0], #8  @ wldrd wR2, [r0], #8
@@ -493,7 +757,7 @@
 #  thread_state pointer is in r3
 #
 
-  # restore integral registerrs
+  # restore integral registers
   l.lwz     r0,  0(r3)
   l.lwz     r1,  4(r3)
   l.lwz     r2,  8(r3)
@@ -503,7 +767,7 @@
   l.lwz     r6, 24(r3)
   l.lwz     r7, 28(r3)
   l.lwz     r8, 32(r3)
-  l.lwz     r9, 36(r3)
+  # skip r9
   l.lwz    r10, 40(r3)
   l.lwz    r11, 44(r3)
   l.lwz    r12, 48(r3)
@@ -530,11 +794,13 @@
   # at last, restore r3
   l.lwz    r3,  12(r3)
 
+  # load new pc into ra
+  l.lwz    r9, 128(r3)
   # jump to pc
   l.jr     r9
    l.nop
 
-#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float)
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
 
 //
 // void libunwind::Registers_mips_o32::jumpto()
@@ -547,6 +813,59 @@
   .set noat
   .set noreorder
   .set nomacro
+#ifdef __mips_hard_float
+#if __mips_fpr != 64
+  ldc1  $f0, (4 * 36 + 8 * 0)($4)
+  ldc1  $f2, (4 * 36 + 8 * 2)($4)
+  ldc1  $f4, (4 * 36 + 8 * 4)($4)
+  ldc1  $f6, (4 * 36 + 8 * 6)($4)
+  ldc1  $f8, (4 * 36 + 8 * 8)($4)
+  ldc1  $f10, (4 * 36 + 8 * 10)($4)
+  ldc1  $f12, (4 * 36 + 8 * 12)($4)
+  ldc1  $f14, (4 * 36 + 8 * 14)($4)
+  ldc1  $f16, (4 * 36 + 8 * 16)($4)
+  ldc1  $f18, (4 * 36 + 8 * 18)($4)
+  ldc1  $f20, (4 * 36 + 8 * 20)($4)
+  ldc1  $f22, (4 * 36 + 8 * 22)($4)
+  ldc1  $f24, (4 * 36 + 8 * 24)($4)
+  ldc1  $f26, (4 * 36 + 8 * 26)($4)
+  ldc1  $f28, (4 * 36 + 8 * 28)($4)
+  ldc1  $f30, (4 * 36 + 8 * 30)($4)
+#else
+  ldc1  $f0, (4 * 36 + 8 * 0)($4)
+  ldc1  $f1, (4 * 36 + 8 * 1)($4)
+  ldc1  $f2, (4 * 36 + 8 * 2)($4)
+  ldc1  $f3, (4 * 36 + 8 * 3)($4)
+  ldc1  $f4, (4 * 36 + 8 * 4)($4)
+  ldc1  $f5, (4 * 36 + 8 * 5)($4)
+  ldc1  $f6, (4 * 36 + 8 * 6)($4)
+  ldc1  $f7, (4 * 36 + 8 * 7)($4)
+  ldc1  $f8, (4 * 36 + 8 * 8)($4)
+  ldc1  $f9, (4 * 36 + 8 * 9)($4)
+  ldc1  $f10, (4 * 36 + 8 * 10)($4)
+  ldc1  $f11, (4 * 36 + 8 * 11)($4)
+  ldc1  $f12, (4 * 36 + 8 * 12)($4)
+  ldc1  $f13, (4 * 36 + 8 * 13)($4)
+  ldc1  $f14, (4 * 36 + 8 * 14)($4)
+  ldc1  $f15, (4 * 36 + 8 * 15)($4)
+  ldc1  $f16, (4 * 36 + 8 * 16)($4)
+  ldc1  $f17, (4 * 36 + 8 * 17)($4)
+  ldc1  $f18, (4 * 36 + 8 * 18)($4)
+  ldc1  $f19, (4 * 36 + 8 * 19)($4)
+  ldc1  $f20, (4 * 36 + 8 * 20)($4)
+  ldc1  $f21, (4 * 36 + 8 * 21)($4)
+  ldc1  $f22, (4 * 36 + 8 * 22)($4)
+  ldc1  $f23, (4 * 36 + 8 * 23)($4)
+  ldc1  $f24, (4 * 36 + 8 * 24)($4)
+  ldc1  $f25, (4 * 36 + 8 * 25)($4)
+  ldc1  $f26, (4 * 36 + 8 * 26)($4)
+  ldc1  $f27, (4 * 36 + 8 * 27)($4)
+  ldc1  $f28, (4 * 36 + 8 * 28)($4)
+  ldc1  $f29, (4 * 36 + 8 * 29)($4)
+  ldc1  $f30, (4 * 36 + 8 * 30)($4)
+  ldc1  $f31, (4 * 36 + 8 * 31)($4)
+#endif
+#endif
   // restore hi and lo
   lw    $8, (4 * 33)($4)
   mthi  $8
@@ -590,19 +909,53 @@
   lw    $4, (4 * 4)($4)
   .set pop
 
-#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float)
+#elif defined(__mips64)
 
 //
-// void libunwind::Registers_mips_n64::jumpto()
+// void libunwind::Registers_mips_newabi::jumpto()
 //
 // On entry:
 //  thread state pointer is in a0 ($4)
 //
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_n646jumptoEv)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
   .set push
   .set noat
   .set noreorder
   .set nomacro
+#ifdef __mips_hard_float
+  ldc1  $f0, (8 * 35)($4)
+  ldc1  $f1, (8 * 36)($4)
+  ldc1  $f2, (8 * 37)($4)
+  ldc1  $f3, (8 * 38)($4)
+  ldc1  $f4, (8 * 39)($4)
+  ldc1  $f5, (8 * 40)($4)
+  ldc1  $f6, (8 * 41)($4)
+  ldc1  $f7, (8 * 42)($4)
+  ldc1  $f8, (8 * 43)($4)
+  ldc1  $f9, (8 * 44)($4)
+  ldc1  $f10, (8 * 45)($4)
+  ldc1  $f11, (8 * 46)($4)
+  ldc1  $f12, (8 * 47)($4)
+  ldc1  $f13, (8 * 48)($4)
+  ldc1  $f14, (8 * 49)($4)
+  ldc1  $f15, (8 * 50)($4)
+  ldc1  $f16, (8 * 51)($4)
+  ldc1  $f17, (8 * 52)($4)
+  ldc1  $f18, (8 * 53)($4)
+  ldc1  $f19, (8 * 54)($4)
+  ldc1  $f20, (8 * 55)($4)
+  ldc1  $f21, (8 * 56)($4)
+  ldc1  $f22, (8 * 57)($4)
+  ldc1  $f23, (8 * 58)($4)
+  ldc1  $f24, (8 * 59)($4)
+  ldc1  $f25, (8 * 60)($4)
+  ldc1  $f26, (8 * 61)($4)
+  ldc1  $f27, (8 * 62)($4)
+  ldc1  $f28, (8 * 63)($4)
+  ldc1  $f29, (8 * 64)($4)
+  ldc1  $f30, (8 * 65)($4)
+  ldc1  $f31, (8 * 66)($4)
+#endif
   // restore hi and lo
   ld    $8, (8 * 33)($4)
   mthi  $8
@@ -646,6 +999,28 @@
   ld    $4, (8 * 4)($4)
   .set pop
 
+#elif defined(__sparc__)
+
+//
+// void libunwind::Registers_sparc_o32::jumpto()
+//
+// On entry:
+//  thread_state pointer is in o0
+//
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv)
+  ta 3
+  ldd [%o0 + 64],  %l0
+  ldd [%o0 + 72],  %l2
+  ldd [%o0 + 80],  %l4
+  ldd [%o0 + 88],  %l6
+  ldd [%o0 + 96],  %i0
+  ldd [%o0 + 104], %i2
+  ldd [%o0 + 112], %i4
+  ldd [%o0 + 120], %i6
+  ld  [%o0 + 60],  %o7
+  jmp %o7
+   nop
+
 #endif
 
 #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
diff --git a/src/UnwindRegistersSave.S b/src/UnwindRegistersSave.S
index 4583f50..c7c4959 100644
--- a/src/UnwindRegistersSave.S
+++ b/src/UnwindRegistersSave.S
@@ -1,9 +1,8 @@
 //===------------------------ UnwindRegistersSave.S -----------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 
@@ -116,7 +115,7 @@
   xorl  %eax, %eax    # return UNW_ESUCCESS
   ret
 
-#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float)
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
 
 #
 # extern int unw_getcontext(unw_context_t* thread_state)
@@ -167,12 +166,65 @@
   sw    $8,  (4 * 33)($4)
   mflo  $8
   sw    $8,  (4 * 34)($4)
+#ifdef __mips_hard_float
+#if __mips_fpr != 64
+  sdc1  $f0, (4 * 36 + 8 * 0)($4)
+  sdc1  $f2, (4 * 36 + 8 * 2)($4)
+  sdc1  $f4, (4 * 36 + 8 * 4)($4)
+  sdc1  $f6, (4 * 36 + 8 * 6)($4)
+  sdc1  $f8, (4 * 36 + 8 * 8)($4)
+  sdc1  $f10, (4 * 36 + 8 * 10)($4)
+  sdc1  $f12, (4 * 36 + 8 * 12)($4)
+  sdc1  $f14, (4 * 36 + 8 * 14)($4)
+  sdc1  $f16, (4 * 36 + 8 * 16)($4)
+  sdc1  $f18, (4 * 36 + 8 * 18)($4)
+  sdc1  $f20, (4 * 36 + 8 * 20)($4)
+  sdc1  $f22, (4 * 36 + 8 * 22)($4)
+  sdc1  $f24, (4 * 36 + 8 * 24)($4)
+  sdc1  $f26, (4 * 36 + 8 * 26)($4)
+  sdc1  $f28, (4 * 36 + 8 * 28)($4)
+  sdc1  $f30, (4 * 36 + 8 * 30)($4)
+#else
+  sdc1  $f0, (4 * 36 + 8 * 0)($4)
+  sdc1  $f1, (4 * 36 + 8 * 1)($4)
+  sdc1  $f2, (4 * 36 + 8 * 2)($4)
+  sdc1  $f3, (4 * 36 + 8 * 3)($4)
+  sdc1  $f4, (4 * 36 + 8 * 4)($4)
+  sdc1  $f5, (4 * 36 + 8 * 5)($4)
+  sdc1  $f6, (4 * 36 + 8 * 6)($4)
+  sdc1  $f7, (4 * 36 + 8 * 7)($4)
+  sdc1  $f8, (4 * 36 + 8 * 8)($4)
+  sdc1  $f9, (4 * 36 + 8 * 9)($4)
+  sdc1  $f10, (4 * 36 + 8 * 10)($4)
+  sdc1  $f11, (4 * 36 + 8 * 11)($4)
+  sdc1  $f12, (4 * 36 + 8 * 12)($4)
+  sdc1  $f13, (4 * 36 + 8 * 13)($4)
+  sdc1  $f14, (4 * 36 + 8 * 14)($4)
+  sdc1  $f15, (4 * 36 + 8 * 15)($4)
+  sdc1  $f16, (4 * 36 + 8 * 16)($4)
+  sdc1  $f17, (4 * 36 + 8 * 17)($4)
+  sdc1  $f18, (4 * 36 + 8 * 18)($4)
+  sdc1  $f19, (4 * 36 + 8 * 19)($4)
+  sdc1  $f20, (4 * 36 + 8 * 20)($4)
+  sdc1  $f21, (4 * 36 + 8 * 21)($4)
+  sdc1  $f22, (4 * 36 + 8 * 22)($4)
+  sdc1  $f23, (4 * 36 + 8 * 23)($4)
+  sdc1  $f24, (4 * 36 + 8 * 24)($4)
+  sdc1  $f25, (4 * 36 + 8 * 25)($4)
+  sdc1  $f26, (4 * 36 + 8 * 26)($4)
+  sdc1  $f27, (4 * 36 + 8 * 27)($4)
+  sdc1  $f28, (4 * 36 + 8 * 28)($4)
+  sdc1  $f29, (4 * 36 + 8 * 29)($4)
+  sdc1  $f30, (4 * 36 + 8 * 30)($4)
+  sdc1  $f31, (4 * 36 + 8 * 31)($4)
+#endif
+#endif
   jr	$31
   # return UNW_ESUCCESS
   or    $2, $0, $0
   .set pop
 
-#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float)
+#elif defined(__mips64)
 
 #
 # extern int unw_getcontext(unw_context_t* thread_state)
@@ -223,6 +275,40 @@
   sd    $8,  (8 * 33)($4)
   mflo  $8
   sd    $8,  (8 * 34)($4)
+#ifdef __mips_hard_float
+  sdc1  $f0, (8 * 35)($4)
+  sdc1  $f1, (8 * 36)($4)
+  sdc1  $f2, (8 * 37)($4)
+  sdc1  $f3, (8 * 38)($4)
+  sdc1  $f4, (8 * 39)($4)
+  sdc1  $f5, (8 * 40)($4)
+  sdc1  $f6, (8 * 41)($4)
+  sdc1  $f7, (8 * 42)($4)
+  sdc1  $f8, (8 * 43)($4)
+  sdc1  $f9, (8 * 44)($4)
+  sdc1  $f10, (8 * 45)($4)
+  sdc1  $f11, (8 * 46)($4)
+  sdc1  $f12, (8 * 47)($4)
+  sdc1  $f13, (8 * 48)($4)
+  sdc1  $f14, (8 * 49)($4)
+  sdc1  $f15, (8 * 50)($4)
+  sdc1  $f16, (8 * 51)($4)
+  sdc1  $f17, (8 * 52)($4)
+  sdc1  $f18, (8 * 53)($4)
+  sdc1  $f19, (8 * 54)($4)
+  sdc1  $f20, (8 * 55)($4)
+  sdc1  $f21, (8 * 56)($4)
+  sdc1  $f22, (8 * 57)($4)
+  sdc1  $f23, (8 * 58)($4)
+  sdc1  $f24, (8 * 59)($4)
+  sdc1  $f25, (8 * 60)($4)
+  sdc1  $f26, (8 * 61)($4)
+  sdc1  $f27, (8 * 62)($4)
+  sdc1  $f28, (8 * 63)($4)
+  sdc1  $f29, (8 * 64)($4)
+  sdc1  $f30, (8 * 65)($4)
+  sdc1  $f31, (8 * 66)($4)
+#endif
   jr	$31
   # return UNW_ESUCCESS
   or    $2, $0, $0
@@ -237,6 +323,237 @@
 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)
+
+// store register (GPR)
+#define PPC64_STR(n) \
+  std   %r##n, (8 * (n + 2))(%r3)
+
+  // save GPRs
+  PPC64_STR(0)
+  mflr  %r0
+  std   %r0, PPC64_OFFS_SRR0(%r3) // store lr as ssr0
+  PPC64_STR(1)
+  PPC64_STR(2)
+  PPC64_STR(3)
+  PPC64_STR(4)
+  PPC64_STR(5)
+  PPC64_STR(6)
+  PPC64_STR(7)
+  PPC64_STR(8)
+  PPC64_STR(9)
+  PPC64_STR(10)
+  PPC64_STR(11)
+  PPC64_STR(12)
+  PPC64_STR(13)
+  PPC64_STR(14)
+  PPC64_STR(15)
+  PPC64_STR(16)
+  PPC64_STR(17)
+  PPC64_STR(18)
+  PPC64_STR(19)
+  PPC64_STR(20)
+  PPC64_STR(21)
+  PPC64_STR(22)
+  PPC64_STR(23)
+  PPC64_STR(24)
+  PPC64_STR(25)
+  PPC64_STR(26)
+  PPC64_STR(27)
+  PPC64_STR(28)
+  PPC64_STR(29)
+  PPC64_STR(30)
+  PPC64_STR(31)
+
+  mfcr  %r0
+  std   %r0,  PPC64_OFFS_CR(%r3)
+  mfxer %r0
+  std   %r0,  PPC64_OFFS_XER(%r3)
+  mflr  %r0
+  std   %r0,  PPC64_OFFS_LR(%r3)
+  mfctr %r0
+  std   %r0,  PPC64_OFFS_CTR(%r3)
+  mfvrsave    %r0
+  std   %r0,  PPC64_OFFS_VRSAVE(%r3)
+
+#ifdef PPC64_HAS_VMX
+  // save VS registers
+  // (note that this also saves floating point registers and V registers,
+  // because part of VS is mapped to these registers)
+
+  addi  %r4, %r3, PPC64_OFFS_FP
+
+// store VS register
+#define PPC64_STVS(n)      \
+  stxvd2x %vs##n, 0, %r4  ;\
+  addi    %r4, %r4, 16
+
+  PPC64_STVS(0)
+  PPC64_STVS(1)
+  PPC64_STVS(2)
+  PPC64_STVS(3)
+  PPC64_STVS(4)
+  PPC64_STVS(5)
+  PPC64_STVS(6)
+  PPC64_STVS(7)
+  PPC64_STVS(8)
+  PPC64_STVS(9)
+  PPC64_STVS(10)
+  PPC64_STVS(11)
+  PPC64_STVS(12)
+  PPC64_STVS(13)
+  PPC64_STVS(14)
+  PPC64_STVS(15)
+  PPC64_STVS(16)
+  PPC64_STVS(17)
+  PPC64_STVS(18)
+  PPC64_STVS(19)
+  PPC64_STVS(20)
+  PPC64_STVS(21)
+  PPC64_STVS(22)
+  PPC64_STVS(23)
+  PPC64_STVS(24)
+  PPC64_STVS(25)
+  PPC64_STVS(26)
+  PPC64_STVS(27)
+  PPC64_STVS(28)
+  PPC64_STVS(29)
+  PPC64_STVS(30)
+  PPC64_STVS(31)
+  PPC64_STVS(32)
+  PPC64_STVS(33)
+  PPC64_STVS(34)
+  PPC64_STVS(35)
+  PPC64_STVS(36)
+  PPC64_STVS(37)
+  PPC64_STVS(38)
+  PPC64_STVS(39)
+  PPC64_STVS(40)
+  PPC64_STVS(41)
+  PPC64_STVS(42)
+  PPC64_STVS(43)
+  PPC64_STVS(44)
+  PPC64_STVS(45)
+  PPC64_STVS(46)
+  PPC64_STVS(47)
+  PPC64_STVS(48)
+  PPC64_STVS(49)
+  PPC64_STVS(50)
+  PPC64_STVS(51)
+  PPC64_STVS(52)
+  PPC64_STVS(53)
+  PPC64_STVS(54)
+  PPC64_STVS(55)
+  PPC64_STVS(56)
+  PPC64_STVS(57)
+  PPC64_STVS(58)
+  PPC64_STVS(59)
+  PPC64_STVS(60)
+  PPC64_STVS(61)
+  PPC64_STVS(62)
+  PPC64_STVS(63)
+
+#else
+
+// store FP register
+#define PPC64_STF(n) \
+  stfd  %f##n, (PPC64_OFFS_FP + n * 16)(%r3)
+
+  // save float registers
+  PPC64_STF(0)
+  PPC64_STF(1)
+  PPC64_STF(2)
+  PPC64_STF(3)
+  PPC64_STF(4)
+  PPC64_STF(5)
+  PPC64_STF(6)
+  PPC64_STF(7)
+  PPC64_STF(8)
+  PPC64_STF(9)
+  PPC64_STF(10)
+  PPC64_STF(11)
+  PPC64_STF(12)
+  PPC64_STF(13)
+  PPC64_STF(14)
+  PPC64_STF(15)
+  PPC64_STF(16)
+  PPC64_STF(17)
+  PPC64_STF(18)
+  PPC64_STF(19)
+  PPC64_STF(20)
+  PPC64_STF(21)
+  PPC64_STF(22)
+  PPC64_STF(23)
+  PPC64_STF(24)
+  PPC64_STF(25)
+  PPC64_STF(26)
+  PPC64_STF(27)
+  PPC64_STF(28)
+  PPC64_STF(29)
+  PPC64_STF(30)
+  PPC64_STF(31)
+
+  // save vector registers
+
+  // Use 16-bytes below the stack pointer as an
+  // aligned buffer to save each vector register.
+  // Note that the stack pointer is always 16-byte aligned.
+  subi  %r4, %r1, 16
+
+#define PPC64_STV_UNALIGNED(n)                 \
+  stvx  %v##n, 0, %r4                         ;\
+  ld    %r5, 0(%r4)                           ;\
+  std   %r5, (PPC64_OFFS_V + n * 16)(%r3)     ;\
+  ld    %r5, 8(%r4)                           ;\
+  std   %r5, (PPC64_OFFS_V + n * 16 + 8)(%r3)
+
+  PPC64_STV_UNALIGNED(0)
+  PPC64_STV_UNALIGNED(1)
+  PPC64_STV_UNALIGNED(2)
+  PPC64_STV_UNALIGNED(3)
+  PPC64_STV_UNALIGNED(4)
+  PPC64_STV_UNALIGNED(5)
+  PPC64_STV_UNALIGNED(6)
+  PPC64_STV_UNALIGNED(7)
+  PPC64_STV_UNALIGNED(8)
+  PPC64_STV_UNALIGNED(9)
+  PPC64_STV_UNALIGNED(10)
+  PPC64_STV_UNALIGNED(11)
+  PPC64_STV_UNALIGNED(12)
+  PPC64_STV_UNALIGNED(13)
+  PPC64_STV_UNALIGNED(14)
+  PPC64_STV_UNALIGNED(15)
+  PPC64_STV_UNALIGNED(16)
+  PPC64_STV_UNALIGNED(17)
+  PPC64_STV_UNALIGNED(18)
+  PPC64_STV_UNALIGNED(19)
+  PPC64_STV_UNALIGNED(20)
+  PPC64_STV_UNALIGNED(21)
+  PPC64_STV_UNALIGNED(22)
+  PPC64_STV_UNALIGNED(23)
+  PPC64_STV_UNALIGNED(24)
+  PPC64_STV_UNALIGNED(25)
+  PPC64_STV_UNALIGNED(26)
+  PPC64_STV_UNALIGNED(27)
+  PPC64_STV_UNALIGNED(28)
+  PPC64_STV_UNALIGNED(29)
+  PPC64_STV_UNALIGNED(30)
+  PPC64_STV_UNALIGNED(31)
+
+#endif
+
+  li    %r3,  0   // return UNW_ESUCCESS
+  blr
+
+
 #elif defined(__ppc__)
 
 ;
@@ -490,7 +807,7 @@
 #if defined(__ELF__)
   .fpu vfpv3-d16
 #endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPv)
   vstmia r0, {d0-d15}
   JMP(lr)
 
@@ -504,7 +821,7 @@
 #if defined(__ELF__)
   .fpu vfpv3-d16
 #endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPv)
   vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
   JMP(lr)
 
@@ -518,7 +835,7 @@
 #if defined(__ELF__)
   .fpu vfpv3
 #endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPv)
   @ 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
   @ want the compiler to generate instructions that access those) but this is
@@ -541,7 +858,7 @@
 #if defined(__ELF__)
   .arch armv5te
 #endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPv)
   stcl p1, cr0, [r0], #8  @ wstrd wR0, [r0], #8
   stcl p1, cr1, [r0], #8  @ wstrd wR1, [r0], #8
   stcl p1, cr2, [r0], #8  @ wstrd wR2, [r0], #8
@@ -620,9 +937,41 @@
   l.sw     116(r3), r29
   l.sw     120(r3), r30
   l.sw     124(r3), r31
-#endif
+  # store ra to pc
+  l.sw     128(r3), r9
+  # zero epcr
+  l.sw     132(r3), r0
 
+#elif defined(__sparc__)
+
+#
+# extern int unw_getcontext(unw_context_t* thread_state)
+#
+# On entry:
+#  thread_state pointer is in o0
+#
+DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
+  ta 3
+  add %o7, 8, %o7
+  std %g0, [%o0 +   0]
+  std %g2, [%o0 +   8]
+  std %g4, [%o0 +  16]
+  std %g6, [%o0 +  24]
+  std %o0, [%o0 +  32]
+  std %o2, [%o0 +  40]
+  std %o4, [%o0 +  48]
+  std %o6, [%o0 +  56]
+  std %l0, [%o0 +  64]
+  std %l2, [%o0 +  72]
+  std %l4, [%o0 +  80]
+  std %l6, [%o0 +  88]
+  std %i0, [%o0 +  96]
+  std %i2, [%o0 + 104]
+  std %i4, [%o0 + 112]
+  std %i6, [%o0 + 120]
+  jmp %o7
+   clr %o0                   // return UNW_ESUCCESS
+#endif
 #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
 
 NO_EXEC_STACK_DIRECTIVE
-
diff --git a/src/Unwind_AppleExtras.cpp b/src/Unwind_AppleExtras.cpp
index 39f379c..248d995 100644
--- a/src/Unwind_AppleExtras.cpp
+++ b/src/Unwind_AppleExtras.cpp
@@ -1,9 +1,8 @@
 //===--------------------- Unwind_AppleExtras.cpp -------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 //===----------------------------------------------------------------------===//
diff --git a/src/assembly.h b/src/assembly.h
index 2b2269c..a15b89f 100644
--- a/src/assembly.h
+++ b/src/assembly.h
@@ -1,9 +1,8 @@
 /* ===-- assembly.h - libUnwind assembler support macros -------------------===
  *
- *                     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.
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  *
  * ===----------------------------------------------------------------------===
  *
@@ -16,7 +15,20 @@
 #ifndef UNWIND_ASSEMBLY_H
 #define UNWIND_ASSEMBLY_H
 
-#if defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__)
+#if defined(__powerpc64__)
+#define SEPARATOR ;
+#define PPC64_OFFS_SRR0   0
+#define PPC64_OFFS_CR     272
+#define PPC64_OFFS_XER    280
+#define PPC64_OFFS_LR     288
+#define PPC64_OFFS_CTR    296
+#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(__POWERPC__) || defined(__powerpc__) || defined(__ppc__)
 #define SEPARATOR @
 #elif defined(__arm64__)
 #define SEPARATOR %%
@@ -31,6 +43,7 @@
 #if defined(__APPLE__)
 
 #define SYMBOL_IS_FUNC(name)
+#define EXPORT_SYMBOL(name)
 #define HIDDEN_SYMBOL(name) .private_extern name
 #define NO_EXEC_STACK_DIRECTIVE
 
@@ -41,6 +54,7 @@
 #else
 #define SYMBOL_IS_FUNC(name) .type name,@function
 #endif
+#define EXPORT_SYMBOL(name)
 #define HIDDEN_SYMBOL(name) .hidden name
 
 #if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
@@ -57,10 +71,21 @@
     .scl 2 SEPARATOR                                                           \
     .type 32 SEPARATOR                                                         \
   .endef
+#define EXPORT_SYMBOL2(name)                              \
+  .section .drectve,"yn" SEPARATOR                        \
+  .ascii "-export:", #name, "\0" SEPARATOR                \
+  .text
+#if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS)
+#define EXPORT_SYMBOL(name)
+#else
+#define EXPORT_SYMBOL(name) EXPORT_SYMBOL2(name)
+#endif
 #define HIDDEN_SYMBOL(name)
 
 #define NO_EXEC_STACK_DIRECTIVE
 
+#elif defined(__sparc__)
+
 #else
 
 #error Unsupported target
@@ -69,6 +94,7 @@
 
 #define DEFINE_LIBUNWIND_FUNCTION(name)                   \
   .globl SYMBOL_NAME(name) SEPARATOR                      \
+  EXPORT_SYMBOL(name) SEPARATOR                           \
   SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR             \
   SYMBOL_NAME(name):
 
diff --git a/src/config.h b/src/config.h
index 0f29b77..c2fff50 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,9 +1,8 @@
 //===----------------------------- config.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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 //  Defines macros used within libunwind project.
@@ -38,7 +37,11 @@
     #define _LIBUNWIND_SUPPORT_DWARF_UNWIND   1
   #endif
 #elif defined(_WIN32)
-  #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
+  #ifdef __SEH__
+    #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1
+  #else
+    #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
+  #endif
 #else
   #if defined(__ARM_DWARF_EH__) || !defined(__arm__)
     #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
@@ -63,17 +66,23 @@
 #define _LIBUNWIND_BUILD_SJLJ_APIS
 #endif
 
-#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__)
 #define _LIBUNWIND_SUPPORT_FRAME_APIS
 #endif
 
 #if defined(__i386__) || defined(__x86_64__) ||                                \
-    defined(__ppc__) || defined(__ppc64__) ||                                  \
+    defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) ||        \
     (!defined(__APPLE__) && defined(__arm__)) ||                               \
     (defined(__arm64__) || defined(__aarch64__)) ||                            \
     defined(__mips__)
+#if !defined(_LIBUNWIND_BUILD_SJLJ_APIS)
 #define _LIBUNWIND_BUILD_ZERO_COST_APIS
 #endif
+#endif
+
+#if defined(__powerpc64__) && defined(_ARCH_PWR8)
+#define PPC64_HAS_VMX
+#endif
 
 #if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL)
 #define _LIBUNWIND_ABORT(msg)                                                  \
@@ -91,8 +100,11 @@
 #endif
 
 #if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL)
+#define _LIBUNWIND_LOG0(msg)
 #define _LIBUNWIND_LOG(msg, ...)
 #else
+#define _LIBUNWIND_LOG0(msg)                                               \
+  fprintf(stderr, "libunwind: " msg "\n")
 #define _LIBUNWIND_LOG(msg, ...)                                               \
   fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__)
 #endif
@@ -152,7 +164,7 @@
 #if defined(_LIBUNWIND_IS_NATIVE_ONLY)
 # define COMP_OP ==
 #else
-# define COMP_OP <
+# define COMP_OP <=
 #endif
 template <typename _Type, typename _Mem>
 struct check_fit {
diff --git a/src/dwarf2.h b/src/dwarf2.h
index 0dcd2ca..40f0daf 100644
--- a/src/dwarf2.h
+++ b/src/dwarf2.h
@@ -1,9 +1,8 @@
 //===------------------------------- dwarf2.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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 
@@ -49,7 +48,10 @@
   // GNU extensions
   DW_CFA_GNU_window_save              = 0x2D,
   DW_CFA_GNU_args_size                = 0x2E,
-  DW_CFA_GNU_negative_offset_extended = 0x2F
+  DW_CFA_GNU_negative_offset_extended = 0x2F,
+
+  // AARCH64 extensions
+  DW_CFA_AARCH64_negate_ra_state      = 0x2D
 };
 
 
diff --git a/src/libunwind.cpp b/src/libunwind.cpp
index 0b7fb40..03dfeae 100644
--- a/src/libunwind.cpp
+++ b/src/libunwind.cpp
@@ -1,9 +1,8 @@
 //===--------------------------- libunwind.cpp ----------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 //  Implements unw_* functions from <libunwind.h>
@@ -12,12 +11,6 @@
 
 #include <libunwind.h>
 
-#ifndef NDEBUG
-#include <cstdlib> // getenv
-#endif
-#include <new>
-#include <algorithm>
-
 #include "libunwind_ext.h"
 #include "config.h"
 
@@ -51,6 +44,8 @@
 # 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__)
@@ -59,18 +54,21 @@
 # define REGISTER_KIND Registers_arm
 #elif defined(__or1k__)
 # define REGISTER_KIND Registers_or1k
-#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float)
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
 # define REGISTER_KIND Registers_mips_o32
-#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float)
-# define REGISTER_KIND Registers_mips_n64
+#elif defined(__mips64)
+# define REGISTER_KIND Registers_mips_newabi
 #elif defined(__mips__)
 # warning The MIPS architecture is not supported with this ABI and environment!
+#elif defined(__sparc__)
+# define REGISTER_KIND Registers_sparc
 #else
 # error Architecture not supported
 #endif
   // Use "placement new" to allocate UnwindCursor in the cursor buffer.
-  new ((void *)cursor) UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
-                                 context, LocalAddressSpace::sThisAddressSpace);
+  new (reinterpret_cast<UnwindCursor<LocalAddressSpace, REGISTER_KIND> *>(cursor))
+      UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
+          context, LocalAddressSpace::sThisAddressSpace);
 #undef REGISTER_KIND
   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
   co->setInfoBasedOnIPRegister();
@@ -78,88 +76,6 @@
   return UNW_ESUCCESS;
 }
 
-#ifdef UNW_REMOTE
-/// Create a cursor into a thread in another process.
-_LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor,
-                                             unw_addr_space_t as,
-                                             void *arg) {
-  // special case: unw_init_remote(xx, unw_local_addr_space, xx)
-  if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace)
-    return unw_init_local(cursor, NULL); //FIXME
-
-  // use "placement new" to allocate UnwindCursor in the cursor buffer
-  switch (as->cpuType) {
-  case CPU_TYPE_I386:
-    new ((void *)cursor)
-        UnwindCursor<RemoteAddressSpace<Pointer32<LittleEndian>>,
-                     Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg);
-    break;
-  case CPU_TYPE_X86_64:
-    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<RemoteAddressSpace<Pointer32<BigEndian>>,
-                     Registers_ppc>(((unw_addr_space_ppc *)as)->oas, arg);
-    break;
-  default:
-    return UNW_EUNSPEC;
-  }
-  return UNW_ESUCCESS;
-}
-
-
-static bool is64bit(task_t task) {
-  return false; // FIXME
-}
-
-/// Create an address_space object for use in examining another task.
-_LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) {
-#if __i386__
-  if (is64bit(task)) {
-    unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task);
-    as->taskPort = task;
-    as->cpuType = CPU_TYPE_X86_64;
-    //as->oas
-  } else {
-    unw_addr_space_i386 *as = new unw_addr_space_i386(task);
-    as->taskPort = task;
-    as->cpuType = CPU_TYPE_I386;
-    //as->oas
-  }
-#else
-// FIXME
-#endif
-}
-
-
-/// Delete an address_space object.
-_LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) {
-  switch (asp->cpuType) {
-#if __i386__ || __x86_64__
-  case CPU_TYPE_I386: {
-    unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp;
-    delete as;
-  }
-  break;
-  case CPU_TYPE_X86_64: {
-    unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp;
-    delete as;
-  }
-  break;
-#endif
-  case CPU_TYPE_POWERPC: {
-    unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp;
-    delete as;
-  }
-  break;
-  }
-}
-#endif // UNW_REMOTE
-
-
 /// 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) {
@@ -186,8 +102,20 @@
     co->setReg(regNum, (pint_t)value);
     // specical case altering IP to re-find info (being called by personality
     // function)
-    if (regNum == UNW_REG_IP)
+    if (regNum == UNW_REG_IP) {
+      unw_proc_info_t info;
+      // First, get the FDE for the old location and then update it.
+      co->getInfo(&info);
       co->setInfoBasedOnIPRegister(false);
+      // If the original call expects stack adjustment, perform this now.
+      // Normal frame unwinding would have included the offset already in the
+      // CFA computation.
+      // Note: for PA-RISC and other platforms where the stack grows up,
+      // this should actually be - info.gp. LLVM doesn't currently support
+      // any such platforms and Clang doesn't export a macro for them.
+      if (info.gp)
+        co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp);
+    }
     return UNW_ESUCCESS;
   }
   return UNW_EBADREG;
diff --git a/src/libunwind_ext.h b/src/libunwind_ext.h
index ec645a8..01b58a9 100644
--- a/src/libunwind_ext.h
+++ b/src/libunwind_ext.h
@@ -1,9 +1,8 @@
 //===------------------------ libunwind_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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //
 //  Extensions to libunwind API.
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 97917b8..d902e3e 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -16,6 +16,7 @@
 pythonize_bool(LIBUNWIND_ENABLE_SHARED)
 pythonize_bool(LIBUNWIND_ENABLE_THREADS)
 pythonize_bool(LIBUNWIND_ENABLE_EXCEPTIONS)
+pythonize_bool(LIBUNWIND_USE_COMPILER_RT)
 pythonize_bool(LIBUNWIND_BUILD_EXTERNAL_THREAD_LIBRARY)
 set(LIBUNWIND_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
     "TargetInfo to use when setting up test environment.")
diff --git a/test/alignment.pass.cpp b/test/alignment.pass.cpp
index 1a3ca5a..b0da7f1 100644
--- a/test/alignment.pass.cpp
+++ b/test/alignment.pass.cpp
@@ -1,10 +1,9 @@
 // -*- C++ -*-
 //===----------------------------------------------------------------------===//
 //
-//                     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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 
diff --git a/test/libunwind/test/config.py b/test/libunwind/test/config.py
index 2a0c828..8034625 100644
--- a/test/libunwind/test/config.py
+++ b/test/libunwind/test/config.py
@@ -1,9 +1,8 @@
 #===----------------------------------------------------------------------===##
 #
-#                     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.
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 #
 #===----------------------------------------------------------------------===##
 import os
diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in
index 888b960..34da72a 100644
--- a/test/lit.site.cfg.in
+++ b/test/lit.site.cfg.in
@@ -7,21 +7,24 @@
 config.libcxx_src_root          = "@LIBUNWIND_LIBCXX_PATH@"
 config.libunwind_headers        = "@LIBUNWIND_SOURCE_DIR@/include"
 config.cxx_library_root         = "@LIBUNWIND_LIBCXX_LIBRARY_PATH@"
-config.llvm_unwinder            = "1"
-config.enable_threads           = "@LIBUNWIND_ENABLE_THREADS@"
+config.llvm_unwinder            = True
+config.builtins_library         = "@LIBUNWIND_BUILTINS_LIBRARY@"
+config.enable_threads           = @LIBUNWIND_ENABLE_THREADS@
 config.use_sanitizer            = "@LLVM_USE_SANITIZER@"
-config.enable_32bit             = "@LIBUNWIND_BUILD_32_BITS@"
+config.enable_32bit             = @LIBUNWIND_BUILD_32_BITS@
 config.target_info              = "@LIBUNWIND_TARGET_INFO@"
+config.test_linker_flags        = "@LIBUNWIND_TEST_LINKER_FLAGS@"
+config.test_compiler_flags      = "@LIBUNWIND_TEST_COMPILER_FLAGS@"
 config.executor                 = "@LIBUNWIND_EXECUTOR@"
-config.libunwind_shared         = "@LIBUNWIND_ENABLE_SHARED@"
-config.enable_shared            = "@LIBCXX_ENABLE_SHARED@"
-config.enable_exceptions        = "@LIBUNWIND_ENABLE_EXCEPTIONS@"
+config.libunwind_shared         = @LIBUNWIND_ENABLE_SHARED@
+config.enable_shared            = @LIBCXX_ENABLE_SHARED@
+config.enable_exceptions        = @LIBUNWIND_ENABLE_EXCEPTIONS@
 config.host_triple              = "@LLVM_HOST_TRIPLE@"
 config.target_triple            = "@TARGET_TRIPLE@"
-config.use_target               = len("@LIBUNWIND_TARGET_TRIPLE@") > 0
+config.use_target               = bool("@LIBUNWIND_TARGET_TRIPLE@")
 config.sysroot                  = "@LIBUNWIND_SYSROOT@"
 config.gcc_toolchain            = "@LIBUNWIND_GCC_TOOLCHAIN@"
-config.cxx_ext_threads          = "@LIBUNWIND_BUILD_EXTERNAL_THREAD_LIBRARY@"
+config.cxx_ext_threads          = @LIBUNWIND_BUILD_EXTERNAL_THREAD_LIBRARY@
 
 # Let the main config do the real work.
 lit_config.load_config(config, "@LIBUNWIND_SOURCE_DIR@/test/lit.cfg")