Commit 571a4c86c3

Andrew Kelley <andrew@ziglang.org>
2023-08-12 02:19:17
libunwind: update to LLVM 17
release/17.x branch, commit 8f4dd44097c9ae25dd203d5ac87f3b48f854bba8
1 parent 6a07b70
lib/libunwind/include/__libunwind_config.h
@@ -196,9 +196,9 @@
 # define _LIBUNWIND_TARGET_RISCV 1
 # define _LIBUNWIND_TARGET_VE 1
 # define _LIBUNWIND_TARGET_S390X 1
-#define _LIBUNWIND_TARGET_LOONGARCH 1
+ #define _LIBUNWIND_TARGET_LOONGARCH 1
 # define _LIBUNWIND_CONTEXT_SIZE 167
-# define _LIBUNWIND_CURSOR_SIZE 179
+# define _LIBUNWIND_CURSOR_SIZE 204
 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
 #endif // _LIBUNWIND_IS_NATIVE_ONLY
 
lib/libunwind/include/unwind.h
@@ -56,9 +56,9 @@ typedef enum {
 typedef struct _Unwind_Context _Unwind_Context;   // opaque
 
 #if defined(_LIBUNWIND_ARM_EHABI)
-#include "unwind_arm_ehabi.h"
+#include <unwind_arm_ehabi.h>
 #else
-#include "unwind_itanium.h"
+#include <unwind_itanium.h>
 #endif
 
 typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
lib/libunwind/src/AddressSpace.hpp
@@ -66,6 +66,10 @@ char *getFuncNameFromTBTable(uintptr_t pc, uint16_t &NameLen,
   // In 10.7.0 or later, libSystem.dylib implements this function.
   extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
 
+namespace libunwind {
+  bool findDynamicUnwindSections(void *, unw_dynamic_unwind_sections *);
+}
+
 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
 
 // When statically linked on bare-metal, the symbols for the EH table are looked
@@ -497,6 +501,22 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
     info.compact_unwind_section_length = (size_t)dyldInfo.compact_unwind_section_length;
     return true;
   }
+
+  unw_dynamic_unwind_sections dynamicUnwindSectionInfo;
+  if (findDynamicUnwindSections((void *)targetAddr,
+                                &dynamicUnwindSectionInfo)) {
+    info.dso_base = dynamicUnwindSectionInfo.dso_base;
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+    info.dwarf_section = (uintptr_t)dynamicUnwindSectionInfo.dwarf_section;
+    info.dwarf_section_length = dynamicUnwindSectionInfo.dwarf_section_length;
+#endif
+    info.compact_unwind_section =
+        (uintptr_t)dynamicUnwindSectionInfo.compact_unwind_section;
+    info.compact_unwind_section_length =
+        dynamicUnwindSectionInfo.compact_unwind_section_length;
+    return true;
+  }
+
 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
   info.dso_base = 0;
   // Bare metal is statically linked, so no need to ask the dynamic loader
lib/libunwind/src/config.h
@@ -162,10 +162,14 @@
 #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__)
+#define _LIBUNWIND_LOG0(msg) do {                                              \
+    fprintf(stderr, "libunwind: " msg "\n");                                   \
+    fflush(stderr);                                                            \
+  } while (0)
+#define _LIBUNWIND_LOG(msg, ...) do {                                          \
+    fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__);                      \
+    fflush(stderr);                                                            \
+  } while (0)
 #endif
 
 #if defined(NDEBUG)
