diff options
Diffstat (limited to 'lld/ELF/Arch')
| -rw-r--r-- | lld/ELF/Arch/AArch64.cpp | 23 | ||||
| -rw-r--r-- | lld/ELF/Arch/AMDGPU.cpp | 25 | ||||
| -rw-r--r-- | lld/ELF/Arch/ARM.cpp | 12 | ||||
| -rw-r--r-- | lld/ELF/Arch/AVR.cpp | 8 | ||||
| -rw-r--r-- | lld/ELF/Arch/Hexagon.cpp | 5 | ||||
| -rw-r--r-- | lld/ELF/Arch/MSP430.cpp | 3 | ||||
| -rw-r--r-- | lld/ELF/Arch/Mips.cpp | 3 | ||||
| -rw-r--r-- | lld/ELF/Arch/MipsArchTree.cpp | 3 | ||||
| -rw-r--r-- | lld/ELF/Arch/PPC.cpp | 15 | ||||
| -rw-r--r-- | lld/ELF/Arch/PPC64.cpp | 31 | ||||
| -rw-r--r-- | lld/ELF/Arch/RISCV.cpp | 6 | ||||
| -rw-r--r-- | lld/ELF/Arch/SPARCV9.cpp | 1 | ||||
| -rw-r--r-- | lld/ELF/Arch/X86.cpp | 1 | ||||
| -rw-r--r-- | lld/ELF/Arch/X86_64.cpp | 7 |
14 files changed, 94 insertions, 49 deletions
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 5789bc935b63..1949169d6447 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -9,9 +9,8 @@ #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" -#include "Thunks.h" #include "lld/Common/ErrorHandler.h" -#include "llvm/Object/ELF.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/Support/Endian.h" using namespace llvm; @@ -197,6 +196,13 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const { switch (type) { case R_AARCH64_TLSDESC: return read64(buf + 8); + case R_AARCH64_NONE: + return 0; + case R_AARCH64_PREL32: + return SignExtend64<32>(read32(buf)); + case R_AARCH64_ABS64: + case R_AARCH64_PREL64: + return read64(buf); default: internalLinkerError(getErrorLocation(buf), "cannot read addend for relocation " + toString(type)); @@ -249,9 +255,11 @@ void AArch64::writePlt(uint8_t *buf, const Symbol &sym, bool AArch64::needsThunk(RelExpr expr, RelType type, const InputFile *file, uint64_t branchAddr, const Symbol &s, int64_t a) const { - // If s is an undefined weak symbol and does not have a PLT entry then it - // will be resolved as a branch to the next instruction. - if (s.isUndefWeak() && !s.isInPlt()) + // If s is an undefined weak symbol and does not have a PLT entry then it will + // be resolved as a branch to the next instruction. If it is hidden, its + // binding has been converted to local, so we just check isUndefined() here. A + // undefined non-weak symbol will have been errored. + if (s.isUndefined() && !s.isInPlt()) return false; // ELF for the ARM 64-bit architecture, section Call and Jump relocations // only permits range extension thunks for R_AARCH64_CALL26 and @@ -685,6 +693,11 @@ bool AArch64Relaxer::tryRelaxAdrpLdr(const Relocation &adrpRel, return false; Symbol &sym = *adrpRel.sym; + // GOT references to absolute symbols can't be relaxed to use ADRP/ADD in + // position-independent code because these instructions produce a relative + // address. + if (config->isPic && !cast<Defined>(sym).section) + return false; // Check if the address difference is within 4GB range. int64_t val = getAArch64Page(sym.getVA()) - getAArch64Page(secAddr + adrpRel.offset); diff --git a/lld/ELF/Arch/AMDGPU.cpp b/lld/ELF/Arch/AMDGPU.cpp index cd7e7830d374..0368f82c6a65 100644 --- a/lld/ELF/Arch/AMDGPU.cpp +++ b/lld/ELF/Arch/AMDGPU.cpp @@ -10,7 +10,7 @@ #include "Symbols.h" #include "Target.h" #include "lld/Common/ErrorHandler.h" -#include "llvm/Object/ELF.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/Support/Endian.h" using namespace llvm; @@ -48,10 +48,10 @@ static uint32_t getEFlags(InputFile *file) { } uint32_t AMDGPU::calcEFlagsV3() const { - uint32_t ret = getEFlags(objectFiles[0]); + uint32_t ret = getEFlags(ctx->objectFiles[0]); // Verify that all input files have the same e_flags. - for (InputFile *f : makeArrayRef(objectFiles).slice(1)) { + for (InputFile *f : makeArrayRef(ctx->objectFiles).slice(1)) { if (ret == getEFlags(f)) continue; error("incompatible e_flags: " + toString(f)); @@ -61,14 +61,15 @@ uint32_t AMDGPU::calcEFlagsV3() const { } uint32_t AMDGPU::calcEFlagsV4() const { - uint32_t retMach = getEFlags(objectFiles[0]) & EF_AMDGPU_MACH; - uint32_t retXnack = getEFlags(objectFiles[0]) & EF_AMDGPU_FEATURE_XNACK_V4; + uint32_t retMach = getEFlags(ctx->objectFiles[0]) & EF_AMDGPU_MACH; + uint32_t retXnack = + getEFlags(ctx->objectFiles[0]) & EF_AMDGPU_FEATURE_XNACK_V4; uint32_t retSramEcc = - getEFlags(objectFiles[0]) & EF_AMDGPU_FEATURE_SRAMECC_V4; + getEFlags(ctx->objectFiles[0]) & EF_AMDGPU_FEATURE_SRAMECC_V4; // Verify that all input files have compatible e_flags (same mach, all // features in the same category are either ANY, ANY and ON, or ANY and OFF). - for (InputFile *f : makeArrayRef(objectFiles).slice(1)) { + for (InputFile *f : makeArrayRef(ctx->objectFiles).slice(1)) { if (retMach != (getEFlags(f) & EF_AMDGPU_MACH)) { error("incompatible mach: " + toString(f)); return 0; @@ -105,15 +106,19 @@ uint32_t AMDGPU::calcEFlagsV4() const { } uint32_t AMDGPU::calcEFlags() const { - assert(!objectFiles.empty()); + if (ctx->objectFiles.empty()) + return 0; - uint8_t abiVersion = cast<ObjFile<ELF64LE>>(objectFiles[0])->getObj() - .getHeader().e_ident[EI_ABIVERSION]; + uint8_t abiVersion = cast<ObjFile<ELF64LE>>(ctx->objectFiles[0]) + ->getObj() + .getHeader() + .e_ident[EI_ABIVERSION]; switch (abiVersion) { case ELFABIVERSION_AMDGPU_HSA_V2: case ELFABIVERSION_AMDGPU_HSA_V3: return calcEFlagsV3(); case ELFABIVERSION_AMDGPU_HSA_V4: + case ELFABIVERSION_AMDGPU_HSA_V5: return calcEFlagsV4(); default: error("unknown abi version: " + Twine(abiVersion)); diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp index b7c2eb74757c..425c45884330 100644 --- a/lld/ELF/Arch/ARM.cpp +++ b/lld/ELF/Arch/ARM.cpp @@ -6,13 +6,11 @@ // //===----------------------------------------------------------------------===// -#include "InputFiles.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" -#include "Thunks.h" #include "lld/Common/ErrorHandler.h" -#include "llvm/Object/ELF.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/Support/Endian.h" using namespace llvm; @@ -296,9 +294,11 @@ void ARM::addPltSymbols(InputSection &isec, uint64_t off) const { bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file, uint64_t branchAddr, const Symbol &s, int64_t a) const { - // If S is an undefined weak symbol and does not have a PLT entry then it - // will be resolved as a branch to the next instruction. - if (s.isUndefWeak() && !s.isInPlt()) + // If s is an undefined weak symbol and does not have a PLT entry then it will + // be resolved as a branch to the next instruction. If it is hidden, its + // binding has been converted to local, so we just check isUndefined() here. A + // undefined non-weak symbol will have been errored. + if (s.isUndefined() && !s.isInPlt()) return false; // A state change from ARM to Thumb and vice versa must go through an // interworking thunk if the relocation type is not R_ARM_CALL or diff --git a/lld/ELF/Arch/AVR.cpp b/lld/ELF/Arch/AVR.cpp index a3051dad9e8b..d972f8e8fdea 100644 --- a/lld/ELF/Arch/AVR.cpp +++ b/lld/ELF/Arch/AVR.cpp @@ -29,7 +29,7 @@ #include "Symbols.h" #include "Target.h" #include "lld/Common/ErrorHandler.h" -#include "llvm/Object/ELF.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/Support/Endian.h" using namespace llvm; @@ -226,12 +226,12 @@ static uint32_t getEFlags(InputFile *file) { } uint32_t AVR::calcEFlags() const { - assert(!objectFiles.empty()); + assert(!ctx->objectFiles.empty()); - uint32_t flags = getEFlags(objectFiles[0]); + uint32_t flags = getEFlags(ctx->objectFiles[0]); bool hasLinkRelaxFlag = flags & EF_AVR_LINKRELAX_PREPARED; - for (InputFile *f : makeArrayRef(objectFiles).slice(1)) { + for (InputFile *f : makeArrayRef(ctx->objectFiles).slice(1)) { uint32_t objFlags = getEFlags(f); if ((objFlags & EF_AVR_ARCH_MASK) != (flags & EF_AVR_ARCH_MASK)) error(toString(f) + diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp index c33bd935f363..6bca4070629e 100644 --- a/lld/ELF/Arch/Hexagon.cpp +++ b/lld/ELF/Arch/Hexagon.cpp @@ -12,7 +12,6 @@ #include "Target.h" #include "lld/Common/ErrorHandler.h" #include "llvm/BinaryFormat/ELF.h" -#include "llvm/Object/ELF.h" #include "llvm/Support/Endian.h" using namespace llvm; @@ -60,12 +59,12 @@ Hexagon::Hexagon() { } uint32_t Hexagon::calcEFlags() const { - assert(!objectFiles.empty()); + assert(!ctx->objectFiles.empty()); // The architecture revision must always be equal to or greater than // greatest revision in the list of inputs. uint32_t ret = 0; - for (InputFile *f : objectFiles) { + for (InputFile *f : ctx->objectFiles) { uint32_t eflags = cast<ObjFile<ELF32LE>>(f)->getObj().getHeader().e_flags; if (eflags > ret) ret = eflags; diff --git a/lld/ELF/Arch/MSP430.cpp b/lld/ELF/Arch/MSP430.cpp index 4af90b40a346..378b2878d442 100644 --- a/lld/ELF/Arch/MSP430.cpp +++ b/lld/ELF/Arch/MSP430.cpp @@ -15,11 +15,10 @@ // //===----------------------------------------------------------------------===// -#include "InputFiles.h" #include "Symbols.h" #include "Target.h" #include "lld/Common/ErrorHandler.h" -#include "llvm/Object/ELF.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/Support/Endian.h" using namespace llvm; diff --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp index 8ab076cdeb19..61da4a73a6fd 100644 --- a/lld/ELF/Arch/Mips.cpp +++ b/lld/ELF/Arch/Mips.cpp @@ -11,9 +11,8 @@ #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" -#include "Thunks.h" #include "lld/Common/ErrorHandler.h" -#include "llvm/Object/ELF.h" +#include "llvm/BinaryFormat/ELF.h" using namespace llvm; using namespace llvm::object; diff --git a/lld/ELF/Arch/MipsArchTree.cpp b/lld/ELF/Arch/MipsArchTree.cpp index 77c05a818a5d..f1fcf1610cb1 100644 --- a/lld/ELF/Arch/MipsArchTree.cpp +++ b/lld/ELF/Arch/MipsArchTree.cpp @@ -16,7 +16,6 @@ #include "lld/Common/ErrorHandler.h" #include "llvm/BinaryFormat/ELF.h" -#include "llvm/Object/ELF.h" #include "llvm/Support/MipsABIFlags.h" using namespace llvm; @@ -296,7 +295,7 @@ static uint32_t getArchFlags(ArrayRef<FileFlags> files) { template <class ELFT> uint32_t elf::calcMipsEFlags() { std::vector<FileFlags> v; - for (InputFile *f : objectFiles) + for (InputFile *f : ctx->objectFiles) v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader().e_flags}); if (v.empty()) { // If we don't have any input files, we'll have to rely on the information diff --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp index 97e4d6633138..47c31e3a3b94 100644 --- a/lld/ELF/Arch/PPC.cpp +++ b/lld/ELF/Arch/PPC.cpp @@ -30,6 +30,7 @@ public: RelExpr getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const override; RelType getDynRel(RelType type) const override; + int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override; void writeGotHeader(uint8_t *buf) const override; void writePltHeader(uint8_t *buf) const override { llvm_unreachable("should call writePPC32GlinkSection() instead"); @@ -275,6 +276,20 @@ RelType PPC::getDynRel(RelType type) const { return R_PPC_NONE; } +int64_t PPC::getImplicitAddend(const uint8_t *buf, RelType type) const { + switch (type) { + case R_PPC_NONE: + return 0; + case R_PPC_ADDR32: + case R_PPC_REL32: + return SignExtend64<32>(read32(buf)); + default: + internalLinkerError(getErrorLocation(buf), + "cannot read addend for relocation " + toString(type)); + return 0; + } +} + static std::pair<RelType, uint64_t> fromDTPREL(RelType type, uint64_t val) { uint64_t dtpBiasedVal = val - 0x8000; switch (type) { diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index d9e4fc97ea0b..9b72029e8e1d 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "InputFiles.h" #include "SymbolTable.h" #include "Symbols.h" #include "SyntheticSections.h" @@ -196,8 +197,8 @@ static bool addOptional(StringRef name, uint64_t value, Symbol *sym = symtab->find(name); if (!sym || sym->isDefined()) return false; - sym->resolve(Defined{/*file=*/nullptr, saver().save(name), STB_GLOBAL, - STV_HIDDEN, STT_FUNC, value, + sym->resolve(Defined{/*file=*/nullptr, StringRef(), STB_GLOBAL, STV_HIDDEN, + STT_FUNC, value, /*size=*/0, /*section=*/nullptr}); defined.push_back(cast<Defined>(sym)); return true; @@ -363,6 +364,7 @@ public: RelExpr getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const override; RelType getDynRel(RelType type) const override; + int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override; void writePltHeader(uint8_t *buf) const override; void writePlt(uint8_t *buf, const Symbol &sym, uint64_t pltEntryAddr) const override; @@ -620,7 +622,7 @@ static uint32_t getEFlags(InputFile *file) { // This file implements v2 ABI. This function makes sure that all // object files have v2 or an unspecified version as an ABI version. uint32_t PPC64::calcEFlags() const { - for (InputFile *f : objectFiles) { + for (InputFile *f : ctx->objectFiles) { uint32_t flag = getEFlags(f); if (flag == 1) error(toString(f) + ": ABI version 1 is not supported"); @@ -1059,6 +1061,22 @@ RelType PPC64::getDynRel(RelType type) const { return R_PPC64_NONE; } +int64_t PPC64::getImplicitAddend(const uint8_t *buf, RelType type) const { + switch (type) { + case R_PPC64_NONE: + return 0; + case R_PPC64_REL32: + return SignExtend64<32>(read32(buf)); + case R_PPC64_ADDR64: + case R_PPC64_REL64: + return read64(buf); + default: + internalLinkerError(getErrorLocation(buf), + "cannot read addend for relocation " + toString(type)); + return 0; + } +} + void PPC64::writeGotHeader(uint8_t *buf) const { write64(buf, getPPC64TocBase()); } @@ -1368,9 +1386,10 @@ bool PPC64::needsThunk(RelExpr expr, RelType type, const InputFile *file, if (type == R_PPC64_REL24_NOTOC && (s.stOther >> 5) > 1) return true; - // If a symbol is a weak undefined and we are compiling an executable - // it doesn't need a range-extending thunk since it can't be called. - if (s.isUndefWeak() && !config->shared) + // An undefined weak symbol not in a PLT does not need a thunk. If it is + // hidden, its binding has been converted to local, so we just check + // isUndefined() here. A undefined non-weak symbol has been errored. + if (s.isUndefined()) return false; // If the offset exceeds the range of the branch type then it will need diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp index a0ea403e241d..7ba0214eb2a7 100644 --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -111,12 +111,12 @@ static uint32_t getEFlags(InputFile *f) { uint32_t RISCV::calcEFlags() const { // If there are only binary input files (from -b binary), use a // value of 0 for the ELF header flags. - if (objectFiles.empty()) + if (ctx->objectFiles.empty()) return 0; - uint32_t target = getEFlags(objectFiles.front()); + uint32_t target = getEFlags(ctx->objectFiles.front()); - for (InputFile *f : objectFiles) { + for (InputFile *f : ctx->objectFiles) { uint32_t eflags = getEFlags(f); if (eflags & EF_RISCV_RVC) target |= EF_RISCV_RVC; diff --git a/lld/ELF/Arch/SPARCV9.cpp b/lld/ELF/Arch/SPARCV9.cpp index 1aebb57951cb..4ae742c6c4e9 100644 --- a/lld/ELF/Arch/SPARCV9.cpp +++ b/lld/ELF/Arch/SPARCV9.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// -#include "InputFiles.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" diff --git a/lld/ELF/Arch/X86.cpp b/lld/ELF/Arch/X86.cpp index e084bd646912..d4c2f9aa9489 100644 --- a/lld/ELF/Arch/X86.cpp +++ b/lld/ELF/Arch/X86.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// -#include "InputFiles.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp index f1360f50f8ac..e7fb229e08e0 100644 --- a/lld/ELF/Arch/X86_64.cpp +++ b/lld/ELF/Arch/X86_64.cpp @@ -6,13 +6,12 @@ // //===----------------------------------------------------------------------===// -#include "InputFiles.h" #include "OutputSections.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" #include "lld/Common/ErrorHandler.h" -#include "llvm/Object/ELF.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/Support/Endian.h" using namespace llvm; @@ -264,7 +263,7 @@ bool X86_64::deleteFallThruJmpInsn(InputSection &is, InputFile *file, Relocation &r = is.relocations[rIndex]; // Check if the relocation corresponds to a direct jmp. - const uint8_t *secContents = is.data().data(); + const uint8_t *secContents = is.rawData.data(); // If it is not a direct jmp instruction, there is nothing to do here. if (*(secContents + r.offset - 1) != 0xe9) return false; @@ -280,7 +279,7 @@ bool X86_64::deleteFallThruJmpInsn(InputSection &is, InputFile *file, // Now, check if flip and delete is possible. const unsigned sizeOfJmpCCInsn = 6; - // To flip, there must be atleast one JmpCC and one direct jmp. + // To flip, there must be at least one JmpCC and one direct jmp. if (is.getSize() < sizeOfDirectJmpInsn + sizeOfJmpCCInsn) return false; |
