diff options
Diffstat (limited to 'lld/COFF/Driver.cpp')
-rw-r--r-- | lld/COFF/Driver.cpp | 156 |
1 files changed, 84 insertions, 72 deletions
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 283aeed..7580b469 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -274,8 +274,13 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb, make<std::unique_ptr<Archive>>(std::move(file)); // take ownership int memberIndex = 0; - for (MemoryBufferRef m : getArchiveMembers(ctx, archive)) - addArchiveBuffer(m, "<whole-archive>", filename, memberIndex++); + for (MemoryBufferRef m : getArchiveMembers(ctx, archive)) { + if (!archive->isThin()) + addArchiveBuffer(m, "<whole-archive>", filename, memberIndex++); + else + addThinArchiveBuffer(m, "<whole-archive>"); + } + return; } addFile(make<ArchiveFile>(ctx, mbref)); @@ -386,6 +391,14 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName, Log(ctx) << "Loaded " << obj << " for " << symName; } +void LinkerDriver::addThinArchiveBuffer(MemoryBufferRef mb, StringRef symName) { + // Pass an empty string as the archive name and an offset of 0 so that + // the original filename is used as the buffer identifier. This is + // useful for DTLTO, where having the member identifier be the actual + // path on disk enables distribution of bitcode files during ThinLTO. + addArchiveBuffer(mb, symName, /*parentName=*/"", /*OffsetInArchive=*/0); +} + void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, const Archive::Symbol &sym, StringRef parentName) { @@ -422,11 +435,8 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, reportBufferError(errorCodeToError(mbOrErr.second), childName); llvm::TimeTraceScope timeScope("Archive: ", mbOrErr.first->getBufferIdentifier()); - // Pass empty string as archive name so that the original filename is - // used as the buffer identifier. - ctx.driver.addArchiveBuffer(takeBuffer(std::move(mbOrErr.first)), - toCOFFString(ctx, sym), "", - /*OffsetInArchive=*/0); + ctx.driver.addThinArchiveBuffer(takeBuffer(std::move(mbOrErr.first)), + toCOFFString(ctx, sym)); }); } @@ -490,7 +500,9 @@ void LinkerDriver::parseDirectives(InputFile *file) { file->symtab.parseAlternateName(arg->getValue()); break; case OPT_arm64xsameaddress: - if (!file->symtab.isEC()) + if (file->symtab.isEC()) + parseSameAddress(arg->getValue()); + else Warn(ctx) << arg->getSpelling() << " is not allowed in non-ARM64EC files (" << toString(file) << ")"; @@ -1308,13 +1320,9 @@ void LinkerDriver::convertResources() { } void LinkerDriver::maybeCreateECExportThunk(StringRef name, Symbol *&sym) { - Defined *def; if (!sym) return; - if (auto undef = dyn_cast<Undefined>(sym)) - def = undef->getDefinedWeakAlias(); - else - def = dyn_cast<Defined>(sym); + Defined *def = sym->getDefined(); if (!def) return; @@ -1346,11 +1354,7 @@ void LinkerDriver::createECExportThunks() { Symbol *sym = ctx.symtab.find(targetName); if (!sym) continue; - Defined *targetSym; - if (auto undef = dyn_cast<Undefined>(sym)) - targetSym = undef->getDefinedWeakAlias(); - else - targetSym = dyn_cast<Defined>(sym); + Defined *targetSym = sym->getDefined(); if (!targetSym) continue; @@ -1643,8 +1647,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { config->warnLocallyDefinedImported = false; else if (s == "longsections") config->warnLongSectionNames = false; - else if (s == "exporteddllmain") - config->warnExportedDllMain = false; + else if (s == "importeddllmain") + config->warnImportedDllMain = false; // Other warning numbers are ignored. } } @@ -2088,6 +2092,23 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { Fatal(ctx) << "/manifestinput: requires /manifest:embed"; } + // Handle /thinlto-distributor:<path> + config->dtltoDistributor = args.getLastArgValue(OPT_thinlto_distributor); + + // Handle /thinlto-distributor-arg:<arg> + for (auto *arg : args.filtered(OPT_thinlto_distributor_arg)) + config->dtltoDistributorArgs.push_back(arg->getValue()); + + // Handle /thinlto-remote-compiler:<path> + config->dtltoCompiler = args.getLastArgValue(OPT_thinlto_compiler); + if (!config->dtltoDistributor.empty() && config->dtltoCompiler.empty()) + Err(ctx) << "A value must be specified for /thinlto-remote-compiler if " + "/thinlto-distributor is specified."; + + // Handle /thinlto-remote-compiler-arg:<arg> + for (auto *arg : args.filtered(OPT_thinlto_compiler_arg)) + config->dtltoCompilerArgs.push_back(arg->getValue()); + // Handle /dwodir config->dwoDir = args.getLastArgValue(OPT_dwodir); @@ -2276,6 +2297,13 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { args.filtered(OPT_dependentloadflag, OPT_dependentloadflag_opt)) parseDependentLoadFlags(arg); + for (auto *arg : args.filtered(OPT_arm64xsameaddress)) { + if (ctx.hybridSymtab) + parseSameAddress(arg->getValue()); + else + Warn(ctx) << arg->getSpelling() << " is allowed only on EC targets"; + } + if (tar) { llvm::TimeTraceScope timeScope("Reproducer: response file"); tar->append( @@ -2527,28 +2555,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { e.symbolName = symtab.mangleMaybe(e.sym); } - // Add weak aliases. Weak aliases is a mechanism to give remaining - // undefined symbols final chance to be resolved successfully. - for (auto pair : symtab.alternateNames) { - StringRef from = pair.first; - StringRef to = pair.second; - Symbol *sym = symtab.find(from); - if (!sym) - continue; - if (auto *u = dyn_cast<Undefined>(sym)) { - if (u->weakAlias) { - // On ARM64EC, anti-dependency aliases are treated as undefined - // symbols unless a demangled symbol aliases a defined one, which - // is part of the implementation. - if (!symtab.isEC() || !u->isAntiDep) - continue; - if (!isa<Undefined>(u->weakAlias) && - !isArm64ECMangledFunctionName(u->getName())) - continue; - } - u->setWeakAlias(symtab.addUndefined(to)); - } - } + symtab.resolveAlternateNames(); }); ctx.forEachActiveSymtab([&](SymbolTable &symtab) { @@ -2670,12 +2677,46 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { createECExportThunks(); // Resolve remaining undefined symbols and warn about imported locals. + std::vector<Undefined *> aliases; ctx.forEachSymtab( - [&](SymbolTable &symtab) { symtab.resolveRemainingUndefines(); }); + [&](SymbolTable &symtab) { symtab.resolveRemainingUndefines(aliases); }); if (errorCount()) return; + ctx.forEachActiveSymtab([](SymbolTable &symtab) { + symtab.initializeECThunks(); + symtab.initializeLoadConfig(); + }); + + // Identify unreferenced COMDAT sections. + if (config->doGC) { + if (config->mingw) { + // markLive doesn't traverse .eh_frame, but the personality function is + // only reached that way. The proper solution would be to parse and + // traverse the .eh_frame section, like the ELF linker does. + // For now, just manually try to retain the known possible personality + // functions. This doesn't bring in more object files, but only marks + // functions that already have been included to be retained. + ctx.forEachSymtab([&](SymbolTable &symtab) { + for (const char *n : {"__gxx_personality_v0", "__gcc_personality_v0", + "rust_eh_personality"}) { + Defined *d = dyn_cast_or_null<Defined>(symtab.findUnderscore(n)); + if (d && !d->isGCRoot) { + d->isGCRoot = true; + config->gcroot.push_back(d); + } + } + }); + } + + markLive(ctx); + } + + ctx.symtab.initializeSameAddressThunks(); + for (auto alias : aliases) + alias->resolveWeakAlias(); + if (config->mingw) { // Make sure the crtend.o object is the last object file. This object // file can contain terminating section chunks that need to be placed @@ -2767,35 +2808,6 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { if (auto *arg = args.getLastArg(OPT_print_symbol_order)) config->printSymbolOrder = arg->getValue(); - if (ctx.symtab.isEC()) - ctx.symtab.initializeECThunks(); - ctx.forEachActiveSymtab( - [](SymbolTable &symtab) { symtab.initializeLoadConfig(); }); - - // Identify unreferenced COMDAT sections. - if (config->doGC) { - if (config->mingw) { - // markLive doesn't traverse .eh_frame, but the personality function is - // only reached that way. The proper solution would be to parse and - // traverse the .eh_frame section, like the ELF linker does. - // For now, just manually try to retain the known possible personality - // functions. This doesn't bring in more object files, but only marks - // functions that already have been included to be retained. - ctx.forEachSymtab([&](SymbolTable &symtab) { - for (const char *n : {"__gxx_personality_v0", "__gcc_personality_v0", - "rust_eh_personality"}) { - Defined *d = dyn_cast_or_null<Defined>(symtab.findUnderscore(n)); - if (d && !d->isGCRoot) { - d->isGCRoot = true; - config->gcroot.push_back(d); - } - } - }); - } - - markLive(ctx); - } - // Needs to happen after the last call to addFile(). convertResources(); |