lib/libunwind/src/DwarfInstructions.hpp
@@ -224,7 +224,8 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
         p &= ~0xfULL;
         // CFA is the bottom of the current stack frame.
         for (; p < cfa; p += 16) {
-          __asm__ __volatile__(".arch_extension memtag\n"
+          __asm__ __volatile__(".arch armv8.5-a\n"
+                               ".arch_extension memtag\n"
                                "stg %[Ptr], [%[Ptr]]\n"
                                :
                                : [Ptr] "r"(p)
lib/libunwind/src/libunwind.cpp
@@ -349,7 +349,87 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
 #endif // !defined(__USING_SJLJ_EXCEPTIONS__)
 
+#ifdef __APPLE__
 
+namespace libunwind {
+
+static constexpr size_t MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS = 8;
+
+static RWMutex findDynamicUnwindSectionsLock;
+static size_t numDynamicUnwindSectionsFinders = 0;
+static unw_find_dynamic_unwind_sections
+    dynamicUnwindSectionsFinders[MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS] = {0};
+
+bool findDynamicUnwindSections(void *addr, unw_dynamic_unwind_sections *info) {
+  bool found = false;
+  findDynamicUnwindSectionsLock.lock_shared();
+  for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) {
+    if (dynamicUnwindSectionsFinders[i]((unw_word_t)addr, info)) {
+      found = true;
+      break;
+    }
+  }
+  findDynamicUnwindSectionsLock.unlock_shared();
+  return found;
+}
+
+} // namespace libunwind
+
+int __unw_add_find_dynamic_unwind_sections(
+    unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) {
+  findDynamicUnwindSectionsLock.lock();
+
+  // Check that we have enough space...
+  if (numDynamicUnwindSectionsFinders == MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS) {
+    findDynamicUnwindSectionsLock.unlock();
+    return UNW_ENOMEM;
+  }
+
+  // Check for value already present...
+  for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) {
+    if (dynamicUnwindSectionsFinders[i] == find_dynamic_unwind_sections) {
+      findDynamicUnwindSectionsLock.unlock();
+      return UNW_EINVAL;
+    }
+  }
+
+  // Success -- add callback entry.
+  dynamicUnwindSectionsFinders[numDynamicUnwindSectionsFinders++] =
+    find_dynamic_unwind_sections;
+  findDynamicUnwindSectionsLock.unlock();
+
+  return UNW_ESUCCESS;
+}
+
+int __unw_remove_find_dynamic_unwind_sections(
+    unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) {
+  findDynamicUnwindSectionsLock.lock();
+
+  // Find index to remove.
+  size_t finderIdx = numDynamicUnwindSectionsFinders;
+  for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) {
+    if (dynamicUnwindSectionsFinders[i] == find_dynamic_unwind_sections) {
+      finderIdx = i;
+      break;
+    }
+  }
+
+  // If no such registration is present then error out.
+  if (finderIdx == numDynamicUnwindSectionsFinders) {
+    findDynamicUnwindSectionsLock.unlock();
+    return UNW_EINVAL;
+  }
+
+  // Remove entry.
+  for (size_t i = finderIdx; i != numDynamicUnwindSectionsFinders - 1; ++i)
+    dynamicUnwindSectionsFinders[i] = dynamicUnwindSectionsFinders[i + 1];
+  dynamicUnwindSectionsFinders[--numDynamicUnwindSectionsFinders] = nullptr;
+
+  findDynamicUnwindSectionsLock.unlock();
+  return UNW_ESUCCESS;
+}
+
+#endif // __APPLE__
 
 // Add logging hooks in Debug builds only
 #ifndef NDEBUG
lib/libunwind/src/libunwind_ext.h
@@ -58,6 +58,71 @@ extern void __unw_remove_dynamic_fde(unw_word_t fde);
 extern void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start);
 extern void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start);
 
