Commit 6295415da7

Andrew Kelley <andrew@ziglang.org>
2024-04-26 23:40:08
libunwind: update to LLVM 18
release/18.x branch, commit 78b99c73ee4b96fe9ce0e294d4632326afb2db42
1 parent a6856ef
lib/libunwind/include/mach-o/compact_unwind_encoding.h
@@ -108,7 +108,7 @@ enum {
 //    are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries.
 //    Each entry contains which register to restore.
 // UNWIND_X86_MODE_STACK_IMMD:
-//    A "frameless" (EBP not used as frame pointer) function with a small 
+//    A "frameless" (EBP not used as frame pointer) function with a small
 //    constant stack size.  To return, a constant (encoded in the compact
 //    unwind encoding) is added to the ESP. Then the return is done by
 //    popping the stack into the pc.
@@ -119,16 +119,16 @@ enum {
 //    UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION contains which registers were
 //    saved and their order.
 // UNWIND_X86_MODE_STACK_IND:
-//    A "frameless" (EBP not used as frame pointer) function large constant 
+//    A "frameless" (EBP not used as frame pointer) function large constant
 //    stack size.  This case is like the previous, except the stack size is too
-//    large to encode in the compact unwind encoding.  Instead it requires that 
-//    the function contains "subl $nnnnnnnn,ESP" in its prolog.  The compact 
+//    large to encode in the compact unwind encoding.  Instead it requires that
+//    the function contains "subl $nnnnnnnn,ESP" in its prolog.  The compact
 //    encoding contains the offset to the nnnnnnnn value in the function in
-//    UNWIND_X86_FRAMELESS_STACK_SIZE.  
+//    UNWIND_X86_FRAMELESS_STACK_SIZE.
 // UNWIND_X86_MODE_DWARF:
 //    No compact unwind encoding is available.  Instead the low 24-bits of the
 //    compact encoding is the offset of the DWARF FDE in the __eh_frame section.
-//    This mode is never used in object files.  It is only generated by the 
+//    This mode is never used in object files.  It is only generated by the
 //    linker in final linked images which have only DWARF unwind info for a
 //    function.
 //
@@ -233,36 +233,36 @@ enum {
 // For x86_64 there are four modes for the compact unwind encoding:
 // UNWIND_X86_64_MODE_RBP_FRAME:
 //    RBP based frame where RBP is push on stack immediately after return address,
-//    then RSP is moved to RBP. Thus, to unwind RSP is restored with the current 
-//    EPB value, then RBP is restored by popping off the stack, and the return 
+//    then RSP is moved to RBP. Thus, to unwind RSP is restored with the current
+//    EPB value, then RBP is restored by popping off the stack, and the return
 //    is done by popping the stack once more into the pc.
 //    All non-volatile registers that need to be restored must have been saved
-//    in a small range in the stack that starts RBP-8 to RBP-2040.  The offset/8 
+//    in a small range in the stack that starts RBP-8 to RBP-2040.  The offset/8
 //    is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits.  The registers saved
 //    are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries.
-//    Each entry contains which register to restore.  
+//    Each entry contains which register to restore.
 // UNWIND_X86_64_MODE_STACK_IMMD:
-//    A "frameless" (RBP not used as frame pointer) function with a small 
-//    constant stack size.  To return, a constant (encoded in the compact 
-//    unwind encoding) is added to the RSP. Then the return is done by 
+//    A "frameless" (RBP not used as frame pointer) function with a small
+//    constant stack size.  To return, a constant (encoded in the compact
+//    unwind encoding) is added to the RSP. Then the return is done by
 //    popping the stack into the pc.
 //    All non-volatile registers that need to be restored must have been saved
 //    on the stack immediately after the return address.  The stack_size/8 is
 //    encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048).
 //    The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT.
 //    UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION contains which registers were
-//    saved and their order.  
+//    saved and their order.
 // UNWIND_X86_64_MODE_STACK_IND:
-//    A "frameless" (RBP not used as frame pointer) function large constant 
+//    A "frameless" (RBP not used as frame pointer) function large constant
 //    stack size.  This case is like the previous, except the stack size is too
-//    large to encode in the compact unwind encoding.  Instead it requires that 
-//    the function contains "subq $nnnnnnnn,RSP" in its prolog.  The compact 
+//    large to encode in the compact unwind encoding.  Instead it requires that
+//    the function contains "subq $nnnnnnnn,RSP" in its prolog.  The compact
 //    encoding contains the offset to the nnnnnnnn value in the function in
-//    UNWIND_X86_64_FRAMELESS_STACK_SIZE.  
+//    UNWIND_X86_64_FRAMELESS_STACK_SIZE.
 // UNWIND_X86_64_MODE_DWARF:
 //    No compact unwind encoding is available.  Instead the low 24-bits of the
 //    compact encoding is the offset of the DWARF FDE in the __eh_frame section.
-//    This mode is never used in object files.  It is only generated by the 
+//    This mode is never used in object files.  It is only generated by the
 //    linker in final linked images which have only DWARF unwind info for a
 //    function.
 //
@@ -307,20 +307,20 @@ enum {
 //    This is a standard arm64 prolog where FP/LR are immediately pushed on the
 //    stack, then SP is copied to FP. If there are any non-volatile registers
 //    saved, then are copied into the stack frame in pairs in a contiguous
-//    range right below the saved FP/LR pair.  Any subset of the five X pairs 
+//    range right below the saved FP/LR pair.  Any subset of the five X pairs
 //    and four D pairs can be saved, but the memory layout must be in register
-//    number order.  
+//    number order.
 // UNWIND_ARM64_MODE_FRAMELESS:
-//    A "frameless" leaf function, where FP/LR are not saved. The return address 
+//    A "frameless" leaf function, where FP/LR are not saved. The return address
 //    remains in LR throughout the function. If any non-volatile registers
 //    are saved, they must be pushed onto the stack before any stack space is
 //    allocated for local variables.  The stack sized (including any saved
-//    non-volatile registers) divided by 16 is encoded in the bits 
+//    non-volatile registers) divided by 16 is encoded in the bits
 //    UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK.
 // UNWIND_ARM64_MODE_DWARF:
 //    No compact unwind encoding is available.  Instead the low 24-bits of the
 //    compact encoding is the offset of the DWARF FDE in the __eh_frame section.
-//    This mode is never used in object files.  It is only generated by the 
+//    This mode is never used in object files.  It is only generated by the
 //    linker in final linked images which have only DWARF unwind info for a
 //    function.
 //
@@ -337,19 +337,19 @@ enum {
 
 //
 // A compiler can generated compact unwind information for a function by adding
-// a "row" to the __LD,__compact_unwind section.  This section has the 
-// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers. 
-// It is removed by the new linker, so never ends up in final executables. 
-// This section is a table, initially with one row per function (that needs 
+// a "row" to the __LD,__compact_unwind section.  This section has the
+// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers.
+// It is removed by the new linker, so never ends up in final executables.
+// This section is a table, initially with one row per function (that needs
 // unwind info).  The table columns and some conceptual entries are:
 //
 //     range-start               pointer to start of function/range
-//     range-length              
-//     compact-unwind-encoding   32-bit encoding  
+//     range-length
+//     compact-unwind-encoding   32-bit encoding
 //     personality-function      or zero if no personality function
 //     lsda                      or zero if no LSDA data
 //
-// The length and encoding fields are 32-bits.  The other are all pointer sized. 
+// The length and encoding fields are 32-bits.  The other are all pointer sized.
 //
 // In x86_64 assembly, these entry would look like:
 //
@@ -372,23 +372,23 @@ enum {
 //     .quad    except_tab1
 //
 //
-// Notes: There is no need for any labels in the the __compact_unwind section.  
-//        The use of the .set directive is to force the evaluation of the 
+// Notes: There is no need for any labels in the __compact_unwind section.
+//        The use of the .set directive is to force the evaluation of the
 //        range-length at assembly time, instead of generating relocations.
 //
-// To support future compiler optimizations where which non-volatile registers 
+// To support future compiler optimizations where which non-volatile registers
 // are saved changes within a function (e.g. delay saving non-volatiles until
 // necessary), there can by multiple lines in the __compact_unwind table for one
-// function, each with a different (non-overlapping) range and each with 
-// different compact unwind encodings that correspond to the non-volatiles 
+// function, each with a different (non-overlapping) range and each with
+// different compact unwind encodings that correspond to the non-volatiles
 // saved at that range of the function.
 //
 // If a particular function is so wacky that there is no compact unwind way
-// to encode it, then the compiler can emit traditional DWARF unwind info.  
+// to encode it, then the compiler can emit traditional DWARF unwind info.
 // The runtime will use which ever is available.
 //
-// Runtime support for compact unwind encodings are only available on 10.6 
-// and later.  So, the compiler should not generate it when targeting pre-10.6. 
+// Runtime support for compact unwind encodings are only available on 10.6
+// and later.  So, the compiler should not generate it when targeting pre-10.6.
 
 
 
@@ -402,7 +402,7 @@ enum {
 //
 // The __TEXT,__unwind_info section is laid out for an efficient two level lookup.
 // The header of the section contains a coarse index that maps function address
-// to the page (4096 byte block) containing the unwind info for that function.  
+// to the page (4096 byte block) containing the unwind info for that function.
 //
 
 #define UNWIND_SECTION_VERSION 1
lib/libunwind/include/__libunwind_config.h
@@ -36,6 +36,9 @@
 # if defined(__linux__)
 #  define _LIBUNWIND_TARGET_LINUX 1
 # endif
+# if defined(__HAIKU__)
+#  define _LIBUNWIND_TARGET_HAIKU 1
+# endif
 # if defined(__i386__)
 #  define _LIBUNWIND_TARGET_I386
 #  define _LIBUNWIND_CONTEXT_SIZE 8
@@ -196,7 +199,7 @@
 # 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 204
 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
lib/libunwind/include/libunwind.h
@@ -876,6 +876,9 @@ enum {
   UNW_MIPS_F29 = 61,
   UNW_MIPS_F30 = 62,
   UNW_MIPS_F31 = 63,
+  // HI,LO have been dropped since r6, we keep them here.
+  // So, when we add DSP/MSA etc, we can use the same register indexes
+  // for r6 and pre-r6.
   UNW_MIPS_HI = 64,
   UNW_MIPS_LO = 65,
 };
lib/libunwind/src/AddressSpace.hpp
@@ -414,8 +414,8 @@ static bool checkForUnwindInfoSegment(const Elf_Phdr *phdr, size_t image_base,
     cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
     cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
     if (EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
-            *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
-            hdrInfo)) {
+            *cbdata->addressSpace, eh_frame_hdr_start,
+            eh_frame_hdr_start + phdr->p_memsz, hdrInfo)) {
       // .eh_frame_hdr records the start of .eh_frame, but not its size.
       // Rely on a zero terminator to find the end of the section.
       cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
@@ -638,7 +638,8 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
     info.dwarf_index_section_length = SIZE_MAX;
     EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
     if (!EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
-            *this, info.dwarf_index_section, info.dwarf_index_section_length,
+            *this, info.dwarf_index_section,
+            info.dwarf_index_section + info.dwarf_index_section_length,
             hdrInfo)) {
       return false;
     }
lib/libunwind/src/config.h
@@ -46,6 +46,12 @@
 #elif defined(_AIX)
 // The traceback table at the end of each function is used for unwinding.
 #define _LIBUNWIND_SUPPORT_TBTAB_UNWIND 1
+#elif defined(__HAIKU__)
+  #if defined(_LIBUNWIND_USE_HAIKU_BSD_LIB)
+    #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1
+  #endif
+  #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
+  #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1
 #else
   // Assume an ELF system with a dl_iterate_phdr function.
   #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1
@@ -83,7 +89,7 @@
   __asm__(".globl " SYMBOL_NAME(aliasname));                                   \
   __asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name));                     \
   _LIBUNWIND_ALIAS_VISIBILITY(SYMBOL_NAME(aliasname))
-#elif defined(__ELF__) || defined(_AIX)
+#elif defined(__ELF__) || defined(_AIX) || defined(__wasm__)
 #define _LIBUNWIND_WEAK_ALIAS(name, aliasname)                                 \
   extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname                        \
       __attribute__((weak, alias(#name)));
@@ -108,10 +114,6 @@
 #define _LIBUNWIND_BUILD_SJLJ_APIS
 #endif
 
-#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__)
-#define _LIBUNWIND_SUPPORT_FRAME_APIS
-#endif
-
 #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) ||        \
     (!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) ||       \
     defined(__mips__) || defined(__riscv) || defined(__hexagon__) ||           \
@@ -125,7 +127,7 @@
 #if defined(_LIBUNWIND_REMEMBER_STACK_ALLOC) || defined(__APPLE__) ||          \
     defined(__linux__) || defined(__ANDROID__) || defined(__MINGW32__) ||      \
     defined(_LIBUNWIND_IS_BAREMETAL)
-#define _LIBUNWIND_REMEMBER_ALLOC(_size) alloca(_size)
+#define _LIBUNWIND_REMEMBER_ALLOC(_size) __builtin_alloca(_size)
 #define _LIBUNWIND_REMEMBER_FREE(_ptr)                                         \
   do {                                                                         \
   } while (0)
lib/libunwind/src/DwarfInstructions.hpp
@@ -68,7 +68,7 @@ private:
       return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
              prolog.cfaRegisterOffset);
     if (prolog.cfaExpression != 0)
-      return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, 
+      return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
                                 registers, 0);
     assert(0 && "getCFA(): unknown location");
     __builtin_unreachable();
lib/libunwind/src/EHHeaderParser.hpp
@@ -55,6 +55,19 @@ template <typename A>
 bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
                                     pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {
   pint_t p = ehHdrStart;
+
+  // Ensure that we don't read data beyond the end of .eh_frame_hdr
+  if (ehHdrEnd - ehHdrStart < 4) {
+    // Don't print a message for an empty .eh_frame_hdr (this can happen if
+    // the linker script defines symbols for it even in the empty case).
+    if (ehHdrEnd == ehHdrStart)
+      return false;
+    _LIBUNWIND_LOG("unsupported .eh_frame_hdr at %" PRIx64
+                   ": need at least 4 bytes of data but only got %zd",
+                   static_cast<uint64_t>(ehHdrStart),
+                   static_cast<size_t>(ehHdrEnd - ehHdrStart));
+    return false;
+  }
   uint8_t version = addressSpace.get8(p++);
   if (version != 1) {
     _LIBUNWIND_LOG("unsupported .eh_frame_hdr version: %" PRIu8 " at %" PRIx64,
lib/libunwind/src/FrameHeaderCache.hpp
@@ -31,8 +31,8 @@
 
 class _LIBUNWIND_HIDDEN FrameHeaderCache {
   struct CacheEntry {
-    uintptr_t LowPC() { return Info.dso_base; };
-    uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; };
+    uintptr_t LowPC() { return Info.dso_base; }
+    uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; }
     UnwindInfoSections Info;
     CacheEntry *Next;
   };
@@ -41,7 +41,7 @@ class _LIBUNWIND_HIDDEN FrameHeaderCache {
 
   // Can't depend on the C++ standard library in libunwind, so use an array to
   // allocate the entries, and two linked lists for ordering unused and recently
-  // used entries.  FIXME: Would the the extra memory for a doubly-linked list
+  // used entries.  FIXME: Would the extra memory for a doubly-linked list
   // be better than the runtime cost of traversing a very short singly-linked
   // list on a cache miss? The entries themselves are all small and consecutive,
   // so unlikely to cause page faults when following the pointers. The memory
lib/libunwind/src/libunwind.cpp
@@ -26,7 +26,7 @@
 #include <sanitizer/asan_interface.h>
 #endif
 
-#if !defined(__USING_SJLJ_EXCEPTIONS__)
+#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
 #include "AddressSpace.hpp"
 #include "UnwindCursor.hpp"
 
@@ -324,7 +324,7 @@ void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
   CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
   CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
   auto p = (LocalAddressSpace::pint_t)eh_frame_start;
-  while (true) {
+  while (LocalAddressSpace::sThisAddressSpace.get32(p)) {
     if (CFI_Parser<LocalAddressSpace>::decodeFDE(
             LocalAddressSpace::sThisAddressSpace, p, &fdeInfo, &cieInfo,
             true) == NULL) {
@@ -347,7 +347,8 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
 }
 
 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
-#endif // !defined(__USING_SJLJ_EXCEPTIONS__)
+#endif // !defined(__USING_SJLJ_EXCEPTIONS__) &&
+       // !defined(__USING_WASM_EXCEPTIONS__)
 
 #ifdef __APPLE__
 
lib/libunwind/src/Registers.hpp
@@ -619,6 +619,8 @@ public:
   void      setIP(uint32_t value) { _registers.__srr0 = value; }
   uint64_t  getCR() const         { return _registers.__cr; }
   void      setCR(uint32_t value) { _registers.__cr = value; }
+  uint64_t  getLR() const         { return _registers.__lr; }
+  void      setLR(uint32_t value) { _registers.__lr = value; }
 
 private:
   struct ppc_thread_state_t {
@@ -1189,6 +1191,8 @@ public:
   void      setIP(uint64_t value) { _registers.__srr0 = value; }
   uint64_t  getCR() const         { return _registers.__cr; }
   void      setCR(uint64_t value) { _registers.__cr = value; }
+  uint64_t  getLR() const         { return _registers.__lr; }
+  void      setLR(uint64_t value) { _registers.__lr = value; }
 
 private:
   struct ppc64_thread_state_t {
@@ -2869,7 +2873,7 @@ inline bool Registers_mips_o32::validRegister(int regNum) const {
     return false;
   if (regNum <= UNW_MIPS_R31)
     return true;
-#if __mips_isa_rev != 6
+#if __mips_isa_rev < 6
   if (regNum == UNW_MIPS_HI)
     return true;
   if (regNum == UNW_MIPS_LO)
@@ -2903,10 +2907,12 @@ inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
     return _registers.__pc;
   case UNW_REG_SP:
     return _registers.__r[29];
+#if __mips_isa_rev < 6
   case UNW_MIPS_HI:
     return _registers.__hi;
   case UNW_MIPS_LO:
     return _registers.__lo;
+#endif
   }
   _LIBUNWIND_ABORT("unsupported mips_o32 register");
 }
@@ -2936,11 +2942,13 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
   case UNW_REG_SP:
     _registers.__r[29] = value;
     return;
+#if __mips_isa_rev < 6
   case UNW_MIPS_HI:
     _registers.__hi = value;
     return;
   case UNW_MIPS_LO:
     _registers.__lo = value;
+#endif
     return;
   }
   _LIBUNWIND_ABORT("unsupported mips_o32 register");
@@ -3120,10 +3128,12 @@ inline const char *Registers_mips_o32::getRegisterName(int regNum) {
     return "$f30";
   case UNW_MIPS_F31:
     return "$f31";
+#if __mips_isa_rev < 6
   case UNW_MIPS_HI:
     return "$hi";
   case UNW_MIPS_LO:
     return "$lo";
+#endif
   default:
     return "unknown register";
   }
@@ -3193,7 +3203,7 @@ inline bool Registers_mips_newabi::validRegister(int regNum) const {
     return false;
   if (regNum <= UNW_MIPS_R31)
     return true;
-#if __mips_isa_rev != 6
+#if __mips_isa_rev < 6
   if (regNum == UNW_MIPS_HI)
     return true;
   if (regNum == UNW_MIPS_LO)
@@ -3212,10 +3222,12 @@ inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
     return _registers.__pc;
   case UNW_REG_SP:
     return _registers.__r[29];
+#if __mips_isa_rev < 6
   case UNW_MIPS_HI:
     return _registers.__hi;
   case UNW_MIPS_LO:
     return _registers.__lo;
+#endif
   }
   _LIBUNWIND_ABORT("unsupported mips_newabi register");
 }
@@ -3233,12 +3245,14 @@ inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
   case UNW_REG_SP:
     _registers.__r[29] = value;
     return;
+#if __mips_isa_rev < 6
   case UNW_MIPS_HI:
     _registers.__hi = value;
     return;
   case UNW_MIPS_LO:
     _registers.__lo = value;
     return;
+#endif
   }
   _LIBUNWIND_ABORT("unsupported mips_newabi register");
 }
@@ -3417,10 +3431,12 @@ inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
     return "$f30";
   case UNW_MIPS_F31:
     return "$f31";
+#if __mips_isa_rev < 6
   case UNW_MIPS_HI:
     return "$hi";
   case UNW_MIPS_LO:
     return "$lo";
+#endif
   default:
     return "unknown register";
   }
lib/libunwind/src/Unwind-sjlj.c
@@ -82,7 +82,8 @@ struct _Unwind_FunctionContext {
 static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL;
 #endif
 
-static struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() {
+static struct _Unwind_FunctionContext *
+__Unwind_SjLj_GetTopOfFunctionStack(void) {
 #if defined(__APPLE__)
   return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key);
 #else
@@ -426,7 +427,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
 /// 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%" PRIuPTR
+  _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIxPTR
                        ")",
                        (void *)context, index, new_value);
   _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
@@ -437,7 +438,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
 /// 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%" PRIu32,
+  _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,
                        (void *)context, ufc->resumeLocation + 1);
   return ufc->resumeLocation + 1;
 }
@@ -450,7 +451,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
                                               int *ipBefore) {
   _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
   *ipBefore = 0;
-  _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIu32,
+  _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIxPTR,
                        (void *)context, (void *)ipBefore,
                        ufc->resumeLocation + 1);
   return ufc->resumeLocation + 1;
@@ -460,7 +461,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
 /// 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%" PRIuPTR ")",
+  _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIxPTR ")",
                        (void *)context, new_value);
   _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
   ufc->resumeLocation = new_value - 1;
lib/libunwind/src/Unwind-wasm.c
@@ -0,0 +1,123 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 Wasm exception handling proposal
+//  (https://github.com/WebAssembly/exception-handling) based C++ exceptions
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdbool.h>
+
+#include "config.h"
+
+#ifdef __USING_WASM_EXCEPTIONS__
+
+#include "unwind.h"
+#include <threads.h>
+
+_Unwind_Reason_Code __gxx_personality_wasm0(int version, _Unwind_Action actions,
+                                            uint64_t exceptionClass,
+                                            _Unwind_Exception *unwind_exception,
+                                            _Unwind_Context *context);
+
+struct _Unwind_LandingPadContext {
+  // Input information to personality function
+  uintptr_t lpad_index; // landing pad index
+  uintptr_t lsda;       // LSDA address
+
+  // Output information computed by personality function
+  uintptr_t selector; // selector value
+};
+
+// Communication channel between compiler-generated user code and personality
+// function
+thread_local struct _Unwind_LandingPadContext __wasm_lpad_context;
+
+/// Calls to this function is in landing pads in compiler-generated user code.
+/// In other EH schemes, stack unwinding is done by libunwind library, which
+/// calls the personality function for each each frame it lands. On the other
+/// hand, WebAssembly stack unwinding process is performed by a VM, and the
+/// personality function cannot be called from there. So the compiler inserts
+/// a call to this function in landing pads in the user code, which in turn
+/// calls the personality function.
+_Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) {
+  struct _Unwind_Exception *exception_object =
+      (struct _Unwind_Exception *)exception_ptr;
+  _LIBUNWIND_TRACE_API("_Unwind_CallPersonality(exception_object=%p)",
+                       (void *)exception_object);
+
+  // Reset the selector.
+  __wasm_lpad_context.selector = 0;
+
+  // Call personality function. Wasm does not have two-phase unwinding, so we
+  // only do the cleanup phase.
+  return __gxx_personality_wasm0(
+      1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object,
+      (struct _Unwind_Context *)&__wasm_lpad_context);
+}
+
+/// Called by __cxa_throw.
+_LIBUNWIND_EXPORT _Unwind_Reason_Code
+_Unwind_RaiseException(_Unwind_Exception *exception_object) {
+  _LIBUNWIND_TRACE_API("_Unwind_RaiseException(exception_object=%p)",
+                       (void *)exception_object);
+  // Use Wasm EH's 'throw' instruction.
+  __builtin_wasm_throw(0, exception_object);
+}
+
+/// Called by __cxa_end_catch.
+_LIBUNWIND_EXPORT void
+_Unwind_DeleteException(_Unwind_Exception *exception_object) {
+  _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
+                       (void *)(exception_object));
+  if (exception_object->exception_cleanup != NULL)
+    (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
+                                           exception_object);
+}
+
+/// Called by personality handler to alter register values.
+_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
+                                     uintptr_t value) {
+  _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, index=%d, value=%lu)",
+                       (void *)context, index, value);
+  // We only use this function to set __wasm_lpad_context.selector field, which
+  // is index 1 in the personality function.
+  if (index == 1)
+    ((struct _Unwind_LandingPadContext *)context)->selector = value;
+}
+
+/// Called by personality handler to get instruction pointer.
+_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
+  // The result will be used as an 1-based index after decrementing 1, so we
+  // increment 2 here
+  uintptr_t result =
+      ((struct _Unwind_LandingPadContext *)context)->lpad_index + 2;
+  _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => %lu", (void *)context,
+                       result);
+  return result;
+}
+
+/// Not used in Wasm.
+_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
+                                     uintptr_t value) {}
+
+/// Called by personality handler to get LSDA for current frame.
+_LIBUNWIND_EXPORT uintptr_t
+_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
+  uintptr_t result = ((struct _Unwind_LandingPadContext *)context)->lsda;
+  _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%lx",
+                       (void *)context, result);
+  return result;
+}
+
+/// Not used in Wasm.
+_LIBUNWIND_EXPORT uintptr_t
+_Unwind_GetRegionStart(struct _Unwind_Context *context) {
+  return 0;
+}
+
+#endif // defined(__USING_WASM_EXCEPTIONS__)
lib/libunwind/src/UnwindCursor.hpp
@@ -33,6 +33,8 @@
 #if defined(_LIBUNWIND_TARGET_LINUX) &&                                        \
     (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \
      defined(_LIBUNWIND_TARGET_S390X))
