forked from OSchip/llvm-project
[ELF] Remove ctx indirection. NFC
Add LLVM_LIBRARY_VISIBILITY to remove unneeded GOT and unique_ptr indirection. We can move other global variables into ctx without indirection concern. In the long term we may consider passing Ctx as a parameter to various functions and eliminate global state as much as possible and then remove `Ctx::reset`.
This commit is contained in:
parent
a623a4c8b4
commit
34fa860048
|
@ -439,7 +439,7 @@ void AArch64Err843419Patcher::init() {
|
|||
};
|
||||
|
||||
// Collect mapping symbols for every executable InputSection.
|
||||
for (ELFFileBase *file : ctx->objectFiles) {
|
||||
for (ELFFileBase *file : ctx.objectFiles) {
|
||||
for (Symbol *b : file->getLocalSymbols()) {
|
||||
auto *def = dyn_cast<Defined>(b);
|
||||
if (!def)
|
||||
|
|
|
@ -327,7 +327,7 @@ void ARMErr657417Patcher::init() {
|
|||
};
|
||||
|
||||
// Collect mapping symbols for every executable InputSection.
|
||||
for (ELFFileBase *file : ctx->objectFiles) {
|
||||
for (ELFFileBase *file : ctx.objectFiles) {
|
||||
for (Symbol *s : file->getLocalSymbols()) {
|
||||
auto *def = dyn_cast<Defined>(s);
|
||||
if (!def)
|
||||
|
|
|
@ -48,10 +48,10 @@ static uint32_t getEFlags(InputFile *file) {
|
|||
}
|
||||
|
||||
uint32_t AMDGPU::calcEFlagsV3() const {
|
||||
uint32_t ret = getEFlags(ctx->objectFiles[0]);
|
||||
uint32_t ret = getEFlags(ctx.objectFiles[0]);
|
||||
|
||||
// Verify that all input files have the same e_flags.
|
||||
for (InputFile *f : makeArrayRef(ctx->objectFiles).slice(1)) {
|
||||
for (InputFile *f : makeArrayRef(ctx.objectFiles).slice(1)) {
|
||||
if (ret == getEFlags(f))
|
||||
continue;
|
||||
error("incompatible e_flags: " + toString(f));
|
||||
|
@ -61,15 +61,15 @@ uint32_t AMDGPU::calcEFlagsV3() const {
|
|||
}
|
||||
|
||||
uint32_t AMDGPU::calcEFlagsV4() const {
|
||||
uint32_t retMach = getEFlags(ctx->objectFiles[0]) & EF_AMDGPU_MACH;
|
||||
uint32_t retMach = getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_MACH;
|
||||
uint32_t retXnack =
|
||||
getEFlags(ctx->objectFiles[0]) & EF_AMDGPU_FEATURE_XNACK_V4;
|
||||
getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_FEATURE_XNACK_V4;
|
||||
uint32_t retSramEcc =
|
||||
getEFlags(ctx->objectFiles[0]) & EF_AMDGPU_FEATURE_SRAMECC_V4;
|
||||
getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_FEATURE_SRAMECC_V4;
|
||||
|
||||
// Verify that all input files have compatible e_flags (same mach, all
|
||||
// features in the same category are either ANY, ANY and ON, or ANY and OFF).
|
||||
for (InputFile *f : makeArrayRef(ctx->objectFiles).slice(1)) {
|
||||
for (InputFile *f : makeArrayRef(ctx.objectFiles).slice(1)) {
|
||||
if (retMach != (getEFlags(f) & EF_AMDGPU_MACH)) {
|
||||
error("incompatible mach: " + toString(f));
|
||||
return 0;
|
||||
|
@ -106,10 +106,10 @@ uint32_t AMDGPU::calcEFlagsV4() const {
|
|||
}
|
||||
|
||||
uint32_t AMDGPU::calcEFlags() const {
|
||||
if (ctx->objectFiles.empty())
|
||||
if (ctx.objectFiles.empty())
|
||||
return 0;
|
||||
|
||||
uint8_t abiVersion = cast<ObjFile<ELF64LE>>(ctx->objectFiles[0])
|
||||
uint8_t abiVersion = cast<ObjFile<ELF64LE>>(ctx.objectFiles[0])
|
||||
->getObj()
|
||||
.getHeader()
|
||||
.e_ident[EI_ABIVERSION];
|
||||
|
|
|
@ -226,12 +226,12 @@ static uint32_t getEFlags(InputFile *file) {
|
|||
}
|
||||
|
||||
uint32_t AVR::calcEFlags() const {
|
||||
assert(!ctx->objectFiles.empty());
|
||||
assert(!ctx.objectFiles.empty());
|
||||
|
||||
uint32_t flags = getEFlags(ctx->objectFiles[0]);
|
||||
uint32_t flags = getEFlags(ctx.objectFiles[0]);
|
||||
bool hasLinkRelaxFlag = flags & EF_AVR_LINKRELAX_PREPARED;
|
||||
|
||||
for (InputFile *f : makeArrayRef(ctx->objectFiles).slice(1)) {
|
||||
for (InputFile *f : makeArrayRef(ctx.objectFiles).slice(1)) {
|
||||
uint32_t objFlags = getEFlags(f);
|
||||
if ((objFlags & EF_AVR_ARCH_MASK) != (flags & EF_AVR_ARCH_MASK))
|
||||
error(toString(f) +
|
||||
|
|
|
@ -59,12 +59,12 @@ Hexagon::Hexagon() {
|
|||
}
|
||||
|
||||
uint32_t Hexagon::calcEFlags() const {
|
||||
assert(!ctx->objectFiles.empty());
|
||||
assert(!ctx.objectFiles.empty());
|
||||
|
||||
// The architecture revision must always be equal to or greater than
|
||||
// greatest revision in the list of inputs.
|
||||
uint32_t ret = 0;
|
||||
for (InputFile *f : ctx->objectFiles) {
|
||||
for (InputFile *f : ctx.objectFiles) {
|
||||
uint32_t eflags = cast<ObjFile<ELF32LE>>(f)->getObj().getHeader().e_flags;
|
||||
if (eflags > ret)
|
||||
ret = eflags;
|
||||
|
|
|
@ -295,7 +295,7 @@ static uint32_t getArchFlags(ArrayRef<FileFlags> files) {
|
|||
|
||||
template <class ELFT> uint32_t elf::calcMipsEFlags() {
|
||||
std::vector<FileFlags> v;
|
||||
for (InputFile *f : ctx->objectFiles)
|
||||
for (InputFile *f : ctx.objectFiles)
|
||||
v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader().e_flags});
|
||||
if (v.empty()) {
|
||||
// If we don't have any input files, we'll have to rely on the information
|
||||
|
|
|
@ -622,7 +622,7 @@ static uint32_t getEFlags(InputFile *file) {
|
|||
// This file implements v2 ABI. This function makes sure that all
|
||||
// object files have v2 or an unspecified version as an ABI version.
|
||||
uint32_t PPC64::calcEFlags() const {
|
||||
for (InputFile *f : ctx->objectFiles) {
|
||||
for (InputFile *f : ctx.objectFiles) {
|
||||
uint32_t flag = getEFlags(f);
|
||||
if (flag == 1)
|
||||
error(toString(f) + ": ABI version 1 is not supported");
|
||||
|
|
|
@ -128,12 +128,12 @@ static uint32_t getEFlags(InputFile *f) {
|
|||
uint32_t RISCV::calcEFlags() const {
|
||||
// If there are only binary input files (from -b binary), use a
|
||||
// value of 0 for the ELF header flags.
|
||||
if (ctx->objectFiles.empty())
|
||||
if (ctx.objectFiles.empty())
|
||||
return 0;
|
||||
|
||||
uint32_t target = getEFlags(ctx->objectFiles.front());
|
||||
uint32_t target = getEFlags(ctx.objectFiles.front());
|
||||
|
||||
for (InputFile *f : ctx->objectFiles) {
|
||||
for (InputFile *f : ctx.objectFiles) {
|
||||
uint32_t eflags = getEFlags(f);
|
||||
if (eflags & EF_RISCV_RVC)
|
||||
target |= EF_RISCV_RVC;
|
||||
|
@ -142,7 +142,7 @@ uint32_t RISCV::calcEFlags() const {
|
|||
error(
|
||||
toString(f) +
|
||||
": cannot link object files with different floating-point ABI from " +
|
||||
toString(ctx->objectFiles[0]));
|
||||
toString(ctx.objectFiles[0]));
|
||||
|
||||
if ((eflags & EF_RISCV_RVE) != (target & EF_RISCV_RVE))
|
||||
error(toString(f) +
|
||||
|
@ -524,7 +524,7 @@ static void initSymbolAnchors() {
|
|||
}
|
||||
// Store anchors (st_value and st_value+st_size) for symbols relative to text
|
||||
// sections.
|
||||
for (InputFile *file : ctx->objectFiles)
|
||||
for (InputFile *file : ctx.objectFiles)
|
||||
for (Symbol *sym : file->getSymbols()) {
|
||||
auto *d = dyn_cast<Defined>(sym);
|
||||
if (!d || d->file != file)
|
||||
|
|
|
@ -395,10 +395,6 @@ struct Ctx {
|
|||
// Symbols in a non-prevailing COMDAT group which should be changed to an
|
||||
// Undefined.
|
||||
SmallVector<std::pair<Symbol *, unsigned>, 0> nonPrevailingSyms;
|
||||
// True if SHT_LLVM_SYMPART is used.
|
||||
std::atomic<bool> hasSympart{false};
|
||||
// True if we need to reserve two .got entries for local-dynamic TLS model.
|
||||
std::atomic<bool> needsTlsLd{false};
|
||||
// A tuple of (reference, extractedFile, sym). Used by --why-extract=.
|
||||
SmallVector<std::tuple<std::string, const InputFile *, const Symbol &>, 0>
|
||||
whyExtractRecords;
|
||||
|
@ -407,10 +403,15 @@ struct Ctx {
|
|||
llvm::DenseMap<const Symbol *,
|
||||
std::pair<const InputFile *, const InputFile *>>
|
||||
backwardReferences;
|
||||
// True if SHT_LLVM_SYMPART is used.
|
||||
std::atomic<bool> hasSympart{false};
|
||||
// True if we need to reserve two .got entries for local-dynamic TLS model.
|
||||
std::atomic<bool> needsTlsLd{false};
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
// The only instance of Ctx struct.
|
||||
extern std::unique_ptr<Ctx> ctx;
|
||||
LLVM_LIBRARY_VISIBILITY extern Ctx ctx;
|
||||
|
||||
// The first two elements of versionDefinitions represent VER_NDX_LOCAL and
|
||||
// VER_NDX_GLOBAL. This helper returns other elements.
|
||||
|
|
|
@ -74,7 +74,7 @@ using namespace lld;
|
|||
using namespace lld::elf;
|
||||
|
||||
ConfigWrapper elf::config;
|
||||
std::unique_ptr<Ctx> elf::ctx;
|
||||
Ctx elf::ctx;
|
||||
std::unique_ptr<LinkerDriver> elf::driver;
|
||||
|
||||
static void setConfigs(opt::InputArgList &args);
|
||||
|
@ -87,6 +87,21 @@ void elf::errorOrWarn(const Twine &msg) {
|
|||
error(msg);
|
||||
}
|
||||
|
||||
void Ctx::reset() {
|
||||
memoryBuffers.clear();
|
||||
objectFiles.clear();
|
||||
sharedFiles.clear();
|
||||
binaryFiles.clear();
|
||||
bitcodeFiles.clear();
|
||||
lazyBitcodeFiles.clear();
|
||||
duplicates.clear();
|
||||
nonPrevailingSyms.clear();
|
||||
whyExtractRecords.clear();
|
||||
backwardReferences.clear();
|
||||
hasSympart.store(false, std::memory_order_relaxed);
|
||||
needsTlsLd.store(false, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
bool elf::link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
|
||||
llvm::raw_ostream &stderrOS, bool exitEarly,
|
||||
bool disableOutput) {
|
||||
|
@ -95,6 +110,8 @@ bool elf::link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
|
|||
|
||||
ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
|
||||
ctx->e.cleanupCallback = []() {
|
||||
elf::ctx.reset();
|
||||
|
||||
inputSections.clear();
|
||||
ehInputSections.clear();
|
||||
outputSections.clear();
|
||||
|
@ -113,7 +130,6 @@ bool elf::link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
|
|||
"--error-limit=0 to see all errors)";
|
||||
|
||||
config = ConfigWrapper();
|
||||
elf::ctx = std::make_unique<Ctx>();
|
||||
driver = std::make_unique<LinkerDriver>();
|
||||
script = std::make_unique<LinkerScript>();
|
||||
symtab = std::make_unique<SymbolTable>();
|
||||
|
@ -195,7 +211,7 @@ std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers(
|
|||
|
||||
// Take ownership of memory buffers created for members of thin archives.
|
||||
std::vector<std::unique_ptr<MemoryBuffer>> mbs = file->takeThinBuffers();
|
||||
std::move(mbs.begin(), mbs.end(), std::back_inserter(ctx->memoryBuffers));
|
||||
std::move(mbs.begin(), mbs.end(), std::back_inserter(ctx.memoryBuffers));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
@ -845,7 +861,7 @@ static std::pair<bool, bool> getPackDynRelocs(opt::InputArgList &args) {
|
|||
static void readCallGraph(MemoryBufferRef mb) {
|
||||
// Build a map from symbol name to section
|
||||
DenseMap<StringRef, Symbol *> map;
|
||||
for (ELFFileBase *file : ctx->objectFiles)
|
||||
for (ELFFileBase *file : ctx.objectFiles)
|
||||
for (Symbol *sym : file->getSymbols())
|
||||
map[sym->getName()] = sym;
|
||||
|
||||
|
@ -924,7 +940,7 @@ processCallGraphRelocations(SmallVector<uint32_t, 32> &symbolIndices,
|
|||
template <class ELFT> static void readCallGraphsFromObjectFiles() {
|
||||
SmallVector<uint32_t, 32> symbolIndices;
|
||||
ArrayRef<typename ELFT::CGProfile> cgProfile;
|
||||
for (auto file : ctx->objectFiles) {
|
||||
for (auto file : ctx.objectFiles) {
|
||||
auto *obj = cast<ObjFile<ELFT>>(file);
|
||||
if (!processCallGraphRelocations(symbolIndices, cgProfile, obj))
|
||||
continue;
|
||||
|
@ -1788,10 +1804,10 @@ static void excludeLibs(opt::InputArgList &args) {
|
|||
sym->versionId = VER_NDX_LOCAL;
|
||||
};
|
||||
|
||||
for (ELFFileBase *file : ctx->objectFiles)
|
||||
for (ELFFileBase *file : ctx.objectFiles)
|
||||
visit(file);
|
||||
|
||||
for (BitcodeFile *file : ctx->bitcodeFiles)
|
||||
for (BitcodeFile *file : ctx.bitcodeFiles)
|
||||
visit(file);
|
||||
}
|
||||
|
||||
|
@ -1805,7 +1821,7 @@ static void handleUndefined(Symbol *sym, const char *option) {
|
|||
return;
|
||||
sym->extract();
|
||||
if (!config->whyExtract.empty())
|
||||
ctx->whyExtractRecords.emplace_back(option, sym->file, *sym);
|
||||
ctx.whyExtractRecords.emplace_back(option, sym->file, *sym);
|
||||
}
|
||||
|
||||
// As an extension to GNU linkers, lld supports a variant of `-u`
|
||||
|
@ -1857,10 +1873,10 @@ static void writeArchiveStats() {
|
|||
|
||||
SmallVector<StringRef, 0> archives;
|
||||
DenseMap<CachedHashStringRef, unsigned> all, extracted;
|
||||
for (ELFFileBase *file : ctx->objectFiles)
|
||||
for (ELFFileBase *file : ctx.objectFiles)
|
||||
if (file->archiveName.size())
|
||||
++extracted[CachedHashStringRef(file->archiveName)];
|
||||
for (BitcodeFile *file : ctx->bitcodeFiles)
|
||||
for (BitcodeFile *file : ctx.bitcodeFiles)
|
||||
if (file->archiveName.size())
|
||||
++extracted[CachedHashStringRef(file->archiveName)];
|
||||
for (std::pair<StringRef, unsigned> f : driver->archiveFiles) {
|
||||
|
@ -1884,14 +1900,14 @@ static void writeWhyExtract() {
|
|||
}
|
||||
|
||||
os << "reference\textracted\tsymbol\n";
|
||||
for (auto &entry : ctx->whyExtractRecords) {
|
||||
for (auto &entry : ctx.whyExtractRecords) {
|
||||
os << std::get<0>(entry) << '\t' << toString(std::get<1>(entry)) << '\t'
|
||||
<< toString(std::get<2>(entry)) << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
static void reportBackrefs() {
|
||||
for (auto &ref : ctx->backwardReferences) {
|
||||
for (auto &ref : ctx.backwardReferences) {
|
||||
const Symbol &sym = *ref.first;
|
||||
std::string to = toString(ref.second.second);
|
||||
// Some libraries have known problems and can cause noise. Filter them out
|
||||
|
@ -1984,7 +2000,7 @@ static void writeDependencyFile() {
|
|||
// symbols of type CommonSymbol.
|
||||
static void replaceCommonSymbols() {
|
||||
llvm::TimeTraceScope timeScope("Replace common symbols");
|
||||
for (ELFFileBase *file : ctx->objectFiles) {
|
||||
for (ELFFileBase *file : ctx.objectFiles) {
|
||||
if (!file->hasCommonSyms)
|
||||
continue;
|
||||
for (Symbol *sym : file->getGlobalSymbols()) {
|
||||
|
@ -2059,7 +2075,7 @@ static void findKeepUniqueSections(opt::InputArgList &args) {
|
|||
|
||||
// Visit the address-significance table in each object file and mark each
|
||||
// referenced symbol as address-significant.
|
||||
for (InputFile *f : ctx->objectFiles) {
|
||||
for (InputFile *f : ctx.objectFiles) {
|
||||
auto *obj = cast<ObjFile<ELFT>>(f);
|
||||
ArrayRef<Symbol *> syms = obj->getSymbols();
|
||||
if (obj->addrsigSec) {
|
||||
|
@ -2145,18 +2161,18 @@ static void markBuffersAsDontNeed(bool skipLinkedOutput) {
|
|||
// buffers as MADV_DONTNEED so that these pages can be reused by the expensive
|
||||
// thin link, saving memory.
|
||||
if (skipLinkedOutput) {
|
||||
for (MemoryBuffer &mb : llvm::make_pointee_range(ctx->memoryBuffers))
|
||||
for (MemoryBuffer &mb : llvm::make_pointee_range(ctx.memoryBuffers))
|
||||
mb.dontNeedIfMmap();
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, just mark MemoryBuffers backing BitcodeFiles.
|
||||
DenseSet<const char *> bufs;
|
||||
for (BitcodeFile *file : ctx->bitcodeFiles)
|
||||
for (BitcodeFile *file : ctx.bitcodeFiles)
|
||||
bufs.insert(file->mb.getBufferStart());
|
||||
for (BitcodeFile *file : ctx->lazyBitcodeFiles)
|
||||
for (BitcodeFile *file : ctx.lazyBitcodeFiles)
|
||||
bufs.insert(file->mb.getBufferStart());
|
||||
for (MemoryBuffer &mb : llvm::make_pointee_range(ctx->memoryBuffers))
|
||||
for (MemoryBuffer &mb : llvm::make_pointee_range(ctx.memoryBuffers))
|
||||
if (bufs.count(mb.getBufferStart()))
|
||||
mb.dontNeedIfMmap();
|
||||
}
|
||||
|
@ -2173,10 +2189,10 @@ void LinkerDriver::compileBitcodeFiles(bool skipLinkedOutput) {
|
|||
llvm::TimeTraceScope timeScope("LTO");
|
||||
// Compile bitcode files and replace bitcode symbols.
|
||||
lto.reset(new BitcodeCompiler);
|
||||
for (BitcodeFile *file : ctx->bitcodeFiles)
|
||||
for (BitcodeFile *file : ctx.bitcodeFiles)
|
||||
lto->add(*file);
|
||||
|
||||
if (!ctx->bitcodeFiles.empty())
|
||||
if (!ctx.bitcodeFiles.empty())
|
||||
markBuffersAsDontNeed(skipLinkedOutput);
|
||||
|
||||
for (InputFile *file : lto->compile()) {
|
||||
|
@ -2188,7 +2204,7 @@ void LinkerDriver::compileBitcodeFiles(bool skipLinkedOutput) {
|
|||
for (Symbol *sym : obj->getGlobalSymbols())
|
||||
if (sym->hasVersionSuffix)
|
||||
sym->parseSymbolVersion();
|
||||
ctx->objectFiles.push_back(obj);
|
||||
ctx.objectFiles.push_back(obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2324,7 +2340,7 @@ static void redirectSymbols(ArrayRef<WrappedSymbol> wrapped) {
|
|||
return;
|
||||
|
||||
// Update pointers in input files.
|
||||
parallelForEach(ctx->objectFiles, [&](ELFFileBase *file) {
|
||||
parallelForEach(ctx.objectFiles, [&](ELFFileBase *file) {
|
||||
for (Symbol *&sym : file->getMutableGlobalSymbols())
|
||||
if (Symbol *s = map.lookup(sym))
|
||||
sym = s;
|
||||
|
@ -2359,7 +2375,7 @@ static uint32_t getAndFeatures() {
|
|||
return 0;
|
||||
|
||||
uint32_t ret = -1;
|
||||
for (ELFFileBase *f : ctx->objectFiles) {
|
||||
for (ELFFileBase *f : ctx.objectFiles) {
|
||||
uint32_t features = f->andFeatures;
|
||||
|
||||
checkAndReportMissingFeature(
|
||||
|
@ -2512,7 +2528,7 @@ void LinkerDriver::link(opt::InputArgList &args) {
|
|||
// We also need one if any shared libraries are used and for pie executables
|
||||
// (probably because the dynamic linker needs it).
|
||||
config->hasDynSymTab =
|
||||
!ctx->sharedFiles.empty() || config->isPic || config->exportDynamic;
|
||||
!ctx.sharedFiles.empty() || config->isPic || config->exportDynamic;
|
||||
|
||||
// Some symbols (such as __ehdr_start) are defined lazily only when there
|
||||
// are undefined symbols for them, so we add these to trigger that logic.
|
||||
|
@ -2558,7 +2574,7 @@ void LinkerDriver::link(opt::InputArgList &args) {
|
|||
// to, i.e. if the symbol's definition is in bitcode. Any other required
|
||||
// libcall symbols will be added to the link after LTO when we add the LTO
|
||||
// object file to the link.
|
||||
if (!ctx->bitcodeFiles.empty())
|
||||
if (!ctx.bitcodeFiles.empty())
|
||||
for (auto *s : lto::LTO::getRuntimeLibcallSymbols())
|
||||
handleLibcall(s);
|
||||
|
||||
|
@ -2567,23 +2583,23 @@ void LinkerDriver::link(opt::InputArgList &args) {
|
|||
|
||||
// No more lazy bitcode can be extracted at this point. Do post parse work
|
||||
// like checking duplicate symbols.
|
||||
parallelForEach(ctx->objectFiles, [](ELFFileBase *file) {
|
||||
parallelForEach(ctx.objectFiles, [](ELFFileBase *file) {
|
||||
initSectionsAndLocalSyms(file, /*ignoreComdats=*/false);
|
||||
});
|
||||
parallelForEach(ctx->objectFiles, postParseObjectFile);
|
||||
parallelForEach(ctx->bitcodeFiles,
|
||||
parallelForEach(ctx.objectFiles, postParseObjectFile);
|
||||
parallelForEach(ctx.bitcodeFiles,
|
||||
[](BitcodeFile *file) { file->postParse(); });
|
||||
for (auto &it : ctx->nonPrevailingSyms) {
|
||||
for (auto &it : ctx.nonPrevailingSyms) {
|
||||
Symbol &sym = *it.first;
|
||||
Undefined(sym.file, sym.getName(), sym.binding, sym.stOther, sym.type,
|
||||
it.second)
|
||||
.overwrite(sym);
|
||||
cast<Undefined>(sym).nonPrevailing = true;
|
||||
}
|
||||
ctx->nonPrevailingSyms.clear();
|
||||
for (const DuplicateSymbol &d : ctx->duplicates)
|
||||
ctx.nonPrevailingSyms.clear();
|
||||
for (const DuplicateSymbol &d : ctx.duplicates)
|
||||
reportDuplicate(*d.sym, d.file, d.section, d.value);
|
||||
ctx->duplicates.clear();
|
||||
ctx.duplicates.clear();
|
||||
|
||||
// Return if there were name resolution errors.
|
||||
if (errorCount())
|
||||
|
@ -2636,7 +2652,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 numObjsBeforeLTO = ctx.objectFiles.size();
|
||||
invokeELFT(compileBitcodeFiles, skipLinkedOutput);
|
||||
|
||||
// Symbol resolution finished. Report backward reference problems,
|
||||
|
@ -2653,12 +2669,12 @@ void LinkerDriver::link(opt::InputArgList &args) {
|
|||
|
||||
// compileBitcodeFiles may have produced lto.tmp object files. After this, no
|
||||
// more file will be added.
|
||||
auto newObjectFiles = makeArrayRef(ctx->objectFiles).slice(numObjsBeforeLTO);
|
||||
auto newObjectFiles = makeArrayRef(ctx.objectFiles).slice(numObjsBeforeLTO);
|
||||
parallelForEach(newObjectFiles, [](ELFFileBase *file) {
|
||||
initSectionsAndLocalSyms(file, /*ignoreComdats=*/true);
|
||||
});
|
||||
parallelForEach(newObjectFiles, postParseObjectFile);
|
||||
for (const DuplicateSymbol &d : ctx->duplicates)
|
||||
for (const DuplicateSymbol &d : ctx.duplicates)
|
||||
reportDuplicate(*d.sym, d.file, d.section, d.value);
|
||||
|
||||
// Handle --exclude-libs again because lto.tmp may reference additional
|
||||
|
@ -2678,7 +2694,7 @@ void LinkerDriver::link(opt::InputArgList &args) {
|
|||
// Now that we have a complete list of input files.
|
||||
// Beyond this point, no new files are added.
|
||||
// Aggregate all input sections into one place.
|
||||
for (InputFile *f : ctx->objectFiles) {
|
||||
for (InputFile *f : ctx.objectFiles) {
|
||||
for (InputSectionBase *s : f->getSections()) {
|
||||
if (!s || s == &InputSection::discarded)
|
||||
continue;
|
||||
|
@ -2688,14 +2704,14 @@ void LinkerDriver::link(opt::InputArgList &args) {
|
|||
inputSections.push_back(s);
|
||||
}
|
||||
}
|
||||
for (BinaryFile *f : ctx->binaryFiles)
|
||||
for (BinaryFile *f : ctx.binaryFiles)
|
||||
for (InputSectionBase *s : f->getSections())
|
||||
inputSections.push_back(cast<InputSection>(s));
|
||||
}
|
||||
|
||||
{
|
||||
llvm::TimeTraceScope timeScope("Strip sections");
|
||||
if (ctx->hasSympart.load(std::memory_order_relaxed)) {
|
||||
if (ctx.hasSympart.load(std::memory_order_relaxed)) {
|
||||
llvm::erase_if(inputSections, [](InputSectionBase *s) {
|
||||
if (s->type != SHT_LLVM_SYMPART)
|
||||
return false;
|
||||
|
|
|
@ -560,7 +560,7 @@ template <class ELFT> void ICF<ELFT>::run() {
|
|||
};
|
||||
for (Symbol *sym : symtab->getSymbols())
|
||||
fold(sym);
|
||||
parallelForEach(ctx->objectFiles, [&](ELFFileBase *file) {
|
||||
parallelForEach(ctx.objectFiles, [&](ELFFileBase *file) {
|
||||
for (Symbol *sym : file->getLocalSymbols())
|
||||
fold(sym);
|
||||
});
|
||||
|
|
|
@ -206,7 +206,7 @@ Optional<MemoryBufferRef> elf::readFile(StringRef path) {
|
|||
}
|
||||
|
||||
MemoryBufferRef mbref = (*mbOrErr)->getMemBufferRef();
|
||||
ctx->memoryBuffers.push_back(std::move(*mbOrErr)); // take MB ownership
|
||||
ctx.memoryBuffers.push_back(std::move(*mbOrErr)); // take MB ownership
|
||||
|
||||
if (tar)
|
||||
tar->append(relativeToRoot(path), mbref.getBuffer());
|
||||
|
@ -235,12 +235,12 @@ static bool isCompatible(InputFile *file) {
|
|||
}
|
||||
|
||||
InputFile *existing = nullptr;
|
||||
if (!ctx->objectFiles.empty())
|
||||
existing = ctx->objectFiles[0];
|
||||
else if (!ctx->sharedFiles.empty())
|
||||
existing = ctx->sharedFiles[0];
|
||||
else if (!ctx->bitcodeFiles.empty())
|
||||
existing = ctx->bitcodeFiles[0];
|
||||
if (!ctx.objectFiles.empty())
|
||||
existing = ctx.objectFiles[0];
|
||||
else if (!ctx.sharedFiles.empty())
|
||||
existing = ctx.sharedFiles[0];
|
||||
else if (!ctx.bitcodeFiles.empty())
|
||||
existing = ctx.bitcodeFiles[0];
|
||||
std::string with;
|
||||
if (existing)
|
||||
with = " with " + toString(existing);
|
||||
|
@ -254,7 +254,7 @@ template <class ELFT> static void doParseFile(InputFile *file) {
|
|||
|
||||
// Binary file
|
||||
if (auto *f = dyn_cast<BinaryFile>(file)) {
|
||||
ctx->binaryFiles.push_back(f);
|
||||
ctx.binaryFiles.push_back(f);
|
||||
f->parse();
|
||||
return;
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ template <class ELFT> static void doParseFile(InputFile *file) {
|
|||
// Lazy object file
|
||||
if (file->lazy) {
|
||||
if (auto *f = dyn_cast<BitcodeFile>(file)) {
|
||||
ctx->lazyBitcodeFiles.push_back(f);
|
||||
ctx.lazyBitcodeFiles.push_back(f);
|
||||
f->parseLazy();
|
||||
} else {
|
||||
cast<ObjFile<ELFT>>(file)->parseLazy();
|
||||
|
@ -281,13 +281,13 @@ template <class ELFT> static void doParseFile(InputFile *file) {
|
|||
|
||||
// LLVM bitcode file
|
||||
if (auto *f = dyn_cast<BitcodeFile>(file)) {
|
||||
ctx->bitcodeFiles.push_back(f);
|
||||
ctx.bitcodeFiles.push_back(f);
|
||||
f->parse();
|
||||
return;
|
||||
}
|
||||
|
||||
// Regular object file
|
||||
ctx->objectFiles.push_back(cast<ELFFileBase>(file));
|
||||
ctx.objectFiles.push_back(cast<ELFFileBase>(file));
|
||||
cast<ObjFile<ELFT>>(file)->parse();
|
||||
}
|
||||
|
||||
|
@ -769,7 +769,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
|
|||
case SHT_NULL:
|
||||
break;
|
||||
case SHT_LLVM_SYMPART:
|
||||
ctx->hasSympart.store(true, std::memory_order_relaxed);
|
||||
ctx.hasSympart.store(true, std::memory_order_relaxed);
|
||||
[[fallthrough]];
|
||||
default:
|
||||
this->sections[i] =
|
||||
|
@ -1179,7 +1179,7 @@ template <class ELFT> void ObjFile<ELFT>::postParse() {
|
|||
}
|
||||
if (sym.file == this) {
|
||||
std::lock_guard<std::mutex> lock(mu);
|
||||
ctx->nonPrevailingSyms.emplace_back(&sym, secIdx);
|
||||
ctx.nonPrevailingSyms.emplace_back(&sym, secIdx);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -1192,7 +1192,7 @@ template <class ELFT> void ObjFile<ELFT>::postParse() {
|
|||
if (binding == STB_WEAK)
|
||||
continue;
|
||||
std::lock_guard<std::mutex> lock(mu);
|
||||
ctx->duplicates.push_back({&sym, this, sec, eSym.st_value});
|
||||
ctx.duplicates.push_back({&sym, this, sec, eSym.st_value});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1422,7 +1422,7 @@ template <class ELFT> void SharedFile::parse() {
|
|||
if (!wasInserted)
|
||||
return;
|
||||
|
||||
ctx->sharedFiles.push_back(this);
|
||||
ctx.sharedFiles.push_back(this);
|
||||
|
||||
verdefs = parseVerdefs<ELFT>(obj.base(), verdefSec);
|
||||
std::vector<uint32_t> verneeds = parseVerneed<ELFT>(obj, verneedSec);
|
||||
|
|
|
@ -211,7 +211,7 @@ BitcodeCompiler::BitcodeCompiler() {
|
|||
config->ltoPartitions);
|
||||
|
||||
// Initialize usedStartStop.
|
||||
if (ctx->bitcodeFiles.empty())
|
||||
if (ctx.bitcodeFiles.empty())
|
||||
return;
|
||||
for (Symbol *sym : symtab->getSymbols()) {
|
||||
if (sym->isPlaceholder())
|
||||
|
@ -293,10 +293,10 @@ void BitcodeCompiler::add(BitcodeFile &f) {
|
|||
// distributed build system that depends on that behavior.
|
||||
static void thinLTOCreateEmptyIndexFiles() {
|
||||
DenseSet<StringRef> linkedBitCodeFiles;
|
||||
for (BitcodeFile *f : ctx->bitcodeFiles)
|
||||
for (BitcodeFile *f : ctx.bitcodeFiles)
|
||||
linkedBitCodeFiles.insert(f->getName());
|
||||
|
||||
for (BitcodeFile *f : ctx->lazyBitcodeFiles) {
|
||||
for (BitcodeFile *f : ctx.lazyBitcodeFiles) {
|
||||
if (!f->lazy)
|
||||
continue;
|
||||
if (linkedBitCodeFiles.contains(f->getName()))
|
||||
|
@ -332,7 +332,7 @@ std::vector<InputFile *> BitcodeCompiler::compile() {
|
|||
files[task] = std::move(mb);
|
||||
}));
|
||||
|
||||
if (!ctx->bitcodeFiles.empty())
|
||||
if (!ctx.bitcodeFiles.empty())
|
||||
checkError(ltoObj->run(
|
||||
[&](size_t task) {
|
||||
return std::make_unique<CachedFileStream>(
|
||||
|
|
|
@ -55,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<Defined *> getSymbols() {
|
||||
std::vector<Defined *> v;
|
||||
for (ELFFileBase *file : ctx->objectFiles)
|
||||
for (ELFFileBase *file : ctx.objectFiles)
|
||||
for (Symbol *b : file->getSymbols())
|
||||
if (auto *dr = dyn_cast<Defined>(b))
|
||||
if (!dr->isSection() && dr->section && dr->section->isLive() &&
|
||||
|
@ -224,7 +224,7 @@ static void writeMapFile(raw_fd_ostream &os) {
|
|||
static void writeCref(raw_fd_ostream &os) {
|
||||
// Collect symbols and files.
|
||||
MapVector<Symbol *, SetVector<InputFile *>> map;
|
||||
for (ELFFileBase *file : ctx->objectFiles) {
|
||||
for (ELFFileBase *file : ctx.objectFiles) {
|
||||
for (Symbol *sym : file->getSymbols()) {
|
||||
if (isa<SharedSymbol>(sym))
|
||||
map[sym].insert(file);
|
||||
|
|
|
@ -328,7 +328,7 @@ template <class ELFT> void MarkLive<ELFT>::mark() {
|
|||
// to from __start_/__stop_ symbols because there will only be one set of
|
||||
// symbols for the whole program.
|
||||
template <class ELFT> void MarkLive<ELFT>::moveToMain() {
|
||||
for (ELFFileBase *file : ctx->objectFiles)
|
||||
for (ELFFileBase *file : ctx.objectFiles)
|
||||
for (Symbol *s : file->getSymbols())
|
||||
if (auto *d = dyn_cast<Defined>(s))
|
||||
if ((d->type == STT_GNU_IFUNC || d->type == STT_TLS) && d->section &&
|
||||
|
|
|
@ -1237,7 +1237,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
|
|||
}
|
||||
if (expr == R_TLSLD_HINT)
|
||||
return 1;
|
||||
ctx->needsTlsLd.store(true, std::memory_order_relaxed);
|
||||
ctx.needsTlsLd.store(true, std::memory_order_relaxed);
|
||||
c.relocations.push_back({expr, type, offset, addend, &sym});
|
||||
return 1;
|
||||
}
|
||||
|
@ -1544,7 +1544,7 @@ template <class ELFT> void elf::scanRelocations() {
|
|||
bool serial = !config->zCombreloc || config->emachine == EM_MIPS ||
|
||||
config->emachine == EM_PPC64;
|
||||
parallel::TaskGroup tg;
|
||||
for (ELFFileBase *f : ctx->objectFiles) {
|
||||
for (ELFFileBase *f : ctx.objectFiles) {
|
||||
auto fn = [f]() {
|
||||
RelocationScanner scanner;
|
||||
for (InputSectionBase *s : f->getSections()) {
|
||||
|
@ -1737,8 +1737,7 @@ void elf::postScanRelocations() {
|
|||
addTpOffsetGotEntry(sym);
|
||||
};
|
||||
|
||||
if (ctx->needsTlsLd.load(std::memory_order_relaxed) &&
|
||||
in.got->addTlsIndex()) {
|
||||
if (ctx.needsTlsLd.load(std::memory_order_relaxed) && in.got->addTlsIndex()) {
|
||||
static Undefined dummy(nullptr, "", STB_LOCAL, 0, 0);
|
||||
if (config->shared)
|
||||
mainPart->relaDyn->addReloc(
|
||||
|
@ -1754,7 +1753,7 @@ void elf::postScanRelocations() {
|
|||
|
||||
// Local symbols may need the aforementioned non-preemptible ifunc and GOT
|
||||
// handling. They don't need regular PLT.
|
||||
for (ELFFileBase *file : ctx->objectFiles)
|
||||
for (ELFFileBase *file : ctx.objectFiles)
|
||||
for (Symbol *sym : file->getLocalSymbols())
|
||||
fn(*sym);
|
||||
}
|
||||
|
|
|
@ -304,7 +304,7 @@ void elf::printTraceSymbol(const Symbol &sym, StringRef name) {
|
|||
|
||||
static void recordWhyExtract(const InputFile *reference,
|
||||
const InputFile &extracted, const Symbol &sym) {
|
||||
ctx->whyExtractRecords.emplace_back(toString(reference), &extracted, sym);
|
||||
ctx.whyExtractRecords.emplace_back(toString(reference), &extracted, sym);
|
||||
}
|
||||
|
||||
void elf::maybeWarnUnorderableSymbol(const Symbol *sym) {
|
||||
|
@ -477,8 +477,8 @@ void Symbol::resolve(const Undefined &other) {
|
|||
// definition. this->file needs to be saved because in the case of LTO it
|
||||
// may be reset to nullptr or be replaced with a file named lto.tmp.
|
||||
if (backref && !isWeak())
|
||||
ctx->backwardReferences.try_emplace(this,
|
||||
std::make_pair(other.file, file));
|
||||
ctx.backwardReferences.try_emplace(this,
|
||||
std::make_pair(other.file, file));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -622,7 +622,7 @@ void Symbol::resolve(const LazyObject &other) {
|
|||
// should be extracted as the canonical definition instead.
|
||||
if (LLVM_UNLIKELY(isCommon()) && elf::config->fortranCommon &&
|
||||
other.file->shouldExtractForCommon(getName())) {
|
||||
ctx->backwardReferences.erase(this);
|
||||
ctx.backwardReferences.erase(this);
|
||||
other.overwrite(*this);
|
||||
other.extract();
|
||||
return;
|
||||
|
@ -631,7 +631,7 @@ void Symbol::resolve(const LazyObject &other) {
|
|||
if (!isUndefined()) {
|
||||
// See the comment in resolveUndefined().
|
||||
if (isDefined())
|
||||
ctx->backwardReferences.erase(this);
|
||||
ctx.backwardReferences.erase(this);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1306,7 +1306,7 @@ DynamicSection<ELFT>::computeContents() {
|
|||
addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH,
|
||||
part.dynStrTab->addString(config->rpath));
|
||||
|
||||
for (SharedFile *file : ctx->sharedFiles)
|
||||
for (SharedFile *file : ctx.sharedFiles)
|
||||
if (file->isNeeded)
|
||||
addInt(DT_NEEDED, part.dynStrTab->addString(file->soName));
|
||||
|
||||
|
@ -1475,7 +1475,7 @@ DynamicSection<ELFT>::computeContents() {
|
|||
if (part.verNeed && part.verNeed->isNeeded()) {
|
||||
addInSec(DT_VERNEED, *part.verNeed);
|
||||
unsigned needNum = 0;
|
||||
for (SharedFile *f : ctx->sharedFiles)
|
||||
for (SharedFile *f : ctx.sharedFiles)
|
||||
if (!f->vernauxs.empty())
|
||||
++needNum;
|
||||
addInt(DT_VERNEEDNUM, needNum);
|
||||
|
@ -3127,7 +3127,7 @@ VersionNeedSection<ELFT>::VersionNeedSection()
|
|||
".gnu.version_r") {}
|
||||
|
||||
template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() {
|
||||
for (SharedFile *f : ctx->sharedFiles) {
|
||||
for (SharedFile *f : ctx.sharedFiles) {
|
||||
if (f->vernauxs.empty())
|
||||
continue;
|
||||
verneeds.emplace_back();
|
||||
|
@ -3295,7 +3295,7 @@ template <class ELFT> void elf::splitSections() {
|
|||
llvm::TimeTraceScope timeScope("Split sections");
|
||||
// splitIntoPieces needs to be called on each MergeInputSection
|
||||
// before calling finalizeContents().
|
||||
parallelForEach(ctx->objectFiles, [](ELFFileBase *file) {
|
||||
parallelForEach(ctx.objectFiles, [](ELFFileBase *file) {
|
||||
for (InputSectionBase *sec : file->getSections()) {
|
||||
if (!sec)
|
||||
continue;
|
||||
|
@ -3686,9 +3686,9 @@ static uint8_t getAbiVersion() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (config->emachine == EM_AMDGPU && !ctx->objectFiles.empty()) {
|
||||
uint8_t ver = ctx->objectFiles[0]->abiVersion;
|
||||
for (InputFile *file : makeArrayRef(ctx->objectFiles).slice(1))
|
||||
if (config->emachine == EM_AMDGPU && !ctx.objectFiles.empty()) {
|
||||
uint8_t ver = ctx.objectFiles[0]->abiVersion;
|
||||
for (InputFile *file : makeArrayRef(ctx.objectFiles).slice(1))
|
||||
if (file->abiVersion != ver)
|
||||
error("incompatible ABI version: " + toString(file));
|
||||
return ver;
|
||||
|
|
|
@ -611,7 +611,7 @@ template <class ELFT> static void markUsedLocalSymbols() {
|
|||
// See MarkLive<ELFT>::resolveReloc().
|
||||
if (config->gcSections)
|
||||
return;
|
||||
for (ELFFileBase *file : ctx->objectFiles) {
|
||||
for (ELFFileBase *file : ctx.objectFiles) {
|
||||
ObjFile<ELFT> *f = cast<ObjFile<ELFT>>(file);
|
||||
for (InputSectionBase *s : f->getSections()) {
|
||||
InputSection *isec = dyn_cast_or_null<InputSection>(s);
|
||||
|
@ -682,7 +682,7 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
|
|||
llvm::TimeTraceScope timeScope("Add local symbols");
|
||||
if (config->copyRelocs && config->discard != DiscardPolicy::None)
|
||||
markUsedLocalSymbols<ELFT>();
|
||||
for (ELFFileBase *file : ctx->objectFiles) {
|
||||
for (ELFFileBase *file : ctx.objectFiles) {
|
||||
for (Symbol *b : file->getLocalSymbols()) {
|
||||
assert(b->isLocal() && "should have been caught in initializeSymbols()");
|
||||
auto *dr = dyn_cast<Defined>(b);
|
||||
|
@ -1281,7 +1281,7 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() {
|
|||
for (Symbol *sym : symtab->getSymbols())
|
||||
addSym(*sym);
|
||||
|
||||
for (ELFFileBase *file : ctx->objectFiles)
|
||||
for (ELFFileBase *file : ctx.objectFiles)
|
||||
for (Symbol *sym : file->getLocalSymbols())
|
||||
addSym(*sym);
|
||||
|
||||
|
@ -1697,7 +1697,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
|
|||
// block sections, input sections can shrink when the jump instructions at
|
||||
// the end of the section are relaxed.
|
||||
static void fixSymbolsAfterShrinking() {
|
||||
for (InputFile *File : ctx->objectFiles) {
|
||||
for (InputFile *File : ctx.objectFiles) {
|
||||
parallelForEach(File->getSymbols(), [&](Symbol *Sym) {
|
||||
auto *def = dyn_cast<Defined>(Sym);
|
||||
if (!def)
|
||||
|
@ -1934,7 +1934,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
|||
// ld.bfd traces all DT_NEEDED to emulate the logic of the dynamic linker to
|
||||
// catch more cases. That is too much for us. Our approach resembles the one
|
||||
// used in ld.gold, achieves a good balance to be useful but not too smart.
|
||||
for (SharedFile *file : ctx->sharedFiles) {
|
||||
for (SharedFile *file : ctx.sharedFiles) {
|
||||
bool allNeededIsKnown =
|
||||
llvm::all_of(file->dtNeeded, [&](StringRef needed) {
|
||||
return symtab->soNames.count(CachedHashStringRef(needed));
|
||||
|
|
Loading…
Reference in New Issue