+#ifdef __APPLE__
+
+// Holds a description of the object-format-header (if any) and unwind info
+// sections for a given address:
+//
+// * dso_base should point to a header for the JIT'd object containing the
+//   given address. The header's type should match the format type that
+//   libunwind was compiled for (so a mach_header or mach_header_64 on Darwin).
+//   A value of zero indicates that no such header exists.
+//
+// * dwarf_section and dwarf_section_length hold the address range of a DWARF
+//   eh-frame section associated with the given address, if any. If the
+//   dwarf_section_length field is zero it indicates that no such section
+//   exists (and in this case dwarf_section should also be set to zero).
+//
+// * compact_unwind_section and compact_unwind_section_length hold the address
+//   range of a compact-unwind info section associated with the given address,
+//   if any. If the compact_unwind_section_length field is zero it indicates
+//   that no such section exists (and in this case compact_unwind_section
+//   should also be set to zero).
+//
+// See the unw_find_dynamic_unwind_sections type below for more details.
+struct unw_dynamic_unwind_sections {
+  unw_word_t dso_base;
+  unw_word_t dwarf_section;
+  size_t     dwarf_section_length;
+  unw_word_t compact_unwind_section;
+  size_t     compact_unwind_section_length;
+};
+
+// Typedef for unwind-info lookup callbacks. Functions of this type can be
+// registered and deregistered using __unw_add_find_dynamic_unwind_sections
+// and __unw_remove_find_dynamic_unwind_sections respectively.
+//
+// An unwind-info lookup callback should return 1 to indicate that it found
+// unwind-info for the given address, or 0 to indicate that it did not find
+// unwind-info for the given address. If found, the callback should populate
+// some or all of the fields of the info argument (which is guaranteed to be
+// non-null with all fields zero-initialized):
+typedef int (*unw_find_dynamic_unwind_sections)(
+    unw_word_t addr, struct unw_dynamic_unwind_sections *info);
+
+// Register a dynamic unwind-info lookup callback. If libunwind does not find
+// unwind info for a given frame in the executable program or normal dynamic
+// shared objects then it will call all registered dynamic lookup functions
+// in registration order until either one of them returns true, or the end
+// of the list is reached. This lookup will happen before libunwind searches
+// any eh-frames registered via __register_frame or
+// __unw_add_dynamic_eh_frame_section.
+//
+// Returns UNW_ESUCCESS for successful registrations. If the given callback
+// has already been registered then UNW_EINVAL will be returned. If all
+// available callback entries are in use then UNW_ENOMEM will be returned.
+extern int __unw_add_find_dynamic_unwind_sections(
+    unw_find_dynamic_unwind_sections find_dynamic_unwind_sections);
+
+// Deregister a dynacim unwind-info lookup callback.
+//
+// Returns UNW_ESUCCESS for successful deregistrations. If the given callback
+// has already been registered then UNW_EINVAL will be returned.
+extern int __unw_remove_find_dynamic_unwind_sections(
+    unw_find_dynamic_unwind_sections find_dynamic_unwind_sections);
+
+#endif
+
 #if defined(_LIBUNWIND_ARM_EHABI)
 extern const uint32_t* decode_eht_entry(const uint32_t*, size_t*, size_t*);
 extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context,
lib/libunwind/src/Unwind-EHABI.cpp
@@ -709,7 +709,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
     // Update info about this frame.
     unw_proc_info_t frameInfo;
     if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
-      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_step "
+      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_get_proc_info "
                                  "failed => _URC_END_OF_STACK",
                                  (void *)exception_object);
       return _URC_FATAL_PHASE2_ERROR;
@@ -885,8 +885,11 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
   return result;
 }
 
-static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation,
-                                  void* valuep) {
+// Only used in _LIBUNWIND_TRACE_API, which is a no-op when assertions are
+// disabled.
+[[gnu::unused]] static uint64_t
+ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation,
+                  const void *valuep) {
   uint64_t value = 0;
   switch (representation) {
     case _UVRSD_UINT32:
lib/libunwind/src/Unwind-seh.cpp
@@ -212,11 +212,20 @@ __libunwind_seh_personality(int version, _Unwind_Action state,
   ms_exc.ExceptionInformation[2] = state;
   DISPATCHER_CONTEXT *disp_ctx =
       __unw_seh_get_disp_ctx((unw_cursor_t *)context);
+  _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() calling "
+                             "LanguageHandler %p(%p, %p, %p, %p)",
+                             (void *)disp_ctx->LanguageHandler, (void *)&ms_exc,
+                             (void *)disp_ctx->EstablisherFrame,
+                             (void *)disp_ctx->ContextRecord, (void *)disp_ctx);
   EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc,
                                                            (PVOID)disp_ctx->EstablisherFrame,
                                                            disp_ctx->ContextRecord,
                                                            disp_ctx);
+  _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() LanguageHandler "
+                             "returned %d",
+                             (int)ms_act);
   switch (ms_act) {
+  case ExceptionContinueExecution: return _URC_END_OF_STACK;
   case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND;
   case 4 /*ExceptionExecuteHandler*/:
     return phase2 ? _URC_INSTALL_CONTEXT : _URC_HANDLER_FOUND;
@@ -238,7 +247,7 @@ unwind_phase2_forced(unw_context_t *uc,
     // 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 "
+      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_get_proc_info "
                                  "failed => _URC_END_OF_STACK",
                                  (void *)exception_object);
       return _URC_FATAL_PHASE2_ERROR;
@@ -304,6 +313,12 @@ unwind_phase2_forced(unw_context_t *uc,
         // We may get control back if landing pad calls _Unwind_Resume().
         __unw_resume(&cursor2);
         break;
+      case _URC_END_OF_STACK:
+        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+                                   "personality returned "
+                                   "_URC_END_OF_STACK",
+                                   (void *)exception_object);
+        break;
       default:
         // Personality routine returned an unknown result code.
         _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
@@ -312,6 +327,8 @@ unwind_phase2_forced(unw_context_t *uc,
                                    (void *)exception_object, personalityResult);
         return _URC_FATAL_PHASE2_ERROR;
       }
