diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 701df85adde9cb9f29ee2a383559b9df4b7fcbc7..9e61fe388d43a56d93df4a6f25fd73e5c66c4661 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -415,10 +415,6 @@ struct Ctx { // OHOS_LOCAL begin struct AdltCtx { - template SharedFileExtended *getSoExt(InputFile *file) { - return cast>(file); - } - llvm::SetVector commonProgramHeaders; bool withCfi = false; // From input .rela.dyn, .rela.plt: @@ -426,12 +422,29 @@ struct Ctx { llvm::DenseMap> gotPltInfo; // sym, soFile->orderIdx array; } adlt; + + template SharedFileExtended *getSoExt(InputFile *file); + template SharedFileExtended *getSoExt(unsigned orderId); // OHOS_LOCAL end }; // The only instance of Ctx struct. extern std::unique_ptr ctx; +// OHOS_LOCAL begin +template +SharedFileExtended *Ctx::getSoExt(InputFile *file) { + assert(file); + return cast>(file); +} + +template +SharedFileExtended *Ctx::getSoExt(unsigned orderId) { + assert(orderId < sharedFilesExtended.size()); + return getSoExt(sharedFilesExtended[orderId]); +} +// OHOS_LOCAL end + // The first two elements of versionDefinitions represent VER_NDX_LOCAL and // VER_NDX_GLOBAL. This helper returns other elements. static inline ArrayRef namedVersionDefs() { diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 23d9512dfb1d300b28943a40514d7425b5487261..bbdb66c1bd0faba74dedfc7ce86f90d6595246f8 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1978,6 +1978,16 @@ template void SharedFileExtended::parseDynamics() { case SHT_GNU_verneed: verneedSec = &sec; break; + case SHT_RELR: + config->relrPackDynRelocs = true; + relrDynSec = &sec; + break; + case SHT_ANDROID_RELA: + config->androidPackDynRelocs = true; + andrPackSec = &sec; + break; + default: + break; } auto secName = check(this->getObj().getSectionName(sec)); if (secName == ".got.plt") diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 65152c33727952018484e56c456d731edfe508f5..2b2f7cfea735a5718cbd8cebc44c63933aa8cf39 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -455,6 +455,10 @@ public: int eFirstGlobal = 0; int gotPltSecIdx = 0; + // related to config->relrPackDynRelocs and config->androidPackDynRelocs + const Elf_Shdr *relrDynSec = nullptr; + const Elf_Shdr *andrPackSec = nullptr; + // .symtab's start of local symbols owned by library llvm::Optional sharedLocalSymbolIndex; // .symtab's start of global symbols owned by library diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 7984401410256df7c663c07ff5d144a63cc9947e..2b7e82ba3b10a3a89459c26c82252abf391583a9 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -433,15 +433,80 @@ private: size_t i = 0; }; +// OHOS_LOCAL begin +class AdltRelocationScanner { +public: + explicit AdltRelocationScanner(InputSectionBase &sec) : sec(sec) {} + InputSectionBase &sec; + + uint32_t relSecType = SHT_NULL; + bool toProcessAux = false; + + bool isScanPackedNeeded() { + return config->adlt && sec.type == SHT_NULL && + (config->relrPackDynRelocs || config->androidPackDynRelocs); + } + bool isRelr() { return config->adlt && relSecType == SHT_RELR; } + + unsigned getDynamicRelocsCount(); + + template void process(Relocation *r, bool fromDynamic); + template void trackGotPlt(Symbol *sym); + template void trackDynReloc(); + + template std::vector scanRelr(); + template std::vector scanAndroid(); +}; + +template +std::vector AdltRelocationScanner::scanRelr() { + auto soFile = sec.getSharedFile(); + auto *shdr = soFile->relrDynSec; + if (!shdr) + return {}; + auto obj = soFile->getObj(); + auto raw = cantFail(obj.relrs(*shdr)); + relSecType = shdr->sh_type; + return obj.decode_relrs(raw); +} + +template +std::vector AdltRelocationScanner::scanAndroid() { + auto soFile = sec.getSharedFile(); + auto *shdr = soFile->andrPackSec; + if (!shdr) + return {}; + auto obj = soFile->getObj(); + relSecType = shdr->sh_type; + return cantFail(obj.android_relas(*shdr)); +} + +template void AdltRelocationScanner::trackGotPlt(Symbol *sym) { + ctx->adlt.gotPltInfo[sym].push_back(sec.getSharedFile()->orderIdx); +} + +template void AdltRelocationScanner::trackDynReloc() { + sec.getSharedFile()->dynRelIndexes.insert(getDynamicRelocsCount() - 1); +} + +unsigned AdltRelocationScanner::getDynamicRelocsCount() { + auto currentSize = isRelr() ? mainPart->relrDyn->relocs.size() + : mainPart->relaDyn->relocs.size(); + return currentSize; +} +// OHOS_LOCAL end + // This class encapsulates states needed to scan relocations for one // InputSectionBase. class RelocationScanner { public: explicit RelocationScanner(InputSectionBase &sec) - : sec(sec), getter(sec), config(elf::config.get()), target(*elf::target) { - } + : adltScanner(sec), sec(sec), getter(sec), config(elf::config.get()), + target(*elf::target) {} template void scan(ArrayRef rels); + AdltRelocationScanner adltScanner; + private: InputSectionBase &sec; OffsetGetter getter; @@ -458,16 +523,10 @@ private: int64_t computeAddend(const RelTy &rel, RelExpr expr, bool isLocal) const; bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym, uint64_t relOff) const; + void processAux(Relocation &r); void processAux(RelExpr expr, RelType type, uint64_t offset, Symbol &sym, int64_t addend) const; template void scanOne(RelTy *&i); - - // ADLT - template - void processForADLT(const RelTy &rel, Relocation *r, bool fromDynamic); - - template - void tracePushRelocADLT(InputSectionBase &isec, Relocation &r) const; }; } // namespace @@ -878,7 +937,7 @@ RelType RelocationScanner::getMipsN32RelType(RelTy *&rel) const { static void addRelativeReloc(InputSectionBase &isec, uint64_t offsetInSec, Symbol &sym, int64_t addend, RelExpr expr, - RelType type) { + RelType type, bool fromRelr=false) { Partition &part = isec.getPartition(); // Add a relative relocation. If relrDyn section is enabled, and the @@ -888,7 +947,8 @@ static void addRelativeReloc(InputSectionBase &isec, uint64_t offsetInSec, // don't store the addend values, so we must write it to the relocated // address. if (part.relrDyn && isec.alignment >= 2 && offsetInSec % 2 == 0) { - isec.relocations.push_back({expr, type, offsetInSec, addend, &sym}); + if (!fromRelr) + isec.relocations.push_back({expr, type, offsetInSec, addend, &sym}); part.relrDyn->relocs.push_back({&isec, offsetInSec}); return; } @@ -1036,6 +1096,13 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type, // sections. Given that it is ro, we will need an extra PT_LOAD. This // complicates things for the dynamic linker and means we would have to reserve // space for the extra PT_LOAD even if we end up not using it. + +// OHOS_LOCAL begin +void RelocationScanner::processAux(Relocation &r) { + processAux(r.expr, r.type, r.offset, *r.sym, r.addend); +} +// OHOS_LOCAL end + void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, Symbol &sym, int64_t addend) const { // If the relocation is known to be a link-time constant, we know no dynamic @@ -1304,38 +1371,9 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym, return 0; } +// OHOS_LOCAL begin template -static void trackDynRelocAdlt(SharedFileExtended *soFile) { - soFile->dynRelIndexes.insert(mainPart->relaDyn->relocs.size() - 1); -} - -template -static void trackGotPltAdlt(Symbol *sym, SharedFileExtended *soFile) { - ctx->adlt.gotPltInfo[sym].push_back(soFile->orderIdx); -} - -// ADLT BEGIN -template -void RelocationScanner::tracePushRelocADLT(InputSectionBase &isec, - Relocation &r) const { - auto file = sec.getSharedFile(); - auto fullOffset = isec.address + r.offset; - lld::outs() << "[ADLT] Before push: [0x" + utohexstr(fullOffset) + - "] type: " + toString(r.type) + - " expr: " + std::to_string(r.expr) + " offset: 0x" + - utohexstr(r.offset) + " addend: 0x" + utohexstr(r.addend) + - ".\n"; - lld::outs() << "section where: "; - file->traceSection(isec); - - lld::outs() << "r->sym: "; - file->traceSymbol(*r.sym); - lld::outs() << "\n"; -} - -template -void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r, - bool fromDynamic) { +void AdltRelocationScanner::process(Relocation *r, bool fromDynamic) { auto file = sec.getSharedFile(); bool isDebug = false; @@ -1353,9 +1391,6 @@ void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r, r->offset -= fromDynamic ? secWhere->address : sec.address; assert(r->type); - if (isDebug) - tracePushRelocADLT(*secWhere, *r); - // resolve relocs switch (r->type) { // dyn relocs @@ -1365,21 +1400,22 @@ void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r, r->sym = d; r->addend -= d->section->address + d->value; addRelativeReloc(*secWhere, r->offset, *r->sym, r->addend, r->expr, - r->type); - trackDynRelocAdlt(file); + r->type, isRelr()); + assert(getDynamicRelocsCount()); + trackDynReloc(); return; } case R_AARCH64_GLOB_DAT: assert(r->sym->exportDynamic); if (!r->sym->needsGot) r->sym->needsGot = 1; - trackGotPltAdlt(r->sym, file); + trackGotPlt(r->sym); return; case R_AARCH64_JUMP_SLOT: assert(r->sym->exportDynamic); if (r->sym->isUndefined() && !r->sym->needsPlt) r->sym->needsPlt = 1; - trackGotPltAdlt(r->sym, file); + trackGotPlt(r->sym); return; // abs relocs case R_AARCH64_ABS32: @@ -1388,10 +1424,10 @@ void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r, case R_AARCH64_ABS64: if (fromDynamic) { assert(r->sym->exportDynamic); - sec.getPartition().relaDyn->addSymbolReloc(target.symbolicRel, *secWhere, + sec.getPartition().relaDyn->addSymbolReloc(r->type, *secWhere, r->offset, *r->sym, r->addend, r->type); - trackDynRelocAdlt(file); + trackDynReloc(); return; } sec.relocations.push_back(*r); @@ -1403,7 +1439,7 @@ void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r, case R_AARCH64_LDST128_ABS_LO12_NC: case R_AARCH64_PREL32: case R_AARCH64_PREL64: - processAux(r->expr, r->type, r->offset, *r->sym, r->addend); + toProcessAux = true; return; // plt relocs case R_AARCH64_CALL26: @@ -1432,13 +1468,13 @@ void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r, LLVM_FALLTHROUGH; case R_AARCH64_LD64_GOT_LO12_NC: case R_AARCH64_LD64_GOTPAGE_LO15: - processAux(r->expr, r->type, r->offset, *r->sym, r->addend); + toProcessAux = true; return; // tls relocs case R_AARCH64_TLSDESC: if (fromDynamic && !r->sym->needsTlsDesc) r->sym->needsTlsDesc = 1; - trackDynRelocAdlt(file); + trackGotPlt(r->sym); return; case R_AARCH64_TLSDESC_CALL: case R_AARCH64_TLS_TPREL64: @@ -1457,11 +1493,12 @@ void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r, break; } } -// ADLT END +// OHOS_LOCAL end template void RelocationScanner::scanOne(RelTy *&i) { const RelTy &rel = *i; - uint32_t symIndex = rel.getSymbol(config->isMips64EL); + uint32_t symIndex = + adltScanner.isRelr() ? 0 : rel.getSymbol(config->isMips64EL); bool fromDynamic = false; if (config->adlt) fromDynamic = sec.getSharedFile()->isDynamicSection(sec); @@ -1498,11 +1535,15 @@ template void RelocationScanner::scanOne(RelTy *&i) { return; // Read an addend. - int64_t addend = computeAddend(rel, expr, sym.isLocal()); + int64_t addend = + adltScanner.isRelr() ? 0 : computeAddend(rel, expr, sym.isLocal()); if (config->adlt) { Relocation r = {expr, type, offset, addend, &sym}; - processForADLT(rel, &r, fromDynamic); + adltScanner.process(&r, fromDynamic); + if (adltScanner.toProcessAux) + processAux(r); + adltScanner.toProcessAux = false; return; } @@ -1716,10 +1757,15 @@ void RelocationScanner::scan(ArrayRef rels) { template void elf::scanRelocations(InputSectionBase &s) { RelocationScanner scanner(s); - if (config->adlt) { - bool isDebug = false; - if (isDebug) - lld::outs() << s.file->getName().str() + ": " + s.name.str() + '\n'; + auto &adlt = scanner.adltScanner; + if (adlt.isScanPackedNeeded()) { + auto relrs = adlt.scanRelr(); + if (!relrs.empty()) + scanner.template scan(makeArrayRef(relrs)); + auto relas = adlt.scanAndroid(); + if (!relas.empty()) + scanner.template scan(makeArrayRef(relas)); + return; } const RelsOrRelas rels = s.template relsOrRelas(); if (rels.areRelocsRel()) @@ -1809,8 +1855,8 @@ static bool handleNonPreemptibleIfunc(Symbol &sym) { template static void addGotPltIndexAdlt(Symbol *s, bool isPlt) { auto &vec = ctx->adlt.gotPltInfo[s]; - for (auto &it : vec) { - auto *soFile = cast>(ctx->sharedFilesExtended[it]); + for (auto &orderId : vec) { + auto *soFile = ctx->getSoExt(orderId); auto &entries = isPlt ? in.relaPlt->relocs : mainPart->relaDyn->relocs; auto &output = isPlt ? soFile->pltRelIndexes : soFile->dynRelIndexes; output.insert(entries.size() - 1); diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 61d52dc894b5ce2f046fd3a6d075277386f7b8bc..6b7cb546167340e847b21d1254a7b250adfc1441 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -2293,7 +2293,7 @@ void SymbolTableBaseSection::sortSymTabSymbolsInAdlt(size_t numLocals) { [makeKey](const SymbolTableEntry& lhs, const SymbolTableEntry& rhs) { return makeKey(lhs) <= makeKey(rhs); }); - + // extract file boundaries for local symbols for (auto iter = symbols.begin(); iter != localEnd; ++iter) if (auto* soext = dyn_cast_or_null>(iter->sym->file)) @@ -4382,7 +4382,7 @@ void AdltSection::finalizeOnWrite() { template void AdltSection::finalizeOnWrite(size_t idx, SoData& soData) { - auto* soext = cast>(ctx->sharedFilesExtended[idx]); + auto* soext = ctx->getSoExt(idx); // require SymbolTableBaseSection::sortSymTabSymbolsInAdlt for .symtab called soData.sharedLocalIndex = soext->sharedLocalSymbolIndex; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 6743de95cd2f016b000c1eb1930453888dafe0f7..736fb3e574466e1a00898e6e29878b851c52e2d1 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -571,17 +571,20 @@ InputSection *AdltWriter::getInputSection(OutputSection *sec) { template void AdltWriter::checkPhdrs() { for (auto *file : ctx->sharedFilesExtended) - if (auto *soFile = ctx->adlt.getSoExt(file)) + if (auto *soFile = ctx->getSoExt(file)) assert(!soFile->programHeaders.empty() && "ADLT: PHdr indexes can't be empty!"); } template void AdltWriter::checkRelocs() { + if (config->relrPackDynRelocs) + 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 : ctx->sharedFilesExtended) - if (auto *soFile = ctx->adlt.getSoExt(file)) { + if (auto *soFile = ctx->getSoExt(file)) { assert(!soFile->dynRelIndexes.empty() && "ADLT: relaDyn indexes can't be empty!"); assert(!soFile->pltRelIndexes.empty() && @@ -593,7 +596,7 @@ template void AdltWriter::trackPhdr(OutputSection *sec, PhdrEntry *phdr) { auto *isec = getInputSection(sec); if (isec && isec->file) - if (auto *soFile = ctx->adlt.getSoExt(isec->file)) { + if (auto *soFile = ctx->getSoExt(isec->file)) { soFile->programHeaders.insert(phdr); return; } @@ -622,7 +625,7 @@ template void AdltWriter::traceRelocs() { }; for (auto *file : ctx->sharedFilesExtended) - if (auto *soFile = ctx->adlt.getSoExt(file)) { + if (auto *soFile = ctx->getSoExt(file)) { lld::outs() << soFile->soName << ":\n"; lld::outs() << "Dyn relocs (" << soFile->dynRelIndexes.size() << ")"; printIndexes(soFile->dynRelIndexes); @@ -665,7 +668,7 @@ template void AdltWriter::tracePhdrs() { printPhTable(common); for (auto *file : ctx->sharedFilesExtended) - if (auto *soFile = ctx->adlt.getSoExt(file)) { + if (auto *soFile = ctx->getSoExt(file)) { auto &headers = soFile->programHeaders; lld::outs() << soFile->soName << "\n"; lld::outs() << "Program headers (" << headers.size() << ")"; @@ -2130,7 +2133,7 @@ template void Writer::finalizeSections() { for (auto &it : llvm::enumerate(ctx->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]);