From ee81a705f753ae168f913b11d0ac226e2892228a Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 17 Apr 2024 07:37:58 -0400 Subject: [PATCH] [ADLT] Generate output rel info. Change-Id: I9dbdb2dfef29e28a87685ed33884dd0260a1ecb7 Signed-off-by: Anton Volkov --- lld/ELF/Config.h | 6 ++++ lld/ELF/InputFiles.cpp | 8 +++-- lld/ELF/InputFiles.h | 9 +++-- lld/ELF/Relocations.cpp | 49 +++++++++++++++++++++---- lld/ELF/SyntheticSections.cpp | 10 +++--- lld/ELF/SyntheticSections.h | 2 +- lld/ELF/Writer.cpp | 67 +++++++++++++++++++++++++++++++---- 7 files changed, 127 insertions(+), 24 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 94e863502a89..9d93f0cfa638 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -404,6 +404,12 @@ struct Ctx { llvm::DenseMap> backwardReferences; + + // ADLT stuff. + // From input .rela.dyn, .rela.plt: + // Keep input library indexes that are needed for got/plt symbol + llvm::DenseMap> + gotPltInfoAdlt; // sym, soFile->ctxIdx array; }; // The only instance of Ctx struct. diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 8ff0f4361e8f..8be3a255cbde 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1647,13 +1647,12 @@ template void SharedFileExtended::parseForAdlt() { this->allSymbols.push_back(cast(d)); } - bool isDebug = false; + bool isDebug = false; // debug hint if (!isDebug) return; const ELFFile obj = this->getObj(); ArrayRef objSections = this->template getELFShdrs(); - StringRef shstrtab = getShStrTab(objSections); lld::outs() << "Parse symbols from .symtab:\n"; auto p = obj.getSection(symTabSecIdx); @@ -1680,7 +1679,7 @@ template void SharedFileExtended::parseForAdlt() { lld::outs() << "Parse offsets of some sections:\n"; for (const Elf_Shdr &sec : objSections) { - auto name = check(obj.getSectionName(sec, shstrtab)); + auto name = check(obj.getSectionName(sec)); if (name == ".init_array" || name == ".fini_array" || name == ".data" || name == ".data.rel.ro" || name == ".bss.rel.ro" || name == ".bss") traceElfSection(sec); @@ -1945,6 +1944,9 @@ template void SharedFileExtended::parseDynamics() { verneedSec = &sec; break; } + auto secName = check(this->getObj().getSectionName(sec)); + if (secName == ".got.plt") + gotPltSecIdx = secIdx; secIdx++; } diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 6279f81ad150..dce2d1bda741 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -450,15 +450,20 @@ public: int symTabSecIdx = 0; int symTabShndxSecIdx = 0; int eFirstGlobal = 0; + int gotPltSecIdx = 0; // .symtab's start of local symbols owned by library - llvm::Optional sharedLocalSymbolIndex; + llvm::Optional sharedLocalSymbolIndex; // .symtab's start of global symbols owned by library llvm::Optional sharedGlobalSymbolIndex; + // Index of this file in context (struct Ctx) + unsigned ctxIdx = 0; // Output information data: llvm::SetVector programHeaderIndexes; - // TODO: dynamic relocation indexes + // From input .rela.dyn, .rela.plt: + llvm::SetVector dynRelIndexes; + llvm::SetVector pltRelIndexes; // SharedFile compability layer: // This is actually a vector of Elf_Verdef pointers. diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 7ef8307d0636..ff8f1002ab44 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1304,6 +1304,16 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym, return 0; } +template +static void trackDynRelocAdlt(SharedFileExtended *soFile) { + soFile->dynRelIndexes.insert(mainPart->relaDyn->relocs.size() - 1); +} + +template +static void trackGotPltAdlt(Symbol *sym, SharedFileExtended *soFile) { + ctx->gotPltInfoAdlt[sym].push_back(soFile->ctxIdx); +} + // ADLT BEGIN template void RelocationScanner::tracePushRelocADLT(InputSectionBase &isec, @@ -1360,21 +1370,24 @@ void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r, title + " " + toString(r->type) + ": r->sym not found! addend: "; Defined *d = file->findDefinedSymbol(r->addend, failTitle); assert(d); + r->sym = d; r->addend -= d->section->address + d->value; - addRelativeReloc(*secWhere, r->offset, *d, r->addend, r->expr, + addRelativeReloc(*secWhere, r->offset, *r->sym, r->addend, r->expr, r->type); + trackDynRelocAdlt(file); return; } case R_AARCH64_GLOB_DAT: assert(r->sym->exportDynamic); - r->sym->needsGot = 1; - if (r->sym->isUndefined()) - r->sym->needsPlt = 1; + if (!r->sym->needsGot) + r->sym->needsGot = 1; + trackGotPltAdlt(r->sym, file); return; case R_AARCH64_JUMP_SLOT: assert(r->sym->exportDynamic); - if (r->sym->isUndefined()) + if (r->sym->isUndefined() && !r->sym->needsPlt) r->sym->needsPlt = 1; + trackGotPltAdlt(r->sym, file); return; // abs relocs case R_AARCH64_ABS32: @@ -1386,6 +1399,7 @@ void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r, sec.getPartition().relaDyn->addSymbolReloc(target.symbolicRel, *secWhere, r->offset, *r->sym, r->addend, r->type); + trackDynRelocAdlt(file); return; } sec.relocations.push_back(*r); @@ -1428,6 +1442,10 @@ void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r, return; // tls relocs case R_AARCH64_TLSDESC: + if (fromDynamic && !r->sym->needsTlsDesc) + r->sym->needsTlsDesc = 1; + trackDynRelocAdlt(file); + return; case R_AARCH64_TLSDESC_CALL: case R_AARCH64_TLS_TPREL64: case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: @@ -1795,6 +1813,16 @@ static bool handleNonPreemptibleIfunc(Symbol &sym) { return true; } +template static void addGotPltIndexAdlt(Symbol *s, bool isPlt) { + auto &vec = ctx->gotPltInfoAdlt[s]; + for (auto &it : vec) { + auto *soFile = cast>(ctx->sharedFilesExtended[it]); + auto &entries = isPlt ? in.relaPlt->relocs : mainPart->relaDyn->relocs; + auto &output = isPlt ? soFile->pltRelIndexes : soFile->dynRelIndexes; + output.insert(entries.size() - 1); + } +} + void elf::postScanRelocations() { auto fn = [](Symbol &sym) { if (handleNonPreemptibleIfunc(sym)) @@ -1804,10 +1832,16 @@ void elf::postScanRelocations() { if (!sym.allocateAux()) return; - if (sym.needsGot) + if (sym.needsGot) { addGotEntry(sym); - if (sym.needsPlt) + if (config->adlt) + invokeELFT(addGotPltIndexAdlt, &sym, false); + } + if (sym.needsPlt) { addPltEntry(*in.plt, *in.gotPlt, *in.relaPlt, target->pltRel, sym); + if (config->adlt) + invokeELFT(addGotPltIndexAdlt, &sym, true); + } if (sym.needsCopy) { if (sym.isObject()) { invokeELFT(addCopyRelSymbol, cast(sym)); @@ -1841,6 +1875,7 @@ void elf::postScanRelocations() { mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible( target->tlsDescRel, *in.got, in.got->getTlsDescOffset(sym), sym, target->tlsDescRel); + invokeELFT(addGotPltIndexAdlt, &sym, false); } if (sym.needsTlsGd) { in.got->addDynTlsEntry(sym); diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 73a11c1aedd7..ebf5d9fe056a 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4085,7 +4085,7 @@ static_assert( "blob array reference occupies 16 bytes in PSOD" ); -static_assert(sizeof(adltBlobStartMark) == 4, +static_assert(sizeof(adltBlobStartMark) == 4, "0xad17 consist of 4 bytes" ); @@ -4110,12 +4110,12 @@ template void AdltSection::finalizeContents() { soInputs.clear(); soInputs.reserve(ctx->sharedFilesExtended.size()); - for (InputFile* file : ctx->sharedFilesExtended) { + for (InputFile* file : ctx->sharedFilesExtended) { auto* soext = cast>(file); soInputs.push_back(makeSoData(soext)); } - assert((soInputs.size() < 1<<16) && + assert((soInputs.size() < 1<<16) && "the number of input libs exeeds ELF limit on number of sections"); const Elf64_Half soNum = soInputs.size(); @@ -4332,7 +4332,7 @@ adlt_blob_array_t AdltSection::writeDtNeeded( needIndexes.push_back(adlt_dt_needed_index_t{ need_data.psodIndex.has_value(), // .hasInternalPSOD need_data.psodIndex.value_or(0), // .PSODindex - need_data.str.strtabOff, // .sonameOffset + need_data.str.strtabOff, // .sonameOffset }); } @@ -4380,7 +4380,7 @@ void AdltSection::writeTo(uint8_t* buf) { size_t blobOff = 0; memcpy(blobBuf + blobOff, &adltBlobStartMark, sizeof(adltBlobStartMark)); blobOff += sizeof(adltBlobStartMark); - + // psod-related data for(const auto& it : llvm::enumerate(soInputs)) { const auto& soData = it.value(); diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 9afb747f29c2..2501d011715b 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -1239,7 +1239,7 @@ public: SectionString str; llvm::Optional psodIndex; }; - + using SectionStringVector = SmallVector; using DtNeededsVec = SmallVector; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index fb2f260f3d94..57cadbb6f7e8 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -116,7 +116,7 @@ static void removeEmptyPTLoad(SmallVector &phdrs) { for (OutputSection *sec : outputSections) if (removed.count(sec->ptLoad)) sec->ptLoad = nullptr; - + if (config->adlt) { assert(it == phdrs.end() && "adlt: ph-index in .adlt invalid due to shift"); } @@ -1871,6 +1871,45 @@ static void removeUnusedSyntheticSections() { }); } +template static void adltTraceRelocationIndexes() { + auto &relaDyn = mainPart->relaDyn; + assert(!relaDyn->relocs.empty() && "ADLT: relaDyn can't be empty!"); + assert(!in.relaPlt->relocs.empty() && "ADLT: relaPlt can't be empty!"); + + bool adltRelocsTrace = false; // debug hint + if (adltRelocsTrace) { + auto traceRelocInfo = [&](auto *relSec, auto &outIndexes) -> void { + bool isPlt = relSec == in.relaPlt.get(); + lld::outs() << (isPlt ? "Plt" : "Dyn") << " indexes: "; + for (auto &it : outIndexes) // simple print + lld::outs() << it << ' '; + lld::outs() << '\n'; + for (auto &it : outIndexes) // print relocs + if (DynamicReloc *rel = &relSec->relocs[it]) + lld::outs() << it << ": " << rel->inputSec->name << " + 0x" + << utohexstr(rel->offsetInSec) << "\t" + << toString(rel->type) << "\t" << rel->sym->getName() + << " + 0x" << utohexstr(rel->addend) << '\n'; + }; + lld::outs() << "[ADLT]\n"; + lld::outs() << "Dyn relocs (" << relaDyn->relocs.size() << ")\n"; + lld::outs() << "Plt relocs (" << in.relaPlt->relocs.size() << ")\n"; + for (auto *file : ctx->sharedFilesExtended) + if (auto *soFile = cast>(file)) { + lld::outs() << "[ADLT] " << soFile->soName << ":\n"; + traceRelocInfo(relaDyn.get(), soFile->dynRelIndexes); + traceRelocInfo(in.relaPlt.get(), soFile->pltRelIndexes); + } + } + for (auto *file : ctx->sharedFilesExtended) { + __attribute__((unused)) auto *soFile = cast>(file); + assert(!soFile->dynRelIndexes.empty() && + "ADLT: relaDyn indexes can't be empty!"); + assert(!soFile->pltRelIndexes.empty() && + "ADLT: relaPlt indexes can't be empty!"); + } +} + // Create output section objects and add them to OutputSections. template void Writer::finalizeSections() { Out::preinitArray = findSection(".preinit_array"); @@ -1962,11 +2001,25 @@ template void Writer::finalizeSections() { // copy relocations, etc. Note that relocations for non-alloc sections are // directly processed by InputSection::relocateNonAlloc. if (config->adlt) - for (InputFile *file : ctx->sharedFilesExtended) - for (InputSectionBase *sec : file->getSections()) { - if (sec && sec->isLive()) - scanRelocations(*sec); - } + for (auto &it : llvm::enumerate(ctx->sharedFilesExtended)) { + auto *soFile = cast>(it.value()); + soFile->ctxIdx = it.index(); + auto sections = soFile->getSections(); + // scan .rela.dyn (base: SHT_NULL) + scanRelocations(*sections[0]); + // scan .rela.plt (base: .got.plt) + scanRelocations(*sections[soFile->gotPltSecIdx]); + // scan other sections + // excluding .rela.plt and .rela.dyn + auto gotPltIdx = static_cast(soFile->gotPltSecIdx); + auto isNotExcludedIdx = [&](auto idx) { + return idx != 0 && idx != gotPltIdx; + }; + for (auto &it : llvm::enumerate(soFile->getSections())) + if (InputSectionBase *sec = it.value()) + if (sec && sec->isLive() && isNotExcludedIdx(it.index())) + scanRelocations(*sec); + } else for (InputSectionBase *sec : inputSections) if (sec->isLive() && isa(sec) && (sec->flags & SHF_ALLOC)) @@ -2164,6 +2217,8 @@ template void Writer::finalizeSections() { finalizeSynthetic(part.verNeed.get()); finalizeSynthetic(part.dynamic.get()); } + if (config->adlt) // check ouput relocation indexes + adltTraceRelocationIndexes(); } if (!script->hasSectionsCommand && !config->relocatable) -- Gitee