+#include <errno.h>
+#include <signal.h>
 #include <sys/syscall.h>
 #include <sys/uio.h>
 #include <unistd.h>
@@ -990,6 +992,7 @@ private:
     R dummy;
     return stepThroughSigReturn(dummy);
   }
+  bool isReadableAddr(const pint_t addr) const;
 #if defined(_LIBUNWIND_TARGET_AARCH64)
   bool setInfoForSigReturn(Registers_arm64 &);
   int stepThroughSigReturn(Registers_arm64 &);
@@ -2301,27 +2304,39 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
     if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {
       functionName = ".anonymous.";
     }
-    _LIBUNWIND_TRACE_UNWINDING("%s: Look up traceback table of func=%s at %p",
-                               __func__, functionName,
-                               reinterpret_cast<void *>(TBTable));
+    _LIBUNWIND_TRACE_UNWINDING(
+        "%s: Look up traceback table of func=%s at %p, pc=%p, "
+        "SP=%p, saves_lr=%d, stores_bc=%d",
+        __func__, functionName, reinterpret_cast<void *>(TBTable),
+        reinterpret_cast<void *>(pc),
+        reinterpret_cast<void *>(registers.getSP()), TBTable->tb.saves_lr,
+        TBTable->tb.stores_bc);
   }
 
 #if defined(__powerpc64__)
