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

+25
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

+20-2
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

+3
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)