aboutsummaryrefslogtreecommitdiffstats
path: root/src/DwarfInstructions.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/DwarfInstructions.hpp')
-rw-r--r--src/DwarfInstructions.hpp39
1 files changed, 31 insertions, 8 deletions
diff --git a/src/DwarfInstructions.hpp b/src/DwarfInstructions.hpp
index ec70c0a11f70..29a070fa3e04 100644
--- a/src/DwarfInstructions.hpp
+++ b/src/DwarfInstructions.hpp
@@ -1,9 +1,8 @@
//===-------------------------- DwarfInstructions.hpp ---------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
// Processor specific interpretation of DWARF unwind info.
@@ -82,12 +81,11 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
const RegisterLocation &savedReg) {
switch (savedReg.location) {
case CFI_Parser<A>::kRegisterInCFA:
- return addressSpace.getRegister(cfa + (pint_t)savedReg.value);
+ return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);
case CFI_Parser<A>::kRegisterAtExpression:
- return addressSpace.getRegister(
- evaluateExpression((pint_t)savedReg.value, addressSpace,
- registers, cfa));
+ return (pint_t)addressSpace.getRegister(evaluateExpression(
+ (pint_t)savedReg.value, addressSpace, registers, cfa));
case CFI_Parser<A>::kRegisterIsExpression:
return evaluateExpression((pint_t)savedReg.value, addressSpace,
@@ -234,6 +232,31 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
}
#endif
+#if defined(_LIBUNWIND_TARGET_PPC64)
+#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)
+#define PPC64_ELFV1_R2_OFFSET 40
+#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)
+#define PPC64_ELFV2_R2_OFFSET 24
+ // If the instruction at return address is a TOC (r2) restore,
+ // then r2 was saved and needs to be restored.
+ // ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,
+ // while in ELFv1 ABI it is saved at SP + 40.
+ if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) {
+ pint_t sp = newRegisters.getRegister(UNW_REG_SP);
+ pint_t r2 = 0;
+ switch (addressSpace.get32(returnAddress)) {
+ case PPC64_ELFV1_R2_LOAD_INST_ENCODING:
+ r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET);
+ break;
+ case PPC64_ELFV2_R2_LOAD_INST_ENCODING:
+ r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);
+ break;
+ }
+ if (r2)
+ 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);