-  // Instruction to reload TOC register "l r2,40(r1)"
+  // Instruction to reload TOC register "ld r2,40(r1)"
   const uint32_t loadTOCRegInst = 0xe8410028;
   const int32_t unwPPCF0Index = UNW_PPC64_F0;
   const int32_t unwPPCV0Index = UNW_PPC64_V0;
 #else
-  // Instruction to reload TOC register "l r2,20(r1)"
+  // Instruction to reload TOC register "lwz r2,20(r1)"
   const uint32_t loadTOCRegInst = 0x80410014;
   const int32_t unwPPCF0Index = UNW_PPC_F0;
   const int32_t unwPPCV0Index = UNW_PPC_V0;
 #endif
 
+  // lastStack points to the stack frame of the next routine up.
+  pint_t curStack = static_cast<pint_t>(registers.getSP());
+  pint_t lastStack = *reinterpret_cast<pint_t *>(curStack);
+
+  if (lastStack == 0)
+    return UNW_STEP_END;
+
   R newRegisters = registers;
 
-  // lastStack points to the stack frame of the next routine up.
-  pint_t lastStack = *(reinterpret_cast<pint_t *>(registers.getSP()));
+  // If backchain is not stored, use the current stack frame.
+  if (!TBTable->tb.stores_bc)
+    lastStack = curStack;
 
   // Return address is the address after call site instruction.
   pint_t returnAddress;
