aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/InputSection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/InputSection.cpp')
-rw-r--r--lld/ELF/InputSection.cpp46
1 files changed, 35 insertions, 11 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index f40bb258b9af..1f9fa961fc26 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -547,8 +547,7 @@ static uint32_t getARMUndefinedRelativeWeakVA(RelType type, uint32_t a,
}
// The comment above getARMUndefinedRelativeWeakVA applies to this function.
-static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t type, uint64_t a,
- uint64_t p) {
+static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t type, uint64_t p) {
switch (type) {
// Unresolved branch relocations to weak references resolve to next
// instruction, this is 4 bytes on from P.
@@ -556,7 +555,7 @@ static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t type, uint64_t a,
case R_AARCH64_CONDBR19:
case R_AARCH64_JUMP26:
case R_AARCH64_TSTBR14:
- return p + 4 + a;
+ return p + 4;
// Unresolved non branch pc-relative relocations
case R_AARCH64_PREL16:
case R_AARCH64_PREL32:
@@ -564,11 +563,25 @@ static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t type, uint64_t a,
case R_AARCH64_ADR_PREL_LO21:
case R_AARCH64_LD_PREL_LO19:
case R_AARCH64_PLT32:
- return p + a;
+ return p;
}
llvm_unreachable("AArch64 pc-relative relocation expected\n");
}
+static uint64_t getRISCVUndefinedRelativeWeakVA(uint64_t type, uint64_t p) {
+ switch (type) {
+ case R_RISCV_BRANCH:
+ case R_RISCV_JAL:
+ case R_RISCV_CALL:
+ case R_RISCV_CALL_PLT:
+ case R_RISCV_RVC_BRANCH:
+ case R_RISCV_RVC_JUMP:
+ return p;
+ default:
+ return 0;
+ }
+}
+
// ARM SBREL relocations are of the form S + A - B where B is the static base
// The ARM ABI defines base to be "addressing origin of the output segment
// defining the symbol S". We defined the "addressing origin"/static base to be
@@ -765,14 +778,18 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
// Some PC relative ARM (Thumb) relocations align down the place.
p = p & 0xfffffffc;
if (sym.isUndefWeak()) {
- // On ARM and AArch64 a branch to an undefined weak resolves to the
- // next instruction, otherwise the place.
+ // On ARM and AArch64 a branch to an undefined weak resolves to the next
+ // instruction, otherwise the place. On RISCV, resolve an undefined weak
+ // to the same instruction to cause an infinite loop (making the user
+ // aware of the issue) while ensuring no overflow.
if (config->emachine == EM_ARM)
dest = getARMUndefinedRelativeWeakVA(type, a, p);
else if (config->emachine == EM_AARCH64)
- dest = getAArch64UndefinedRelativeWeakVA(type, a, p);
+ dest = getAArch64UndefinedRelativeWeakVA(type, p) + a;
else if (config->emachine == EM_PPC)
dest = p;
+ else if (config->emachine == EM_RISCV)
+ dest = getRISCVUndefinedRelativeWeakVA(type, p) + a;
else
dest = sym.getVA(a);
} else {
@@ -839,7 +856,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
case R_TLSGD_GOT:
return in.got->getGlobalDynOffset(sym) + a;
case R_TLSGD_GOTPLT:
- return in.got->getVA() + in.got->getGlobalDynOffset(sym) + a - in.gotPlt->getVA();
+ return in.got->getGlobalDynAddr(sym) + a - in.gotPlt->getVA();
case R_TLSGD_PC:
return in.got->getGlobalDynAddr(sym) + a - p;
case R_TLSLD_GOTPLT:
@@ -901,7 +918,10 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
continue;
}
- if (expr != R_ABS && expr != R_DTPREL && expr != R_RISCV_ADD) {
+ // R_ABS/R_DTPREL and some other relocations can be used from non-SHF_ALLOC
+ // sections.
+ if (expr != R_ABS && expr != R_DTPREL && expr != R_GOTPLTREL &&
+ expr != R_RISCV_ADD) {
std::string msg = getLocation<ELFT>(offset) +
": has non-ABS relocation " + toString(type) +
" against symbol '" + toString(sym) + "'";
@@ -1323,6 +1343,11 @@ template <class ELFT> void EhInputSection::split() {
template <class ELFT, class RelTy>
void EhInputSection::split(ArrayRef<RelTy> rels) {
+ // getReloc expects the relocations to be sorted by r_offset. See the comment
+ // in scanRelocs.
+ SmallVector<RelTy, 0> storage;
+ rels = sortRels(rels, storage);
+
unsigned relI = 0;
for (size_t off = 0, end = data().size(); off != end;) {
size_t size = readEhRecordSize(this, off);
@@ -1426,8 +1451,7 @@ SectionPiece *MergeInputSection::getSectionPiece(uint64_t offset) {
uint64_t MergeInputSection::getParentOffset(uint64_t offset) const {
// If Offset is not at beginning of a section piece, it is not in the map.
// In that case we need to search from the original section piece vector.
- const SectionPiece &piece =
- *(const_cast<MergeInputSection *>(this)->getSectionPiece (offset));
+ const SectionPiece &piece = *getSectionPiece(offset);
uint64_t addend = offset - piece.inputOff;
return piece.outputOff + addend;
}