From 70f25ebc6d1588bdf7fa07e7c42fa3c9a075101d Mon Sep 17 00:00:00 2001 From: Alfredo Dal'Ava Junior Date: Wed, 20 Mar 2019 19:16:32 -0300 Subject: [PATCH 1/7] luporl, adalava pending patches !!!!!!!!! --- lld/ELF/SyntheticSections.cpp | 5 +++ llvm/lib/MC/ELFObjectWriter.cpp | 1 + .../PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp | 33 +++++++++++++++---- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index b1a3f8bc70aec7..10675588ebe2eb 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -2001,6 +2001,11 @@ template void SymbolTableSection::writeTo(uint8_t *Buf) { ESym->setVisibility(Sym->Visibility); } + // The 3 most significant bits of st_other are used by OpenPOWER ABI. + // See getPPC64GlobalEntryToLocalEntryOffset() for more details. + if (Config->EMachine == EM_PPC64) + ESym->st_other |= Sym->StOther & 0xe0; + ESym->st_name = Ent.StrTabOffset; ESym->st_shndx = getSymSectionIndex(Ent.Sym); diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index ade858113a3009..1b505776ca19bd 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -1271,6 +1271,7 @@ void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, // This is the first place we are able to copy this information. Alias->setExternal(Symbol.isExternal()); Alias->setBinding(Symbol.getBinding()); + Alias->setOther(Symbol.getOther()); if (!Symbol.isUndefined() && !Rest.startswith("@@@")) continue; diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp index a1e4e07b25af4b..aaa5dd3fed86c1 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -36,6 +36,8 @@ #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" +#include + using namespace llvm; #define GET_INSTRINFO_MC_DESC @@ -182,16 +184,35 @@ class PPCTargetELFStreamer : public PPCTargetStreamer { void emitAssignment(MCSymbol *S, const MCExpr *Value) override { auto *Symbol = cast(S); + + auto I = UpdateOther.find(Symbol); + if (I != UpdateOther.end()) + UpdateOther.erase(I); + // When encoding an assignment to set symbol A to symbol B, also copy // the st_other bits encoding the local entry point offset. - if (Value->getKind() != MCExpr::SymbolRef) - return; - const auto &RhsSym = cast( - static_cast(Value)->getSymbol()); - unsigned Other = Symbol->getOther(); + if (copyLocalEntry(Symbol, Value)) + UpdateOther.insert(Symbol); + } + + void finish() override { + for (auto *Sym : UpdateOther) + copyLocalEntry(Sym, Sym->getVariableValue()); + } + +private: + std::set UpdateOther; + + bool copyLocalEntry(MCSymbolELF *D, const MCExpr *S) { + if (S->getKind() != MCExpr::SymbolRef) + return false; + const auto &RhsSym = + cast(static_cast(S)->getSymbol()); + unsigned Other = D->getOther(); Other &= ~ELF::STO_PPC64_LOCAL_MASK; Other |= RhsSym.getOther() & ELF::STO_PPC64_LOCAL_MASK; - Symbol->setOther(Other); + D->setOther(Other); + return true; } }; From 31247e381f977da6782a7f02fecc9b31b9bb763e Mon Sep 17 00:00:00 2001 From: Alfredo Dal'Ava Junior Date: Fri, 22 Mar 2019 13:42:27 -0300 Subject: [PATCH 2/7] adalava: change default powerpc64 ABI to ELFv2 on FreeBSD >= 13.0 --- clang/lib/Basic/Targets/PPC.h | 4 +++- llvm/lib/Target/PowerPC/PPCTargetMachine.cpp | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index cbe7a9a2fa85ec..53b9c96f0c08e3 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -370,10 +370,12 @@ class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo { ABI = "elfv1"; } - switch (getTriple().getOS()) { + switch (Triple.getOS()) { case llvm::Triple::FreeBSD: LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + if (Triple.getOSMajorVersion() >= 13) + ABI = "elfv2"; break; default: break; diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp index 580d057602f5f7..e7358f2971004d 100644 --- a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -195,6 +195,20 @@ static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT, if (TT.isMacOSX()) return PPCTargetMachine::PPC_ABI_UNKNOWN; + if (TT.isOSFreeBSD()) { + switch (TT.getArch()) { + case Triple::ppc64le: + case Triple::ppc64: + if (TT.getOSMajorVersion() >= 13) + return PPCTargetMachine::PPC_ABI_ELFv2; + else + return PPCTargetMachine::PPC_ABI_ELFv1; + case Triple::ppc: + default: + return PPCTargetMachine::PPC_ABI_UNKNOWN; + } + } + switch (TT.getArch()) { case Triple::ppc64le: return PPCTargetMachine::PPC_ABI_ELFv2; From 6b293b18528e3435dc58619201ca24c43bc7e991 Mon Sep 17 00:00:00 2001 From: luporl Date: Thu, 21 Mar 2019 18:01:33 -0300 Subject: [PATCH 3/7] [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. --- libunwind/src/DwarfInstructions.hpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp index ec70c0a11f70fd..5418ec7c32714a 100644 --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -234,6 +234,27 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, } #endif +#if defined(_LIBUNWIND_TARGET_PPC64) + // If the instruction at return address is a TOC (r2) restore + // then r2 was saved and needs to be restored + if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0 && + addressSpace.get32(returnAddress) +#if defined(_CALL_ELF) && _CALL_ELF == 2 + == 0xe8410018 // ld r2,24(r1) +#else + == 0xe8410028 // ld r2,40(r1) +#endif + ) { + pint_t sp = newRegisters.getRegister(UNW_REG_SP); +#if defined(_CALL_ELF) && _CALL_ELF == 2 + pint_t r2 = addressSpace.get64(sp + 24); +#else + pint_t r2 = addressSpace.get64(sp + 40); +#endif + 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); From 2b112d8216cabd98e0086a6126b3187a1955ee1f Mon Sep 17 00:00:00 2001 From: luporl Date: Mon, 25 Mar 2019 15:36:00 -0300 Subject: [PATCH 4/7] Addressed review comments --- libunwind/src/DwarfInstructions.hpp | 36 ++++++++++++++++------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp index 5418ec7c32714a..a5021f2471e113 100644 --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -235,23 +235,27 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, #endif #if defined(_LIBUNWIND_TARGET_PPC64) - // If the instruction at return address is a TOC (r2) restore - // then r2 was saved and needs to be restored - if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0 && - addressSpace.get32(returnAddress) -#if defined(_CALL_ELF) && _CALL_ELF == 2 - == 0xe8410018 // ld r2,24(r1) -#else - == 0xe8410028 // ld r2,40(r1) -#endif - ) { +#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028 // ld r2,40(r1) +#define PPC64_ELFV1_R2_OFFSET 24 +#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018 // ld r2,24(r1) +#define PPC64_ELFV2_R2_OFFSET 40 + // 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); -#if defined(_CALL_ELF) && _CALL_ELF == 2 - pint_t r2 = addressSpace.get64(sp + 24); -#else - pint_t r2 = addressSpace.get64(sp + 40); -#endif - newRegisters.setRegister(UNW_PPC64_R2, r2); + 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 From 9f2bdd2f7da10a49f1cece341b20a17ed97ca88b Mon Sep 17 00:00:00 2001 From: Alfredo Dal'Ava Junior Date: Wed, 27 Mar 2019 18:33:52 -0300 Subject: [PATCH 5/7] adalava - implement PPC64::getThunkSectionSpacing() as workaround to "large files issue": https://bugs.llvm.org/show_bug.cgi?id=40740 --- lld/ELF/Arch/PPC64.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index 8a320c9a4e9ef4..46f9718e1142d6 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -123,6 +123,7 @@ class PPC64 final : public TargetInfo { bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, uint8_t StOther) const override; + uint32_t getThunkSectionSpacing() const override; }; } // namespace @@ -925,6 +926,13 @@ bool PPC64::adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, return true; } + +uint32_t PPC64::getThunkSectionSpacing() const { + // REL14 range + return 0x8000; +} + + TargetInfo *elf::getPPC64TargetInfo() { static PPC64 Target; return &Target; From a994896d2bd3ce7127998cf3334fcd32522fe024 Mon Sep 17 00:00:00 2001 From: luporl Date: Fri, 29 Mar 2019 16:41:37 -0300 Subject: [PATCH 6/7] Fixed regression and ELFv1 ASM functions --- libunwind/src/DwarfInstructions.hpp | 8 ++++---- libunwind/src/assembly.h | 22 ++++++++++++++++++++-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp index a5021f2471e113..4109549a911b16 100644 --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -235,10 +235,10 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, #endif #if defined(_LIBUNWIND_TARGET_PPC64) -#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028 // ld r2,40(r1) -#define PPC64_ELFV1_R2_OFFSET 24 -#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018 // ld r2,24(r1) -#define PPC64_ELFV2_R2_OFFSET 40 +#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, diff --git a/libunwind/src/assembly.h b/libunwind/src/assembly.h index 2df930214fae5b..70964710b8223b 100644 --- a/libunwind/src/assembly.h +++ b/libunwind/src/assembly.h @@ -37,6 +37,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) @@ -97,13 +111,17 @@ .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 \ HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ - SYMBOL_NAME(name): + PPC64_OPD1 \ + SYMBOL_NAME(name): \ + PPC64_OPD2 #if defined(__arm__) #if !defined(__ARM_ARCH) From a9e7e3438e4dbc558502df39ff7a223812d09c30 Mon Sep 17 00:00:00 2001 From: Alfredo Dal'Ava Junior Date: Tue, 2 Apr 2019 12:41:16 -0300 Subject: [PATCH 7/7] adalava: add comment to 9f2bdd2f7da10a49f1cece341b20a17ed97ca88b --- lld/ELF/Arch/PPC64.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index 46f9718e1142d6..5048090f9d29bb 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -928,7 +928,17 @@ bool PPC64::adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, uint32_t PPC64::getThunkSectionSpacing() const { - // REL14 range + // The placing of pre-created ThunkSections is controlled by the value + // ThunkSectionSpacing returned by getThunkSectionSpacing(). The aim is to + // place the ThunkSection such that all branches from the InputSections + // prior to the ThunkSection can reach a Thunk placed at the end of the + // ThunkSection. Graphically: + // | up to ThunkSectionSpacing .text input sections | + // | ThunkSection | + // | up to ThunkSectionSpacing .text input sections | + // | ThunkSection | + // + // On PowerPC64, we return the PPC64_REL14 relocation range return 0x8000; }