@@ -2331,33 +2346,41 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
                                reinterpret_cast<void *>(lastStack));
 
     sigcontext *sigContext = reinterpret_cast<sigcontext *>(
-        reinterpret_cast<char *>(lastStack) + STKMIN);
+        reinterpret_cast<char *>(lastStack) + STKMINALIGN);
     returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
 
-    _LIBUNWIND_TRACE_UNWINDING("From sigContext=%p, returnAddress=%p\n",
-                               reinterpret_cast<void *>(sigContext),
-                               reinterpret_cast<void *>(returnAddress));
-
+    bool useSTKMIN = false;
     if (returnAddress < 0x10000000) {
-      // Try again using STKMINALIGN
+      // Try again using STKMIN.
       sigContext = reinterpret_cast<sigcontext *>(
-          reinterpret_cast<char *>(lastStack) + STKMINALIGN);
+          reinterpret_cast<char *>(lastStack) + STKMIN);
       returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
       if (returnAddress < 0x10000000) {
-        _LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p\n",
-                                   reinterpret_cast<void *>(returnAddress));
+        _LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p from sigcontext=%p",
+                                   reinterpret_cast<void *>(returnAddress),
+                                   reinterpret_cast<void *>(sigContext));
         return UNW_EBADFRAME;
-      } else {
-        _LIBUNWIND_TRACE_UNWINDING("Tried again using STKMINALIGN: "
-                                   "sigContext=%p, returnAddress=%p. "
-                                   "Seems to be a valid address\n",
-                                   reinterpret_cast<void *>(sigContext),
-                                   reinterpret_cast<void *>(returnAddress));
       }
