diff --git a/lld/ELF/Adlt.h b/lld/ELF/Adlt.h index b6751cf54607edaea0a222f7e3386cff7cfc8487..5b1dece046b64c7c7c4221826f9a923f5e19138d 100644 --- a/lld/ELF/Adlt.h +++ b/lld/ELF/Adlt.h @@ -41,6 +41,8 @@ public: llvm::SetVector commonProgramHeaders; bool withCfi = false; + bool withRelr = false; + bool withAndroidRela = false; // From input .rela.dyn, .rela.plt: // Keep input library indexes that are needed for got/plt symbol diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index df9355f3b62573f97a0a18ad1e2e828a2e9df4ee..dc1e2e9a20ac478bb2c969d6b4b331e791c9bcca 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1784,6 +1784,18 @@ template void SharedFileExtended::parseDynamics() { case SHT_SYMTAB_SHNDX: symTabShndxSecIdx = secIdx; break; + case SHT_RELR: + if (config->adltTrace && !adltCtx->withRelr) + lld::outs() << "[ADLT] RELR packing mode is ON\n"; + adltCtx->withRelr = true; + relrDynSec = &sec; + break; + case SHT_ANDROID_RELA: + if (config->adltTrace && !adltCtx->withAndroidRela) + lld::outs() << "[ADLT] ANDROID_RELA packing mode is ON\n"; + adltCtx->withAndroidRela = true; + andrPackSec = &sec; + break; case SHT_GNU_versym: versymSec = &sec; break; diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 41f1561bb54510d5989180469742abf8b4e1178c..8829937d28926a19ee05013bd04da6eb062bfc62 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -444,10 +444,16 @@ public: // .symtab's start of global symbols owned by library llvm::Optional sharedGlobalSymbolIndex; + // related to relr and android_rela sections + const Elf_Shdr *relrDynSec = nullptr; + const Elf_Shdr *andrPackSec = nullptr; + // Output information data: llvm::SetVector programHeaders; // From input .rela.dyn, .rela.plt: + llvm::SetVector + relrDynIndexes; // only Relative relocs (if .relr.dyn exists) llvm::SetVector relaDynIndexes; // If not .relr.dyn exists, contains only Got/Abs/Tls // relocs. Otherwise contains relative relocs also. diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index c67ec01bf27ae03c119a1821670d080f85b13121..d3d94f0924a10f851537574dde0198e680baa1b1 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -438,9 +438,9 @@ private: // OHOS_LOCAL begin template class AdltRelocationScanner { public: - AdltRelocationScanner(InputSectionBase &isec) + AdltRelocationScanner(InputSectionBase &isec, bool isRelr = false) : file(adltCtx->getSoExt(isec.file)), - fromDynamic(file->isDynamicSection(&isec)), sec(isec) {} + fromDynamic(file->isDynamicSection(&isec)), sec(isec), isRelr(isRelr) {} SharedFileExtended *getSoExt() { return file; } @@ -451,12 +451,17 @@ public: void trackRelatives(); void trackDynamics(); + bool isScanPackedNeeded(); bool toProcessAux = false; + std::vector scanRelr(); + std::vector scanAndrRela(); + private: SharedFileExtended *file = nullptr; bool fromDynamic = false; InputSectionBase &sec; + bool isRelr = false; }; template @@ -465,14 +470,45 @@ void AdltRelocationScanner::trackGotPlt(Symbol *sym) { } template void AdltRelocationScanner::trackRelatives() { - auto count = mainPart->relaDyn->relocs.size(); - file->relaDynIndexes.insert(count - 1); + auto count = isRelr ? mainPart->relrDyn->relocs.size() + : mainPart->relaDyn->relocs.size(); + (isRelr ? file->relrDynIndexes : file->relaDynIndexes).insert(count - 1); } template void AdltRelocationScanner::trackDynamics() { auto count = mainPart->relaDyn->relocs.size(); file->relaDynIndexes.insert(count - 1); } + +template bool AdltRelocationScanner::isScanPackedNeeded() { + return sec.type == SHT_NULL && + (adltCtx->withRelr || adltCtx->withAndroidRela); +} + +template +std::vector AdltRelocationScanner::scanRelr() { + auto *shdr = file->relrDynSec; + if (!shdr) + return {}; + auto obj = file->getObj(); + auto raw = cantFail(obj.relrs(*shdr)); + return obj.decode_relrs(raw); +} + +template +std::vector AdltRelocationScanner::scanAndrRela() { + auto *shdr = file->andrPackSec; + if (!shdr) + return {}; + auto obj = file->getObj(); + return cantFail(obj.android_relas(*shdr)); +} + +static void addRelrReloc(InputSectionBase &isec, uint64_t offsetInSec) { + Partition &part = isec.getPartition(); + assert(part.relrDyn && isec.alignment >= 2 && offsetInSec % 2 == 0); + part.relrDyn->relocs.push_back({&isec, offsetInSec}); +} // OHOS_LOCAL end // This class encapsulates states needed to scan relocations for one @@ -483,6 +519,7 @@ public: : sec(sec), getter(sec), config(elf::config.get()), target(*elf::target) { } template void scan(ArrayRef rels); + bool isRelr = false; // OHOS_LOCAL private: InputSectionBase &sec; @@ -1366,12 +1403,16 @@ void AdltRelocationScanner::process(Relocation *r) { switch (r->type) { // dyn relocs case R_AARCH64_RELATIVE: { - Defined *d = &file->getDefinedLocalSym(r->addend); - assert(d && "R_AARCH64_RELATIVE: r->sym not found by addend!"); - r->sym = d; - r->addend -= d->section->address + d->value; - addRelativeReloc(secWhere, r->offset, *r->sym, r->addend, r->expr, - r->type); + if (adltCtx->withRelr) { + addRelrReloc(secWhere, r->offset); + } else { + Defined *d = &file->getDefinedLocalSym(r->addend); + assert(d && "R_AARCH64_RELATIVE: r->sym not found by addend!"); + r->sym = d; + r->addend -= d->section->address + d->value; + addRelativeReloc(secWhere, r->offset, *r->sym, r->addend, r->expr, + r->type); + } trackRelatives(); return; } @@ -1466,7 +1507,7 @@ template void RelocationScanner::scanOne(RelTy *&i) { const RelTy &rel = *i; std::unique_ptr> adltScanner = nullptr; if (config->adlt) - adltScanner = std::make_unique>(sec); + adltScanner = std::make_unique>(sec, isRelr); uint32_t symIndex = rel.getSymbol(config->isMips64EL); Symbol &sym = config->adlt ? adltScanner->getSymbol(symIndex) @@ -1500,7 +1541,7 @@ template void RelocationScanner::scanOne(RelTy *&i) { return; // Read an addend. - int64_t addend = computeAddend(rel, expr, sym.isLocal()); + int64_t addend = isRelr ? 0 : computeAddend(rel, expr, sym.isLocal()); if (config->adlt) { Relocation r = {expr, type, offset, addend, &sym}; @@ -1720,6 +1761,23 @@ void RelocationScanner::scan(ArrayRef rels) { template void elf::scanRelocations(InputSectionBase &s) { RelocationScanner scanner(s); + // OHOS_LOCAL begin + if (config->adlt) { + auto adltScanner = std::make_unique>(s); + if (adltScanner->isScanPackedNeeded()) { + auto relrs = adltScanner->scanRelr(); + if (!relrs.empty()) { + scanner.isRelr = true; + scanner.template scan(makeArrayRef(relrs)); + scanner.isRelr = false; + } + auto relas = adltScanner->scanAndrRela(); + if (!relas.empty()) + scanner.template scan(makeArrayRef(relas)); + return; + } + } + // OHOS_LOCAL end const RelsOrRelas rels = s.template relsOrRelas(); if (rels.areRelocsRel()) scanner.template scan(rels.rels); diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 491a61dd15da04be1d3469dd45c4c24416b19e33..638db635494ddf0567093f42189f6b5eb470dd03 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4067,7 +4067,7 @@ static_assert(sizeof(adlt_section_header_t) == 56, "please update version if header has been changed" ); -static_assert(sizeof(adlt_psod_t) == 160, +static_assert(sizeof(adlt_psod_t) == 176, "please udpate version if adlt_psod_t layout or content changed" ); @@ -4201,6 +4201,7 @@ AdltSection::makeSoData(const SharedFileExtended* soext) { data.initArrayName = soext->getUniqueName(".init_array"); data.finiArrayName = soext->getUniqueName(".fini_array"); + data.relrDynIndx = soext->relrDynIndexes.getArrayRef(); data.relaDynIndx = soext->relaDynIndexes.getArrayRef(); data.relaPltIndx = soext->relaPltIndexes.getArrayRef(); @@ -4251,6 +4252,7 @@ adlt_psod_t AdltSection::serialize(const SoData& soData) const { soData.sharedGlobalIndex.value_or(0), }, // .sharedGlobalSymbolIndex adlt_blob_u16_array_t {}, // .phIndexes, filled in writeTo + adlt_blob_u32_array_t {}, // .relrDynIndx, filled in writeTo adlt_blob_u32_array_t {}, // .relaDynIndx, filled in writeTo adlt_blob_u32_array_t {}, // .relaPltIndx, filled in writeTo }; @@ -4270,6 +4272,7 @@ size_t AdltSection::estimateBlobSize() const { for (const auto& soData: soInputs) { blobSize += sizeof(adlt_dt_needed_index_t) * soData.dtNeededs.size(); blobSize += sizeof(uint16_t) * soData.programHeadersAllocated; + blobSize += sizeof(uint32_t) * soData.relrDynIndx.size(); blobSize += sizeof(uint32_t) * soData.relaDynIndx.size(); blobSize += sizeof(uint32_t) * soData.relaPltIndx.size(); }; @@ -4427,6 +4430,9 @@ void AdltSection::writeTo(uint8_t* buf) { const auto& soData = it.value(); auto& psod = psods[it.index()]; + psod.relrDynIndx = writeArray(blobBuf, blobOff, soData.relrDynIndx); + blobOff += psod.relrDynIndx.size; + psod.relaDynIndx = writeArray(blobBuf, blobOff, soData.relaDynIndx); blobOff += psod.relaDynIndx.size; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index b51c85ce2ea810c1eab4d880926a0b39dc16e9a6..eb1e6bd9fa2d5a35fade87544e607f2a684bad5a 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -1263,6 +1263,7 @@ public: ArrayRef programHeaders; SmallVector phIndexes; + ArrayRef relrDynIndx; ArrayRef relaDynIndx; ArrayRef relaPltIndx; }; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 93fd33ccb2b9f1cf12d28e30dfa3d9165d0e3286..8febe7e917b69df1720fdabb8ea3406c23141bfb 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -381,7 +381,8 @@ template void elf::createSyntheticSections() { add(*part.memtagAndroidNote); } - if (config->androidPackDynRelocs) + if (config->androidPackDynRelocs || + (config->adlt && adltCtx->withAndroidRela)) part.relaDyn = std::make_unique>(relaDynName); else @@ -417,7 +418,7 @@ template void elf::createSyntheticSections() { add(*part.relaDyn); } - if (config->relrPackDynRelocs) { + if (config->relrPackDynRelocs || (config->adlt && adltCtx->withRelr)) { part.relrDyn = std::make_unique>(); add(*part.relrDyn); } @@ -509,9 +510,14 @@ template void elf::createSyntheticSections() { // that would cause a section type mismatch. However, because the Android // dynamic loader reads .rel.plt after .rel.dyn, we can get the desired // behaviour by placing the iplt section in .rel.plt. + + // OHOS_LOCAL begin + bool adltWithAndroidRela = config->adlt && adltCtx->withAndroidRela; + bool androidPackNeeded = config->androidPackDynRelocs || adltWithAndroidRela; in.relaIplt = std::make_unique>( - config->androidPackDynRelocs ? in.relaPlt->name : relaDynName, + androidPackNeeded ? in.relaPlt->name : relaDynName, /*sort=*/false); + // OHOS_LOCAL end add(*in.relaIplt); if ((config->emachine == EM_386 || config->emachine == EM_X86_64) && @@ -550,19 +556,73 @@ template void elf::createSyntheticSections() { // OHOS_LOCAL begin namespace { -static struct AdltWriter { +class AdltTracePrinter { +public: + void printRelocsHead(SyntheticSection *relSec, + llvm::SetVector indexes); + void printRelrTable(RelrBaseSection *relSec, + llvm::SetVector indexes); + void printRelaTable(RelocationBaseSection *relSec, + llvm::SetVector indexes); +private: + void printIndexes(llvm::SetVector indexes); + StringRef getSymbolName(Symbol *sym); +}; + +struct AdltWriter { InputSection *getInputSection(OutputSection *sec); StringRef phdrTypeToStr(uint32_t p_type); - template void checkPhdrs(); - template void checkRelocs(); + template void checkPhdrs(); + template void checkRelocs(); - template void trackPhdr(OutputSection *sec, PhdrEntry *phdr); - template void traceRelocs(); - template void tracePhdrs(); -} adltWriter; + template void trackPhdr(OutputSection *sec, PhdrEntry *phdr); + template void traceRelocs(); + template void tracePhdrs(); +}; +static AdltWriter adltWriter; } // namespace +void AdltTracePrinter::printRelocsHead(SyntheticSection *relSec, + llvm::SetVector indexes) { + lld::outs() << relSec->name << " relocs (" << indexes.size() << "): "; + printIndexes(indexes); +} + +void AdltTracePrinter::printRelrTable(RelrBaseSection *relSec, + llvm::SetVector indexes) { + SmallVector &relocs = relSec->relocs; + for (auto &it : indexes) // print relocs + if (RelativeReloc *rel = &relocs[it]) + lld::outs() << it << ":\t" << rel->inputSec->name << " + 0x" + << utohexstr(rel->offsetInSec) << "\t" + << toString(R_AARCH64_RELATIVE) << "\t" << "0x" + << utohexstr(rel->getOffset()) << '\n'; +} +void AdltTracePrinter::printRelaTable(RelocationBaseSection *relSec, + llvm::SetVector indexes) { + SmallVector relocs = relSec->relocs; + for (auto &it : indexes) // print relocs + if (DynamicReloc *rel = &relocs[it]) + lld::outs() << it << ":\t" << rel->inputSec->name << " + 0x" + << utohexstr(rel->offsetInSec) << "\t" << toString(rel->type) + << "\t" << getSymbolName(rel->sym) << " + 0x" + << utohexstr(rel->addend) << '\n'; +} + +void AdltTracePrinter::printIndexes(llvm::SetVector indexes) { + for (auto &it : indexes) + lld::outs() << it << ' '; + lld::outs() << "\n"; +} +StringRef AdltTracePrinter::getSymbolName(Symbol *sym) { + if (sym->getName().empty() && sym->isSection()) { + Defined *d = cast(sym); + return d->section->name; + } + return sym->getName(); +} + InputSection *AdltWriter::getInputSection(OutputSection *sec) { if (!sec || !sec->hasInputSections || sec->commands.empty()) return nullptr; @@ -581,11 +641,17 @@ template void AdltWriter::checkPhdrs() { } template void AdltWriter::checkRelocs() { + if (adltCtx->withRelr) + assert(!mainPart->relrDyn->relocs.empty() && + "ADLT: relrDyn can't be empty!"); assert(!mainPart->relaDyn->relocs.empty() && "ADLT: relaDyn can't be empty!"); assert(!in.relaPlt->relocs.empty() && "ADLT: relaPlt can't be empty!"); for (auto *file : adltCtx->sharedFilesExtended) if (auto *soFile = adltCtx->getSoExt(file)) { + if (adltCtx->withRelr) + assert(!soFile->relrDynIndexes.empty() && + "ADLT: .relr.dyn indexes can't be empty!"); assert(!soFile->relaDynIndexes.empty() && "ADLT: relaDyn indexes can't be empty!"); assert(!soFile->relaPltIndexes.empty() && @@ -605,44 +671,29 @@ void AdltWriter::trackPhdr(OutputSection *sec, PhdrEntry *phdr) { template void AdltWriter::traceRelocs() { lld::outs() << "[ADLT]\n"; - auto dynRelsSize = mainPart->relaDyn->relocs.size(); - lld::outs() << "Dyn relocs (" << dynRelsSize << ")\n"; - lld::outs() << "Plt relocs (" << in.relaPlt->relocs.size() << ")\n"; - - auto printIndexes = [&](auto &vec) { - lld::outs() << ": "; - for (auto &it : vec) - lld::outs() << it << ' '; - lld::outs() << "\n"; + auto &part = mainPart; + auto dynRelsSize = part->relaDyn->relocs.size(); + if (adltCtx->withRelr) + dynRelsSize += part->relrDyn->relocs.size(); + lld::outs() << "Dyn relocs (" << dynRelsSize << ")\n" + << "Plt relocs (" << in.relaPlt->relocs.size() << ")\n"; + AdltTracePrinter printer; + auto printHeadAndRelaTable = [&](auto *sec, auto indexes) { + printer.printRelocsHead(sec, indexes); + printer.printRelaTable(sec, indexes); }; - auto printSym = [&](Symbol *sym) { - if (sym->getName().empty() && sym->isSection()) { - Defined *d = cast(sym); - return d->section->name; - } - return sym->getName(); - }; - - auto printRelaTable = [&](auto *relSec, auto &outIndexes) { - for (auto &it : outIndexes) // print relocs - if (DynamicReloc *rel = &relSec->relocs[it]) - lld::outs() << it << ":\t" << rel->inputSec->name << " + 0x" - << utohexstr(rel->offsetInSec) << "\t" - << toString(rel->type) << "\t" << printSym(rel->sym) - << " + 0x" << utohexstr(rel->addend) << '\n'; - }; - - for (auto *file : adltCtx->sharedFilesExtended) - if (auto *soFile = adltCtx->getSoExt(file)) { - lld::outs() << soFile->soName << ":\n"; - lld::outs() << ".rela.dyn relocs (" << soFile->relaDynIndexes.size() << ")"; - printIndexes(soFile->relaDynIndexes); - printRelaTable(mainPart->relaDyn.get(), soFile->relaDynIndexes); - - lld::outs() << ".rela.plt relocs (" << soFile->relaPltIndexes.size() << ")"; - printIndexes(soFile->relaPltIndexes); - printRelaTable(in.relaPlt.get(), soFile->relaPltIndexes); + for (auto *rawFile : adltCtx->sharedFilesExtended) + if (auto *f = adltCtx->getSoExt(rawFile)) { + lld::outs() << f->soName << ":\n"; + // relative, dynamic + if (adltCtx->withRelr) { + printer.printRelocsHead(part->relrDyn.get(), f->relrDynIndexes); + printer.printRelrTable(part->relrDyn.get(), f->relrDynIndexes); + } + printHeadAndRelaTable(part->relaDyn.get(), f->relaDynIndexes); + // plt + printHeadAndRelaTable(in.relaPlt.get(), f->relaPltIndexes); } } @@ -2142,7 +2193,7 @@ template void Writer::finalizeSections() { for (auto &it : llvm::enumerate(adltCtx->sharedFilesExtended)) { auto *soFile = cast>(it.value()); auto sections = soFile->getSections(); - // scan .rela.dyn (base: SHT_NULL) + // scan .rela.dyn or/and .relr.dyn (base: SHT_NULL) scanRelocations(*sections[0]); // scan .rela.plt (base: .got.plt) scanRelocations(*sections[soFile->gotPltSecIdx]); diff --git a/llvm/include/llvm/BinaryFormat/ADLTSection.h b/llvm/include/llvm/BinaryFormat/ADLTSection.h index 6d57903cdd09deae23b0790d0db0237e8b032713..04cc3fba347757c283ddf9a447da8e02d67328de 100644 --- a/llvm/include/llvm/BinaryFormat/ADLTSection.h +++ b/llvm/include/llvm/BinaryFormat/ADLTSection.h @@ -93,7 +93,8 @@ typedef struct { adlt_blob_array_t dtNeeded; // array of adlt_dt_needed_index_t[] elems adlt_cross_section_ref_t sharedLocalSymbolIndex; adlt_cross_section_ref_t sharedGlobalSymbolIndex; - adlt_blob_u16_array_t phIndexes; // program header indexes, typeof(e_phnum) + adlt_blob_u16_array_t phIndexes; // program header indexes, typeof(e_phnum) + adlt_blob_u32_array_t relrDynIndx; // .relr.dyn dependent indexes, raw list adlt_blob_u32_array_t relaDynIndx; // .rela.dyn dependent indexes, raw list adlt_blob_u32_array_t relaPltIndx; // .rela.plt dependent indexes, raw list } adlt_psod_t; @@ -112,7 +113,7 @@ typedef struct { static const char adltBlobStartMark[4] = {0xA, 0xD, 0x1, 0x7}; -static const adlt_semver_t adltSchemaVersion = {1, 1, 0}; +static const adlt_semver_t adltSchemaVersion = {1, 2, 0}; #ifdef __cplusplus } // namespace adlt