From 596093faaa8ed5821f06158c1be1e518a1eebbb3 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Fri, 17 May 2024 05:42:58 -0400 Subject: [PATCH 1/2] ADLT: refactor #1. AdltCtx. Change-Id: I240eeb84ce242ee242c13d792c155be486378ae5 Signed-off-by: Anton Volkov --- lld/ELF/Adlt.h | 71 +++++++++++++++++ lld/ELF/Config.h | 20 ----- lld/ELF/Driver.cpp | 62 ++++++--------- lld/ELF/InputFiles.cpp | 60 +++++++++----- lld/ELF/InputFiles.h | 22 ++++-- lld/ELF/InputSection.cpp | 19 +++-- lld/ELF/InputSection.h | 5 -- lld/ELF/MapFile.cpp | 5 +- lld/ELF/MarkLive.cpp | 3 +- lld/ELF/Relocations.cpp | 144 +++++++++++++++++++--------------- lld/ELF/SyntheticSections.cpp | 29 +++---- lld/ELF/Writer.cpp | 39 ++++----- 12 files changed, 281 insertions(+), 198 deletions(-) create mode 100644 lld/ELF/Adlt.h diff --git a/lld/ELF/Adlt.h b/lld/ELF/Adlt.h new file mode 100644 index 000000000000..f52c663ae05d --- /dev/null +++ b/lld/ELF/Adlt.h @@ -0,0 +1,71 @@ +//===- Adlt.h -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// OHOS_LOCAL begin +#ifndef LLD_ELF_ADLT_H +#define LLD_ELF_ADLT_H + +#include "llvm/ADT/SetVector.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/Support/Endian.h" +#include + +namespace lld { +namespace elf { + +class ELFFileBase; +class InputFile; +class Symbol; +struct PhdrEntry; + +template class ObjFile; +template class SharedFileExtended; + +class AdltCtx { +public: + llvm::SmallVector sharedFilesExtended; + // Useful getters + template + const SharedFileExtended *getSoExt(const ObjFile *file); + template SharedFileExtended *getSoExt(InputFile *file); + template SharedFileExtended *getSoExt(unsigned orderId); + + llvm::SetVector commonProgramHeaders; + bool withCfi = false; + // From input .rela.dyn, .rela.plt: + // Keep input library indexes that are needed for got/plt symbol + llvm::DenseMap> + gotPltInfo; // sym, soFile->orderIdx array; +}; + +// The only instance of Ctx struct. +extern std::unique_ptr adltCtx; + +template +const SharedFileExtended *AdltCtx::getSoExt(const ObjFile *file) { + assert(file); + return cast>(file); +} + +template +SharedFileExtended *AdltCtx::getSoExt(InputFile *file) { + assert(file); + return cast>(file); +} + +template +SharedFileExtended *AdltCtx::getSoExt(unsigned orderId) { + assert(orderId < sharedFilesExtended.size()); + return getSoExt(sharedFilesExtended[orderId]); +} + +} // namespace elf +} // namespace lld + +// OHOS_LOCAL end +#endif diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 0d220c6afdf3..001f714454bc 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -34,8 +34,6 @@ class BinaryFile; class BitcodeFile; class ELFFileBase; class SharedFile; -template class SharedFileExtended; -struct PhdrEntry; // OHOS_LOCAL class InputSectionBase; class Symbol; @@ -390,7 +388,6 @@ struct Ctx { SmallVector> memoryBuffers; SmallVector objectFiles; SmallVector sharedFiles; - SmallVector sharedFilesExtended; SmallVector binaryFiles; SmallVector bitcodeFiles; SmallVector lazyBitcodeFiles; @@ -409,23 +406,6 @@ struct Ctx { llvm::DenseMap> backwardReferences; - - // 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: - // Keep input library indexes that are needed for got/plt symbol - llvm::DenseMap> - gotPltInfo; // sym, soFile->orderIdx array; - // Store duplicate symbols (only defined). - llvm::DenseSet duplicatedSymNames; - } adlt; - // OHOS_LOCAL end }; // The only instance of Ctx struct. diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index a4ee33280065..3e446a7ad15b 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -24,6 +24,7 @@ #include "Driver.h" #include "Config.h" +#include "Adlt.h" #include "ICF.h" #include "InputFiles.h" #include "InputSection.h" @@ -76,6 +77,7 @@ using namespace lld::elf; std::unique_ptr elf::config; std::unique_ptr elf::ctx; +std::unique_ptr elf::adltCtx; // OHOS_LOCAL std::unique_ptr elf::driver; static void setConfigs(opt::InputArgList &args); @@ -114,6 +116,7 @@ bool elf::link(ArrayRef args, llvm::raw_ostream &stdoutOS, config = std::make_unique(); elf::ctx = std::make_unique(); + elf::adltCtx = std::make_unique(); driver = std::make_unique(); script = std::make_unique(); symtab = std::make_unique(); @@ -849,7 +852,7 @@ static std::pair getPackDynRelocs(opt::InputArgList &args) { static void readCallGraph(MemoryBufferRef mb) { // Build a map from symbol name to section DenseMap map; - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; for (ELFFileBase *file : files) for (Symbol *sym : file->getSymbols()) map[sym->getName()] = sym; @@ -1828,7 +1831,7 @@ static void excludeLibs(opt::InputArgList &args) { sym->versionId = VER_NDX_LOCAL; }; - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; for (ELFFileBase *file : files) visit(file); @@ -2025,7 +2028,7 @@ static void writeDependencyFile() { // symbols of type CommonSymbol. static void replaceCommonSymbols() { llvm::TimeTraceScope timeScope("Replace common symbols"); - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; for (ELFFileBase *file : files) { if (!file->hasCommonSyms) continue; @@ -2102,7 +2105,7 @@ static void findKeepUniqueSections(opt::InputArgList &args) { // Visit the address-significance table in each object file and mark each // referenced symbol as address-significant. - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; for (InputFile *f : files) { auto *obj = cast>(f); ArrayRef syms = obj->getSymbols(); @@ -2357,7 +2360,7 @@ static void redirectSymbols(ArrayRef wrapped) { return; // Update pointers in input files. - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; parallelForEach(files, [&](ELFFileBase *file) { for (Symbol *&sym : file->getMutableGlobalSymbols()) if (Symbol *s = map.lookup(sym)) @@ -2393,7 +2396,7 @@ static uint32_t getAndFeatures() { return 0; uint32_t ret = -1; - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; for (ELFFileBase *f : files) { uint32_t features = f->andFeatures; @@ -2477,46 +2480,25 @@ static void postParseObjectFile(ELFFileBase *file) { } } -static void postParseSharedFileForAdlt(ELFFileBase *file) { +static void postParseSharedFileExtended(ELFFileBase *file) { switch (config->ekind) { case ELF32LEKind: - cast>(file)->postParseForAdlt(); + adltCtx->getSoExt(file)->postParse(); break; case ELF32BEKind: - cast>(file)->postParseForAdlt(); + adltCtx->getSoExt(file)->postParse(); break; case ELF64LEKind: - cast>(file)->postParseForAdlt(); + adltCtx->getSoExt(file)->postParse(); break; case ELF64BEKind: - cast>(file)->postParseForAdlt(); + adltCtx->getSoExt(file)->postParse(); break; default: llvm_unreachable(""); } } -static bool isSectionValidForAdlt(int fileIdx, InputSectionBase *s) { - if (!s || s == &InputSection::discarded) - return false; - uint32_t type = s->type; - StringRef name = s->name; - - bool isBaseType = type == SHT_NOBITS || type == SHT_NOTE || - type == SHT_INIT_ARRAY || type == SHT_FINI_ARRAY; - // TODO: fix .debug_info relocation - bool isNeededProgBits = - type == SHT_PROGBITS && - !(name.startswith(".got.plt") || name.startswith(".plt") || name.startswith(".got") || - name.startswith(".eh_frame_hdr"));// || name.startswith(".debug_")); - bool ret = isBaseType || isNeededProgBits; - - bool isDebug = false; - if (ret && isDebug) - lld::outs() << "[isSectionValidForAdlt]: " << name << "\n"; - return ret; -} - // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. void LinkerDriver::link(opt::InputArgList &args) { @@ -2597,7 +2579,7 @@ void LinkerDriver::link(opt::InputArgList &args) { // producing a shared library. // We also need one if any shared libraries are used and for pie executables // (probably because the dynamic linker needs it). - config->hasDynSymTab = (config->adlt ? !ctx->sharedFilesExtended.empty() + config->hasDynSymTab = (config->adlt ? !adltCtx->sharedFilesExtended.empty() : !ctx->sharedFiles.empty()) || config->isPic || config->exportDynamic; @@ -2655,7 +2637,7 @@ void LinkerDriver::link(opt::InputArgList &args) { // No more lazy bitcode can be extracted at this point. Do post parse work // like checking duplicate symbols. if (config->adlt) - parallelForEach(ctx->sharedFilesExtended, postParseSharedFileForAdlt); + parallelForEach(adltCtx->sharedFilesExtended, postParseSharedFileExtended); parallelForEach(ctx->objectFiles, initializeLocalSymbols); parallelForEach(ctx->objectFiles, postParseObjectFile); @@ -2724,7 +2706,7 @@ void LinkerDriver::link(opt::InputArgList &args) { // With this the symbol table should be complete. After this, no new names // except a few linker-synthesized ones will be added to the symbol table. const size_t numObjsBeforeLTO = ctx->objectFiles.size(); - const size_t numSoBeforeLTO = ctx->sharedFilesExtended.size(); + const size_t numSoBeforeLTO = adltCtx->sharedFilesExtended.size(); invokeELFT(compileBitcodeFiles, skipLinkedOutput); // Symbol resolution finished. Report backward reference problems, @@ -2743,8 +2725,8 @@ void LinkerDriver::link(opt::InputArgList &args) { // more file will be added. if (config->adlt) { auto newSharedFiles = - makeArrayRef(ctx->sharedFilesExtended).slice(numSoBeforeLTO); - parallelForEach(newSharedFiles, postParseSharedFileForAdlt); + makeArrayRef(adltCtx->sharedFilesExtended).slice(numSoBeforeLTO); + parallelForEach(newSharedFiles, postParseObjectFile); } auto newObjectFiles = makeArrayRef(ctx->objectFiles).slice(numObjsBeforeLTO); parallelForEach(newObjectFiles, initializeLocalSymbols); @@ -2770,9 +2752,9 @@ void LinkerDriver::link(opt::InputArgList &args) { // Beyond this point, no new files are added. // Aggregate all input sections into one place. if (config->adlt) - for (auto it : llvm::enumerate(ctx->sharedFilesExtended)) - for (InputSectionBase *s : it.value()->getSections()) - if (isSectionValidForAdlt(it.index(), s)) + for (auto *it : adltCtx->sharedFilesExtended) + for (InputSectionBase *s : it->getSections()) + if (it->isSectionValid(s)) inputSections.push_back(s); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 0b6ac03faff1..1fae37b85268 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -8,6 +8,7 @@ #include "InputFiles.h" #include "Config.h" +#include "Adlt.h" #include "DWARF.h" #include "Driver.h" #include "InputSection.h" @@ -162,7 +163,7 @@ template static void doBuildSymsHist(InputFile *file, ESymsCntMap &eSymsHist) { if (!isCompatible(file)) return; - if (auto *f = dyn_cast>(file)) + if (auto *f = adltCtx->getSoExt(file)) f->buildSymsHist(eSymsHist); } @@ -197,10 +198,10 @@ template static void doParseFile(InputFile *file) { // .so file if (config->adlt) - if (auto *f = dyn_cast>(file)) { - f->orderIdx = ctx->sharedFilesExtended.size(); - ctx->sharedFilesExtended.push_back(cast(file)); - f->parseForAdlt(); + if (auto *f = adltCtx->getSoExt(file)) { + f->orderIdx = adltCtx->sharedFilesExtended.size(); + adltCtx->sharedFilesExtended.push_back(f); + f->parse(); return; } @@ -1073,8 +1074,8 @@ void ObjFile::initializeSymbols(const object::ELFFile &obj) { if (!symbols[i]) { StringRef name = CHECK(eSyms[i].getName(stringTable), this); if (config->adlt && eSyms[i].isDefined() && - ctx->adlt.duplicatedSymNames.count(CachedHashStringRef(name)) != 0) { - ctx->adlt.withCfi = ctx->adlt.withCfi || name == "__cfi_check"; + adltCtx->duplicatedSymNames.count(CachedHashStringRef(name)) != 0) { + adltCtx->withCfi = adltCtx->withCfi || name == "__cfi_check"; name = this->getUniqueName(name); } symbols[i] = symtab.insert(name); @@ -1247,7 +1248,7 @@ template void ObjFile::postParse() { continue; std::lock_guard lock(mu); if (config->adlt) { - auto *f = cast>(this); + auto *f = adltCtx->getSoExt(this); bool isDebug = false; if (isDebug) { lld::outs() << "Put to duplicates for: " << archiveName << "\n"; @@ -1622,7 +1623,7 @@ template void SharedFile::parse() { } template -void SharedFileExtended::resolveDuplicatesForAdlt() { +void SharedFileExtended::resolveDuplicates() { auto pred = [&](DuplicateSymbol dup) { auto sym = dup.sym; if (!sym->isDefined()) @@ -1657,8 +1658,9 @@ SharedFileExtended::SharedFileExtended(MemoryBufferRef mb, const_cast(this->fileKind) = InputFile::SharedKind; } -template void SharedFileExtended::parseForAdlt() { - this->parse(); +template +void SharedFileExtended::parse(bool ignoreComdats) { + ObjFile::parse(ignoreComdats); parseDynamics(); parseElfSymTab(); @@ -1702,10 +1704,32 @@ template void SharedFileExtended::parseForAdlt() { lld::outs() << '\n'; } -template void SharedFileExtended::postParseForAdlt() { - this->initializeLocalSymbols(); - this->postParse(); - resolveDuplicatesForAdlt(); +template void SharedFileExtended::postParse() { + ObjFile::initializeLocalSymbols(); + ObjFile::postParse(); + resolveDuplicates(); +} + +template +bool SharedFileExtended::isSectionValid(InputSectionBase *s) { + if (!s || s == &InputSection::discarded) + return false; + uint32_t type = s->type; + StringRef name = s->name; + + bool isBaseType = type == SHT_NOBITS || type == SHT_NOTE || + type == SHT_INIT_ARRAY || type == SHT_FINI_ARRAY; + // TODO: fix .debug_info relocation + bool isNeededProgBits = + type == SHT_PROGBITS && + !(name.startswith(".got.plt") || name.startswith(".plt") || name.startswith(".got") || + name.startswith(".eh_frame_hdr"));// || name.startswith(".debug_")); + bool ret = isBaseType || isNeededProgBits; + + bool isDebug = false; + if (ret && isDebug) + lld::outs() << "[isSectionValidForAdlt]: " << name << "\n"; + return ret; } template @@ -1915,7 +1939,7 @@ Symbol &SharedFileExtended::getDynamicSymbol(uint32_t symbolIndex) const { } template -Symbol &SharedFileExtended::getSymbolADLT(uint32_t symbolIndex, +Symbol &SharedFileExtended::getSymbol(uint32_t symbolIndex, bool fromDynamic) const { Symbol &sym = fromDynamic ? getDynamicSymbol(symbolIndex) : getSymbolFromElfSymTab(symbolIndex); @@ -1925,7 +1949,7 @@ Symbol &SharedFileExtended::getSymbolADLT(uint32_t symbolIndex, return sym; /*if (name.contains("__emutls_v.TLS_data1")) // debug hint - lld::outs() << "debug getSymbolADLT(): " << name << "\n";*/ + lld::outs() << "debug getSymbol(): " << name << "\n";*/ // check SymbolTable auto res = elf::symtab->find(name); @@ -2040,7 +2064,7 @@ template void SharedFileExtended::parseDynamics() { StringRef name = CHECK(sym.getName(this->stringTable), this); // Add postfix for defined duplicates. if (config->adlt && sym.isDefined() && - ctx->adlt.duplicatedSymNames.count(CachedHashStringRef(name)) != 0) + adltCtx->duplicatedSymNames.count(CachedHashStringRef(name)) != 0) name = this->getUniqueName(name); if (sym.getBinding() == STB_LOCAL) { diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index b8d47779488d..4413ccc1e1b2 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -199,6 +199,10 @@ public: .slice(firstGlobal); } + // OHOS_LOCAL begins + virtual bool isSectionValid(InputSectionBase *s) { return true; } + // OHOS_LOCAL end + template typename ELFT::ShdrRange getELFShdrs() const { return typename ELFT::ShdrRange( reinterpret_cast(elfShdrs), numELFShdrs); @@ -243,13 +247,13 @@ public: } virtual ~ObjFile() {} - void parse(bool ignoreComdats = false); + virtual void parse(bool ignoreComdats = false); void parseLazy(); StringRef getShtGroupSignature(ArrayRef sections, const Elf_Shdr &sec); - virtual Symbol &getSymbol(uint32_t symbolIndex) const { + Symbol &getSymbol(uint32_t symbolIndex) const { if (symbolIndex >= this->symbols.size()) fatal(toString(this) + ": invalid symbol index"); return *this->symbols[symbolIndex]; @@ -296,7 +300,7 @@ public: void buildSymsHist(ESymsCntMap &eSymsHist); void initializeLocalSymbols(); - void postParse(); + virtual void postParse(); protected: virtual StringRef getUniqueName(StringRef origName) const; @@ -401,8 +405,10 @@ public: return f->kind() == InputFile::SharedKind; } - void parseForAdlt(); - void postParseForAdlt(); + virtual void parse(bool ignoreComdats = false) override; + virtual void postParse() override; + + virtual bool isSectionValid(InputSectionBase *s) override; StringRef addAdltPostfix(StringRef input) const; bool addAdltPostfix(Symbol *s); @@ -423,7 +429,7 @@ public: template Symbol &getRelocTargetSymADLT(const RelT &rel, InputSectionBase &sec) const { uint32_t symIndex = rel.getSymbol(config->isMips64EL); - return getSymbolADLT(symIndex, isDynamicSection(sec)); + return getSymbol(symIndex, isDynamicSection(sec)); } ArrayRef getLocalSymbols() override { @@ -433,7 +439,7 @@ public: } Symbol &getDynamicSymbol(uint32_t symbolIndex) const; - Symbol &getSymbolADLT(uint32_t symbolIndex, bool fromDynamic) const; + Symbol &getSymbol(uint32_t symbolIndex, bool fromDynamic) const; Symbol &getSymbolFromElfSymTab(uint32_t symbolIndex) const { if (symbolIndex >= this->allSymbols.size()) @@ -492,7 +498,7 @@ private: void parseDynamics(); // SharedFile compability void parseElfSymTab(); // ObjectFile compability - void resolveDuplicatesForAdlt(); + void resolveDuplicates(); StringRef getShStrTab(ArrayRef elfSections); diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 0eb2968413bd..78a34afa8fef 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -8,6 +8,7 @@ #include "InputSection.h" #include "Config.h" +#include "Adlt.h" #include "InputFiles.h" #include "OutputSections.h" #include "Relocations.h" @@ -348,10 +349,11 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef rels) { for (const RelTy &rel : rels) { RelType type = rel.getType(config->isMips64EL); const ObjFile *file = - config->adlt ? getSharedFile() : getFile(); - Symbol &sym = config->adlt - ? getSharedFile()->getRelocTargetSymADLT(rel, *sec) - : file->getRelocTargetSym(rel); + config->adlt ? adltCtx->getSoExt(file) : getFile(); + Symbol &sym = + config->adlt + ? adltCtx->getSoExt(file)->getRelocTargetSymADLT(rel, *sec) + : file->getRelocTargetSym(rel); auto *p = reinterpret_cast(buf); buf += sizeof(RelTy); @@ -847,9 +849,10 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { if (!RelTy::IsRela) addend += target.getImplicitAddend(bufLoc, type); - Symbol &sym = config->adlt ? getSharedFile()->getSymbolFromElfSymTab( - rel.getSymbol(config->isMips64EL)) - : getFile()->getRelocTargetSym(rel); + Symbol &sym = config->adlt + ? adltCtx->getSoExt(file)->getSymbolFromElfSymTab( + rel.getSymbol(config->isMips64EL)) + : getFile()->getRelocTargetSym(rel); if (config->adlt) { // TODO improve switch (type) { case R_AARCH64_RELATIVE: @@ -964,7 +967,7 @@ static void relocateNonAllocForRelocatable(InputSection *sec, uint8_t *buf) { template void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd) { if (flags & SHF_EXECINSTR && - (config->adlt ? LLVM_UNLIKELY(getSharedFile()->splitStack) + (config->adlt ? LLVM_UNLIKELY(adltCtx->getSoExt(file)->splitStack) : LLVM_UNLIKELY(getFile()->splitStack))) adjustSplitStackFunctionPrologues(buf, bufEnd); diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index b9f4541e77a9..1d13d1673304 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -137,11 +137,6 @@ public: return cast_or_null>(file); } - template - SharedFileExtended *getSharedFile() const { - return cast_or_null>(file); - } - // Used by --optimize-bb-jumps and RISC-V linker relaxation temporarily to // indicate the number of bytes which is not counted in the size. This should // be reset to zero after uses. diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp index 51353287c90e..f4a3ad98f434 100644 --- a/lld/ELF/MapFile.cpp +++ b/lld/ELF/MapFile.cpp @@ -23,6 +23,7 @@ #include "LinkerScript.h" #include "OutputSections.h" #include "Symbols.h" +#include "Adlt.h" #include "SyntheticSections.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" @@ -55,7 +56,7 @@ static void writeHeader(raw_ostream &os, uint64_t vma, uint64_t lma, // Returns a list of all symbols that we want to print out. static std::vector getSymbols() { std::vector v; - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; for (ELFFileBase *file : files) for (Symbol *b : file->getSymbols()) if (auto *dr = dyn_cast(b)) @@ -225,7 +226,7 @@ static void writeMapFile(raw_fd_ostream &os) { static void writeCref(raw_fd_ostream &os) { // Collect symbols and files. MapVector> map; - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; for (ELFFileBase *file : files) { for (Symbol *sym : file->getSymbols()) { if (isa(sym)) diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index 61be1e13287f..66974398c92d 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -25,6 +25,7 @@ #include "LinkerScript.h" #include "SymbolTable.h" #include "Symbols.h" +#include "Adlt.h" #include "SyntheticSections.h" #include "Target.h" #include "lld/Common/CommonLinkerContext.h" @@ -345,7 +346,7 @@ template void MarkLive::mark() { // to from __start_/__stop_ symbols because there will only be one set of // symbols for the whole program. template void MarkLive::moveToMain() { - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; for (ELFFileBase *file : files) for (Symbol *s : file->getSymbols()) if (auto *d = dyn_cast(s)) diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 798440141025..cd390a01539d 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -42,6 +42,7 @@ #include "Relocations.h" #include "Config.h" +#include "Adlt.h" #include "InputFiles.h" #include "LinkerScript.h" #include "OutputSections.h" @@ -433,6 +434,44 @@ private: size_t i = 0; }; +// OHOS_LOCAL begin +template class AdltRelocationScanner { +public: + explicit AdltRelocationScanner(InputSectionBase &sec) : sec(sec) {} + + SharedFileExtended *getSoExt() { + return adltCtx->getSoExt(sec.file); + } + void process(Relocation *r, bool fromDynamic); + void trackGotPlt(Symbol *sym); + void trackDynReloc(); + + unsigned getDynamicRelocsCount(); + bool isRelr() { return config->adlt && relSecType == SHT_RELR; } + bool toProcessAux = false; + +private: + uint32_t relSecType = SHT_NULL; + InputSectionBase &sec; +}; + +template +void AdltRelocationScanner::trackGotPlt(Symbol *sym) { + adltCtx->gotPltInfo[sym].push_back(getSoExt()->orderIdx); +} + +template void AdltRelocationScanner::trackDynReloc() { + getSoExt()->dynRelIndexes.insert(getDynamicRelocsCount() - 1); +} + +template +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 { @@ -458,16 +497,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); // OHOS_LOCAL 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 @@ -1036,6 +1069,9 @@ 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. +void RelocationScanner::processAux(Relocation &r) { // OHOS_LOCAL + processAux(r.expr, r.type, r.offset, *r.sym, r.addend); +} 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,39 +1340,10 @@ 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->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) { - auto file = sec.getSharedFile(); +// OHOS_LOCAL begin +template +void AdltRelocationScanner::process(Relocation *r, bool fromDynamic) { + auto file = adltCtx->getSoExt(sec.file); bool isDebug = false; /*if (r->offset == 0x21F) // debug hint @@ -1353,9 +1360,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 @@ -1366,20 +1370,21 @@ void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r, r->addend -= d->section->address + d->value; addRelativeReloc(*secWhere, r->offset, *r->sym, r->addend, r->expr, r->type); - trackDynRelocAdlt(file); + 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 +1393,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 +1408,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 +1437,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,17 +1462,17 @@ 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); bool fromDynamic = false; if (config->adlt) - fromDynamic = sec.getSharedFile()->isDynamicSection(sec); + fromDynamic = adltCtx->getSoExt(sec.file)->isDynamicSection(sec); Symbol &sym = config->adlt - ? sec.getSharedFile()->getSymbolADLT(symIndex, fromDynamic) + ? adltCtx->getSoExt(sec.file)->getSymbol(symIndex, fromDynamic) : sec.getFile()->getSymbol(symIndex); RelType type; @@ -1501,8 +1506,11 @@ template void RelocationScanner::scanOne(RelTy *&i) { int64_t addend = computeAddend(rel, expr, sym.isLocal()); if (config->adlt) { + AdltRelocationScanner adltScanner(sec); Relocation r = {expr, type, offset, addend, &sym}; - processForADLT(rel, &r, fromDynamic); + adltScanner.process(&r, fromDynamic); + if (adltScanner.toProcessAux) + processAux(r); return; } @@ -1716,6 +1724,7 @@ void RelocationScanner::scan(ArrayRef rels) { template void elf::scanRelocations(InputSectionBase &s) { RelocationScanner scanner(s); + AdltRelocationScanner adltScanner(s); if (config->adlt) { bool isDebug = false; if (isDebug) @@ -1807,15 +1816,24 @@ static bool handleNonPreemptibleIfunc(Symbol &sym) { return true; } -template static void addGotPltIndexAdlt(Symbol *s, bool isPlt) { - auto &vec = ctx->adlt.gotPltInfo[s]; - for (auto &it : vec) { - auto *soFile = cast>(ctx->sharedFilesExtended[it]); +// OHOS_LOCAL begin +namespace lld { +namespace elf { +namespace adlt { +template static void addGotPltIndex(Symbol *s, bool isPlt) { + auto &vec = adltCtx->gotPltInfo[s]; + for (auto &orderId : vec) { + auto *soFile = adltCtx->getSoExt(orderId); auto &entries = isPlt ? in.relaPlt->relocs : mainPart->relaDyn->relocs; auto &output = isPlt ? soFile->pltRelIndexes : soFile->dynRelIndexes; output.insert(entries.size() - 1); } } +} // namespace adlt +} // namespace elf +} // namespace lld + +// OHOS_LOCAL end void elf::postScanRelocations() { auto fn = [](Symbol &sym) { @@ -1829,12 +1847,12 @@ void elf::postScanRelocations() { if (sym.needsGot) { addGotEntry(sym); if (config->adlt) - invokeELFT(addGotPltIndexAdlt, &sym, false); + invokeELFT(adlt::addGotPltIndex, &sym, false); } if (sym.needsPlt) { addPltEntry(*in.plt, *in.gotPlt, *in.relaPlt, target->pltRel, sym); if (config->adlt) - invokeELFT(addGotPltIndexAdlt, &sym, true); + invokeELFT(adlt::addGotPltIndex, &sym, true); } if (sym.needsCopy) { if (sym.isObject()) { @@ -1869,7 +1887,7 @@ void elf::postScanRelocations() { mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible( target->tlsDescRel, *in.got, in.got->getTlsDescOffset(sym), sym, target->tlsDescRel); - invokeELFT(addGotPltIndexAdlt, &sym, false); + invokeELFT(adlt::addGotPltIndex, &sym, false); } if (sym.needsTlsGd) { in.got->addDynTlsEntry(sym); @@ -1923,7 +1941,7 @@ void elf::postScanRelocations() { // Local symbols may need the aforementioned non-preemptible ifunc and GOT // handling. They don't need regular PLT. - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; for (ELFFileBase *file : files) for (Symbol *sym : file->getLocalSymbols()) fn(*sym); diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 61d52dc894b5..e2d32416c65b 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -15,6 +15,7 @@ #include "SyntheticSections.h" #include "Config.h" +#include "Adlt.h" #include "DWARF.h" #include "EhFrame.h" #include "InputFiles.h" @@ -1398,8 +1399,8 @@ DynamicSection::computeContents() { part.dynStrTab->addString(config->rpath)); if (config->adlt) { - for (InputFile *file : ctx->sharedFilesExtended) { - auto *f = cast>(file); + for (InputFile *file : adltCtx->sharedFilesExtended) { + auto *f = adltCtx->getSoExt(file); for (size_t i = 0; i < f->dtNeeded.size(); i++) { auto tag = DT_NEEDED; auto val = part.dynStrTab->addString(f->dtNeeded[i]); @@ -1557,8 +1558,8 @@ DynamicSection::computeContents() { return &osd->osec; return (OutputSection *)nullptr; }; - for (InputFile *file : ctx->sharedFilesExtended) { - auto *f = cast>(file); + for (InputFile *file : adltCtx->sharedFilesExtended) { + auto *f = adltCtx->getSoExt(file); auto initArray = findSection(f->addAdltPostfix(".init_array")); auto finiArray = findSection(f->addAdltPostfix(".fini_array")); if (initArray) { @@ -2276,8 +2277,8 @@ void SymbolTableBaseSection::sortSymTabSymbolsInAdlt(size_t numLocals) { return {-1, file}; }; - for (InputFile* file : ctx->sharedFilesExtended) { - auto* soext = cast>(file); + for (InputFile* file : adltCtx->sharedFilesExtended) { + auto* soext = adltCtx->getSoExt(file); soext->sharedLocalSymbolIndex = llvm::None; soext->sharedGlobalSymbolIndex = llvm::None; } @@ -2293,7 +2294,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)) @@ -3495,7 +3496,7 @@ template void elf::splitSections() { llvm::TimeTraceScope timeScope("Split sections"); // splitIntoPieces needs to be called on each MergeInputSection // before calling finalizeContents(). - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; parallelForEach(files, [](ELFFileBase *file) { for (InputSectionBase *sec : file->getSections()) { if (!sec) @@ -4104,9 +4105,9 @@ AdltSection::AdltSection(StringTableSection& strTabSec) template void AdltSection::finalizeContents() { soInputs.clear(); - soInputs.reserve(ctx->sharedFilesExtended.size()); - for (InputFile* file : ctx->sharedFilesExtended) { - auto* soext = cast>(file); + soInputs.reserve(adltCtx->sharedFilesExtended.size()); + for (InputFile* file : adltCtx->sharedFilesExtended) { + auto* soext = adltCtx->getSoExt(file); soInputs.push_back(makeSoData(soext)); } @@ -4199,7 +4200,7 @@ typename AdltSection::CommonData AdltSection::makeCommonData() { return CommonData { UINT32_MAX, // .symtabSecIndex, filled in writeTo - ctx->adlt.commonProgramHeaders.size(), // .programHeadersAllocated + adltCtx->commonProgramHeaders.size(), // .programHeadersAllocated {}, // .phIndexes filled in writeTo }; } @@ -4348,7 +4349,7 @@ void AdltSection::extractProgramHeaderIndexes() { phdrsIndexes[it.value()] = static_cast(it.index()); }; - for (const PhdrEntry* phentry : ctx->adlt.commonProgramHeaders) { + for (const PhdrEntry* phentry : adltCtx->commonProgramHeaders) { auto it = phdrsIndexes.find(phentry); if (it != phdrsIndexes.end()) { common.phIndexes.push_back(it->second); @@ -4382,7 +4383,7 @@ void AdltSection::finalizeOnWrite() { template void AdltSection::finalizeOnWrite(size_t idx, SoData& soData) { - auto* soext = cast>(ctx->sharedFilesExtended[idx]); + auto* soext = adltCtx->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 6743de95cd2f..c04b8f858f9b 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -11,6 +11,7 @@ #include "ARMErrataFix.h" #include "CallGraphSort.h" #include "Config.h" +#include "Adlt.h" #include "InputFiles.h" #include "LinkerScript.h" #include "MapFile.h" @@ -570,8 +571,8 @@ InputSection *AdltWriter::getInputSection(OutputSection *sec) { } template void AdltWriter::checkPhdrs() { - for (auto *file : ctx->sharedFilesExtended) - if (auto *soFile = ctx->adlt.getSoExt(file)) + for (auto *file : adltCtx->sharedFilesExtended) + if (auto *soFile = adltCtx->getSoExt(file)) assert(!soFile->programHeaders.empty() && "ADLT: PHdr indexes can't be empty!"); } @@ -580,8 +581,8 @@ template void AdltWriter::checkRelocs() { 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)) { + for (auto *file : adltCtx->sharedFilesExtended) + if (auto *soFile = adltCtx->getSoExt(file)) { assert(!soFile->dynRelIndexes.empty() && "ADLT: relaDyn indexes can't be empty!"); assert(!soFile->pltRelIndexes.empty() && @@ -593,11 +594,11 @@ 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 = adltCtx->getSoExt(isec->file)) { soFile->programHeaders.insert(phdr); return; } - ctx->adlt.commonProgramHeaders.insert(phdr); + adltCtx->commonProgramHeaders.insert(phdr); } template void AdltWriter::traceRelocs() { @@ -621,8 +622,8 @@ template void AdltWriter::traceRelocs() { << " + 0x" << utohexstr(rel->addend) << '\n'; }; - for (auto *file : ctx->sharedFilesExtended) - if (auto *soFile = ctx->adlt.getSoExt(file)) { + for (auto *file : adltCtx->sharedFilesExtended) + if (auto *soFile = adltCtx->getSoExt(file)) { lld::outs() << soFile->soName << ":\n"; lld::outs() << "Dyn relocs (" << soFile->dynRelIndexes.size() << ")"; printIndexes(soFile->dynRelIndexes); @@ -659,13 +660,13 @@ template void AdltWriter::tracePhdrs() { << "\t" << p->firstSec->name << '\n'; }; - auto &common = ctx->adlt.commonProgramHeaders; + auto &common = adltCtx->commonProgramHeaders; lld::outs() << "Common Program Headers (" << common.size() << ")"; printIndexes(common); printPhTable(common); - for (auto *file : ctx->sharedFilesExtended) - if (auto *soFile = ctx->adlt.getSoExt(file)) { + for (auto *file : adltCtx->sharedFilesExtended) + if (auto *soFile = adltCtx->getSoExt(file)) { auto &headers = soFile->programHeaders; lld::outs() << soFile->soName << "\n"; lld::outs() << "Program headers (" << headers.size() << ")"; @@ -790,7 +791,7 @@ template static void markUsedLocalSymbols() { // See MarkLive::resolveReloc(). if (config->gcSections) return; - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; for (ELFFileBase *file : files) { ObjFile *f = cast>(file); for (InputSectionBase *s : f->getSections()) { @@ -862,7 +863,7 @@ template void Writer::copyLocalSymbols() { llvm::TimeTraceScope timeScope("Add local symbols"); if (config->copyRelocs && config->discard != DiscardPolicy::None) markUsedLocalSymbols(); - auto files = /*config->adlt ? ctx->sharedFilesExtended :*/ ctx->objectFiles; + auto files = ctx->objectFiles; for (ELFFileBase *file : files) { for (Symbol *b : file->getLocalSymbols()) { assert(b->isLocal() && "should have been caught in initializeSymbols()"); @@ -1189,7 +1190,7 @@ void PhdrEntry::add(OutputSection *sec) { // OHOS_LOCAL begin if (config->adlt) { - if (ctx->adlt.withCfi && p_type == PT_LOAD) { + if (adltCtx->withCfi && p_type == PT_LOAD) { // check cfi.h: LIBRARY_ALIGNMENT and _BITS constexpr uint32_t kCFILibraryAlignment = 1UL << 18; firstSec->alignment = kCFILibraryAlignment; @@ -1489,7 +1490,7 @@ static DenseMap buildSectionOrder() { for (Symbol *sym : symtab->symbols()) addSym(*sym); - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = ctx->objectFiles; for (ELFFileBase *file : files) for (Symbol *sym : file->getLocalSymbols()) addSym(*sym); @@ -1906,7 +1907,7 @@ template void Writer::finalizeAddressDependentContent() { // block sections, input sections can shrink when the jump instructions at // the end of the section are relaxed. static void fixSymbolsAfterShrinking() { - auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; for (InputFile *File : files) { parallelForEach(File->getSymbols(), [&](Symbol *Sym) { auto *def = dyn_cast(Sym); @@ -2127,8 +2128,8 @@ template void Writer::finalizeSections() { // copy relocations, etc. Note that relocations for non-alloc sections are // directly processed by InputSection::relocateNonAlloc. if (config->adlt) - for (auto &it : llvm::enumerate(ctx->sharedFilesExtended)) { - auto *soFile = cast>(it.value()); + for (auto *file : adltCtx->sharedFilesExtended) { + auto *soFile = adltCtx->getSoExt(file); auto sections = soFile->getSections(); // scan .rela.dyn (base: SHT_NULL) scanRelocations(*sections[0]); @@ -2520,7 +2521,7 @@ SmallVector Writer::createPhdrs(Partition &part) { auto file = adltWriter.getInputSection(sec)->file; if (!file) return llvm::None; - return cast>(file)->orderIdx; + return adltCtx->getSoExt(file)->orderIdx; }; // OHOS_LOCAL end -- Gitee From a37ba52f6848c0ef2bd464f41b161f4885799aab Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Fri, 24 May 2024 03:38:30 -0400 Subject: [PATCH 2/2] ADLT: refactor #2. Change-Id: Ie7b81d8a7c536b7f2faa90b8ecdd997dfdf9efb5 Signed-off-by: Anton Volkov --- lld/ELF/Adlt.cpp | 44 ++ lld/ELF/Adlt.h | 41 +- lld/ELF/CMakeLists.txt | 1 + lld/ELF/Driver.cpp | 47 +- lld/ELF/InputFiles.cpp | 928 +++++++++++----------------------- lld/ELF/InputFiles.h | 136 ++--- lld/ELF/InputSection.cpp | 32 +- lld/ELF/InputSection.h | 7 +- lld/ELF/MapFile.cpp | 5 +- lld/ELF/MarkLive.cpp | 2 +- lld/ELF/Relocations.cpp | 111 ++-- lld/ELF/SyntheticSections.cpp | 111 ++-- lld/ELF/SyntheticSections.h | 5 +- lld/ELF/Writer.cpp | 124 ++--- 14 files changed, 592 insertions(+), 1002 deletions(-) create mode 100644 lld/ELF/Adlt.cpp diff --git a/lld/ELF/Adlt.cpp b/lld/ELF/Adlt.cpp new file mode 100644 index 000000000000..9e2e1d469535 --- /dev/null +++ b/lld/ELF/Adlt.cpp @@ -0,0 +1,44 @@ +//===- Adlt.cpp -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// OHOS_LOCAL begin +#include "Adlt.h" +#include "llvm/Support/Casting.h" + +#include "InputFiles.h" + + +using namespace llvm; + +using namespace lld; +using namespace lld::elf; + +SharedFileExtended *AdltCtx::getSoExt(InputFile *file) { + assert(file); + return cast(file); +} + +const SharedFileExtended *AdltCtx::getSoExt(const InputFile *file) { + assert(file); + return cast(file); // todo: reuse? +} + +SharedFileExtended *AdltCtx::getSoExt(unsigned orderId) { + assert(orderId < sharedFilesExtended.size()); + return sharedFilesExtended[orderId]; +} + +void AdltCtx::checkDuplicatedSymbols() { + assert(!symNamesHist.empty()); + for (auto entry : symNamesHist) + if (entry.second > 1) + duplicatedSymNames.insert(entry.first); + symNamesHist.clear(); +} + +// OHOS_LOCAL end diff --git a/lld/ELF/Adlt.h b/lld/ELF/Adlt.h index f52c663ae05d..aae297c6ed31 100644 --- a/lld/ELF/Adlt.h +++ b/lld/ELF/Adlt.h @@ -11,6 +11,7 @@ #define LLD_ELF_ADLT_H #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/CachedHashString.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/Support/Endian.h" #include @@ -24,16 +25,17 @@ class Symbol; struct PhdrEntry; template class ObjFile; -template class SharedFileExtended; +class SharedFileExtended; class AdltCtx { public: - llvm::SmallVector sharedFilesExtended; - // Useful getters - template - const SharedFileExtended *getSoExt(const ObjFile *file); - template SharedFileExtended *getSoExt(InputFile *file); - template SharedFileExtended *getSoExt(unsigned orderId); + llvm::SmallVector sharedFilesExtended; + + void checkDuplicatedSymbols(); + + SharedFileExtended *getSoExt(InputFile *file); + const SharedFileExtended *getSoExt(const InputFile *file); + SharedFileExtended *getSoExt(unsigned orderId); llvm::SetVector commonProgramHeaders; bool withCfi = false; @@ -41,31 +43,18 @@ public: // Keep input library indexes that are needed for got/plt symbol llvm::DenseMap> gotPltInfo; // sym, soFile->orderIdx array; + + // Store duplicate symbols (only defined). + llvm::DenseMap + symNamesHist; // hash, count usages + llvm::DenseSet duplicatedSymNames; }; // The only instance of Ctx struct. extern std::unique_ptr adltCtx; -template -const SharedFileExtended *AdltCtx::getSoExt(const ObjFile *file) { - assert(file); - return cast>(file); -} - -template -SharedFileExtended *AdltCtx::getSoExt(InputFile *file) { - assert(file); - return cast>(file); -} - -template -SharedFileExtended *AdltCtx::getSoExt(unsigned orderId) { - assert(orderId < sharedFilesExtended.size()); - return getSoExt(sharedFilesExtended[orderId]); -} - } // namespace elf } // namespace lld +#endif // LLD_ELF_ADLT_H // OHOS_LOCAL end -#endif diff --git a/lld/ELF/CMakeLists.txt b/lld/ELF/CMakeLists.txt index b37035d3e742..de8b3bf51d58 100644 --- a/lld/ELF/CMakeLists.txt +++ b/lld/ELF/CMakeLists.txt @@ -45,6 +45,7 @@ add_lld_library(lldELF Target.cpp Thunks.cpp Writer.cpp + Adlt.cpp LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 3e446a7ad15b..6b7700483314 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -280,7 +280,7 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) { // cannot be stored into SharedFile::soName. path = mbref.getBufferIdentifier(); if (config->adlt) - files.push_back(createSharedFileExtended( + files.push_back(make( mbref, withLOption ? path::filename(path) : path)); else files.push_back( @@ -852,7 +852,7 @@ static std::pair getPackDynRelocs(opt::InputArgList &args) { static void readCallGraph(MemoryBufferRef mb) { // Build a map from symbol name to section DenseMap map; - auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; + auto files = ctx->objectFiles; for (ELFFileBase *file : files) for (Symbol *sym : file->getSymbols()) map[sym->getName()] = sym; @@ -1831,7 +1831,7 @@ static void excludeLibs(opt::InputArgList &args) { sym->versionId = VER_NDX_LOCAL; }; - auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; + auto files = ctx->objectFiles; for (ELFFileBase *file : files) visit(file); @@ -2028,7 +2028,7 @@ static void writeDependencyFile() { // symbols of type CommonSymbol. static void replaceCommonSymbols() { llvm::TimeTraceScope timeScope("Replace common symbols"); - auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; + auto files = ctx->objectFiles; for (ELFFileBase *file : files) { if (!file->hasCommonSyms) continue; @@ -2105,7 +2105,7 @@ static void findKeepUniqueSections(opt::InputArgList &args) { // Visit the address-significance table in each object file and mark each // referenced symbol as address-significant. - auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; + auto files = ctx->objectFiles; for (InputFile *f : files) { auto *obj = cast>(f); ArrayRef syms = obj->getSymbols(); @@ -2360,7 +2360,7 @@ static void redirectSymbols(ArrayRef wrapped) { return; // Update pointers in input files. - auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; + auto files = ctx->objectFiles; parallelForEach(files, [&](ELFFileBase *file) { for (Symbol *&sym : file->getMutableGlobalSymbols()) if (Symbol *s = map.lookup(sym)) @@ -2396,8 +2396,7 @@ static uint32_t getAndFeatures() { return 0; uint32_t ret = -1; - auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; - for (ELFFileBase *f : files) { + for (ELFFileBase *f : ctx->objectFiles) { uint32_t features = f->andFeatures; checkAndReportMissingFeature( @@ -2481,18 +2480,19 @@ static void postParseObjectFile(ELFFileBase *file) { } static void postParseSharedFileExtended(ELFFileBase *file) { + auto *soExt = adltCtx->getSoExt(file); switch (config->ekind) { case ELF32LEKind: - adltCtx->getSoExt(file)->postParse(); + soExt->postParse(); break; case ELF32BEKind: - adltCtx->getSoExt(file)->postParse(); + soExt->postParse(); break; case ELF64LEKind: - adltCtx->getSoExt(file)->postParse(); + soExt->postParse(); break; case ELF64BEKind: - adltCtx->getSoExt(file)->postParse(); + soExt->postParse(); break; default: llvm_unreachable(""); @@ -2550,17 +2550,6 @@ void LinkerDriver::link(opt::InputArgList &args) { for (StringRef name : config->undefined) addUnusedUndefined(name)->referenced = true; - // Fill duplicatedSymNames for defined syms. This will help to find duplicates. - if (config->adlt) { - ESymsCntMap eSymsHist; - for (auto *file : files) - buildSymsHist(file, eSymsHist); - for (auto eSym : eSymsHist) - if (eSym.second > 1) - ctx->adlt.duplicatedSymNames.insert(eSym.first); - eSymsHist.clear(); - } - // Add all files to the symbol table. This will add almost all // symbols that we need to the symbol table. This process might // add files to the link, via autolinking, these files are always @@ -2636,8 +2625,10 @@ void LinkerDriver::link(opt::InputArgList &args) { // No more lazy bitcode can be extracted at this point. Do post parse work // like checking duplicate symbols. - if (config->adlt) + if (config->adlt) { + adltCtx->checkDuplicatedSymbols(); parallelForEach(adltCtx->sharedFilesExtended, postParseSharedFileExtended); + } parallelForEach(ctx->objectFiles, initializeLocalSymbols); parallelForEach(ctx->objectFiles, postParseObjectFile); @@ -2706,7 +2697,6 @@ void LinkerDriver::link(opt::InputArgList &args) { // With this the symbol table should be complete. After this, no new names // except a few linker-synthesized ones will be added to the symbol table. const size_t numObjsBeforeLTO = ctx->objectFiles.size(); - const size_t numSoBeforeLTO = adltCtx->sharedFilesExtended.size(); invokeELFT(compileBitcodeFiles, skipLinkedOutput); // Symbol resolution finished. Report backward reference problems, @@ -2723,11 +2713,6 @@ void LinkerDriver::link(opt::InputArgList &args) { // compileBitcodeFiles may have produced lto.tmp object files. After this, no // more file will be added. - if (config->adlt) { - auto newSharedFiles = - makeArrayRef(adltCtx->sharedFilesExtended).slice(numSoBeforeLTO); - parallelForEach(newSharedFiles, postParseObjectFile); - } auto newObjectFiles = makeArrayRef(ctx->objectFiles).slice(numObjsBeforeLTO); parallelForEach(newObjectFiles, initializeLocalSymbols); parallelForEach(newObjectFiles, postParseObjectFile); @@ -2754,7 +2739,7 @@ void LinkerDriver::link(opt::InputArgList &args) { if (config->adlt) for (auto *it : adltCtx->sharedFilesExtended) for (InputSectionBase *s : it->getSections()) - if (it->isSectionValid(s)) + if (it->isValidSection(s)) inputSections.push_back(s); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 1fae37b85268..ff995222317c 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -159,18 +159,6 @@ static bool isCompatible(InputFile *file) { return false; } -template -static void doBuildSymsHist(InputFile *file, ESymsCntMap &eSymsHist) { - if (!isCompatible(file)) - return; - if (auto *f = adltCtx->getSoExt(file)) - f->buildSymsHist(eSymsHist); -} - -void elf::buildSymsHist(InputFile *file, ESymsCntMap &eSymsHist) { - invokeELFT(doBuildSymsHist, file, eSymsHist); -} - template static void doParseFile(InputFile *file) { if (!isCompatible(file)) return; @@ -197,13 +185,10 @@ template static void doParseFile(InputFile *file) { message(toString(file)); // .so file - if (config->adlt) - if (auto *f = adltCtx->getSoExt(file)) { - f->orderIdx = adltCtx->sharedFilesExtended.size(); - adltCtx->sharedFilesExtended.push_back(f); - f->parse(); - return; - } + if (config->adlt) { + adltCtx->getSoExt(file)->parse(); + return; + } if (auto *f = dyn_cast(file)) { f->parse(); @@ -414,11 +399,6 @@ StringRef ObjFile::getShtGroupSignature(ArrayRef sections, return CHECK(sym.getName(this->stringTable), this); } -template -StringRef ObjFile::getUniqueName(StringRef origName) const { - return origName; -} - template bool ObjFile::shouldMerge(const Elf_Shdr &sec, StringRef name) { // On a regular link we don't merge sections if -O0 (default is -O1). This @@ -580,13 +560,6 @@ void ObjFile::initializeSections(bool ignoreComdats, continue; } auto secName = check(obj.getSectionName(sec, shstrtab)); - if (config->adlt && sec.sh_type == SHT_NULL) { - auto name = getUniqueName(secName); - this->sections[i] = createInputSection(i, sec, name); - this->sections[i]->address = sec.sh_addr; - this->sections[i]->size = sec.sh_size; - } - switch (sec.sh_type) { case SHT_GROUP: { // De-duplicate section groups by their signatures. @@ -608,12 +581,7 @@ void ObjFile::initializeSections(bool ignoreComdats, .second; if (keepGroup) { if (config->relocatable) { - auto name = config->adlt ? getUniqueName(secName) : secName; - this->sections[i] = createInputSection(i, sec, name); - if (config->adlt) { - this->sections[i]->address = sec.sh_addr; - this->sections[i]->size = sec.sh_size; - } + this->sections[i] = createInputSection(i, sec, secName); } selectedGroups.push_back(entries); continue; @@ -641,12 +609,7 @@ void ObjFile::initializeSections(bool ignoreComdats, ctx->hasSympart.store(true, std::memory_order_relaxed); LLVM_FALLTHROUGH; default: - auto name = config->adlt ? getUniqueName(secName) : secName; - this->sections[i] = createInputSection(i, sec, name); - if (config->adlt) { - this->sections[i]->address = sec.sh_addr; - this->sections[i]->size = sec.sh_size; - } + this->sections[i] = createInputSection(i, sec, secName); } } @@ -1042,24 +1005,12 @@ InputSectionBase *ObjFile::createInputSection(uint32_t idx, if (name == ".eh_frame" && !config->relocatable) return make(*this, sec, name); - const bool doNotMerge = config->adlt && name.startswith(".rodata"); - if ((sec.sh_flags & SHF_MERGE) && !doNotMerge && shouldMerge(sec, name)) + if ((sec.sh_flags & SHF_MERGE) && shouldMerge(sec, name)) return make(*this, sec, name); return make(*this, sec, name); } -template -void ObjFile::buildSymsHist(ESymsCntMap &eSymsHist) { - ArrayRef eSyms = this->getELFSyms(); - for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) { - if (!eSyms[i].isDefined()) - continue; - StringRef name = CHECK(eSyms[i].getName(stringTable), this); - eSymsHist[CachedHashStringRef(name)]++; - } -} - // Initialize this->Symbols. this->Symbols is a parallel array as // its corresponding ELF symbol table. template @@ -1073,11 +1024,6 @@ void ObjFile::initializeSymbols(const object::ELFFile &obj) { for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) if (!symbols[i]) { StringRef name = CHECK(eSyms[i].getName(stringTable), this); - if (config->adlt && eSyms[i].isDefined() && - adltCtx->duplicatedSymNames.count(CachedHashStringRef(name)) != 0) { - adltCtx->withCfi = adltCtx->withCfi || name == "__cfi_check"; - name = this->getUniqueName(name); - } symbols[i] = symtab.insert(name); } @@ -1178,12 +1124,10 @@ template void ObjFile::initializeLocalSymbols() { else { auto p = this->getObj().getSection(secIdx); if (p.takeError()) { - fatal("getSection failed: " + llvm::toString(p.takeError())); + fatal("getSection failed: " + llvm::toString(p.takeError())); } - const Elf_Shdr *eSec = *p; - auto value = config->adlt ? eSym.st_value - eSec->sh_addr : eSym.st_value; new (symbols[i]) Defined(this, name, STB_LOCAL, eSym.st_other, type, - value, eSym.st_size, sec); + eSym.st_value, eSym.st_size, sec); } symbols[i]->isUsedInRegularObj = true; } @@ -1246,16 +1190,10 @@ template void ObjFile::postParse() { if (sym.binding == STB_WEAK || binding == STB_WEAK) continue; - std::lock_guard lock(mu); - if (config->adlt) { - auto *f = adltCtx->getSoExt(this); - bool isDebug = false; - if (isDebug) { - lld::outs() << "Put to duplicates for: " << archiveName << "\n"; - f->traceSymbol(sym); - } + { + std::lock_guard lock(mu); + ctx->duplicates.push_back({&sym, this, sec, eSym.st_value}); } - ctx->duplicates.push_back({&sym, this, sec, eSym.st_value}); } } @@ -1385,36 +1323,6 @@ std::vector SharedFile::parseVerneed(const ELFFile &obj, return verneeds; } -template -std::vector SharedFileExtended::parseVerneed(const ELFFile &obj, - const typename ELFT::Shdr *sec) { - if (!sec) - return {}; - std::vector verneeds; - ArrayRef data = CHECK(obj.getSectionContents(*sec), this); - const uint8_t *verneedBuf = data.begin(); - for (unsigned i = 0; i != sec->sh_info; ++i) { - if (verneedBuf + sizeof(typename ELFT::Verneed) > data.end()) - fatal(toString(this) + " has an invalid Verneed"); - auto *vn = reinterpret_cast(verneedBuf); - const uint8_t *vernauxBuf = verneedBuf + vn->vn_aux; - for (unsigned j = 0; j != vn->vn_cnt; ++j) { - if (vernauxBuf + sizeof(typename ELFT::Vernaux) > data.end()) - fatal(toString(this) + " has an invalid Vernaux"); - auto *aux = reinterpret_cast(vernauxBuf); - if (aux->vna_name >= this->stringTable.size()) - fatal(toString(this) + " has a Vernaux with an invalid vna_name"); - uint16_t version = aux->vna_other & VERSYM_VERSION; - if (version >= verneeds.size()) - verneeds.resize(version + 1); - verneeds[version] = aux->vna_name; - vernauxBuf += aux->vna_next; - } - verneedBuf += vn->vn_next; - } - return verneeds; -} - // We do not usually care about alignments of data in shared object // files because the loader takes care of it. However, if we promote a // DSO symbol to point to .bss due to copy relocation, we need to keep @@ -1622,396 +1530,131 @@ template void SharedFile::parse() { } } -template -void SharedFileExtended::resolveDuplicates() { - auto pred = [&](DuplicateSymbol dup) { - auto sym = dup.sym; - if (!sym->isDefined()) - return true; +SharedFileExtended::SharedFileExtended(MemoryBufferRef mb, StringRef soName) + : SharedFile(mb, soName), discardedSymbol(Undefined{this, "", 0, 0, 0, 0}), + discardedSection(InputSection::discarded) {} - auto d = cast(sym); - return !d->section && !d->getOutputSection(); +template +InputSection * +SharedFileExtended::createInputSection(const typename ELFT::Shdr &sec, + StringRef name) { + auto getSectionContents = [&](auto &sec) -> ArrayRef { + if (sec.sh_type == SHT_NOBITS) + return makeArrayRef(nullptr, sec.sh_size); + return check(getObj().getSectionContents(sec)); }; - static std::mutex mu; - { - std::lock_guard lock(mu); - llvm::erase_if(ctx->duplicates, pred); - } - - if (ctx->duplicates.empty()) - return; - - { - std::lock_guard lock(mu); - for (DuplicateSymbol &dup : ctx->duplicates) - warn("duplicate: " + dup.file->getName() + ": " + dup.section->name + - ": " + dup.sym->getName()); - ctx->duplicates.clear(); + auto getFlags = [&](uint64_t flags) -> uint64_t { + flags &= ~(uint64_t)SHF_INFO_LINK & ~(uint64_t)SHF_GROUP; + return flags; + }; + auto makeInputSection = [&]() { + return make(this, getFlags(sec.sh_flags), sec.sh_type, + sec.sh_addralign, getSectionContents(sec), name, + InputSectionBase::Regular); + }; + auto isec = makeInputSection(); + if (name.startswith(".n")) { + if (name == ".note.gnu.property") { + // this->andFeatures = readAndFeatures(isec); + return &discardedSection; + } } + return isec; } -template -SharedFileExtended::SharedFileExtended(MemoryBufferRef mb, - StringRef soName) - : ObjFile(mb, soName), soName(soName), - simpleSoName(path::stem(soName)) { - const_cast(this->fileKind) = InputFile::SharedKind; -} +InputSection *SharedFileExtended::getRelocTarget(unsigned idx, unsigned info) { + if (info < this->sections.size()) { // TODO REFACTOR + InputSection *target = cast(this->sections[info]); + if (target == &discardedSection) + return &discardedSection; -template -void SharedFileExtended::parse(bool ignoreComdats) { - ObjFile::parse(ignoreComdats); - parseDynamics(); - parseElfSymTab(); - - bool isDebug = false; // debug hint - if (!isDebug) - return; - - const ELFFile obj = this->getObj(); - ArrayRef objSections = this->template getELFShdrs(); - - lld::outs() << "Parse symbols from .symtab:\n"; - auto p = obj.getSection(symTabSecIdx); - if (p.takeError()) { - fatal("getSection failed: " + llvm::toString(p.takeError())); - } - const Elf_Shdr *elfSymTab = *p; - StringRef strTable = *obj.getStringTableForSymtab(*elfSymTab); - - auto eSyms = *obj.symbols(elfSymTab); - this->symbols.resize(this->symbols.size() + eSyms.size()); - for (const Elf_Sym &sym : eSyms) { - if (!sym.isDefined()) - continue; - - auto rawSec = obj.getSection(sym.st_shndx); - if (rawSec.takeError()) - continue; - if (isDebug) - traceElfSymbol(sym, strTable); - } - if (isDebug) - lld::outs() << '\n'; - - lld::outs() << "Parse offsets of some sections:\n"; - for (const Elf_Shdr &sec : objSections) { - 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); + if (target != nullptr) + return target; } - lld::outs() << '\n'; -} - -template void SharedFileExtended::postParse() { - ObjFile::initializeLocalSymbols(); - ObjFile::postParse(); - resolveDuplicates(); -} - -template -bool SharedFileExtended::isSectionValid(InputSectionBase *s) { - if (!s || s == &InputSection::discarded) - return false; - uint32_t type = s->type; - StringRef name = s->name; - - bool isBaseType = type == SHT_NOBITS || type == SHT_NOTE || - type == SHT_INIT_ARRAY || type == SHT_FINI_ARRAY; - // TODO: fix .debug_info relocation - bool isNeededProgBits = - type == SHT_PROGBITS && - !(name.startswith(".got.plt") || name.startswith(".plt") || name.startswith(".got") || - name.startswith(".eh_frame_hdr"));// || name.startswith(".debug_")); - bool ret = isBaseType || isNeededProgBits; - - bool isDebug = false; - if (ret && isDebug) - lld::outs() << "[isSectionValidForAdlt]: " << name << "\n"; - return ret; -} - -template -StringRef SharedFileExtended::addAdltPostfix(StringRef input) const { - if (input.empty()) return input; - auto suffix = Twine("__") + Twine::utohexstr(this->orderIdx); - return saver().save(input + suffix); -} - -template -bool SharedFileExtended::addAdltPostfix(Symbol *s) { - StringRef newName = addAdltPostfix(s->getName()); - if (s->getName() == newName) - return false; - s->setName(newName); - return true; -} - -template -StringRef SharedFileExtended::getUniqueName(StringRef origName) const { - return addAdltPostfix(origName); -} - -// TODO: optimize 2 lookups -template -bool SharedFileExtended::saveSymbol(const Defined& d) const { - auto found = elf::symtab->find(d.getName()); - if (found) - return false; - in.symTab->addSymbol(elf::symtab->addSymbol(d)); - return true; + error(toString(this) + Twine(": relocation section (index ") + Twine(idx) + + ") has invalid sh_info (" + Twine(info) + ")"); + return &discardedSection; } -template -Defined *SharedFileExtended::findSectionSymbol(uint64_t offset) const { - bool isDebug = false; - /*if (offset == 0x7738) // debug hint - isDebug = true;*/ - llvm::SmallVector candidates; - for (auto *sym : this->allSymbols) { - if (!sym || !sym->isSection()) - continue; - assert(sym->isDefined()); - Defined *d = cast(sym); - uint64_t low = d->section->address; - uint64_t high = low + d->section->size; - - if (isDebug) - lld::outs() << "offset: 0x" + utohexstr(offset) + - " sect name: " + d->section->name + "low 0x" + - utohexstr(low) + " high: 0x" + utohexstr(high) + "\n"; - bool isGood = (offset >= low) && (offset < high); - if (!isGood) - continue; - candidates.push_back(d); - } - if (candidates.empty()) // no suitable items found - return nullptr; - - llvm::sort(candidates, [offset](Defined *d1, Defined *d2) { - auto a1 = d1->section->address; - auto a2 = d2->section->address; - return (offset - a1 < offset - a2); - }); - - auto d = *candidates.begin(); - if (isDebug) - traceSymbol(*d, "found section sym: "); - return d; +template void SharedFileExtended::parse() { + orderIdx = adltCtx->sharedFilesExtended.size(); + object::ELFFile obj = getObj(); + initSections(obj); + initSymbols(obj); + adltCtx->sharedFilesExtended.push_back(this); } -template -InputSectionBase * -SharedFileExtended::findInputSection(StringRef name) const { - for (InputSectionBase *sec : this->sections) - if (sec && sec->name == name) - return sec; - return nullptr; +template void SharedFileExtended::postParse() { + createSymbols(getObj()); + // assert(ctx->duplicates.empty()); } template -InputSectionBase * -SharedFileExtended::findInputSection(uint64_t offset) const { - llvm::SmallVector candidates; - for (InputSectionBase *sec : this->sections) { - if (!sec) - continue; - if (sec->address == offset) - return sec; - uint64_t low = sec->address; - uint64_t high = low + sec->size; - bool isGood = (offset >= low) && (offset < high); - if (!isGood) - continue; - candidates.push_back(sec); - } - if (candidates.empty()) // no suitable items found - return nullptr; - - auto lessAddr = [&](auto *s1, auto *s2) { return s1->address < s2->address; }; - auto i = candidates.begin(); - auto e = candidates.end(); - auto ret = std::min_element(i, e, lessAddr); - return *ret; -} +void SharedFileExtended::initSections(const llvm::object::ELFFile &obj) { + typedef typename ELFT::Shdr Elf_Shdr; + typedef typename ELFT::Dyn Elf_Dyn; + ArrayRef objSections = getELFShdrs(); + StringRef shstrtab = CHECK(obj.getSectionStringTable(objSections), this); + uint64_t size = objSections.size(); + this->sections.resize(size); -template -bool SharedFileExtended::isDynamicSection(InputSectionBase &sec) const { - return sec.type == llvm::ELF::SHT_NULL || sec.name.startswith(".got.plt"); -} + ArrayRef dynamicTags; -template -Defined *SharedFileExtended::findDefinedSymbol( - uint64_t offset, llvm::function_ref extraCond) const { - bool isDebug = false; - /*if (offset == 0x7738) // debug hint - isDebug = true;*/ - auto predRange = [=](Symbol *sym) { - if (!sym || sym->isUndefined()) - return false; - - Defined *d = cast(sym); - if (d->file != this) - return false; - - bool goodVal = d->section->address + d->value == offset; - return goodVal && extraCond(d); + auto createSection = [&](auto idx, StringRef secName, const Elf_Shdr &sec) { + auto name = getUniqueName(secName); + this->sections[idx] = createInputSection(sec, name); + this->sections[idx]->address = sec.sh_addr; + this->sections[idx]->size = sec.sh_size; + sectionsMap[sec.sh_addr] = idx; }; - auto i = this->allSymbols.begin(); - auto e = this->allSymbols.end(); - auto ret = std::find_if(i, e, predRange); - if (ret != e) { // item was found - Defined *d = cast(*ret); - if (isDebug) - traceSymbol(*d, d->isSection() ? "found section sym: " - : "found defined sym: "); - return d; - } - - auto *sectionSym = findSectionSymbol(offset); - if (isDebug && sectionSym) - traceSymbol(*sectionSym, "found section sym: "); - return sectionSym; -} - -template -StringRef -SharedFileExtended::getShStrTab(ArrayRef elfSections) { - return CHECK(this->getObj().getSectionStringTable(elfSections), this); -} - -template -void SharedFileExtended::traceElfSymbol(const Elf_Sym &sym, - StringRef strTable) const { - const ELFFile obj = this->getObj(); - auto rawSec = obj.getSection(sym.st_shndx); - auto parsedSec = - !rawSec.takeError() ? *obj.getSection(sym.st_shndx) : nullptr; - lld::outs() << "File: " << soName << " symName: " << *sym.getName(strTable) - << " val: 0x" << utohexstr(sym.st_value) << " sec of sym: " - << (parsedSec ? *obj.getSectionName(*parsedSec) : "unknown!") - << " sym type: 0x" << utohexstr(sym.getType()) - << " sym binding: 0x" << utohexstr(sym.getBinding()) << '\n'; -} - -template -void SharedFileExtended::traceElfSection(const Elf_Shdr &sec) const { - const ELFFile obj = this->getObj(); - - auto secName = *obj.getSectionName(sec); - lld::outs() << "File: " << soName << " sec: " << secName << " sec addr: 0x" - << utohexstr(sec.sh_addr) << " sec offs: 0x" - << utohexstr(sec.sh_offset) << " sec ent size: 0x" - << utohexstr(sec.sh_entsize) << '\n'; -} - -template -void SharedFileExtended::traceSymbol(const Symbol &sym, - StringRef title) const { - lld::outs() << "File: " << soName << ": " + title - << " symName: " << sym.getName() << " exportDynamic: 0x" - << utohexstr(sym.exportDynamic); - if (!sym.isDefined()) { - lld::outs() << '\n'; - return; - } - auto &d = cast(sym); - lld::outs() << " val: 0x" << utohexstr(d.value) - << " sec of sym: " << (d.section ? d.section->name : "unknown!") - << " sym type: 0x" << utohexstr(d.type) << " sym binding: 0x" - << utohexstr(d.binding) << '\n'; -} - -template -void SharedFileExtended::traceSection(const SectionBase &sec, - StringRef title) const { - lld::outs() << "File: " << soName << ": " + title << " sec: " << sec.name - << " sec addr: 0x" << utohexstr(sec.address) << " sec offs: 0x" - << utohexstr(sec.getOffset(0)) << " sec ent size: 0x" - << utohexstr(sec.entsize) << '\n'; -} - -template -Symbol &SharedFileExtended::getDynamicSymbol(uint32_t symbolIndex) const { - return *this->symbols[symbolIndex]; -} - -template -Symbol &SharedFileExtended::getSymbol(uint32_t symbolIndex, - bool fromDynamic) const { - Symbol &sym = fromDynamic ? getDynamicSymbol(symbolIndex) - : getSymbolFromElfSymTab(symbolIndex); - - StringRef name = sym.getName(); - if (name.empty()) - return sym; - - /*if (name.contains("__emutls_v.TLS_data1")) // debug hint - lld::outs() << "debug getSymbol(): " << name << "\n";*/ - - // check SymbolTable - auto res = elf::symtab->find(name); - if (res && (res->exportDynamic || res->versionId)) - return *res; - - // check SymbolTableBaseSection - auto found = llvm::find_if( - in.symTab->getSymbols(), [&](const SymbolTableEntry &entry) { - return entry.sym->getName() == name; - }); - // add a local sym if it was not previously added - if (found == in.symTab->getSymbols().end()) - in.symTab->addSymbol(&sym); - return sym; -} - -template void SharedFileExtended::parseDynamics() { - const ELFFile obj = this->getObj(); - ArrayRef sections = this->template getELFShdrs(); - - ArrayRef dynamicTags; - const Elf_Shdr *versymSec = nullptr; - const Elf_Shdr *verdefSec = nullptr; - const Elf_Shdr *verneedSec = nullptr; - - // parse external lib deps - int secIdx = 0; - for (const Elf_Shdr &sec : sections) { + for (size_t i = 0; i != size; ++i) { + if (this->sections[i] == &InputSection::discarded) + continue; + const Elf_Shdr &sec = objSections[i]; + auto secName = check(obj.getSectionName(sec, shstrtab)); + if (secName == ".got.plt") + gotPltSecIdx = i; switch (sec.sh_type) { case SHT_DYNAMIC: dynamicTags = CHECK(obj.template getSectionContentsAsArray(sec), this); + createSection(i, secName, sec); break; case SHT_DYNSYM: - dynSymSecIdx = secIdx; + dynSymSecIdx = i; break; case SHT_SYMTAB: - symTabSecIdx = secIdx; - break; - case SHT_SYMTAB_SHNDX: - symTabShndxSecIdx = secIdx; + symTabSecIdx = i; break; case SHT_GNU_versym: - versymSec = &sec; - break; case SHT_GNU_verdef: - verdefSec = &sec; - break; case SHT_GNU_verneed: - verneedSec = &sec; break; + case SHT_SYMTAB_SHNDX: + symTabShndxSecIdx = i; + break; + case SHT_STRTAB: + case SHT_REL: + case SHT_RELA: + // case SHT_NULL: + break; + LLVM_FALLTHROUGH; + default: + createSection(i, secName, sec); } - auto secName = check(this->getObj().getSectionName(sec)); - if (secName == ".got.plt") - gotPltSecIdx = secIdx; - secIdx++; } - if (versymSec && this->numELFSyms == 0) { - error("SHT_GNU_versym should be associated with symbol table"); - return; + // Based on ObjFile::initializeSections(...) + for (size_t i = 0; i != size; ++i) { + const Elf_Shdr &sec = objSections[i]; + if (sec.sh_type == SHT_REL || sec.sh_type == SHT_RELA) { + const uint32_t info = sec.sh_info; + InputSectionBase *s = getRelocTarget(i, info); + if (!s) + continue; + s->relSecIdx = i; + } } // Search for a DT_SONAME tag to initialize this->soName. @@ -2021,176 +1664,219 @@ template void SharedFileExtended::parseDynamics() { if (val >= this->stringTable.size()) fatal(toString(this) + ": invalid DT_NEEDED entry"); dtNeeded.push_back(this->stringTable.data() + val); - } else if (dyn.d_tag == DT_SONAME) { + }/* else if (dyn.d_tag == DT_SONAME) { uint64_t val = dyn.getVal(); if (val >= this->stringTable.size()) fatal(toString(this) + ": invalid DT_SONAME entry"); soName = this->stringTable.data() + val; - } + }*/ } +} - verdefs = parseVerdefs(obj.base(), verdefSec); - std::vector verneeds = parseVerneed(obj, verneedSec); - - // Parse ".gnu.version" section which is a parallel array for the symbol - // table. If a given file doesn't have a ".gnu.version" section, we use - // VER_NDX_GLOBAL. - size_t size = this->numELFSyms - this->firstGlobal; - std::vector versyms(size, VER_NDX_GLOBAL); - if (versymSec) { - ArrayRef versym = - CHECK(obj.template getSectionContentsAsArray(*versymSec), - this) - .slice(this->firstGlobal); - for (size_t i = 0; i < size; ++i) - versyms[i] = versym[i].vs_index; +template +void SharedFileExtended::initSymbols(const llvm::object::ELFFile &obj) { + using Elf_Shdr = typename ELFT::Shdr; + using Elf_Sym = typename ELFT::Sym; + ArrayRef objSections = getELFShdrs(); + const Elf_Shdr *eSymTabSec = &objSections[symTabSecIdx]; + const Elf_Shdr *eDynSymSec = &objSections[dynSymSecIdx]; + assert(eSymTabSec && "ADLT: merging stripped libraries is not supported!"); + ArrayRef eDynSyms = CHECK(obj.symbols(eDynSymSec), this); + + symTabFirstGlobal = eSymTabSec->sh_info; + symbols.resize(eDynSyms.size()); + localSymbols.resize(symTabFirstGlobal); + + for (size_t i = 0; i < eDynSyms.size(); i++) { + const Elf_Sym &eSym = eDynSyms[i]; + StringRef name = CHECK(eSym.getName(stringTable), this); + if (eSym.getBinding() == STB_GLOBAL && eSym.isDefined()) + adltCtx->symNamesHist[CachedHashStringRef(name)]++; } +} - // System libraries can have a lot of symbols with versions. Using a - // fixed buffer for computing the versions name (foo@ver) can save a - // lot of allocations. - SmallString<0> versionedNameBuffer; +template +void SharedFileExtended::createSymbols(const llvm::object::ELFFile &obj) { + using Elf_Shdr = typename ELFT::Shdr; + using Elf_Sym = typename ELFT::Sym; + ArrayRef objSections = getELFShdrs(); + const Elf_Shdr *eSymTabSec = &objSections[symTabSecIdx]; + const Elf_Shdr *eDynSymSec = &objSections[dynSymSecIdx]; + assert(eSymTabSec && "ADLT: merging stripped libraries is not supported!"); + ArrayRef eDynSyms = CHECK(obj.symbols(eDynSymSec), this); + ArrayRef eSyms = CHECK(obj.symbols(eSymTabSec), this); + StringRef eStringTable = + CHECK(obj.getStringTableForSymtab(*eSymTabSec, objSections), this); + + Symbol *s = nullptr; + Defined *d = nullptr; + + auto addUndefined = [&](unsigned idx, const Elf_Sym &eSym, StringRef name) { + assert(eSym.isUndefined()); + s = symtab->addSymbol(Undefined{this, name, eSym.getBinding(), + eSym.st_other, eSym.getType()}); + s->exportDynamic = true; + s->isUsedInRegularObj = true; + this->symbols[idx] = s; + }; - // Add symbols to the symbol table. - SymbolTable &symtab = *elf::symtab; - ArrayRef syms = this->template getGlobalELFSyms(); - for (size_t i = 0, e = syms.size(); i != e; ++i) { - const Elf_Sym &sym = syms[i]; + auto addGlobalDefined = [&](unsigned idx, const Elf_Sym &eSym, + StringRef name) { + assert(eSym.isDefined()); + if (adltCtx->duplicatedSymNames.count(CachedHashStringRef(name))) + name = getUniqueName(name); + auto *sec = sections[eSym.st_shndx]; + s = symtab->addSymbol(Defined{this, name, eSym.getBinding(), eSym.st_other, + eSym.getType(), eSym.st_value, eSym.st_size, + sec}); + s->isUsedInRegularObj = true; + s->exportDynamic = true; + this->symbols[idx] = s; + definedSymbolsMap[eSym.st_value] = idx; + }; - // ELF spec requires that all local symbols precede weak or global - // symbols in each symbol table, and the index of first non-local symbol - // is stored to sh_info. If a local symbol appears after some non-local - // symbol, that's a violation of the spec. - StringRef name = CHECK(sym.getName(this->stringTable), this); - // Add postfix for defined duplicates. - if (config->adlt && sym.isDefined() && - adltCtx->duplicatedSymNames.count(CachedHashStringRef(name)) != 0) - name = this->getUniqueName(name); + auto addLocalDefined = [&](unsigned idx, const Elf_Sym &eSym, + StringRef name) { + assert(eSym.isDefined()); + name = getUniqueName(name); + auto *sec = sections[eSym.st_shndx]; + d = make(this, name, eSym.getBinding(), eSym.st_other, + eSym.getType(), eSym.st_value, eSym.st_size, sec); + d->isUsedInRegularObj = true; + this->localSymbols[idx] = d; + if (d->type != STT_NOTYPE) + definedSymbolsMap[eSym.st_value] = idx; + }; - if (sym.getBinding() == STB_LOCAL) { - warn("found local symbol '" + name + - "' in global part of symbol table in file " + toString(this)); + for (size_t i = 0; i < eDynSyms.size(); i++) { + const Elf_Sym &eSym = eDynSyms[i]; + StringRef name = CHECK(eSym.getName(stringTable), this); + if (!i && eSym.isUndefined() && eSym.st_shndx == SHN_UNDEF) + continue; // skip local undefined (first entry) + switch (eSym.getBinding()) { + case STB_WEAK: + addUndefined(i, eSym, name); + requiredSymbols.push_back(s); continue; - } - - uint16_t idx = versyms[i] & ~VERSYM_HIDDEN; - if (sym.isUndefined()) { - // For unversioned undefined symbols, VER_NDX_GLOBAL makes more sense but - // as of binutils 2.34, GNU ld produces VER_NDX_LOCAL. - if (idx != VER_NDX_LOCAL && idx != VER_NDX_GLOBAL) { - if (idx >= verneeds.size()) { - error("corrupt input file: version need index " + Twine(idx) + - " for symbol " + name + " is out of bounds\n>>> defined in " + - toString(this)); - continue; - } - StringRef verName = this->stringTable.data() + verneeds[idx]; - versionedNameBuffer.clear(); - name = saver().save( - (name + "@" + verName).toStringRef(versionedNameBuffer)); + case STB_GLOBAL: + if (eSym.isUndefined()) { + addUndefined(i, eSym, name); + continue; } - Symbol *s = symtab.addSymbol( - Undefined{this, name, sym.getBinding(), sym.st_other, sym.getType()}); - s->exportDynamic = true; - if (s->isUndefined() && sym.getBinding() != STB_WEAK && - config->unresolvedSymbolsInShlib != UnresolvedPolicy::Ignore) - requiredSymbols.push_back(s); - continue; + addGlobalDefined(i, eSym, name); + break; + default: + llvm_unreachable(""); } - // MIPS BFD linker puts _gp_disp symbol into DSO files and incorrectly - // assigns VER_NDX_LOCAL to this section global symbol. Here is a - // workaround for this bug. - if (config->emachine == EM_MIPS && idx == VER_NDX_LOCAL && - name == "_gp_disp") - continue; + } - uint32_t alignment = getAlignment(sections, sym); - if (!(versyms[i] & VERSYM_HIDDEN)) { - auto *s = symtab.addSymbol( - SharedSymbol{*this, name, sym.getBinding(), sym.st_other, - sym.getType(), sym.st_value, sym.st_size, alignment}); - if (s->file == this) - s->verdefIndex = idx; + for (size_t i = 0; i < symTabFirstGlobal; i++) { + const Elf_Sym &eSym = eSyms[i]; + StringRef name = CHECK(eSym.getName(eStringTable), this); + if (!i && eSym.isUndefined() && eSym.st_shndx == SHN_UNDEF) + continue; // skip local undefined (first entry) + switch (eSym.getBinding()) { + case STB_LOCAL: + if (eSym.getType() == STT_FILE) + continue; // TODO: support + addLocalDefined(i, eSym, name); + break; + default: + llvm_unreachable(""); } + } +} - // Also add the symbol with the versioned name to handle undefined symbols - // with explicit versions. - if (idx == VER_NDX_GLOBAL) - continue; +InputSectionBase &SharedFileExtended::getSection(unsigned offset) { + auto *sec = sections[sectionsMap[offset]]; + if (offset && sec->type == SHT_NULL) + sec = findSection(offset); + return *sec; +} - if (idx >= verdefs.size() || idx == VER_NDX_LOCAL) { - error("corrupt input file: version definition index " + Twine(idx) + - " for symbol " + name + " is out of bounds\n>>> defined in " + - toString(this)); - continue; - } +InputSectionBase &SharedFileExtended::getSectionByOrder(unsigned idx) { + auto *sec = sections[idx]; + if (!sec) + sec = sections[0]; // discarded + return *sec; +} - StringRef verName = - this->stringTable.data() + - reinterpret_cast(verdefs[idx])->getAux()->vda_name; - versionedNameBuffer.clear(); - name = (name + "@" + verName).toStringRef(versionedNameBuffer); - auto *s = symtab.addSymbol( - SharedSymbol{*this, saver().save(name), sym.getBinding(), sym.st_other, - sym.getType(), sym.st_value, sym.st_size, alignment}); - if (s->file == this) - s->verdefIndex = idx; - } +StringRef SharedFileExtended::getUniqueName(StringRef origName) const { + if (origName.empty()) + return origName; + auto postfix = "__" + utohexstr(orderIdx); + return saver().save(origName + postfix); } -template void SharedFileExtended::parseElfSymTab() { - const ELFFile obj = this->getObj(); - ArrayRef eSections = this->template getELFShdrs(); +Symbol &SharedFileExtended::getDynamicSymbol(uint32_t symbolIndex) { + assert(symbolIndex && (symbolIndex < symbols.size())); + return *symbols[symbolIndex]; +} - // Find a symbol table. - const Elf_Shdr *eSymtabSec = findSection(eSections, SHT_SYMTAB); - if (!eSymtabSec) - return; +Symbol &SharedFileExtended::getLocalSymbol(uint32_t symbolIndex) { + assert(symbolIndex && (symbolIndex < localSymbols.size())); + return *localSymbols[symbolIndex]; +} + +Symbol &SharedFileExtended::getSymbol(uint32_t symbolIndex, bool fromDynamic) { + if (!symbolIndex) + return discardedSymbol; + if (symbolIndex > localSymbols.size()) + return getDynamicSymbol(symbolIndex - (symTabFirstGlobal + 1)); + return fromDynamic ? getDynamicSymbol(symbolIndex) + : getLocalSymbol(symbolIndex); +} - eFirstGlobal = eSymtabSec->sh_info; +InputSectionBase *SharedFileExtended::findSection(unsigned offset) { + llvm::SmallVector candidates; + for (InputSectionBase *sec : sections) { + if (!sec) + continue; + auto low = sec->address, high = low + sec->size; + if (offset >= low && offset < high) + candidates.push_back(sec); + } + if (candidates.empty()) // no suitable items found + return nullptr; - ArrayRef eSyms = CHECK(obj.symbols(eSymtabSec), this); - auto numESyms = uint32_t(eSyms.size()); - auto eStringTable = CHECK(obj.getStringTableForSymtab(*eSymtabSec, eSections), this); - this->allSymbols.resize(numESyms); + llvm::sort(candidates, [offset](InputSectionBase *a, InputSectionBase *b) { + return (offset - a->address < offset - b->address); + }); + return *candidates.begin(); +} - for (size_t i = 0; i < numESyms; i++) { - const Elf_Sym &eSym = eSyms[i]; - StringRef name(eStringTable.data() + eSym.st_name); - auto bind = eSym.getBinding(); - auto type = eSym.getType(); - auto other = eSym.st_other; - if (eSym.isDefined()) { - auto secIdx = eSym.st_shndx; - if (LLVM_UNLIKELY(secIdx == SHN_XINDEX)) - secIdx = check( - getExtendedSymbolTableIndex(eSym, i, this->getShndxTable())); - else if (secIdx >= SHN_LORESERVE) - secIdx = 0; - auto p = obj.getSection(secIdx); - if (p.takeError()) { - fatal("getSection failed: " + llvm::toString(p.takeError())); - } - const Elf_Shdr *eSec = *p; - InputSectionBase *sec = this->sections[secIdx]; - auto val = eSym.st_value; - if (type != STT_TLS) - val -= eSec->sh_addr; - auto dynSym = llvm::find_if(this->symbols, [=](const Symbol *s) { - return s && s->getName() == name; - }); - bool isInDynSym = dynSym != this->symbols.end(); - if (!isInDynSym) - name = addAdltPostfix(name); - /*if (name == "TLS_data1") // debug hint - lld::outs() << name << '\n'; */ - this->allSymbols[i] = - make(this, name, bind, other, type, val, eSym.st_size, sec); - } else { - this->allSymbols[i] = make(this, name, bind, other, type, - /*discardedSecIdx=*/i); - } +Defined &SharedFileExtended::getDefinedLocalSym(unsigned offset) { + auto getSym = [&](unsigned offs) { + return localSymbols[definedSymbolsMap[offs]]; + }; + auto *d = getSym(offset); + if (!d) { + auto sec = findSection(offset); + d = getSym(sec->address); } + assert(d && d->isDefined()); + return *d; +} + +bool SharedFileExtended::isDynamicSection(InputSectionBase *s) { + return s->type == llvm::ELF::SHT_NULL || s->name.startswith(".got.plt"); +} + +bool SharedFileExtended::isValidSection(InputSectionBase *s) { + if (!s || s == &InputSection::discarded) + return false; + uint32_t type = s->type; + StringRef name = s->name; + + bool isBaseType = type == SHT_NOBITS || type == SHT_NOTE || + type == SHT_INIT_ARRAY || type == SHT_FINI_ARRAY; + // TODO: fix .debug sections relocation + bool isNeededProgBits = + type == SHT_PROGBITS && + !(name.startswith(".plt") || name.startswith(".got") || + name.startswith(".eh_frame_hdr") || name.startswith(".debug_")); + bool ret = isBaseType || isNeededProgBits; + return ret; } static ELFKind getBitcodeELFKind(const Triple &t) { @@ -2433,27 +2119,6 @@ ELFFileBase *elf::createObjFile(MemoryBufferRef mb, StringRef archiveName, return f; } -ELFFileBase *elf::createSharedFileExtended(MemoryBufferRef mb, StringRef soName) { - ELFFileBase *f; - switch (getELFKind(mb, soName)) { - case ELF32LEKind: - f = make>(mb, soName); - break; - case ELF32BEKind: - f = make>(mb, soName); - break; - case ELF64LEKind: - f = make>(mb, soName); - break; - case ELF64BEKind: - f = make>(mb, soName); - break; - default: - llvm_unreachable("getELFKind"); - } - return f; -} - template void ObjFile::parseLazy() { const ArrayRef eSyms = this->getELFSyms(); SymbolTable &symtab = *elf::symtab; @@ -2507,7 +2172,12 @@ template void SharedFile::parse(); template void SharedFile::parse(); template void SharedFile::parse(); -template class elf::SharedFileExtended; -template class elf::SharedFileExtended; -template class elf::SharedFileExtended; -template class elf::SharedFileExtended; +template void SharedFileExtended::parse(); +template void SharedFileExtended::parse(); +template void SharedFileExtended::parse(); +template void SharedFileExtended::parse(); + +template void SharedFileExtended::postParse(); +template void SharedFileExtended::postParse(); +template void SharedFileExtended::postParse(); +template void SharedFileExtended::postParse(); diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 4413ccc1e1b2..d8180f2bfdde 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -47,8 +47,6 @@ extern std::unique_ptr tar; llvm::Optional readFile(StringRef path); // Add symbols in File to the symbol table. -typedef llvm::DenseMap ESymsCntMap; -void buildSymsHist(InputFile *file, ESymsCntMap &eSymsHist); void parseFile(InputFile *file); // The root class of input files. @@ -96,14 +94,6 @@ public: fileKind == BitcodeKind); return symbols; } - - // ADLT beg - ArrayRef getAllSymbols() const { return allSymbols; } - - SmallVector allSymbols; - // ADLT end - - // Get filename to use for linker script processing. StringRef getNameForScript() const; @@ -200,7 +190,7 @@ public: } // OHOS_LOCAL begins - virtual bool isSectionValid(InputSectionBase *s) { return true; } + virtual bool isValidSection(InputSectionBase *s) { return true; } // OHOS_LOCAL end template typename ELFT::ShdrRange getELFShdrs() const { @@ -298,13 +288,9 @@ public: // Get cached DWARF information. DWARFCache *getDwarf(); - void buildSymsHist(ESymsCntMap &eSymsHist); void initializeLocalSymbols(); virtual void postParse(); -protected: - virtual StringRef getUniqueName(StringRef origName) const; - private: void initializeSections(bool ignoreComdats, const llvm::object::ELFFile &obj); @@ -393,75 +379,39 @@ private: }; -// ADLT -template -class SharedFileExtended : public ObjFile { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - +// OHOS_LOCAL begin +class SharedFileExtended : public SharedFile { public: SharedFileExtended(MemoryBufferRef mb, StringRef soName); + template void parse(); + template void postParse(); - static bool classof(const InputFile *f) { - return f->kind() == InputFile::SharedKind; - } - - virtual void parse(bool ignoreComdats = false) override; - virtual void postParse() override; - - virtual bool isSectionValid(InputSectionBase *s) override; - - StringRef addAdltPostfix(StringRef input) const; - bool addAdltPostfix(Symbol *s); - - bool saveSymbol(const Defined& d) const; - - Defined *findSectionSymbol(uint64_t offset) const; - Defined *findDefinedSymbol( - uint64_t offset, - llvm::function_ref extraCond = [](Defined *) { - return true; - }) const; - - InputSectionBase *findInputSection(StringRef name) const; - InputSectionBase *findInputSection(uint64_t offset) const; - bool isDynamicSection(InputSectionBase &sec) const; - - template - Symbol &getRelocTargetSymADLT(const RelT &rel, InputSectionBase &sec) const { + template Symbol &getRelocTargetSym(const RelT &rel) { uint32_t symIndex = rel.getSymbol(config->isMips64EL); - return getSymbol(symIndex, isDynamicSection(sec)); - } - - ArrayRef getLocalSymbols() override { - if (this->allSymbols.empty()) - return {}; - return llvm::makeArrayRef(this->allSymbols).slice(1, eFirstGlobal - 1); + return getSymbol(symIndex); } - Symbol &getDynamicSymbol(uint32_t symbolIndex) const; - Symbol &getSymbol(uint32_t symbolIndex, bool fromDynamic) const; + InputSectionBase &getSection(unsigned offset); + InputSectionBase &getSectionByOrder(unsigned idx); - Symbol &getSymbolFromElfSymTab(uint32_t symbolIndex) const { - if (symbolIndex >= this->allSymbols.size()) - fatal(toString(this) + ": invalid symbol index"); - return *this->allSymbols[symbolIndex]; - } + StringRef getUniqueName(StringRef origName) const; - void traceElfSymbol(const Elf_Sym &sym, StringRef strTable) const; - void traceElfSection(const Elf_Shdr &sec) const; + InputSectionBase *findSection(unsigned offset); + Symbol &getSymbol(unsigned symbolIndex, bool fromDynamic = false); + Defined &getDefinedLocalSym(unsigned offset); - void traceSymbol(const Symbol &sym, StringRef title = "") const; - void traceSection(const SectionBase &sec, StringRef title = "") const; + bool isDynamicSection(InputSectionBase *s); + bool isValidSection(InputSectionBase *s) override; -public: // the input order of the file as it presented in ADLT image size_t orderIdx; int dynSymSecIdx = 0; int symTabSecIdx = 0; - int symTabShndxSecIdx = 0; - int eFirstGlobal = 0; int gotPltSecIdx = 0; + int symTabShndxSecIdx = 0; + unsigned symTabFirstGlobal = 0; + // .symtab's start of local symbols owned by library llvm::Optional sharedLocalSymbolIndex; // .symtab's start of global symbols owned by library @@ -471,40 +421,34 @@ public: llvm::SetVector programHeaders; // From input .rela.dyn, .rela.plt: - llvm::SetVector dynRelIndexes; - llvm::SetVector pltRelIndexes; + llvm::SetVector dynRelIndexes; + llvm::SetVector pltRelIndexes; - // SharedFile compability layer: - // This is actually a vector of Elf_Verdef pointers. - SmallVector verdefs; - // If the output file needs Elf_Verneed data structures for this file, this is - // a vector of Elf_Vernaux version identifiers that map onto the entries in - // Verdefs, otherwise it is empty. - SmallVector vernauxs; - static unsigned vernauxNum; - SmallVector dtNeeded; - StringRef soName; - StringRef simpleSoName; - // Used for --as-needed - // bool isNeeded; - // Non-weak undefined symbols which are not yet resolved when the SO is - // parsed. Only filled for `--no-allow-shlib-undefined`. - SmallVector requiredSymbols; +private: + SmallVector localSymbols; + llvm::DenseMap sectionsMap; // offset, orderIdx + llvm::DenseMap definedSymbolsMap; // abs offset, orderIdx -protected: - virtual StringRef getUniqueName(StringRef origName) const override; + Symbol discardedSymbol; + InputSection& discardedSection; -private: - void parseDynamics(); // SharedFile compability - void parseElfSymTab(); // ObjectFile compability + Symbol &getDynamicSymbol(unsigned symbolIndex); + Symbol &getLocalSymbol(unsigned symbolIndex); - void resolveDuplicates(); + template + void initSections(const llvm::object::ELFFile &obj); + template + void initSymbols(const llvm::object::ELFFile &obj); + template + void createSymbols(const llvm::object::ELFFile &obj); - StringRef getShStrTab(ArrayRef elfSections); + template + InputSection *createInputSection(const typename ELFT::Shdr &sec, + StringRef name); - std::vector parseVerneed(const llvm::object::ELFFile &obj, - const typename ELFT::Shdr *sec); + InputSection *getRelocTarget(unsigned idx, unsigned info); }; +// OHOS_LOCAL end class BinaryFile : public InputFile { public: @@ -516,8 +460,6 @@ public: ELFFileBase *createObjFile(MemoryBufferRef mb, StringRef archiveName = "", bool lazy = false); -ELFFileBase *createSharedFileExtended(MemoryBufferRef mb, StringRef soName = ""); - std::string replaceThinLTOSuffix(StringRef path); } // namespace elf diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 78a34afa8fef..b67836144c11 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -49,6 +49,14 @@ static ArrayRef getSectionContents(ObjFile &file, return makeArrayRef(nullptr, hdr.sh_size); return check(file.getObj().getSectionContents(hdr)); } +/* +template +static ArrayRef getSectionContents(SharedFileExtended &file, + const typename ELFT::Shdr &hdr) { + if (hdr.sh_type == SHT_NOBITS) + return makeArrayRef(nullptr, hdr.sh_size); + return check(file.getObj().getSectionContents(hdr)); +}*/ InputSectionBase::InputSectionBase(InputFile *file, uint64_t flags, uint32_t type, uint64_t entsize, @@ -348,12 +356,8 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef rels) { for (const RelTy &rel : rels) { RelType type = rel.getType(config->isMips64EL); - const ObjFile *file = - config->adlt ? adltCtx->getSoExt(file) : getFile(); - Symbol &sym = - config->adlt - ? adltCtx->getSoExt(file)->getRelocTargetSymADLT(rel, *sec) - : file->getRelocTargetSym(rel); + const ObjFile *file = getFile(); // ADLT TODO + Symbol &sym = file->getRelocTargetSym(rel); auto *p = reinterpret_cast(buf); buf += sizeof(RelTy); @@ -849,11 +853,10 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { if (!RelTy::IsRela) addend += target.getImplicitAddend(bufLoc, type); - Symbol &sym = config->adlt - ? adltCtx->getSoExt(file)->getSymbolFromElfSymTab( - rel.getSymbol(config->isMips64EL)) - : getFile()->getRelocTargetSym(rel); - if (config->adlt) { // TODO improve + // ADLT TODO + Symbol &sym = config->adlt ? getSoExt()->getRelocTargetSym(rel) + : getFile()->getRelocTargetSym(rel); + /*if (config->adlt) { // TODO improve switch (type) { case R_AARCH64_RELATIVE: case R_AARCH64_GLOB_DAT: @@ -862,7 +865,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { default: break; } - } + }*/ RelExpr expr = target.getRelExpr(type, sym, bufLoc); if (expr == R_NONE) continue; @@ -966,9 +969,8 @@ static void relocateNonAllocForRelocatable(InputSection *sec, uint8_t *buf) { template void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd) { - if (flags & SHF_EXECINSTR && - (config->adlt ? LLVM_UNLIKELY(adltCtx->getSoExt(file)->splitStack) - : LLVM_UNLIKELY(getFile()->splitStack))) + if (!config->adlt && flags & SHF_EXECINSTR && + LLVM_UNLIKELY(getFile()->splitStack)) adjustSplitStackFunctionPrologues(buf, bufEnd); if (flags & SHF_ALLOC) { diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 1d13d1673304..f584c83ab454 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -17,6 +17,7 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Object/ELF.h" +#include "Adlt.h" namespace lld { namespace elf { @@ -28,7 +29,7 @@ class Defined; struct Partition; class SyntheticSection; template class ObjFile; -template class SharedFileExtended; +class SharedFileExtended; class OutputSection; extern std::vector partitions; @@ -137,6 +138,10 @@ public: return cast_or_null>(file); } + SharedFileExtended *getSoExt() const { + return adltCtx->getSoExt(file); + } + // Used by --optimize-bb-jumps and RISC-V linker relaxation temporarily to // indicate the number of bytes which is not counted in the size. This should // be reset to zero after uses. diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp index f4a3ad98f434..5c1d109ef73b 100644 --- a/lld/ELF/MapFile.cpp +++ b/lld/ELF/MapFile.cpp @@ -23,7 +23,6 @@ #include "LinkerScript.h" #include "OutputSections.h" #include "Symbols.h" -#include "Adlt.h" #include "SyntheticSections.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" @@ -56,7 +55,7 @@ static void writeHeader(raw_ostream &os, uint64_t vma, uint64_t lma, // Returns a list of all symbols that we want to print out. static std::vector getSymbols() { std::vector v; - auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; + auto files = ctx->objectFiles; for (ELFFileBase *file : files) for (Symbol *b : file->getSymbols()) if (auto *dr = dyn_cast(b)) @@ -226,7 +225,7 @@ static void writeMapFile(raw_fd_ostream &os) { static void writeCref(raw_fd_ostream &os) { // Collect symbols and files. MapVector> map; - auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; + auto files = ctx->objectFiles; for (ELFFileBase *file : files) { for (Symbol *sym : file->getSymbols()) { if (isa(sym)) diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index 66974398c92d..38d8eeae1798 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -346,7 +346,7 @@ template void MarkLive::mark() { // to from __start_/__stop_ symbols because there will only be one set of // symbols for the whole program. template void MarkLive::moveToMain() { - auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; + auto files = ctx->objectFiles; for (ELFFileBase *file : files) for (Symbol *s : file->getSymbols()) if (auto *d = dyn_cast(s)) diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index cd390a01539d..81858e7a1586 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -435,14 +435,17 @@ private: }; // OHOS_LOCAL begin -template class AdltRelocationScanner { +class AdltRelocationScanner { public: - explicit AdltRelocationScanner(InputSectionBase &sec) : sec(sec) {} + AdltRelocationScanner(InputSectionBase &isec) + : file(adltCtx->getSoExt(isec.file)), + fromDynamic(file->isDynamicSection(&isec)), sec(isec) {} - SharedFileExtended *getSoExt() { - return adltCtx->getSoExt(sec.file); - } - void process(Relocation *r, bool fromDynamic); + SharedFileExtended *getSoExt() { return file; } + + Symbol &getSymbol(uint32_t idx) { return file->getSymbol(idx, fromDynamic); } + + void process(Relocation *r); void trackGotPlt(Symbol *sym); void trackDynReloc(); @@ -451,21 +454,21 @@ public: bool toProcessAux = false; private: - uint32_t relSecType = SHT_NULL; + SharedFileExtended *file = nullptr; + bool fromDynamic = false; InputSectionBase &sec; + uint32_t relSecType = SHT_NULL; }; -template -void AdltRelocationScanner::trackGotPlt(Symbol *sym) { - adltCtx->gotPltInfo[sym].push_back(getSoExt()->orderIdx); +void AdltRelocationScanner::trackGotPlt(Symbol *sym) { + adltCtx->gotPltInfo[sym].push_back(file->orderIdx); } -template void AdltRelocationScanner::trackDynReloc() { - getSoExt()->dynRelIndexes.insert(getDynamicRelocsCount() - 1); +void AdltRelocationScanner::trackDynReloc() { + file->dynRelIndexes.insert(getDynamicRelocsCount() - 1); } -template -unsigned AdltRelocationScanner::getDynamicRelocsCount() { +unsigned AdltRelocationScanner::getDynamicRelocsCount() { auto currentSize = isRelr() ? mainPart->relrDyn->relocs.size() : mainPart->relaDyn->relocs.size(); return currentSize; @@ -1341,35 +1344,22 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym, } // OHOS_LOCAL begin -template -void AdltRelocationScanner::process(Relocation *r, bool fromDynamic) { - auto file = adltCtx->getSoExt(sec.file); - bool isDebug = false; - - /*if (r->offset == 0x21F) // debug hint - isDebug = true; - /*if (r->type == R_AARCH64_ABS64 && - r->sym->getName() == "__emutls_t.TLS_data1") - isDebug = true;*/ - - // parse offset (where) - InputSectionBase *secWhere = file->findInputSection(r->offset); - assert(secWhere && "not found!"); - - // process offset - r->offset -= fromDynamic ? secWhere->address : sec.address; - assert(r->type); - +void AdltRelocationScanner::process(Relocation *r) { + if (r->offset == 0x17fc) + lld::outs() << "dbg\n"; + + // prepare + InputSectionBase &secWhere = + (sec.type != SHT_NULL) ? sec : file->getSection(r->offset); + r->offset -= secWhere.address; // resolve relocs switch (r->type) { // dyn relocs case R_AARCH64_RELATIVE: { - Defined *d = file->findDefinedSymbol(r->addend); - assert(d && "R_AARCH64_RELATIVE: r->sym not found by addend!"); + Defined *d = &file->getDefinedLocalSym(r->addend); r->sym = d; - r->addend -= d->section->address + d->value; - addRelativeReloc(*secWhere, r->offset, *r->sym, r->addend, r->expr, - r->type); + r->addend -= d->section->address; + addRelativeReloc(secWhere, r->offset, *r->sym, r->addend, r->expr, r->type); assert(getDynamicRelocsCount()); trackDynReloc(); return; @@ -1393,7 +1383,7 @@ void AdltRelocationScanner::process(Relocation *r, bool fromDynamic) { case R_AARCH64_ABS64: if (fromDynamic) { assert(r->sym->exportDynamic); - sec.getPartition().relaDyn->addSymbolReloc(r->type, *secWhere, + sec.getPartition().relaDyn->addSymbolReloc(r->type, secWhere, r->offset, *r->sym, r->addend, r->type); trackDynReloc(); @@ -1426,10 +1416,8 @@ void AdltRelocationScanner::process(Relocation *r, bool fromDynamic) { return; case R_AARCH64_ADR_GOT_PAGE: if (r->sym->isDefined() && !r->sym->needsGot) { - if (isDebug) - lld::outs() << "[ADLT] R_AARCH64_ADR_GOT_PAGE: sym not in GOT! "; - r->expr = R_PC; // prev: R_AARCH64_GOT_PAGE_PC || R_AARCH64_GOT_PAGE || - // R_GOT || R_GOT_PC + // prev: R_AARCH64_GOT_PAGE_PC || R_AARCH64_GOT_PAGE || R_GOT || R_GOT_PC + r->expr = R_PC; // TODO: replace reloc R_AARCH64_ADR_GOT_PAGE sec.relocations.push_back(*r); return; @@ -1467,13 +1455,12 @@ void AdltRelocationScanner::process(Relocation *r, bool fromDynamic) { template void RelocationScanner::scanOne(RelTy *&i) { const RelTy &rel = *i; uint32_t symIndex = rel.getSymbol(config->isMips64EL); - bool fromDynamic = false; + std::unique_ptr adltScanner = nullptr; if (config->adlt) - fromDynamic = adltCtx->getSoExt(sec.file)->isDynamicSection(sec); - Symbol &sym = - config->adlt - ? adltCtx->getSoExt(sec.file)->getSymbol(symIndex, fromDynamic) - : sec.getFile()->getSymbol(symIndex); + adltScanner = std::make_unique(sec); + + Symbol &sym = config->adlt ? adltScanner->getSymbol(symIndex) + : sec.getFile()->getSymbol(symIndex); RelType type; // Deal with MIPS oddity. @@ -1506,10 +1493,9 @@ template void RelocationScanner::scanOne(RelTy *&i) { int64_t addend = computeAddend(rel, expr, sym.isLocal()); if (config->adlt) { - AdltRelocationScanner adltScanner(sec); Relocation r = {expr, type, offset, addend, &sym}; - adltScanner.process(&r, fromDynamic); - if (adltScanner.toProcessAux) + adltScanner->process(&r); + if (adltScanner->toProcessAux) processAux(r); return; } @@ -1724,12 +1710,7 @@ void RelocationScanner::scan(ArrayRef rels) { template void elf::scanRelocations(InputSectionBase &s) { RelocationScanner scanner(s); - AdltRelocationScanner adltScanner(s); - if (config->adlt) { - bool isDebug = false; - if (isDebug) - lld::outs() << s.file->getName().str() + ": " + s.name.str() + '\n'; - } + // AdltRelocationScanner adltScanner(s); const RelsOrRelas rels = s.template relsOrRelas(); if (rels.areRelocsRel()) scanner.template scan(rels.rels); @@ -1823,7 +1804,7 @@ namespace adlt { template static void addGotPltIndex(Symbol *s, bool isPlt) { auto &vec = adltCtx->gotPltInfo[s]; for (auto &orderId : vec) { - auto *soFile = adltCtx->getSoExt(orderId); + auto *soFile = adltCtx->getSoExt(orderId); auto &entries = isPlt ? in.relaPlt->relocs : mainPart->relaDyn->relocs; auto &output = isPlt ? soFile->pltRelIndexes : soFile->dynRelIndexes; output.insert(entries.size() - 1); @@ -1941,10 +1922,14 @@ void elf::postScanRelocations() { // Local symbols may need the aforementioned non-preemptible ifunc and GOT // handling. They don't need regular PLT. - auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; - for (ELFFileBase *file : files) - for (Symbol *sym : file->getLocalSymbols()) - fn(*sym); + if (config->adlt) + for (auto *soExt : adltCtx->sharedFilesExtended) + for (Symbol *sym : soExt->getLocalSymbols()) + fn(*sym); + else + for (auto *file : ctx->objectFiles) + for (Symbol *sym : file->getLocalSymbols()) + fn(*sym); } static bool mergeCmp(const InputSection *a, const InputSection *b) { diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index e2d32416c65b..182cedf25d1d 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1399,11 +1399,10 @@ DynamicSection::computeContents() { part.dynStrTab->addString(config->rpath)); if (config->adlt) { - for (InputFile *file : adltCtx->sharedFilesExtended) { - auto *f = adltCtx->getSoExt(file); - for (size_t i = 0; i < f->dtNeeded.size(); i++) { + for (auto *soExt : adltCtx->sharedFilesExtended) { + for (size_t i = 0; i < soExt->dtNeeded.size(); i++) { auto tag = DT_NEEDED; - auto val = part.dynStrTab->addString(f->dtNeeded[i]); + auto val = part.dynStrTab->addString(soExt->dtNeeded[i]); if (llvm::find(entries, std::pair{tag, val}) == entries.end()) addInt(tag, val); @@ -1532,7 +1531,8 @@ DynamicSection::computeContents() { } if (config->emachine == EM_AARCH64) { - if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) + if (!config->adlt && + config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) addInt(DT_AARCH64_BTI_PLT, 0); if (config->zPacPlt) addInt(DT_AARCH64_PAC_PLT, 0); @@ -1558,10 +1558,9 @@ DynamicSection::computeContents() { return &osd->osec; return (OutputSection *)nullptr; }; - for (InputFile *file : adltCtx->sharedFilesExtended) { - auto *f = adltCtx->getSoExt(file); - auto initArray = findSection(f->addAdltPostfix(".init_array")); - auto finiArray = findSection(f->addAdltPostfix(".fini_array")); + for (auto *soExt : adltCtx->sharedFilesExtended) { + auto initArray = findSection(soExt->getUniqueName(".init_array")); + auto finiArray = findSection(soExt->getUniqueName(".fini_array")); if (initArray) { addInt(DT_INIT_ARRAY, initArray->addr); addInt(DT_INIT_ARRAYSZ, initArray->size); @@ -2271,14 +2270,13 @@ void SymbolTableBaseSection::sortSymTabSymbolsInAdlt(size_t numLocals) { using SortKey = std::tuple; auto makeKey = [](const SymbolTableEntry& ent) -> SortKey { const InputFile* file = ent.sym->file; - if(auto* soext = dyn_cast_or_null>(file)) { + if (auto *soext = adltCtx->getSoExt(file)) { return {static_cast(soext->orderIdx), file}; } return {-1, file}; }; - for (InputFile* file : adltCtx->sharedFilesExtended) { - auto* soext = adltCtx->getSoExt(file); + for (auto* soext : adltCtx->sharedFilesExtended) { soext->sharedLocalSymbolIndex = llvm::None; soext->sharedGlobalSymbolIndex = llvm::None; } @@ -2297,13 +2295,13 @@ void SymbolTableBaseSection::sortSymTabSymbolsInAdlt(size_t numLocals) { // extract file boundaries for local symbols for (auto iter = symbols.begin(); iter != localEnd; ++iter) - if (auto* soext = dyn_cast_or_null>(iter->sym->file)) + if (auto* soext = dyn_cast_or_null(iter->sym->file)) if (!soext->sharedLocalSymbolIndex) soext->sharedLocalSymbolIndex = std::distance(symbols.begin(), iter); // extract file boundaries for global symbols for (auto iter = localEnd; iter != symbols.end(); ++iter) - if (auto* soext = dyn_cast_or_null>(iter->sym->file)) + if (auto* soext = dyn_cast_or_null(iter->sym->file)) if (!soext->sharedGlobalSymbolIndex) soext->sharedGlobalSymbolIndex = std::distance(symbols.begin(), iter); } @@ -3496,8 +3494,7 @@ template void elf::splitSections() { llvm::TimeTraceScope timeScope("Split sections"); // splitIntoPieces needs to be called on each MergeInputSection // before calling finalizeContents(). - auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; - parallelForEach(files, [](ELFFileBase *file) { + parallelForEach(ctx->objectFiles, [](ELFFileBase *file) { for (InputSectionBase *sec : file->getSections()) { if (!sec) continue; @@ -4094,22 +4091,18 @@ static_assert(sizeof(adlt_psod_t) == 160, ); -template -AdltSection::AdltSection(StringTableSection& strTabSec) +AdltSection::AdltSection(StringTableSection& strTabSec) : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".adlt") , strTabSec(strTabSec) { assert(config->adlt); } -template -void AdltSection::finalizeContents() { +void AdltSection::finalizeContents() { soInputs.clear(); soInputs.reserve(adltCtx->sharedFilesExtended.size()); - for (InputFile* file : adltCtx->sharedFilesExtended) { - auto* soext = adltCtx->getSoExt(file); + for (SharedFileExtended* soext : adltCtx->sharedFilesExtended) soInputs.push_back(makeSoData(soext)); - } assert((soInputs.size() < 1<<16) && "the number of input libs exeeds ELF limit on number of sections"); @@ -4135,8 +4128,7 @@ void AdltSection::finalizeContents() { extractInitFiniArray(); } -template -void AdltSection::buildSonameIndex() { +void AdltSection::buildSonameIndex() { for (const auto& it : llvm::enumerate(soInputs)) { const auto& soData = it.value(); auto res = sonameToIndexMap.try_emplace( @@ -4149,8 +4141,7 @@ void AdltSection::buildSonameIndex() { } } -template -void AdltSection::linkInternalDtNeeded() { +void AdltSection::linkInternalDtNeeded() { for (auto it : llvm::enumerate(soInputs)) { auto& soData = it.value(); for (auto& needed : soData.dtNeededs) { @@ -4163,8 +4154,7 @@ void AdltSection::linkInternalDtNeeded() { } } -template -OutputSection* AdltSection::findOutSection(StringRef name) { +OutputSection* AdltSection::findOutSection(StringRef name) { if (name.empty()) return nullptr; const unsigned partition = 1; @@ -4176,8 +4166,7 @@ OutputSection* AdltSection::findOutSection(StringRef name) { return nullptr; } -template -void AdltSection::extractInitFiniArray() { +void AdltSection::extractInitFiniArray() { for (auto& soData : soInputs) { auto initArrayName = soData.initArrayName; auto finiArrayName = soData.finiArrayName; @@ -4186,8 +4175,7 @@ void AdltSection::extractInitFiniArray() { } } -template -size_t AdltSection::estimateOverallMappedSize() { +size_t AdltSection::estimateOverallMappedSize() { size_t totalMemsz = 0; for (PhdrEntry* ph : mainPart->phdrs) if (ph->p_type == PT_LOAD) @@ -4195,9 +4183,8 @@ size_t AdltSection::estimateOverallMappedSize() { return totalMemsz; } -template -typename AdltSection::CommonData -AdltSection::makeCommonData() { +typename AdltSection::CommonData +AdltSection::makeCommonData() { return CommonData { UINT32_MAX, // .symtabSecIndex, filled in writeTo adltCtx->commonProgramHeaders.size(), // .programHeadersAllocated @@ -4205,9 +4192,8 @@ AdltSection::makeCommonData() { }; } -template -typename AdltSection::SoData -AdltSection::makeSoData(const SharedFileExtended* soext) { +typename AdltSection::SoData +AdltSection::makeSoData(const SharedFileExtended* soext) { assert(soext); SoData data = {}; StringRef soname = soext->soName; @@ -4220,8 +4206,8 @@ AdltSection::makeSoData(const SharedFileExtended* soext) { }); } - data.initArrayName = soext->addAdltPostfix(".init_array"); - data.finiArrayName = soext->addAdltPostfix(".fini_array"); + data.initArrayName = soext->getUniqueName(".init_array"); + data.finiArrayName = soext->getUniqueName(".fini_array"); data.relaDynIndx = soext->dynRelIndexes.getArrayRef(); data.relaPltIndx = soext->pltRelIndexes.getArrayRef(); @@ -4232,8 +4218,7 @@ AdltSection::makeSoData(const SharedFileExtended* soext) { return data; } -template -Elf64_Xword AdltSection::calculateHash(StringRef str) const { +Elf64_Xword AdltSection::calculateHash(StringRef str) const { switch(static_cast(header.stringHashType)) { case ADLT_HASH_TYPE_NONE: return 0x0; @@ -4248,8 +4233,7 @@ Elf64_Xword AdltSection::calculateHash(StringRef str) const { } } -template -adlt_psod_t AdltSection::serialize(const SoData& soData) const { +adlt_psod_t AdltSection::serialize(const SoData& soData) const { return adlt_psod_t { soData.soName.strtabOff, // .soName calculateHash(soData.soName.ref), // .soNameHash @@ -4278,13 +4262,11 @@ adlt_psod_t AdltSection::serialize(const SoData& soData) const { }; } -template -Elf64_Off AdltSection::getBlobStartOffset() const { +Elf64_Off AdltSection::getBlobStartOffset() const { return sizeof(adlt_section_header_t) + sizeof(adlt_psod_t) * soInputs.size(); } -template -size_t AdltSection::estimateBlobSize() const { +size_t AdltSection::estimateBlobSize() const { size_t blobSize = sizeof(adltBlobStartMark); blobSize += sizeof(uint16_t) * common.programHeadersAllocated; @@ -4299,9 +4281,8 @@ size_t AdltSection::estimateBlobSize() const { return blobSize; } -template template -adlt_blob_array_t AdltSection::writeArray( +adlt_blob_array_t AdltSection::writeArray( uint8_t* buff, size_t offset, const SmallVector& data) { if (data.empty()) return {0x0, 0}; @@ -4311,9 +4292,8 @@ adlt_blob_array_t AdltSection::writeArray( return {offset, to_write}; } -template template -adlt_blob_array_t AdltSection::writeArray( +adlt_blob_array_t AdltSection::writeArray( uint8_t* buff, size_t offset, const ArrayRef& data) { if (data.empty()) return {0x0, 0}; @@ -4324,8 +4304,7 @@ adlt_blob_array_t AdltSection::writeArray( } -template -adlt_blob_array_t AdltSection::writeDtNeeded( +adlt_blob_array_t AdltSection::writeDtNeeded( uint8_t* buff, size_t offset, const DtNeededsVec& neededVec) { if (neededVec.empty()) return {0x0, 0}; @@ -4342,8 +4321,7 @@ adlt_blob_array_t AdltSection::writeDtNeeded( return writeArray(buff, offset, needIndexes); } -template -void AdltSection::extractProgramHeaderIndexes() { +void AdltSection::extractProgramHeaderIndexes() { phdrsIndexes.clear(); for (const auto& it : llvm::enumerate(mainPart->phdrs)) { phdrsIndexes[it.value()] = static_cast(it.index()); @@ -4365,8 +4343,7 @@ void AdltSection::extractProgramHeaderIndexes() { } } -template -void AdltSection::finalizeOnWrite() { +void AdltSection::finalizeOnWrite() { // require optimizing Writer::removeEmptyPTLoad been called extractProgramHeaderIndexes(); // require Writer::setPhdrs previously been called @@ -4381,9 +4358,8 @@ void AdltSection::finalizeOnWrite() { } } -template -void AdltSection::finalizeOnWrite(size_t idx, SoData& soData) { - auto* soext = adltCtx->getSoExt(idx); +void AdltSection::finalizeOnWrite(size_t idx, SoData& soData) { + auto* soext = adltCtx->getSoExt(idx); // require SymbolTableBaseSection::sortSymTabSymbolsInAdlt for .symtab called soData.sharedLocalIndex = soext->sharedLocalSymbolIndex; @@ -4407,8 +4383,7 @@ void AdltSection::finalizeOnWrite(size_t idx, SoData& soData) { } } -template -void AdltSection::writeTo(uint8_t* buf) { +void AdltSection::writeTo(uint8_t* buf) { // TODO: take care of endianness, use write32 / write64 etc. finalizeOnWrite(); @@ -4479,8 +4454,7 @@ void AdltSection::writeTo(uint8_t* buf) { } } -template -size_t AdltSection::getSize() const { +size_t AdltSection::getSize() const { assert(sizeof(adlt_section_header_t) + sizeof(adlt_psod_t) * soInputs.size() <= header.blobStart); @@ -4579,8 +4553,3 @@ template class elf::PartitionProgramHeadersSection; template class elf::PartitionProgramHeadersSection; template class elf::PartitionProgramHeadersSection; template class elf::PartitionProgramHeadersSection; - -template class elf::adlt::AdltSection; -template class elf::adlt::AdltSection; -template class elf::adlt::AdltSection; -template class elf::adlt::AdltSection; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index b51c85ce2ea8..713d7fae6c5c 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -35,7 +35,7 @@ namespace elf { class Defined; struct PhdrEntry; class SymbolTableBaseSection; -template class SharedFileExtended; +class SharedFileExtended; class SyntheticSection : public InputSection { public: @@ -1228,7 +1228,6 @@ namespace adlt { using namespace llvm::adlt; -template class AdltSection final : public SyntheticSection { public: struct SectionString { @@ -1294,7 +1293,7 @@ private: Elf64_Xword calculateHash(StringRef str) const; CommonData makeCommonData(); - SoData makeSoData(const SharedFileExtended*); + SoData makeSoData(const SharedFileExtended*); adlt_psod_t serialize(const SoData&) const; size_t estimateBlobSize() const; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index c04b8f858f9b..5f2e406b26e2 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -316,7 +316,7 @@ template void elf::createSyntheticSections() { if (config->adlt) { in.adltStrTab = std::make_unique(".adlt.strtab", false); - in.adltData = std::make_unique>(*in.adltStrTab); + in.adltData = std::make_unique(*in.adltStrTab); add(*in.adltStrTab); add(*in.adltData); } @@ -527,7 +527,7 @@ template void elf::createSyntheticSections() { in.iplt = std::make_unique(); add(*in.iplt); - if (config->andFeatures) + if (!config->adlt && config->andFeatures) add(*make()); // .note.GNU-stack is always added when we are creating a re-linkable @@ -553,12 +553,12 @@ static struct AdltWriter { InputSection *getInputSection(OutputSection *sec); StringRef phdrTypeToStr(uint32_t p_type); - template void checkPhdrs(); - template void checkRelocs(); + void checkPhdrs(); + void checkRelocs(); - template void trackPhdr(OutputSection *sec, PhdrEntry *phdr); - template void traceRelocs(); - template void tracePhdrs(); + void trackPhdr(OutputSection *sec, PhdrEntry *phdr); + void traceRelocs(); + void tracePhdrs(); } adltWriter; } // namespace @@ -570,38 +570,34 @@ InputSection *AdltWriter::getInputSection(OutputSection *sec) { return isd->sections.front(); } -template void AdltWriter::checkPhdrs() { - for (auto *file : adltCtx->sharedFilesExtended) - if (auto *soFile = adltCtx->getSoExt(file)) - assert(!soFile->programHeaders.empty() && - "ADLT: PHdr indexes can't be empty!"); +void AdltWriter::checkPhdrs() { + for (auto *soExt : adltCtx->sharedFilesExtended) + assert(!soExt->programHeaders.empty() && + "ADLT: PHdr indexes can't be empty!"); } -template void AdltWriter::checkRelocs() { +void AdltWriter::checkRelocs() { 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)) { - assert(!soFile->dynRelIndexes.empty() && - "ADLT: relaDyn indexes can't be empty!"); - assert(!soFile->pltRelIndexes.empty() && - "ADLT: relaPlt indexes can't be empty!"); - } + for (auto *soExt : adltCtx->sharedFilesExtended) { + assert(!soExt->dynRelIndexes.empty() && + "ADLT: relaDyn indexes can't be empty!"); + assert(!soExt->pltRelIndexes.empty() && + "ADLT: relaPlt indexes can't be empty!"); + } } -template void AdltWriter::trackPhdr(OutputSection *sec, PhdrEntry *phdr) { auto *isec = getInputSection(sec); - if (isec && isec->file) - if (auto *soFile = adltCtx->getSoExt(isec->file)) { - soFile->programHeaders.insert(phdr); - return; - } + if (isec && isec->file) { + isec->getSoExt()->programHeaders.insert(phdr); + return; + } adltCtx->commonProgramHeaders.insert(phdr); } -template void AdltWriter::traceRelocs() { +void AdltWriter::traceRelocs() { lld::outs() << "[ADLT]\n"; lld::outs() << "Dyn relocs (" << mainPart->relaDyn->relocs.size() << ")\n"; lld::outs() << "Plt relocs (" << in.relaPlt->relocs.size() << ")\n"; @@ -613,29 +609,36 @@ template void AdltWriter::traceRelocs() { lld::outs() << "\n"; }; + auto printSym = [&](Symbol *sym) { + if (sym->getName().empty() && sym->isSection()) { + Defined *d = cast(sym); + return d->section->name; + } + return sym->getName(); + }; + auto printRelocTable = [&](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" << rel->sym->getName() + << 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() << "Dyn relocs (" << soFile->dynRelIndexes.size() << ")"; - printIndexes(soFile->dynRelIndexes); - printRelocTable(mainPart->relaDyn.get(), soFile->dynRelIndexes); + for (SharedFileExtended *soFile : adltCtx->sharedFilesExtended) { + lld::outs() << soFile->soName << ":\n"; + lld::outs() << "Dyn relocs (" << soFile->dynRelIndexes.size() << ")"; + printIndexes(soFile->dynRelIndexes); + printRelocTable(mainPart->relaDyn.get(), soFile->dynRelIndexes); - lld::outs() << "Plt relocs (" << soFile->pltRelIndexes.size() << ")"; - printIndexes(soFile->pltRelIndexes); - printRelocTable(in.relaPlt.get(), soFile->pltRelIndexes); - } + lld::outs() << "Plt relocs (" << soFile->pltRelIndexes.size() << ")"; + printIndexes(soFile->pltRelIndexes); + printRelocTable(in.relaPlt.get(), soFile->pltRelIndexes); + } } -template void AdltWriter::tracePhdrs() { +void AdltWriter::tracePhdrs() { lld::outs() << "[ADLT]\n"; lld::outs() << "Program Headers (" << mainPart->phdrs.size() << ")\n"; @@ -665,14 +668,13 @@ template void AdltWriter::tracePhdrs() { printIndexes(common); printPhTable(common); - for (auto *file : adltCtx->sharedFilesExtended) - if (auto *soFile = adltCtx->getSoExt(file)) { - auto &headers = soFile->programHeaders; - lld::outs() << soFile->soName << "\n"; - lld::outs() << "Program headers (" << headers.size() << ")"; - printIndexes(headers); - printPhTable(headers); - } + for (auto *soExt : adltCtx->sharedFilesExtended) { + auto &headers = soExt->programHeaders; + lld::outs() << soExt->soName << "\n"; + lld::outs() << "Program headers (" << headers.size() << ")"; + printIndexes(headers); + printPhTable(headers); + } } StringRef AdltWriter::phdrTypeToStr(uint32_t p_type) { @@ -791,8 +793,7 @@ template static void markUsedLocalSymbols() { // See MarkLive::resolveReloc(). if (config->gcSections) return; - auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; - for (ELFFileBase *file : files) { + for (ELFFileBase *file : ctx->objectFiles) { ObjFile *f = cast>(file); for (InputSectionBase *s : f->getSections()) { InputSection *isec = dyn_cast_or_null(s); @@ -1198,7 +1199,7 @@ void PhdrEntry::add(OutputSection *sec) { } if (p_type == PT_LOAD || p_type == PT_TLS) - invokeELFT(adltWriter.trackPhdr, sec, this); + adltWriter.trackPhdr(sec, this); } // OHOS_LOCAL end } @@ -1907,8 +1908,7 @@ template void Writer::finalizeAddressDependentContent() { // block sections, input sections can shrink when the jump instructions at // the end of the section are relaxed. static void fixSymbolsAfterShrinking() { - auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; - for (InputFile *File : files) { + for (InputFile *File : ctx->objectFiles) { parallelForEach(File->getSymbols(), [&](Symbol *Sym) { auto *def = dyn_cast(Sym); if (!def) @@ -2128,8 +2128,7 @@ template void Writer::finalizeSections() { // copy relocations, etc. Note that relocations for non-alloc sections are // directly processed by InputSection::relocateNonAlloc. if (config->adlt) - for (auto *file : adltCtx->sharedFilesExtended) { - auto *soFile = adltCtx->getSoExt(file); + for (auto *soFile : adltCtx->sharedFilesExtended) { auto sections = soFile->getSections(); // scan .rela.dyn (base: SHT_NULL) scanRelocations(*sections[0]); @@ -2208,9 +2207,10 @@ template void Writer::finalizeSections() { if (sym->includeInDynsym()) { partitions[sym->partition - 1].dynSymTab->addSymbol(sym); - if (auto *file = dyn_cast_or_null(sym->file)) - if (file->isNeeded && !sym->isUndefined()) - addVerneed(sym); + if (!config->adlt) // ADLT support ver syms + if (auto *file = dyn_cast_or_null(sym->file)) + if (file->isNeeded && !sym->isUndefined()) + addVerneed(sym); } } @@ -2345,11 +2345,11 @@ template void Writer::finalizeSections() { } // OHOS_LOCAL begin if (config->adlt) { // check ouput entries and indexes - adltWriter.checkPhdrs(); - adltWriter.checkRelocs(); + adltWriter.checkPhdrs(); + adltWriter.checkRelocs(); if (config->adltTrace) { - adltWriter.tracePhdrs(); - adltWriter.traceRelocs(); + adltWriter.tracePhdrs(); + adltWriter.traceRelocs(); } } // OHOS_LOCAL end @@ -2521,7 +2521,7 @@ SmallVector Writer::createPhdrs(Partition &part) { auto file = adltWriter.getInputSection(sec)->file; if (!file) return llvm::None; - return adltCtx->getSoExt(file)->orderIdx; + return adltCtx->getSoExt(file)->orderIdx; }; // OHOS_LOCAL end -- Gitee