+      useSTKMIN = true;
     }
+    _LIBUNWIND_TRACE_UNWINDING("Returning from a signal handler %s: "
+                               "sigContext=%p, returnAddress=%p. "
+                               "Seems to be a valid address",
+                               useSTKMIN ? "STKMIN" : "STKMINALIGN",
+                               reinterpret_cast<void *>(sigContext),
+                               reinterpret_cast<void *>(returnAddress));
+
     // Restore the condition register from sigcontext.
     newRegisters.setCR(sigContext->sc_jmpbuf.jmp_context.cr);
 
+    // Save the LR in sigcontext for stepping up when the function that
+    // raised the signal is a leaf function. This LR has the return address
+    // to the caller of the leaf function.
+    newRegisters.setLR(sigContext->sc_jmpbuf.jmp_context.lr);
+    _LIBUNWIND_TRACE_UNWINDING(
+        "Save LR=%p from sigcontext",
+        reinterpret_cast<void *>(sigContext->sc_jmpbuf.jmp_context.lr));
+
     // Restore GPRs from sigcontext.
     for (int i = 0; i < 32; ++i)
       newRegisters.setRegister(i, sigContext->sc_jmpbuf.jmp_context.gpr[i]);
@@ -2380,13 +2403,26 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
     }
   } else {
     // Step up a normal frame.
-    returnAddress = reinterpret_cast<pint_t *>(lastStack)[2];
 
-    _LIBUNWIND_TRACE_UNWINDING("Extract info from lastStack=%p, "
-                               "returnAddress=%p\n",
-                               reinterpret_cast<void *>(lastStack),
-                               reinterpret_cast<void *>(returnAddress));
-    _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d\n",
+    if (!TBTable->tb.saves_lr && registers.getLR()) {
+      // This case should only occur if we were called from a signal handler
+      // and the signal occurred in a function that doesn't save the LR.
+      returnAddress = static_cast<pint_t>(registers.getLR());
+      _LIBUNWIND_TRACE_UNWINDING("Use saved LR=%p",
+                                 reinterpret_cast<void *>(returnAddress));
+    } else {
+      // Otherwise, use the LR value in the stack link area.
+      returnAddress = reinterpret_cast<pint_t *>(lastStack)[2];
+    }
+
+    // Reset LR in the current context.
+    newRegisters.setLR(NULL);
+
+    _LIBUNWIND_TRACE_UNWINDING(
+        "Extract info from lastStack=%p, returnAddress=%p",
+        reinterpret_cast<void *>(lastStack),
+        reinterpret_cast<void *>(returnAddress));
+    _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d",
                                TBTable->tb.fpr_saved, TBTable->tb.gpr_saved,
                                TBTable->tb.saves_cr);
 
