From 7cc86836b84f2697ccabced840c23eef1307a85b Mon Sep 17 00:00:00 2001 From: Nikolai Kholiavin Date: Fri, 1 Mar 2024 15:01:06 +0000 Subject: [PATCH] [ADLT] Emit symbolic and improve relative relocations Make relative (R_AARCH64_RELATIVE) relocations work for offsets and addends which are not exactly the start of some symbol (which can happen for CFI-generated data, for example). Pass through and emit symbolic relocations (R_AARCH64_ABS64) against exported symbols, because they can't be applied statically, and a relative relocation might not be present for that offset. Signed-off-by: Nikolai Kholiavin --- lld/ELF/Relocations.cpp | 56 ++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 27a9bd789ee5..478a5a4252f6 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -463,7 +463,7 @@ private: template void addRelativeRelocForAdlt(const RelTy &rel, Defined &symWhere, - Defined &inputSym) const; + uint64_t offset, Defined &inputSym) const; void pushRelocAdlt(Relocation *r) const; template @@ -1308,6 +1308,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym, template void RelocationScanner::addRelativeRelocForAdlt(const RelTy &rel, Defined &symWhere, + uint64_t offset, Defined &inputSym) const { // auto file = sec.getSharedFile(); std::string title = "addRelativeRelocForAdlt: "; @@ -1318,7 +1319,8 @@ void RelocationScanner::addRelativeRelocForAdlt(const RelTy &rel, int64_t addend = computeAddend(rel, expr, false); // todo: rewrite - addend = inputSym.isSection() ? (addend - inputSym.section->address) : 0; + addend -= inputSym.section->address + inputSym.value; + /* { failTitle = "addend: 0x" + utohexstr(addend) + " was not decreased!"; @@ -1329,7 +1331,7 @@ void RelocationScanner::addRelativeRelocForAdlt(const RelTy &rel, file->traceSection(*ISec, failTitle); }*/ // finally - addRelativeReloc(*cast(symWhere.section), symWhere.value, + addRelativeReloc(*cast(symWhere.section), offset, inputSym, addend, expr, type); } @@ -1364,6 +1366,8 @@ void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r) { // parse offset (where) std::string failTitle = title + "symWhere not found! offset: "; + // Symbolize at the relocation offset. The right section is enough, even if + // symWhere doesn't start exactly at r->offset Defined *symWhere = file->findDefinedSymbol(r->offset, failTitle); file->saveSymbol(*symWhere); @@ -1372,13 +1376,6 @@ void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r) { if (r->offset == 0x1f20) // debug hint isDebug = true;*/ - // process offset - failTitle = "offset: 0x" + utohexstr(r->offset) + " was not decreased!"; - if (static_cast(r->offset - sec.address) >= 0) - r->offset -= sec.address; - else - file->traceSection(sec, failTitle); - // prepare to resolve relocs /*if (r->sym->getName().contains("_ZdlPv")) // debug hint isDebug = true;*/ @@ -1386,16 +1383,45 @@ void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r) { if (isDebug) tracePushRelocADLT(*symWhere, *r); - // resolve relocs - switch (r->type) { - // dyn relocs - case R_AARCH64_RELATIVE: + // Compute offset in the right section + uint64_t dynOffset = r->offset - symWhere->section->address; + + if (r->type == target.relativeRel) { + // Add relative relocation "against" the target symbol (the right section + // symbol is enough) failTitle = title + " " + toString(r->type) + ": r->sym not found! addend: "; if (auto *d = file->findDefinedSymbol( r->addend, failTitle, [](Defined *d) { return !d->isPreemptible; })) - addRelativeRelocForAdlt(rel, *symWhere, *d); + addRelativeRelocForAdlt(rel, *symWhere, dynOffset, *d); return; + } + + // Assume that: + // !r->sym->exportDynamic => + // symbol is defined and non-preemtible when it matters => + // relative relocation for that offset was emitted, so no extra work + // needed. + // TODO: presumably this can be optimized to a relative relocation, if r->sym + // is now defined in ADLT and non-preemtible + if (r->type == target.symbolicRel && r->sym->exportDynamic) { + // TODO: .rela.dyn might not match the original relocation section? + sec.getPartition().relaDyn->addSymbolReloc( + target.symbolicRel, cast(*symWhere->section), + dynOffset, *r->sym, r->addend, r->type); + return; + } + + // process offset + failTitle = "offset: 0x" + utohexstr(r->offset) + " was not decreased!"; + if (static_cast(r->offset - sec.address) >= 0) + r->offset -= sec.address; + else + file->traceSection(sec, failTitle); + + // resolve relocs + switch (r->type) { + // dyn relocs case R_AARCH64_GLOB_DAT: r->sym->needsGot = 1; if (r->sym->isUndefined()) -- Gitee