Skip to content

Commit 19a71f6

Browse files
committed
Merging r360861, with an additional change to also add the PPC64_OPD1
and PPC64_OPD2 lines to the DEFINE_LIBUNWIND_PRIVATE_FUNCTION() macro, which was removed in r357640: ------------------------------------------------------------------------ r360861 | mstorsjo | 2019-05-15 23:49:13 -0700 (Wed, 15 May 2019) | 13 lines [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. The unwind logic is able to handle both ELFv1 and ELFv2 stacks. Reported by Bug 41050 Patch by Leandro Lupori! Differential Revision: https://reviews.llvm.org/D59694 ------------------------------------------------------------------------ llvm-svn: 365542
1 parent 635f8ff commit 19a71f6

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

libunwind/src/DwarfInstructions.hpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,31 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
234234
}
235235
#endif
236236

237+
#if defined(_LIBUNWIND_TARGET_PPC64)
238+
#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)
239+
#define PPC64_ELFV1_R2_OFFSET 40
240+
#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)
241+
#define PPC64_ELFV2_R2_OFFSET 24
242+
// If the instruction at return address is a TOC (r2) restore,
243+
// then r2 was saved and needs to be restored.
244+
// ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,
245+
// while in ELFv1 ABI it is saved at SP + 40.
246+
if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) {
247+
pint_t sp = newRegisters.getRegister(UNW_REG_SP);
248+
pint_t r2 = 0;
249+
switch (addressSpace.get32(returnAddress)) {
250+
case PPC64_ELFV1_R2_LOAD_INST_ENCODING:
251+
r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET);
252+
break;
253+
case PPC64_ELFV2_R2_LOAD_INST_ENCODING:
254+
r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);
255+
break;
256+
}
257+
if (r2)
258+
newRegisters.setRegister(UNW_PPC64_R2, r2);
259+
}
260+
#endif
261+
237262
// Return address is address after call site instruction, so setting IP to
238263
// that does simualates a return.
239264
newRegisters.setIP(returnAddress);

libunwind/src/assembly.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,20 @@
3535
#define SEPARATOR ;
3636
#endif
3737

38+
#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1)
39+
#define PPC64_OPD1 .section .opd,"aw",@progbits SEPARATOR
40+
#define PPC64_OPD2 SEPARATOR \
41+
.p2align 3 SEPARATOR \
42+
.quad .Lfunc_begin0 SEPARATOR \
43+
.quad .TOC.@tocbase SEPARATOR \
44+
.quad 0 SEPARATOR \
45+
.text SEPARATOR \
46+
.Lfunc_begin0:
47+
#else
48+
#define PPC64_OPD1
49+
#define PPC64_OPD2
50+
#endif
51+
3852
#define GLUE2(a, b) a ## b
3953
#define GLUE(a, b) GLUE2(a, b)
4054
#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
@@ -95,13 +109,17 @@
95109
.globl SYMBOL_NAME(name) SEPARATOR \
96110
EXPORT_SYMBOL(name) SEPARATOR \
97111
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
98-
SYMBOL_NAME(name):
112+
PPC64_OPD1 \
113+
SYMBOL_NAME(name): \
114+
PPC64_OPD2
99115

100116
#define DEFINE_LIBUNWIND_PRIVATE_FUNCTION(name) \
101117
.globl SYMBOL_NAME(name) SEPARATOR \
102118
HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
103119
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
104-
SYMBOL_NAME(name):
120+
PPC64_OPD1 \
121+
SYMBOL_NAME(name): \
122+
PPC64_OPD2
105123

106124
#if defined(__arm__)
107125
#if !defined(__ARM_ARCH)

libunwind/test/lit.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ config.suffixes = ['.cpp', '.s']
2323
# test_source_root: The root path where tests are located.
2424
config.test_source_root = os.path.dirname(__file__)
2525

26+
# needed to test libunwind with code that throws exceptions
27+
config.enable_exceptions = True
28+
2629
# Infer the libcxx_test_source_root for configuration import.
2730
# If libcxx_source_root isn't specified in the config, assume that the libcxx
2831
# and libunwind source directories are sibling directories.

0 commit comments

Comments
 (0)