+      if (personalityResult == _URC_END_OF_STACK)
+        break;
     }
   }
 
lib/libunwind/src/Unwind_AppleExtras.cpp
@@ -1,113 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//
-//===----------------------------------------------------------------------===//
-
-#include "config.h"
-
-
-// static linker symbols to prevent wrong two level namespace for _Unwind symbols
-#if defined(__arm__)
-   #define NOT_HERE_BEFORE_5_0(sym)     \
-       extern const char sym##_tmp30 __asm("$ld$hide$os3.0$_" #sym ); \
-       __attribute__((visibility("default"))) const char sym##_tmp30 = 0; \
-       extern const char sym##_tmp31 __asm("$ld$hide$os3.1$_" #sym ); \
-          __attribute__((visibility("default"))) const char sym##_tmp31 = 0; \
-       extern const char sym##_tmp32 __asm("$ld$hide$os3.2$_" #sym );\
-           __attribute__((visibility("default"))) const char sym##_tmp32 = 0; \
-       extern const char sym##_tmp40 __asm("$ld$hide$os4.0$_" #sym ); \
-          __attribute__((visibility("default"))) const char sym##_tmp40 = 0; \
-       extern const char sym##_tmp41 __asm("$ld$hide$os4.1$_" #sym ); \
-          __attribute__((visibility("default"))) const char sym##_tmp41 = 0; \
-       extern const char sym##_tmp42 __asm("$ld$hide$os4.2$_" #sym ); \
-          __attribute__((visibility("default"))) const char sym##_tmp42 = 0; \
-       extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); \
-          __attribute__((visibility("default"))) const char sym##_tmp43 = 0;
-#elif defined(__aarch64__)
-  #define NOT_HERE_BEFORE_10_6(sym)
-  #define NEVER_HERE(sym)
-#else
-  #define NOT_HERE_BEFORE_10_6(sym) \
-    extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
-          __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
-    extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
-          __attribute__((visibility("default"))) const char sym##_tmp5 = 0;
-  #define NEVER_HERE(sym) \
-    extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
-          __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
-    extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
-          __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \
-    extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); \
-          __attribute__((visibility("default"))) const char sym##_tmp6 = 0;
-#endif
-
-
-#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
-
-//
-// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in
-// earlier versions
-//
-NOT_HERE_BEFORE_10_6(_Unwind_DeleteException)
-NOT_HERE_BEFORE_10_6(_Unwind_Find_FDE)
-NOT_HERE_BEFORE_10_6(_Unwind_ForcedUnwind)
-NOT_HERE_BEFORE_10_6(_Unwind_GetGR)
-NOT_HERE_BEFORE_10_6(_Unwind_GetIP)
-NOT_HERE_BEFORE_10_6(_Unwind_GetLanguageSpecificData)
-NOT_HERE_BEFORE_10_6(_Unwind_GetRegionStart)
-NOT_HERE_BEFORE_10_6(_Unwind_RaiseException)
-NOT_HERE_BEFORE_10_6(_Unwind_Resume)
-NOT_HERE_BEFORE_10_6(_Unwind_SetGR)
-NOT_HERE_BEFORE_10_6(_Unwind_SetIP)
-NOT_HERE_BEFORE_10_6(_Unwind_Backtrace)
-NOT_HERE_BEFORE_10_6(_Unwind_FindEnclosingFunction)
-NOT_HERE_BEFORE_10_6(_Unwind_GetCFA)
-NOT_HERE_BEFORE_10_6(_Unwind_GetDataRelBase)
-NOT_HERE_BEFORE_10_6(_Unwind_GetTextRelBase)
-NOT_HERE_BEFORE_10_6(_Unwind_Resume_or_Rethrow)
-NOT_HERE_BEFORE_10_6(_Unwind_GetIPInfo)
-NOT_HERE_BEFORE_10_6(__register_frame)
-NOT_HERE_BEFORE_10_6(__deregister_frame)
-
-//
-// symbols in libSystem.dylib for compatibility, but we don't want any new code
-// using them
-//
-NEVER_HERE(__register_frame_info_bases)
-NEVER_HERE(__register_frame_info)
-NEVER_HERE(__register_frame_info_table_bases)
-NEVER_HERE(__register_frame_info_table)
-NEVER_HERE(__register_frame_table)
-NEVER_HERE(__deregister_frame_info)
-NEVER_HERE(__deregister_frame_info_bases)
-
-#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
-
-
-
-
-#if defined(_LIBUNWIND_BUILD_SJLJ_APIS)
-//
-// symbols in libSystem.dylib in iOS 5.0 and later, but are in libgcc_s.dylib in
-// earlier versions
-//
-NOT_HERE_BEFORE_5_0(_Unwind_GetLanguageSpecificData)
-NOT_HERE_BEFORE_5_0(_Unwind_GetRegionStart)
-NOT_HERE_BEFORE_5_0(_Unwind_GetIP)
-NOT_HERE_BEFORE_5_0(_Unwind_SetGR)
-NOT_HERE_BEFORE_5_0(_Unwind_SetIP)
-NOT_HERE_BEFORE_5_0(_Unwind_DeleteException)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Register)
-NOT_HERE_BEFORE_5_0(_Unwind_GetGR)
-NOT_HERE_BEFORE_5_0(_Unwind_GetIPInfo)
-NOT_HERE_BEFORE_5_0(_Unwind_GetCFA)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_RaiseException)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister)
-
-#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS)
lib/libunwind/src/UnwindCursor.hpp
@@ -31,7 +31,8 @@
 #endif
 
 #if defined(_LIBUNWIND_TARGET_LINUX) &&                                        \