@@ -2450,7 +2486,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
 
       struct vec_ext *vec_ext = reinterpret_cast<struct vec_ext *>(charPtr);
 
-      _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d\n", vec_ext->vr_saved);
+      _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d", vec_ext->vr_saved);
 
       // Restore vector register(s) if saved on the stack.
       if (vec_ext->vr_saved) {
@@ -2480,11 +2516,11 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
 
     // Do we need to set the TOC register?
     _LIBUNWIND_TRACE_UNWINDING(
-        "Current gpr2=%p\n",
+        "Current gpr2=%p",
         reinterpret_cast<void *>(newRegisters.getRegister(2)));
     if (firstInstruction == loadTOCRegInst) {
       _LIBUNWIND_TRACE_UNWINDING(
-          "Set gpr2=%p from frame\n",
+          "Set gpr2=%p from frame",
           reinterpret_cast<void *>(reinterpret_cast<pint_t *>(lastStack)[5]));
       newRegisters.setRegister(2, reinterpret_cast<pint_t *>(lastStack)[5]);
     }
@@ -2516,7 +2552,6 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
   } else {
     isSignalFrame = false;
   }
-
   return UNW_STEP_SUCCESS;
 }
 #endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
@@ -2668,20 +2703,12 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
   // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S
   const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
   // The PC might contain an invalid address if the unwind info is bad, so
