--- third_party/libunwind/src/src/DwarfInstructions.hpp.orig 2026-02-11 09:05:39 UTC
+++ third_party/libunwind/src/src/DwarfInstructions.hpp
@@ -396,6 +396,23 @@ int DwarfInstructions::stepWithDwarf(
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::stepWithDwarf(
r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);
break;
}
+#endif
if (r2)
newRegisters.setRegister(UNW_PPC64_R2, r2);
}