-    (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_S390X))
+    (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \
+     defined(_LIBUNWIND_TARGET_S390X))
 #include <sys/syscall.h>
 #include <sys/uio.h>
 #include <unistd.h>
@@ -506,7 +507,14 @@ public:
 #endif
 
   DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; }
-  void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; }
+  void setDispatcherContext(DISPATCHER_CONTEXT *disp) {
+    _dispContext = *disp;
+    _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;
+  }
 
   // libunwind does not and should not depend on C++ library which means that we
   // need our own definition of inline placement new.
@@ -568,10 +576,12 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
                 "UnwindCursor<> requires more alignment than unw_cursor_t");
   memset(&_info, 0, sizeof(_info));
   memset(&_histTable, 0, sizeof(_histTable));
+  memset(&_dispContext, 0, sizeof(_dispContext));
   _dispContext.ContextRecord = &_msContext;
   _dispContext.HistoryTable = &_histTable;
   // Initialize MS context from ours.
   R r(context);
+  RtlCaptureContext(&_msContext);
   _msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT;
 #if defined(_LIBUNWIND_TARGET_X86_64)
   _msContext.Rax = r.getRegister(UNW_X86_64_RAX);
@@ -669,6 +679,7 @@ UnwindCursor<A, R>::UnwindCursor(CONTEXT *context, A &as)
                 "UnwindCursor<> does not fit in unw_cursor_t");
   memset(&_info, 0, sizeof(_info));
   memset(&_histTable, 0, sizeof(_histTable));
