diff options
Diffstat (limited to 'lld/ELF/InputSection.cpp')
-rw-r--r-- | lld/ELF/InputSection.cpp | 46 |
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; } |