-  // directly accessing it could cause a segfault. Use process_vm_readv to read
-  // the memory safely instead. process_vm_readv was added in Linux 3.2, and
-  // AArch64 supported was added in Linux 3.7, so the syscall is guaranteed to
-  // be present. Unfortunately, there are Linux AArch64 environments where the
-  // libc wrapper for the syscall might not be present (e.g. Android 5), so call
-  // the syscall directly instead.
-  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);
+  // directly accessing it could cause a SIGSEGV.
+  if (!isReadableAddr(pc))
+    return false;
+  auto *instructions = reinterpret_cast<const uint32_t *>(pc);
   // Look for instructions: mov x8, #0x8b; svc #0x0
-  if (bytesRead != sizeof instructions || instructions[0] != 0xd2801168 ||
-      instructions[1] != 0xd4000001)
+  if (instructions[0] != 0xd2801168 || instructions[1] != 0xd4000001)
     return false;
 
   _info = {};
@@ -2730,18 +2757,17 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
 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);
+  // The PC might contain an invalid address if the unwind info is bad, so
+  // directly accessing it could cause a SIGSEGV.
+  if (!isReadableAddr(pc))
+    return false;
+  const auto *instructions = reinterpret_cast<const uint32_t *>(pc);
   // 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)
+  if (instructions[0] != 0x08b00893 || instructions[1] != 0x00000073)
     return false;
 
   _info = {};
