$NetBSD: patch-third__party_libunwind_src_src_DwarfInstructions.hpp,v 1.4 2026/04/21 15:21:21 kikadf Exp $

* Part of patchset to build chromium on NetBSD
* Based on OpenBSD's chromium patches, and
  pkgsrc's qt5-qtwebengine patches

--- third_party/libunwind/src/src/DwarfInstructions.hpp.orig	2026-04-14 23:31:37.000000000 +0200
+++ third_party/libunwind/src/src/DwarfInstructions.hpp
@@ -396,6 +396,23 @@ int DwarfInstructions<A, R>::stepWithDwa
       if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) {
         pint_t sp = newRegisters.getRegister(UNW_REG_SP);
         pint_t r2 = 0;
+#if defined(_LIBUNWIND_IS_NATIVE_ONLY) && defined(__OpenBSD__)
+        // Can't addressSpace.get32(returnAddress), because it might be
+        // in execute-only memory.  If returning to a different shared
+        // object, then restore r2.  This assumes one TOC per object.
+        // ELFv2 allows more than one (3.3 TOC, Modules Containing
+        // Multiple TOCs), but we have no way to detect that.
+        void *IPObject = NULL;
+        void *RAObject = NULL;
+        Dl_info info;
+        if (dladdr((void *)registers.getIP(), &info))
+          IPObject = info.dli_fbase;
+        if (dladdr((void *)returnAddress, &info))
+          RAObject = info.dli_fbase;
+        // Assume ELFv2.
+        if (IPObject != RAObject)
+          r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);
+#else
         switch (addressSpace.get32(returnAddress)) {
         case PPC64_ELFV1_R2_LOAD_INST_ENCODING:
           r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET);
@@ -404,6 +421,7 @@ int DwarfInstructions<A, R>::stepWithDwa
           r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);
           break;
         }
+#endif
         if (r2)
           newRegisters.setRegister(UNW_PPC64_R2, r2);
       }
