Skip to content

Commit 6b293b1

Browse files
luporlluporl
luporl
authored and
luporl
committed
[PPC64][libunwind] Fix r2 not properly restored
This change makes each unwind step inspect the instruction at the return address and, if needed, read r2 from its saved location and modify the context appropriately. One point that (maybe) could be improved is to try to find if the binary being unwound is ELFv1 or ELFv2 at run time, instead of at compile time, or, find out the correct save location of r2 in some other way.
1 parent 31247e3 commit 6b293b1

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

libunwind/src/DwarfInstructions.hpp

+21
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,27 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
234234
}
235235
#endif
236236

237+
#if defined(_LIBUNWIND_TARGET_PPC64)
238+
// If the instruction at return address is a TOC (r2) restore
239+
// then r2 was saved and needs to be restored
240+
if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0 &&
241+
addressSpace.get32(returnAddress)
242+
#if defined(_CALL_ELF) && _CALL_ELF == 2
243+
== 0xe8410018 // ld r2,24(r1)
244+
#else
245+
== 0xe8410028 // ld r2,40(r1)
246+
#endif
247+
) {
248+
pint_t sp = newRegisters.getRegister(UNW_REG_SP);
249+
#if defined(_CALL_ELF) && _CALL_ELF == 2
250+
pint_t r2 = addressSpace.get64(sp + 24);
251+
#else
252+
pint_t r2 = addressSpace.get64(sp + 40);
253+
#endif
254+
newRegisters.setRegister(UNW_PPC64_R2, r2);
255+
}
256+
#endif
257+
237258
// Return address is address after call site instruction, so setting IP to
238259
// that does simualates a return.
239260
newRegisters.setIP(returnAddress);

0 commit comments

Comments
 (0)