+  memset(&_dispContext, 0, sizeof(_dispContext));
   _dispContext.ContextRecord = &_msContext;
   _dispContext.HistoryTable = &_histTable;
   _msContext = *context;
@@ -679,7 +690,7 @@ 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;
+  if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_RIP) return true;
 #elif defined(_LIBUNWIND_TARGET_ARM)
   if ((regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) ||
       regNum == UNW_ARM_RA_AUTH_CODE)
@@ -694,6 +705,7 @@ template <typename A, typename R>
 unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
   switch (regNum) {
 #if defined(_LIBUNWIND_TARGET_X86_64)
+  case UNW_X86_64_RIP:
   case UNW_REG_IP: return _msContext.Rip;
   case UNW_X86_64_RAX: return _msContext.Rax;
   case UNW_X86_64_RDX: return _msContext.Rdx;
@@ -744,6 +756,7 @@ 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_X86_64_RIP:
   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;
@@ -981,6 +994,10 @@ private:
   bool setInfoForSigReturn(Registers_arm64 &);
   int stepThroughSigReturn(Registers_arm64 &);
 #endif
+#if defined(_LIBUNWIND_TARGET_RISCV)
+  bool setInfoForSigReturn(Registers_riscv &);
+  int stepThroughSigReturn(Registers_riscv &);
+#endif
 #if defined(_LIBUNWIND_TARGET_S390X)
   bool setInfoForSigReturn(Registers_s390x &);
   int stepThroughSigReturn(Registers_s390x &);
@@ -1978,6 +1995,9 @@ bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
       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);
+      _dispContext.HandlerData = reinterpret_cast<void *>(_info.lsda);
+      _dispContext.LanguageHandler =
+          reinterpret_cast<EXCEPTION_ROUTINE *>(base + *handler);
       if (*handler) {
         _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
       } else
@@ -2705,6 +2725,60 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
 #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
        // defined(_LIBUNWIND_TARGET_AARCH64)
 
+#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&                               \
+    defined(_LIBUNWIND_TARGET_RISCV)
+template <typename A, typename R>
+bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_riscv &) {
+  const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP));
+  uint32_t instructions[2];
+  struct iovec local_iov = {&instructions, sizeof instructions};
+  struct iovec remote_iov = {reinterpret_cast<void *>(pc), sizeof instructions};
+  long bytesRead =
+      syscall(SYS_process_vm_readv, getpid(), &local_iov, 1, &remote_iov, 1, 0);
+  // Look for the two instructions used in the sigreturn trampoline
+  // __vdso_rt_sigreturn:
+  //
+  // 0x08b00893 li a7,0x8b
+  // 0x00000073 ecall
+  if (bytesRead != sizeof instructions || instructions[0] != 0x08b00893 ||
+      instructions[1] != 0x00000073)
+    return false;
+
+  _info = {};
+  _info.start_ip = pc;
+  _info.end_ip = pc + 4;
+  _isSigReturn = true;
+  return true;
+}
+
+template <typename A, typename R>
+int UnwindCursor<A, R>::stepThroughSigReturn(Registers_riscv &) {
+  // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
+  //  - 128-byte siginfo struct
+  //  - ucontext_t struct:
+  //     - 8-byte long (__uc_flags)
+  //     - 8-byte pointer (*uc_link)
+  //     - 24-byte uc_stack
+  //     - 8-byte uc_sigmask
+  //     - 120-byte of padding to allow sigset_t to be expanded in the future
+  //     - 8 bytes of padding because sigcontext has 16-byte alignment
+  //     - struct sigcontext uc_mcontext
+  // [1]
+  // https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/signal.c
+  const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128;
+
+  const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;
+  _registers.setIP(_addressSpace.get64(sigctx));
+  for (int i = UNW_RISCV_X1; i <= UNW_RISCV_X31; ++i) {
+    uint64_t value = _addressSpace.get64(sigctx + static_cast<pint_t>(i * 8));
+    _registers.setRegister(i, value);
+  }
+  _isSignalFrame = true;
+  return UNW_STEP_SUCCESS;
+}
+#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
+       // defined(_LIBUNWIND_TARGET_RISCV)
+
 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&                               \
     defined(_LIBUNWIND_TARGET_S390X)
 template <typename A, typename R>