@@ -2790,13 +2816,11 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_s390x &) {
   // onto the stack.
   const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
   // The PC might contain an invalid address if the unwind info is bad, so
-  // directly accessing it could cause a segfault. Use process_vm_readv to
-  // read the memory safely instead.
-  uint16_t inst;
-  struct iovec local_iov = {&inst, sizeof inst};
-  struct iovec remote_iov = {reinterpret_cast<void *>(pc), sizeof inst};
-  long bytesRead = process_vm_readv(getpid(), &local_iov, 1, &remote_iov, 1, 0);
-  if (bytesRead == sizeof inst && (inst == 0x0a77 || inst == 0x0aad)) {
+  // directly accessing it could cause a SIGSEGV.
+  if (!isReadableAddr(pc))
+    return false;
+  const auto inst = *reinterpret_cast<const uint16_t *>(pc);
+  if (inst == 0x0a77 || inst == 0x0aad) {
     _info = {};
     _info.start_ip = pc;
     _info.end_ip = pc + 2;
@@ -2942,6 +2966,37 @@ bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
                                          buf, bufLen, offset);
 }
 
+#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
+template <typename A, typename R>
+bool UnwindCursor<A, R>::isReadableAddr(const pint_t addr) const {
+  // We use SYS_rt_sigprocmask, inspired by Abseil's AddressIsReadable.
+
+  const auto sigsetAddr = reinterpret_cast<sigset_t *>(addr);
+  // We have to check that addr is nullptr because sigprocmask allows that
+  // as an argument without failure.
+  if (!sigsetAddr)
+    return false;
+  const auto saveErrno = errno;
+  // We MUST use a raw syscall here, as wrappers may try to access
+  // sigsetAddr which may cause a SIGSEGV. A raw syscall however is
+  // safe. Additionally, we need to pass the kernel_sigset_size, which is
+  // different from libc sizeof(sigset_t). For the majority of architectures,
+  // it's 64 bits (_NSIG), and libc NSIG is _NSIG + 1.
+  const auto kernelSigsetSize = NSIG / 8;
+  [[maybe_unused]] const int Result = syscall(
+      SYS_rt_sigprocmask, /*how=*/~0, sigsetAddr, nullptr, kernelSigsetSize);
+  // Because our "how" is invalid, this syscall should always fail, and our
+  // errno should always be EINVAL or an EFAULT. This relies on the Linux
+  // kernel to check copy_from_user before checking if the "how" argument is
+  // invalid.
+  assert(Result == -1);
+  assert(errno == EFAULT || errno == EINVAL);
+  const auto readable = errno != EFAULT;
+  errno = saveErrno;
+  return readable;
+}
+#endif
+
 #if defined(_LIBUNWIND_USE_CET)
 extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) {
   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
lib/libunwind/src/UnwindLevel1-gcc-ext.c
@@ -143,7 +143,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
   // Create a mock exception object for force unwinding.
   _Unwind_Exception ex;
   memset(&ex, '\0', sizeof(ex));
-  strcpy((char *)&ex.exception_class, "CLNGUNW");
+  memcpy(&ex.exception_class, "CLNGUNW", sizeof(ex.exception_class));
 #endif
 
   // walk each frame
lib/libunwind/src/UnwindRegistersRestore.S
@@ -673,7 +673,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
   ldr    d30,     [x0, #0x200]
   ldr    d31,     [x0, #0x208]
 
-  // Finally, restore sp. This must be done after the the last read from the
+  // Finally, restore sp. This must be done after the last read from the
   // context struct, because it is allocated on the stack, and an exception
   // could clobber the de-allocated portion of the stack after sp has been
   // restored.
@@ -993,11 +993,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
   ldc1  $f31, (4 * 36 + 8 * 31)($4)
 #endif
 #endif
+#if __mips_isa_rev < 6
   // restore hi and lo
   lw    $8, (4 * 33)($4)
   mthi  $8
   lw    $8, (4 * 34)($4)
   mtlo  $8
+#endif
   // r0 is zero
   lw    $1, (4 * 1)($4)
   lw    $2, (4 * 2)($4)
@@ -1054,11 +1056,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
     ldc1 $f\i, (280+8*\i)($4)
   .endr
 #endif
+#if __mips_isa_rev < 6
   // restore hi and lo
   ld    $8, (8 * 33)($4)
   mthi  $8
   ld    $8, (8 * 34)($4)
   mtlo  $8
+#endif
   // r0 is zero
   ld    $1, (8 * 1)($4)
   ld    $2, (8 * 2)($4)
lib/libunwind/src/UnwindRegistersSave.S
@@ -174,11 +174,13 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   sw    $31, (4 * 31)($4)
   # Store return address to pc
   sw    $31, (4 * 32)($4)
+#if __mips_isa_rev < 6
   # hi and lo
   mfhi  $8
   sw    $8,  (4 * 33)($4)
   mflo  $8
   sw    $8,  (4 * 34)($4)
+#endif
 #ifdef __mips_hard_float
 #if __mips_fpr != 64
   sdc1  $f0, (4 * 36 + 8 * 0)($4)
@@ -255,11 +257,13 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   .endr
   # Store return address to pc
   sd    $31, (8 * 32)($4)
+#if __mips_isa_rev < 6
   # hi and lo
   mfhi  $8
   sd    $8,  (8 * 33)($4)
   mflo  $8
   sd    $8,  (8 * 34)($4)
+#endif
 #ifdef __mips_hard_float
   .irp i,FROM_0_TO_31
     sdc1 $f\i, (280+8*\i)($4)
@@ -301,9 +305,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   mflr  0
   std   0, PPC64_OFFS_SRR0(3) // store lr as ssr0
   PPC64_STR(1)
+  PPC64_STR(4)        // Save r4 first since it will be used for fixing r2.
+#if defined(_AIX)
+  // The TOC register (r2) was changed by the glue code if unw_getcontext
+  // is called from a different module. Save the original TOC register
+  // in the context if this is the case.
+  mflr   4
+  lwz    4, 0(4)      // Get the first instruction at the return address.
+  xoris  0, 4, 0xe841 // Is it reloading the TOC register "ld 2,40(1)"?
+  cmplwi 0, 0x28
+  bne    0, LnoR2Fix  // No need to fix up r2 if it is not.
+  ld     2, 40(1)     // Use the saved TOC register in the stack.
+LnoR2Fix:
+#endif
   PPC64_STR(2)
   PPC64_STR(3)
-  PPC64_STR(4)
   PPC64_STR(5)
   PPC64_STR(6)
   PPC64_STR(7)
@@ -336,7 +352,12 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   std   0,  PPC64_OFFS_CR(3)
   mfxer 0
   std   0,  PPC64_OFFS_XER(3)
+#if defined(_AIX)
+  // LR value saved from the register is not used, initialize it to 0.
+  li    0,  0
+#else
   mflr  0
+#endif
   std   0,  PPC64_OFFS_LR(3)
   mfctr 0
   std   0,  PPC64_OFFS_CTR(3)
@@ -543,9 +564,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   mflr    0
   stw     0,   0(3) // store lr as ssr0
   stw     1,  12(3)
+  stw     4,  24(3) // Save r4 first since it will be used for fixing r2.
+#if defined(_AIX)
+  // The TOC register (r2) was changed by the glue code if unw_getcontext
+  // is called from a different module. Save the original TOC register
+  // in the context if this is the case.
+  mflr    4
+  lwz     4,  0(4)      // Get the instruction at the return address.
+  xoris   0,  4, 0x8041 // Is it reloading the TOC register "lwz 2,20(1)"?
+  cmplwi  0,  0x14
+  bne     0,  LnoR2Fix  // No need to fix up r2 if it is not.
+  lwz     2,  20(1)     // Use the saved TOC register in the stack.
+LnoR2Fix:
+#endif
   stw     2,  16(3)
   stw     3,  20(3)
-  stw     4,  24(3)
   stw     5,  28(3)
   stw     6,  32(3)
   stw     7,  36(3)
@@ -582,6 +615,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   // save CR registers
   mfcr    0
   stw     0, 136(3)
+#if defined(_AIX)
+  // LR value from the register is not used, initialize it to 0.
+  li      0, 0
+  stw     0, 144(3)
+#endif
   // save CTR register
   mfctr   0
   stw     0, 148(3)
@@ -742,7 +780,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
 @
 @ On entry:
 @  thread_state pointer is in r0
-@ 
+@
 @ Per EHABI #4.7 this only saves the core integer registers.
 @ EHABI #7.4.5 notes that in general all VRS registers should be restored
 @ however this is very hard to do for VFP registers because it is unknown
src/libunwind.zig
@@ -164,6 +164,7 @@ const unwind_src_list = [_][]const u8{
     "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1.c",
     "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1-gcc-ext.c",
     "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-sjlj.c",
+    "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-wasm.c",
     "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersRestore.S",
     "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersSave.S",
     "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind_AIXExtras.cpp",