aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/Arch
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Arch')
-rw-r--r--lld/ELF/Arch/AArch64.cpp23
-rw-r--r--lld/ELF/Arch/AMDGPU.cpp25
-rw-r--r--lld/ELF/Arch/ARM.cpp12
-rw-r--r--lld/ELF/Arch/AVR.cpp8
-rw-r--r--lld/ELF/Arch/Hexagon.cpp5
-rw-r--r--lld/ELF/Arch/MSP430.cpp3
-rw-r--r--lld/ELF/Arch/Mips.cpp3
-rw-r--r--lld/ELF/Arch/MipsArchTree.cpp3
-rw-r--r--lld/ELF/Arch/PPC.cpp15
-rw-r--r--lld/ELF/Arch/PPC64.cpp31
-rw-r--r--lld/ELF/Arch/RISCV.cpp6
-rw-r--r--lld/ELF/Arch/SPARCV9.cpp1
-rw-r--r--lld/ELF/Arch/X86.cpp1
-rw-r--r--lld/ELF/Arch/X86_64.cpp7
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;