lib/libunwind/src/UnwindLevel1-gcc-ext.c
@@ -167,7 +167,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
     }
 
     // Update the pr_cache in the mock exception object.
-    const uint32_t* unwindInfo = (uint32_t *) frameInfo.unwind_info;
+    uint32_t *unwindInfo = (uint32_t *)frameInfo.unwind_info;
     ex.pr_cache.fnstart = frameInfo.start_ip;
     ex.pr_cache.ehtp = (_Unwind_EHT_Header *) unwindInfo;
     ex.pr_cache.additional= frameInfo.flags;
lib/libunwind/src/UnwindLevel1.c
@@ -321,7 +321,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
     unw_proc_info_t frameInfo;
     if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
       _LIBUNWIND_TRACE_UNWINDING(
-          "unwind_phase2_forced(ex_obj=%p): __unw_step_stage2 "
+          "unwind_phase2_forced(ex_obj=%p): __unw_get_proc_info "
           "failed => _URC_END_OF_STACK",
           (void *)exception_object);
       return _URC_FATAL_PHASE2_ERROR;
lib/libunwind/src/UnwindRegistersRestore.S
@@ -194,9 +194,20 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
   addi  4, 3, PPC64_OFFS_FP
 
 // load VS register
+#ifdef __LITTLE_ENDIAN__
+// For little-endian targets, we need a swap since lxvd2x will load the register
+// in the incorrect doubleword order.
+// FIXME: when supporting targets older than Power9 on LE is no longer required,
+//        this can be changed to simply `lxv n, (16 * n)(4)`.
 #define PPC64_LVS(n)         \
   lxvd2x  n, 0, 4           ;\
+  xxswapd n, n              ;\
   addi    4, 4, 16
+#else
+#define PPC64_LVS(n)         \
+  lxvd2x  n, 0, 4           ;\
+  addi    4, 4, 16
+#endif
 
   // restore the first 32 VS regs (and also all floating point regs)
   PPC64_LVS(0)
@@ -232,9 +243,16 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
   PPC64_LVS(30)
   PPC64_LVS(31)
 
+#ifdef __LITTLE_ENDIAN__
+#define PPC64_CLVS_RESTORE(n)                    \
+  addi   4, 3, PPC64_OFFS_FP + n * 16           ;\
+  lxvd2x n, 0, 4                                ;\
+  xxswapd n, n
+#else
 #define PPC64_CLVS_RESTORE(n)                    \
   addi   4, 3, PPC64_OFFS_FP + n * 16           ;\
   lxvd2x n, 0, 4
+#endif
 
 #if !defined(_AIX)
   // use VRSAVE to conditionally restore the remaining VS regs, that are
@@ -1203,8 +1221,8 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv)
     ld.d $r\i, $a0, (8 * \i)
   .endr
 
-  ld.d    $r4,  $a0, (8 * 4)   // restore $a0 last
-  ld.d    $r1,  $a0, (8 * 32)  // load new pc into $ra
+  ld.d    $ra,  $a0, (8 * 32)  // load new pc into $ra
+  ld.d    $a0,  $a0, (8 * 4)   // restore $a0 last
 
   jr      $ra
 
lib/libunwind/src/UnwindRegistersSave.S
@@ -351,9 +351,20 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   addi  4, 3, PPC64_OFFS_FP
 
 // store VS register
+#ifdef __LITTLE_ENDIAN__
+// For little-endian targets, we need a swap since stxvd2x will store the
+// register in the incorrect doubleword order.
+// FIXME: when supporting targets older than Power9 on LE is no longer required
+//        this can be changed to simply `stxv n, 16 * n(4)`.
 #define PPC64_STVS(n)      \
+  xxswapd n, n            ;\
   stxvd2x n, 0, 4         ;\
   addi    4, 4, 16
+#else
+#define PPC64_STVS(n)      \
+  stxvd2x n, 0, 4         ;\
+  addi    4, 4, 16
+#endif
 
   PPC64_STVS(0)
   PPC64_STVS(1)