diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-07-06 15:34:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-07-06 15:34:04 +0000 |
commit | 28cb8d7d187c08a04faab403144fdda0f48f7906 (patch) | |
tree | a5a0fdc549030cb1da79ec220e7cd4e107885618 | |
parent | 2bcfbb511a63150d7b74d910c8dbda707d78a5e9 (diff) |
Vendor import of LLVM libunwind release_80 branch r364487:vendor/llvm-libunwind/libunwind-release_80-r364487
Notes
Notes:
svn path=/vendor/llvm-libunwind/dist-release_80/; revision=349783
svn path=/vendor/llvm-libunwind/libunwind-release_80-r364487/; revision=349784; tag=vendor/llvm-libunwind/libunwind-release_80-r364487
-rw-r--r-- | src/DwarfInstructions.hpp | 25 | ||||
-rw-r--r-- | src/assembly.h | 18 |
2 files changed, 42 insertions, 1 deletions
diff --git a/src/DwarfInstructions.hpp b/src/DwarfInstructions.hpp index ec70c0a11f70..4109549a911b 100644 --- a/src/DwarfInstructions.hpp +++ b/src/DwarfInstructions.hpp @@ -234,6 +234,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); diff --git a/src/assembly.h b/src/assembly.h index 7806892e9dcf..02ac36d90fe1 100644 --- a/src/assembly.h +++ b/src/assembly.h @@ -35,6 +35,20 @@ #define SEPARATOR ; #endif +#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1) +#define PPC64_OPD1 .section .opd,"aw",@progbits SEPARATOR +#define PPC64_OPD2 SEPARATOR \ + .p2align 3 SEPARATOR \ + .quad .Lfunc_begin0 SEPARATOR \ + .quad .TOC.@tocbase SEPARATOR \ + .quad 0 SEPARATOR \ + .text SEPARATOR \ +.Lfunc_begin0: +#else +#define PPC64_OPD1 +#define PPC64_OPD2 +#endif + #define GLUE2(a, b) a ## b #define GLUE(a, b) GLUE2(a, b) #define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name) @@ -95,7 +109,9 @@ .globl SYMBOL_NAME(name) SEPARATOR \ EXPORT_SYMBOL(name) SEPARATOR \ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ - SYMBOL_NAME(name): + PPC64_OPD1 \ + SYMBOL_NAME(name): \ + PPC64_OPD2 #define DEFINE_LIBUNWIND_PRIVATE_FUNCTION(name) \ .globl SYMBOL_NAME(name) SEPARATOR \ |