diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -232,6 +232,27 @@ } #endif +#if defined(_LIBUNWIND_TARGET_PPC64) + // If the instruction at return address is a TOC (r2) restore + // then r2 was saved and needs to be restored + if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0 && + addressSpace.get32(returnAddress) +#if defined(_CALL_ELF) && _CALL_ELF == 2 + == 0xe8410018 // ld r2,24(r1) +#else + == 0xe8410028 // ld r2,40(r1) +#endif + ) { + pint_t sp = newRegisters.getRegister(UNW_REG_SP); +#if defined(_CALL_ELF) && _CALL_ELF == 2 + pint_t r2 = addressSpace.get64(sp + 24); +#else + pint_t r2 = addressSpace.get64(sp + 40); +#endif + newRegisters.setRegister(UNW_PPC64_R2, r2); + } +#endif + // Return address is address after call site instruction, so setting IP to // that does simualates a return. newRegisters.setIP(returnAddress);