Index: vendor/lld/dist/COFF/Driver.cpp =================================================================== --- vendor/lld/dist/COFF/Driver.cpp (revision 311539) +++ vendor/lld/dist/COFF/Driver.cpp (revision 311540) @@ -1,860 +1,865 @@ //===- Driver.cpp ---------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Driver.h" #include "Config.h" #include "Error.h" #include "InputFiles.h" #include "Memory.h" #include "SymbolTable.h" #include "Symbols.h" #include "Writer.h" #include "lld/Driver/Driver.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/LibDriver/LibDriver.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" +#include "llvm/Support/TarWriter.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include #include #ifdef _MSC_VER // depends on for __uncaught_exception. #include #endif #include using namespace llvm; using namespace llvm::COFF; using llvm::sys::Process; using llvm::sys::fs::OpenFlags; using llvm::sys::fs::file_magic; using llvm::sys::fs::identify_magic; namespace lld { namespace coff { Configuration *Config; LinkerDriver *Driver; BumpPtrAllocator BAlloc; StringSaver Saver{BAlloc}; std::vector SpecificAllocBase::Instances; bool link(ArrayRef Args) { Config = make(); Driver = make(); Driver->link(Args); return true; } // Drop directory components and replace extension with ".exe" or ".dll". static std::string getOutputPath(StringRef Path) { auto P = Path.find_last_of("\\/"); StringRef S = (P == StringRef::npos) ? Path : Path.substr(P + 1); const char* E = Config->DLL ? ".dll" : ".exe"; return (S.substr(0, S.rfind('.')) + E).str(); } // ErrorOr is not default constructible, so it cannot be used as the type // parameter of a future. // FIXME: We could open the file in createFutureForFile and avoid needing to // return an error here, but for the moment that would cost us a file descriptor // (a limited resource on Windows) for the duration that the future is pending. typedef std::pair, std::error_code> MBErrPair; // Create a std::future that opens and maps a file using the best strategy for // the host platform. static std::future createFutureForFile(std::string Path) { #if LLVM_ON_WIN32 // On Windows, file I/O is relatively slow so it is best to do this // asynchronously. auto Strategy = std::launch::async; #else auto Strategy = std::launch::deferred; #endif return std::async(Strategy, [=]() { auto MBOrErr = MemoryBuffer::getFile(Path); if (!MBOrErr) return MBErrPair{nullptr, MBOrErr.getError()}; return MBErrPair{std::move(*MBOrErr), std::error_code()}; }); } MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr MB) { MemoryBufferRef MBRef = *MB; OwningMBs.push_back(std::move(MB)); - if (Driver->Cpio) - Driver->Cpio->append(relativeToRoot(MBRef.getBufferIdentifier()), - MBRef.getBuffer()); + if (Driver->Tar) + Driver->Tar->append(relativeToRoot(MBRef.getBufferIdentifier()), + MBRef.getBuffer()); return MBRef; } void LinkerDriver::addBuffer(std::unique_ptr MB) { MemoryBufferRef MBRef = takeBuffer(std::move(MB)); // File type is detected by contents, not by file extension. file_magic Magic = identify_magic(MBRef.getBuffer()); if (Magic == file_magic::windows_resource) { Resources.push_back(MBRef); return; } FilePaths.push_back(MBRef.getBufferIdentifier()); if (Magic == file_magic::archive) return Symtab.addFile(make(MBRef)); if (Magic == file_magic::bitcode) return Symtab.addFile(make(MBRef)); if (Magic == file_magic::coff_cl_gl_object) fatal(MBRef.getBufferIdentifier() + ": is not a native COFF file. " "Recompile without /GL"); Symtab.addFile(make(MBRef)); } void LinkerDriver::enqueuePath(StringRef Path) { auto Future = std::make_shared>(createFutureForFile(Path)); std::string PathStr = Path; enqueueTask([=]() { auto MBOrErr = Future->get(); if (MBOrErr.second) fatal(MBOrErr.second, "could not open " + PathStr); Driver->addBuffer(std::move(MBOrErr.first)); }); if (Config->OutputFile == "") Config->OutputFile = getOutputPath(Path); } void LinkerDriver::addArchiveBuffer(MemoryBufferRef MB, StringRef SymName, StringRef ParentName) { file_magic Magic = identify_magic(MB.getBuffer()); if (Magic == file_magic::coff_import_library) { Symtab.addFile(make(MB)); return; } InputFile *Obj; if (Magic == file_magic::coff_object) Obj = make(MB); else if (Magic == file_magic::bitcode) Obj = make(MB); else fatal("unknown file type: " + MB.getBufferIdentifier()); Obj->ParentName = ParentName; Symtab.addFile(Obj); if (Config->Verbose) outs() << "Loaded " << toString(Obj) << " for " << SymName << "\n"; } void LinkerDriver::enqueueArchiveMember(const Archive::Child &C, StringRef SymName, StringRef ParentName) { if (!C.getParent()->isThin()) { MemoryBufferRef MB = check( C.getMemoryBufferRef(), "could not get the buffer for the member defining symbol " + SymName); enqueueTask([=]() { Driver->addArchiveBuffer(MB, SymName, ParentName); }); return; } auto Future = std::make_shared>(createFutureForFile( check(C.getFullName(), "could not get the filename for the member defining symbol " + SymName))); enqueueTask([=]() { auto MBOrErr = Future->get(); if (MBOrErr.second) fatal(MBOrErr.second, "could not get the buffer for the member defining " + SymName); Driver->addArchiveBuffer(takeBuffer(std::move(MBOrErr.first)), SymName, ParentName); }); } static bool isDecorated(StringRef Sym) { return Sym.startswith("_") || Sym.startswith("@") || Sym.startswith("?"); } // Parses .drectve section contents and returns a list of files // specified by /defaultlib. void LinkerDriver::parseDirectives(StringRef S) { opt::InputArgList Args = Parser.parse(S); for (auto *Arg : Args) { switch (Arg->getOption().getID()) { case OPT_alternatename: parseAlternateName(Arg->getValue()); break; case OPT_defaultlib: if (Optional Path = findLib(Arg->getValue())) enqueuePath(*Path); break; case OPT_export: { Export E = parseExport(Arg->getValue()); E.Directives = true; Config->Exports.push_back(E); break; } case OPT_failifmismatch: checkFailIfMismatch(Arg->getValue()); break; case OPT_incl: addUndefined(Arg->getValue()); break; case OPT_merge: parseMerge(Arg->getValue()); break; case OPT_nodefaultlib: Config->NoDefaultLibs.insert(doFindLib(Arg->getValue())); break; case OPT_section: parseSection(Arg->getValue()); break; case OPT_editandcontinue: case OPT_fastfail: case OPT_guardsym: case OPT_throwingnew: break; default: fatal(Arg->getSpelling() + " is not allowed in .drectve"); } } } // Find file from search paths. You can omit ".obj", this function takes // care of that. Note that the returned path is not guaranteed to exist. StringRef LinkerDriver::doFindFile(StringRef Filename) { bool HasPathSep = (Filename.find_first_of("/\\") != StringRef::npos); if (HasPathSep) return Filename; bool HasExt = (Filename.find('.') != StringRef::npos); for (StringRef Dir : SearchPaths) { SmallString<128> Path = Dir; sys::path::append(Path, Filename); if (sys::fs::exists(Path.str())) return Saver.save(Path.str()); if (!HasExt) { Path.append(".obj"); if (sys::fs::exists(Path.str())) return Saver.save(Path.str()); } } return Filename; } // Resolves a file path. This never returns the same path // (in that case, it returns None). Optional LinkerDriver::findFile(StringRef Filename) { StringRef Path = doFindFile(Filename); bool Seen = !VisitedFiles.insert(Path.lower()).second; if (Seen) return None; return Path; } // Find library file from search path. StringRef LinkerDriver::doFindLib(StringRef Filename) { // Add ".lib" to Filename if that has no file extension. bool HasExt = (Filename.find('.') != StringRef::npos); if (!HasExt) Filename = Saver.save(Filename + ".lib"); return doFindFile(Filename); } // Resolves a library path. /nodefaultlib options are taken into // consideration. This never returns the same path (in that case, // it returns None). Optional LinkerDriver::findLib(StringRef Filename) { if (Config->NoDefaultLibAll) return None; if (!VisitedLibs.insert(Filename.lower()).second) return None; StringRef Path = doFindLib(Filename); if (Config->NoDefaultLibs.count(Path)) return None; if (!VisitedFiles.insert(Path.lower()).second) return None; return Path; } // Parses LIB environment which contains a list of search paths. void LinkerDriver::addLibSearchPaths() { Optional EnvOpt = Process::GetEnv("LIB"); if (!EnvOpt.hasValue()) return; StringRef Env = Saver.save(*EnvOpt); while (!Env.empty()) { StringRef Path; std::tie(Path, Env) = Env.split(';'); SearchPaths.push_back(Path); } } SymbolBody *LinkerDriver::addUndefined(StringRef Name) { SymbolBody *B = Symtab.addUndefined(Name); Config->GCRoot.insert(B); return B; } // Symbol names are mangled by appending "_" prefix on x86. StringRef LinkerDriver::mangle(StringRef Sym) { assert(Config->Machine != IMAGE_FILE_MACHINE_UNKNOWN); if (Config->Machine == I386) return Saver.save("_" + Sym); return Sym; } // Windows specific -- find default entry point name. StringRef LinkerDriver::findDefaultEntry() { // User-defined main functions and their corresponding entry points. static const char *Entries[][2] = { {"main", "mainCRTStartup"}, {"wmain", "wmainCRTStartup"}, {"WinMain", "WinMainCRTStartup"}, {"wWinMain", "wWinMainCRTStartup"}, }; for (auto E : Entries) { StringRef Entry = Symtab.findMangle(mangle(E[0])); if (!Entry.empty() && !isa(Symtab.find(Entry)->body())) return mangle(E[1]); } return ""; } WindowsSubsystem LinkerDriver::inferSubsystem() { if (Config->DLL) return IMAGE_SUBSYSTEM_WINDOWS_GUI; if (Symtab.findUnderscore("main") || Symtab.findUnderscore("wmain")) return IMAGE_SUBSYSTEM_WINDOWS_CUI; if (Symtab.findUnderscore("WinMain") || Symtab.findUnderscore("wWinMain")) return IMAGE_SUBSYSTEM_WINDOWS_GUI; return IMAGE_SUBSYSTEM_UNKNOWN; } static uint64_t getDefaultImageBase() { if (Config->is64()) return Config->DLL ? 0x180000000 : 0x140000000; return Config->DLL ? 0x10000000 : 0x400000; } static std::string createResponseFile(const opt::InputArgList &Args, ArrayRef FilePaths, ArrayRef SearchPaths) { SmallString<0> Data; raw_svector_ostream OS(Data); for (auto *Arg : Args) { switch (Arg->getOption().getID()) { case OPT_linkrepro: case OPT_INPUT: case OPT_defaultlib: case OPT_libpath: break; default: - OS << stringize(Arg) << "\n"; + OS << toString(Arg) << "\n"; } } for (StringRef Path : SearchPaths) { std::string RelPath = relativeToRoot(Path); OS << "/libpath:" << quote(RelPath) << "\n"; } for (StringRef Path : FilePaths) OS << quote(relativeToRoot(Path)) << "\n"; return Data.str(); } static unsigned getDefaultDebugType(const opt::InputArgList &Args) { unsigned DebugTypes = static_cast(DebugType::CV); if (Args.hasArg(OPT_driver)) DebugTypes |= static_cast(DebugType::PData); if (Args.hasArg(OPT_profile)) DebugTypes |= static_cast(DebugType::Fixup); return DebugTypes; } static unsigned parseDebugType(StringRef Arg) { SmallVector Types; Arg.split(Types, ',', /*KeepEmpty=*/false); unsigned DebugTypes = static_cast(DebugType::None); for (StringRef Type : Types) DebugTypes |= StringSwitch(Type.lower()) .Case("cv", static_cast(DebugType::CV)) .Case("pdata", static_cast(DebugType::PData)) .Case("fixup", static_cast(DebugType::Fixup)); return DebugTypes; } static std::string getMapFile(const opt::InputArgList &Args) { auto *Arg = Args.getLastArg(OPT_lldmap, OPT_lldmap_file); if (!Arg) return ""; if (Arg->getOption().getID() == OPT_lldmap_file) return Arg->getValue(); assert(Arg->getOption().getID() == OPT_lldmap); StringRef OutFile = Config->OutputFile; return (OutFile.substr(0, OutFile.rfind('.')) + ".map").str(); } void LinkerDriver::enqueueTask(std::function Task) { TaskQueue.push_back(std::move(Task)); } bool LinkerDriver::run() { bool DidWork = !TaskQueue.empty(); while (!TaskQueue.empty()) { TaskQueue.front()(); TaskQueue.pop_front(); } return DidWork; } void LinkerDriver::link(ArrayRef ArgsArr) { // If the first command line argument is "/lib", link.exe acts like lib.exe. // We call our own implementation of lib.exe that understands bitcode files. if (ArgsArr.size() > 1 && StringRef(ArgsArr[1]).equals_lower("/lib")) { if (llvm::libDriverMain(ArgsArr.slice(1)) != 0) fatal("lib failed"); return; } // Needed for LTO. InitializeAllTargetInfos(); InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmParsers(); InitializeAllAsmPrinters(); InitializeAllDisassemblers(); // Parse command line options. opt::InputArgList Args = Parser.parseLINK(ArgsArr.slice(1)); // Handle /help if (Args.hasArg(OPT_help)) { printHelp(ArgsArr[0]); return; } if (auto *Arg = Args.getLastArg(OPT_linkrepro)) { SmallString<64> Path = StringRef(Arg->getValue()); - sys::path::append(Path, "repro"); - ErrorOr F = CpioFile::create(Path); - if (F) - Cpio.reset(*F); - else - errs() << "/linkrepro: failed to open " << Path - << ".cpio: " << F.getError().message() << '\n'; + sys::path::append(Path, "repro.tar"); + + Expected> ErrOrWriter = + TarWriter::create(Path, "repro"); + + if (ErrOrWriter) { + Tar = std::move(*ErrOrWriter); + } else { + errs() << "/linkrepro: failed to open " << Path << ": " + << toString(ErrOrWriter.takeError()) << '\n'; + } } if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end()) fatal("no input files"); // Construct search path list. SearchPaths.push_back(""); for (auto *Arg : Args.filtered(OPT_libpath)) SearchPaths.push_back(Arg->getValue()); addLibSearchPaths(); // Handle /out if (auto *Arg = Args.getLastArg(OPT_out)) Config->OutputFile = Arg->getValue(); // Handle /verbose if (Args.hasArg(OPT_verbose)) Config->Verbose = true; // Handle /force or /force:unresolved if (Args.hasArg(OPT_force) || Args.hasArg(OPT_force_unresolved)) Config->Force = true; // Handle /debug if (Args.hasArg(OPT_debug)) { Config->Debug = true; Config->DebugTypes = Args.hasArg(OPT_debugtype) ? parseDebugType(Args.getLastArg(OPT_debugtype)->getValue()) : getDefaultDebugType(Args); } // Create a dummy PDB file to satisfy build sytem rules. if (auto *Arg = Args.getLastArg(OPT_pdb)) Config->PDBPath = Arg->getValue(); // Handle /noentry if (Args.hasArg(OPT_noentry)) { if (!Args.hasArg(OPT_dll)) fatal("/noentry must be specified with /dll"); Config->NoEntry = true; } // Handle /dll if (Args.hasArg(OPT_dll)) { Config->DLL = true; Config->ManifestID = 2; } // Handle /fixed if (Args.hasArg(OPT_fixed)) { if (Args.hasArg(OPT_dynamicbase)) fatal("/fixed must not be specified with /dynamicbase"); Config->Relocatable = false; Config->DynamicBase = false; } // Handle /machine if (auto *Arg = Args.getLastArg(OPT_machine)) Config->Machine = getMachineType(Arg->getValue()); // Handle /nodefaultlib: for (auto *Arg : Args.filtered(OPT_nodefaultlib)) Config->NoDefaultLibs.insert(doFindLib(Arg->getValue())); // Handle /nodefaultlib if (Args.hasArg(OPT_nodefaultlib_all)) Config->NoDefaultLibAll = true; // Handle /base if (auto *Arg = Args.getLastArg(OPT_base)) parseNumbers(Arg->getValue(), &Config->ImageBase); // Handle /stack if (auto *Arg = Args.getLastArg(OPT_stack)) parseNumbers(Arg->getValue(), &Config->StackReserve, &Config->StackCommit); // Handle /heap if (auto *Arg = Args.getLastArg(OPT_heap)) parseNumbers(Arg->getValue(), &Config->HeapReserve, &Config->HeapCommit); // Handle /version if (auto *Arg = Args.getLastArg(OPT_version)) parseVersion(Arg->getValue(), &Config->MajorImageVersion, &Config->MinorImageVersion); // Handle /subsystem if (auto *Arg = Args.getLastArg(OPT_subsystem)) parseSubsystem(Arg->getValue(), &Config->Subsystem, &Config->MajorOSVersion, &Config->MinorOSVersion); // Handle /alternatename for (auto *Arg : Args.filtered(OPT_alternatename)) parseAlternateName(Arg->getValue()); // Handle /include for (auto *Arg : Args.filtered(OPT_incl)) addUndefined(Arg->getValue()); // Handle /implib if (auto *Arg = Args.getLastArg(OPT_implib)) Config->Implib = Arg->getValue(); // Handle /opt for (auto *Arg : Args.filtered(OPT_opt)) { std::string Str = StringRef(Arg->getValue()).lower(); SmallVector Vec; StringRef(Str).split(Vec, ','); for (StringRef S : Vec) { if (S == "noref") { Config->DoGC = false; Config->DoICF = false; continue; } if (S == "icf" || StringRef(S).startswith("icf=")) { Config->DoICF = true; continue; } if (S == "noicf") { Config->DoICF = false; continue; } if (StringRef(S).startswith("lldlto=")) { StringRef OptLevel = StringRef(S).substr(7); if (OptLevel.getAsInteger(10, Config->LTOOptLevel) || Config->LTOOptLevel > 3) fatal("/opt:lldlto: invalid optimization level: " + OptLevel); continue; } if (StringRef(S).startswith("lldltojobs=")) { StringRef Jobs = StringRef(S).substr(11); if (Jobs.getAsInteger(10, Config->LTOJobs) || Config->LTOJobs == 0) fatal("/opt:lldltojobs: invalid job count: " + Jobs); continue; } if (S != "ref" && S != "lbr" && S != "nolbr") fatal("/opt: unknown option: " + S); } } // Handle /failifmismatch for (auto *Arg : Args.filtered(OPT_failifmismatch)) checkFailIfMismatch(Arg->getValue()); // Handle /merge for (auto *Arg : Args.filtered(OPT_merge)) parseMerge(Arg->getValue()); // Handle /section for (auto *Arg : Args.filtered(OPT_section)) parseSection(Arg->getValue()); // Handle /manifest if (auto *Arg = Args.getLastArg(OPT_manifest_colon)) parseManifest(Arg->getValue()); // Handle /manifestuac if (auto *Arg = Args.getLastArg(OPT_manifestuac)) parseManifestUAC(Arg->getValue()); // Handle /manifestdependency if (auto *Arg = Args.getLastArg(OPT_manifestdependency)) Config->ManifestDependency = Arg->getValue(); // Handle /manifestfile if (auto *Arg = Args.getLastArg(OPT_manifestfile)) Config->ManifestFile = Arg->getValue(); // Handle /manifestinput for (auto *Arg : Args.filtered(OPT_manifestinput)) Config->ManifestInput.push_back(Arg->getValue()); // Handle miscellaneous boolean flags. if (Args.hasArg(OPT_allowbind_no)) Config->AllowBind = false; if (Args.hasArg(OPT_allowisolation_no)) Config->AllowIsolation = false; if (Args.hasArg(OPT_dynamicbase_no)) Config->DynamicBase = false; if (Args.hasArg(OPT_nxcompat_no)) Config->NxCompat = false; if (Args.hasArg(OPT_tsaware_no)) Config->TerminalServerAware = false; if (Args.hasArg(OPT_nosymtab)) Config->WriteSymtab = false; Config->DumpPdb = Args.hasArg(OPT_dumppdb); Config->DebugPdb = Args.hasArg(OPT_debugpdb); // Create a list of input files. Files can be given as arguments // for /defaultlib option. std::vector MBs; for (auto *Arg : Args.filtered(OPT_INPUT)) if (Optional Path = findFile(Arg->getValue())) enqueuePath(*Path); for (auto *Arg : Args.filtered(OPT_defaultlib)) if (Optional Path = findLib(Arg->getValue())) enqueuePath(*Path); // Windows specific -- Create a resource file containing a manifest file. if (Config->Manifest == Configuration::Embed) addBuffer(createManifestRes()); // Read all input files given via the command line. run(); // We should have inferred a machine type by now from the input files, but if // not we assume x64. if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) { errs() << "warning: /machine is not specified. x64 is assumed.\n"; Config->Machine = AMD64; } // Windows specific -- Input files can be Windows resource files (.res files). // We invoke cvtres.exe to convert resource files to a regular COFF file // then link the result file normally. if (!Resources.empty()) addBuffer(convertResToCOFF(Resources)); - if (Cpio) - Cpio->append("response.txt", - createResponseFile(Args, FilePaths, - ArrayRef(SearchPaths).slice(1))); + if (Tar) + Tar->append("response.txt", + createResponseFile(Args, FilePaths, + ArrayRef(SearchPaths).slice(1))); // Handle /largeaddressaware if (Config->is64() || Args.hasArg(OPT_largeaddressaware)) Config->LargeAddressAware = true; // Handle /highentropyva if (Config->is64() && !Args.hasArg(OPT_highentropyva_no)) Config->HighEntropyVA = true; // Handle /entry and /dll if (auto *Arg = Args.getLastArg(OPT_entry)) { Config->Entry = addUndefined(mangle(Arg->getValue())); } else if (Args.hasArg(OPT_dll) && !Config->NoEntry) { StringRef S = (Config->Machine == I386) ? "__DllMainCRTStartup@12" : "_DllMainCRTStartup"; Config->Entry = addUndefined(S); } else if (!Config->NoEntry) { // Windows specific -- If entry point name is not given, we need to // infer that from user-defined entry name. StringRef S = findDefaultEntry(); if (S.empty()) fatal("entry point must be defined"); Config->Entry = addUndefined(S); if (Config->Verbose) outs() << "Entry name inferred: " << S << "\n"; } // Handle /export for (auto *Arg : Args.filtered(OPT_export)) { Export E = parseExport(Arg->getValue()); if (Config->Machine == I386) { if (!isDecorated(E.Name)) E.Name = Saver.save("_" + E.Name); if (!E.ExtName.empty() && !isDecorated(E.ExtName)) E.ExtName = Saver.save("_" + E.ExtName); } Config->Exports.push_back(E); } // Handle /def if (auto *Arg = Args.getLastArg(OPT_deffile)) { // parseModuleDefs mutates Config object. parseModuleDefs( takeBuffer(check(MemoryBuffer::getFile(Arg->getValue()), Twine("could not open ") + Arg->getValue()))); } // Handle /delayload for (auto *Arg : Args.filtered(OPT_delayload)) { Config->DelayLoads.insert(StringRef(Arg->getValue()).lower()); if (Config->Machine == I386) { Config->DelayLoadHelper = addUndefined("___delayLoadHelper2@8"); } else { Config->DelayLoadHelper = addUndefined("__delayLoadHelper2"); } } // Set default image base if /base is not given. if (Config->ImageBase == uint64_t(-1)) Config->ImageBase = getDefaultImageBase(); Symtab.addRelative(mangle("__ImageBase"), 0); if (Config->Machine == I386) { Config->SEHTable = Symtab.addRelative("___safe_se_handler_table", 0); Config->SEHCount = Symtab.addAbsolute("___safe_se_handler_count", 0); } // We do not support /guard:cf (control flow protection) yet. // Define CFG symbols anyway so that we can link MSVC 2015 CRT. Symtab.addAbsolute(mangle("__guard_fids_table"), 0); Symtab.addAbsolute(mangle("__guard_fids_count"), 0); Symtab.addAbsolute(mangle("__guard_flags"), 0x100); // This code may add new undefined symbols to the link, which may enqueue more // symbol resolution tasks, so we need to continue executing tasks until we // converge. do { // Windows specific -- if entry point is not found, // search for its mangled names. if (Config->Entry) Symtab.mangleMaybe(Config->Entry); // Windows specific -- Make sure we resolve all dllexported symbols. for (Export &E : Config->Exports) { if (!E.ForwardTo.empty()) continue; E.Sym = addUndefined(E.Name); if (!E.Directives) 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 : Config->AlternateNames) { StringRef From = Pair.first; StringRef To = Pair.second; Symbol *Sym = Symtab.find(From); if (!Sym) continue; if (auto *U = dyn_cast(Sym->body())) if (!U->WeakAlias) U->WeakAlias = Symtab.addUndefined(To); } // Windows specific -- if __load_config_used can be resolved, resolve it. if (Symtab.findUnderscore("_load_config_used")) addUndefined(mangle("_load_config_used")); } while (run()); // Do LTO by compiling bitcode input files to a set of native COFF files then // link those files. Symtab.addCombinedLTOObjects(); run(); // Make sure we have resolved all symbols. Symtab.reportRemainingUndefines(); // Windows specific -- if no /subsystem is given, we need to infer // that from entry point name. if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) { Config->Subsystem = inferSubsystem(); if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) fatal("subsystem must be defined"); } // Handle /safeseh. if (Args.hasArg(OPT_safeseh)) for (ObjectFile *File : Symtab.ObjectFiles) if (!File->SEHCompat) fatal("/safeseh: " + File->getName() + " is not compatible with SEH"); // Windows specific -- when we are creating a .dll file, we also // need to create a .lib file. if (!Config->Exports.empty() || Config->DLL) { fixupExports(); writeImportLibrary(); assignExportOrdinals(); } // Windows specific -- Create a side-by-side manifest file. if (Config->Manifest == Configuration::SideBySide) createSideBySideManifest(); // Identify unreferenced COMDAT sections. if (Config->DoGC) markLive(Symtab.getChunks()); // Identify identical COMDAT sections to merge them. if (Config->DoICF) doICF(Symtab.getChunks()); // Write the result. writeResult(&Symtab); // Create a symbol map file containing symbol VAs and their names // to help debugging. std::string MapFile = getMapFile(Args); if (!MapFile.empty()) { std::error_code EC; raw_fd_ostream Out(MapFile, EC, OpenFlags::F_Text); if (EC) fatal(EC, "could not create the symbol map " + MapFile); Symtab.printMap(Out); } // Call exit to avoid calling destructors. exit(0); } } // namespace coff } // namespace lld Index: vendor/lld/dist/COFF/Driver.h =================================================================== --- vendor/lld/dist/COFF/Driver.h (revision 311539) +++ vendor/lld/dist/COFF/Driver.h (revision 311540) @@ -1,191 +1,192 @@ //===- Driver.h -------------------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_COFF_DRIVER_H #define LLD_COFF_DRIVER_H #include "Config.h" #include "SymbolTable.h" #include "lld/Core/LLVM.h" #include "lld/Core/Reproduce.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/TarWriter.h" #include #include #include namespace lld { namespace coff { class LinkerDriver; extern LinkerDriver *Driver; using llvm::COFF::MachineTypes; using llvm::COFF::WindowsSubsystem; using llvm::Optional; class InputFile; // Implemented in MarkLive.cpp. void markLive(const std::vector &Chunks); // Implemented in ICF.cpp. void doICF(const std::vector &Chunks); class ArgParser { public: // Parses command line options. llvm::opt::InputArgList parse(llvm::ArrayRef Args); // Concatenate LINK environment varirable and given arguments and parse them. llvm::opt::InputArgList parseLINK(llvm::ArrayRef Args); // Tokenizes a given string and then parses as command line options. llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); } private: std::vector tokenize(StringRef S); std::vector replaceResponseFiles(std::vector); }; class LinkerDriver { public: LinkerDriver() { coff::Symtab = &Symtab; } void link(llvm::ArrayRef Args); // Used by the resolver to parse .drectve section contents. void parseDirectives(StringRef S); // Used by ArchiveFile to enqueue members. void enqueueArchiveMember(const Archive::Child &C, StringRef SymName, StringRef ParentName); private: ArgParser Parser; SymbolTable Symtab; - std::unique_ptr Cpio; // for /linkrepro + std::unique_ptr Tar; // for /linkrepro // Opens a file. Path has to be resolved already. MemoryBufferRef openFile(StringRef Path); // Searches a file from search paths. Optional findFile(StringRef Filename); Optional findLib(StringRef Filename); StringRef doFindFile(StringRef Filename); StringRef doFindLib(StringRef Filename); // Parses LIB environment which contains a list of search paths. void addLibSearchPaths(); // Library search path. The first element is always "" (current directory). std::vector SearchPaths; std::set VisitedFiles; std::set VisitedLibs; SymbolBody *addUndefined(StringRef Sym); StringRef mangle(StringRef Sym); // Windows specific -- "main" is not the only main function in Windows. // You can choose one from these four -- {w,}{WinMain,main}. // There are four different entry point functions for them, // {w,}{WinMain,main}CRTStartup, respectively. The linker needs to // choose the right one depending on which "main" function is defined. // This function looks up the symbol table and resolve corresponding // entry point name. StringRef findDefaultEntry(); WindowsSubsystem inferSubsystem(); MemoryBufferRef takeBuffer(std::unique_ptr MB); void addBuffer(std::unique_ptr MB); void addArchiveBuffer(MemoryBufferRef MBRef, StringRef SymName, StringRef ParentName); void enqueuePath(StringRef Path); void enqueueTask(std::function Task); bool run(); // Driver is the owner of all opened files. // InputFiles have MemoryBufferRefs to them. std::vector> OwningMBs; std::list> TaskQueue; std::vector FilePaths; std::vector Resources; }; void parseModuleDefs(MemoryBufferRef MB); void writeImportLibrary(); // Functions below this line are defined in DriverUtils.cpp. void printHelp(const char *Argv0); // For /machine option. MachineTypes getMachineType(StringRef Arg); StringRef machineToStr(MachineTypes MT); // Parses a string in the form of "[,]". void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size = nullptr); // Parses a string in the form of "[.]". // Minor's default value is 0. void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor); // Parses a string in the form of "[,[.]]". void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major, uint32_t *Minor); void parseAlternateName(StringRef); void parseMerge(StringRef); void parseSection(StringRef); // Parses a string in the form of "EMBED[,=]|NO". void parseManifest(StringRef Arg); // Parses a string in the form of "level=|uiAccess=" void parseManifestUAC(StringRef Arg); // Create a resource file containing a manifest XML. std::unique_ptr createManifestRes(); void createSideBySideManifest(); // Used for dllexported symbols. Export parseExport(StringRef Arg); void fixupExports(); void assignExportOrdinals(); // Parses a string in the form of "key=value" and check // if value matches previous values for the key. // This feature used in the directive section to reject // incompatible objects. void checkFailIfMismatch(StringRef Arg); // Convert Windows resource files (.res files) to a .obj file // using cvtres.exe. std::unique_ptr convertResToCOFF(const std::vector &MBs); // Create enum with OPT_xxx values for each option in Options.td enum { OPT_INVALID = 0, #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID, #include "Options.inc" #undef OPTION }; } // namespace coff } // namespace lld #endif Index: vendor/lld/dist/COFF/InputFiles.cpp =================================================================== --- vendor/lld/dist/COFF/InputFiles.cpp (revision 311539) +++ vendor/lld/dist/COFF/InputFiles.cpp (revision 311540) @@ -1,398 +1,397 @@ //===- InputFiles.cpp -----------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "InputFiles.h" #include "Chunks.h" #include "Config.h" #include "Driver.h" #include "Error.h" #include "Memory.h" #include "SymbolTable.h" #include "Symbols.h" #include "llvm-c/lto.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/LLVMContext.h" #include "llvm/LTO/legacy/LTOModule.h" #include "llvm/Object/Binary.h" #include "llvm/Object/COFF.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" #include "llvm/Target/TargetOptions.h" #include #include #include using namespace llvm; using namespace llvm::COFF; using namespace llvm::object; using namespace llvm::support::endian; using llvm::Triple; using llvm::support::ulittle32_t; using llvm::sys::fs::file_magic; using llvm::sys::fs::identify_magic; namespace lld { namespace coff { LLVMContext BitcodeFile::Context; ArchiveFile::ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {} void ArchiveFile::parse() { // Parse a MemoryBufferRef as an archive file. File = check(Archive::create(MB), toString(this)); // Read the symbol table to construct Lazy objects. for (const Archive::Symbol &Sym : File->symbols()) Symtab->addLazy(this, Sym); } // Returns a buffer pointing to a member file containing a given symbol. void ArchiveFile::addMember(const Archive::Symbol *Sym) { const Archive::Child &C = check(Sym->getMember(), "could not get the member for symbol " + Sym->getName()); // Return an empty buffer if we have already returned the same buffer. if (!Seen.insert(C.getChildOffset()).second) return; Driver->enqueueArchiveMember(C, Sym->getName(), getName()); } void ObjectFile::parse() { // Parse a memory buffer as a COFF file. std::unique_ptr Bin = check(createBinary(MB), toString(this)); if (auto *Obj = dyn_cast(Bin.get())) { Bin.release(); COFFObj.reset(Obj); } else { fatal(toString(this) + " is not a COFF file"); } // Read section and symbol tables. initializeChunks(); initializeSymbols(); initializeSEH(); } void ObjectFile::initializeChunks() { uint32_t NumSections = COFFObj->getNumberOfSections(); Chunks.reserve(NumSections); SparseChunks.resize(NumSections + 1); for (uint32_t I = 1; I < NumSections + 1; ++I) { const coff_section *Sec; StringRef Name; if (auto EC = COFFObj->getSection(I, Sec)) fatal(EC, "getSection failed: #" + Twine(I)); if (auto EC = COFFObj->getSectionName(Sec, Name)) fatal(EC, "getSectionName failed: #" + Twine(I)); if (Name == ".sxdata") { SXData = Sec; continue; } if (Name == ".drectve") { ArrayRef Data; COFFObj->getSectionContents(Sec, Data); Directives = std::string((const char *)Data.data(), Data.size()); continue; } // Object files may have DWARF debug info or MS CodeView debug info // (or both). // // DWARF sections don't need any special handling from the perspective // of the linker; they are just a data section containing relocations. // We can just link them to complete debug info. // // CodeView needs a linker support. We need to interpret and debug // info, and then write it to a separate .pdb file. // Ignore debug info unless /debug is given. if (!Config->Debug && Name.startswith(".debug")) continue; // CodeView sections are stored to a different vector because they are // not linked in the regular manner. if (Name == ".debug" || Name.startswith(".debug$")) { DebugChunks.push_back(new (Alloc) SectionChunk(this, Sec)); continue; } if (Sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE) continue; auto *C = new (Alloc) SectionChunk(this, Sec); Chunks.push_back(C); SparseChunks[I] = C; } } void ObjectFile::initializeSymbols() { uint32_t NumSymbols = COFFObj->getNumberOfSymbols(); SymbolBodies.reserve(NumSymbols); SparseSymbolBodies.resize(NumSymbols); SmallVector, 8> WeakAliases; int32_t LastSectionNumber = 0; for (uint32_t I = 0; I < NumSymbols; ++I) { // Get a COFFSymbolRef object. ErrorOr SymOrErr = COFFObj->getSymbol(I); if (!SymOrErr) fatal(SymOrErr.getError(), "broken object file: " + toString(this)); COFFSymbolRef Sym = *SymOrErr; const void *AuxP = nullptr; if (Sym.getNumberOfAuxSymbols()) AuxP = COFFObj->getSymbol(I + 1)->getRawPtr(); bool IsFirst = (LastSectionNumber != Sym.getSectionNumber()); SymbolBody *Body = nullptr; if (Sym.isUndefined()) { Body = createUndefined(Sym); } else if (Sym.isWeakExternal()) { Body = createUndefined(Sym); uint32_t TagIndex = static_cast(AuxP)->TagIndex; WeakAliases.emplace_back(Body, TagIndex); } else { Body = createDefined(Sym, AuxP, IsFirst); } if (Body) { SymbolBodies.push_back(Body); SparseSymbolBodies[I] = Body; } I += Sym.getNumberOfAuxSymbols(); LastSectionNumber = Sym.getSectionNumber(); } for (auto WeakAlias : WeakAliases) { auto *U = dyn_cast(WeakAlias.first); if (!U) continue; // Report an error if two undefined symbols have different weak aliases. if (U->WeakAlias && U->WeakAlias != SparseSymbolBodies[WeakAlias.second]) Symtab->reportDuplicate(U->symbol(), this); U->WeakAlias = SparseSymbolBodies[WeakAlias.second]; } } SymbolBody *ObjectFile::createUndefined(COFFSymbolRef Sym) { StringRef Name; COFFObj->getSymbolName(Sym, Name); return Symtab->addUndefined(Name, this, Sym.isWeakExternal())->body(); } SymbolBody *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP, bool IsFirst) { StringRef Name; if (Sym.isCommon()) { auto *C = new (Alloc) CommonChunk(Sym); Chunks.push_back(C); return Symtab->addCommon(this, Sym, C)->body(); } if (Sym.isAbsolute()) { COFFObj->getSymbolName(Sym, Name); // Skip special symbols. if (Name == "@comp.id") return nullptr; // COFF spec 5.10.1. The .sxdata section. if (Name == "@feat.00") { if (Sym.getValue() & 1) SEHCompat = true; return nullptr; } if (Sym.isExternal()) return Symtab->addAbsolute(Name, Sym)->body(); else return new (Alloc) DefinedAbsolute(Name, Sym); } int32_t SectionNumber = Sym.getSectionNumber(); if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG) return nullptr; // Reserved sections numbers don't have contents. if (llvm::COFF::isReservedSectionNumber(SectionNumber)) fatal("broken object file: " + toString(this)); // This symbol references a section which is not present in the section // header. if ((uint32_t)SectionNumber >= SparseChunks.size()) fatal("broken object file: " + toString(this)); // Nothing else to do without a section chunk. auto *SC = cast_or_null(SparseChunks[SectionNumber]); if (!SC) return nullptr; // Handle section definitions if (IsFirst && AuxP) { auto *Aux = reinterpret_cast(AuxP); if (Aux->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) if (auto *ParentSC = cast_or_null( SparseChunks[Aux->getNumber(Sym.isBigObj())])) ParentSC->addAssociative(SC); SC->Checksum = Aux->CheckSum; } DefinedRegular *B; if (Sym.isExternal()) B = cast(Symtab->addRegular(this, Sym, SC)->body()); else B = new (Alloc) DefinedRegular(this, Sym, SC); if (SC->isCOMDAT() && Sym.getValue() == 0 && !AuxP) SC->setSymbol(B); return B; } void ObjectFile::initializeSEH() { if (!SEHCompat || !SXData) return; ArrayRef A; COFFObj->getSectionContents(SXData, A); if (A.size() % 4 != 0) fatal(".sxdata must be an array of symbol table indices"); auto *I = reinterpret_cast(A.data()); auto *E = reinterpret_cast(A.data() + A.size()); for (; I != E; ++I) SEHandlers.insert(SparseSymbolBodies[*I]); } MachineTypes ObjectFile::getMachineType() { if (COFFObj) return static_cast(COFFObj->getMachine()); return IMAGE_FILE_MACHINE_UNKNOWN; } StringRef ltrim1(StringRef S, const char *Chars) { if (!S.empty() && strchr(Chars, S[0])) return S.substr(1); return S; } void ImportFile::parse() { const char *Buf = MB.getBufferStart(); const char *End = MB.getBufferEnd(); const auto *Hdr = reinterpret_cast(Buf); // Check if the total size is valid. if ((size_t)(End - Buf) != (sizeof(*Hdr) + Hdr->SizeOfData)) fatal("broken import library"); // Read names and create an __imp_ symbol. StringRef Name = StringAlloc.save(StringRef(Buf + sizeof(*Hdr))); StringRef ImpName = StringAlloc.save("__imp_" + Name); const char *NameStart = Buf + sizeof(coff_import_header) + Name.size() + 1; DLLName = StringRef(NameStart); StringRef ExtName; switch (Hdr->getNameType()) { case IMPORT_ORDINAL: ExtName = ""; break; case IMPORT_NAME: ExtName = Name; break; case IMPORT_NAME_NOPREFIX: ExtName = ltrim1(Name, "?@_"); break; case IMPORT_NAME_UNDECORATE: ExtName = ltrim1(Name, "?@_"); ExtName = ExtName.substr(0, ExtName.find('@')); break; } this->Hdr = Hdr; ExternalName = ExtName; ImpSym = cast( Symtab->addImportData(ImpName, this)->body()); // If type is function, we need to create a thunk which jump to an // address pointed by the __imp_ symbol. (This allows you to call // DLL functions just like regular non-DLL functions.) if (Hdr->getType() != llvm::COFF::IMPORT_CODE) return; ThunkSym = cast( Symtab->addImportThunk(Name, ImpSym, Hdr->Machine)->body()); } void BitcodeFile::parse() { Context.enableDebugTypeODRUniquing(); ErrorOr> ModOrErr = LTOModule::createFromBuffer( Context, MB.getBufferStart(), MB.getBufferSize(), llvm::TargetOptions()); M = check(std::move(ModOrErr), "could not create LTO module"); StringSaver Saver(Alloc); for (unsigned I = 0, E = M->getSymbolCount(); I != E; ++I) { lto_symbol_attributes Attrs = M->getSymbolAttributes(I); if ((Attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL) continue; StringRef SymName = Saver.save(M->getSymbolName(I)); int SymbolDef = Attrs & LTO_SYMBOL_DEFINITION_MASK; if (SymbolDef == LTO_SYMBOL_DEFINITION_UNDEFINED) { SymbolBodies.push_back(Symtab->addUndefined(SymName, this, false)->body()); } else { bool Replaceable = (SymbolDef == LTO_SYMBOL_DEFINITION_TENTATIVE || // common (Attrs & LTO_SYMBOL_COMDAT) || // comdat (SymbolDef == LTO_SYMBOL_DEFINITION_WEAK && // weak external (Attrs & LTO_SYMBOL_ALIAS))); SymbolBodies.push_back( Symtab->addBitcode(this, SymName, Replaceable)->body()); } } Directives = M->getLinkerOpts(); } MachineTypes BitcodeFile::getMachineType() { if (!M) return IMAGE_FILE_MACHINE_UNKNOWN; switch (Triple(M->getTargetTriple()).getArch()) { case Triple::x86_64: return AMD64; case Triple::x86: return I386; case Triple::arm: return ARMNT; default: return IMAGE_FILE_MACHINE_UNKNOWN; } } +} // namespace coff +} // namespace lld // Returns the last element of a path, which is supposed to be a filename. static StringRef getBasename(StringRef Path) { size_t Pos = Path.find_last_of("\\/"); if (Pos == StringRef::npos) return Path; return Path.substr(Pos + 1); } // Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)". -std::string toString(InputFile *File) { +std::string lld::toString(coff::InputFile *File) { if (!File) return "(internal)"; if (File->ParentName.empty()) return File->getName().lower(); std::string Res = (getBasename(File->ParentName) + "(" + getBasename(File->getName()) + ")") .str(); return StringRef(Res).lower(); } - -} // namespace coff -} // namespace lld Index: vendor/lld/dist/COFF/InputFiles.h =================================================================== --- vendor/lld/dist/COFF/InputFiles.h (revision 311539) +++ vendor/lld/dist/COFF/InputFiles.h (revision 311540) @@ -1,211 +1,210 @@ //===- InputFiles.h ---------------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_COFF_INPUT_FILES_H #define LLD_COFF_INPUT_FILES_H #include "lld/Core/LLVM.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/IR/LLVMContext.h" #include "llvm/LTO/legacy/LTOModule.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" #include "llvm/Support/StringSaver.h" #include #include #include namespace lld { namespace coff { using llvm::LTOModule; using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN; using llvm::COFF::MachineTypes; using llvm::object::Archive; using llvm::object::COFFObjectFile; using llvm::object::COFFSymbolRef; using llvm::object::coff_import_header; using llvm::object::coff_section; class Chunk; class Defined; class DefinedImportData; class DefinedImportThunk; class Lazy; class SectionChunk; struct Symbol; class SymbolBody; class Undefined; // The root class of input files. class InputFile { public: enum Kind { ArchiveKind, ObjectKind, ImportKind, BitcodeKind }; Kind kind() const { return FileKind; } virtual ~InputFile() {} // Returns the filename. StringRef getName() { return MB.getBufferIdentifier(); } // Reads a file (the constructor doesn't do that). virtual void parse() = 0; // Returns the CPU type this file was compiled to. virtual MachineTypes getMachineType() { return IMAGE_FILE_MACHINE_UNKNOWN; } // An archive file name if this file is created from an archive. StringRef ParentName; // Returns .drectve section contents if exist. StringRef getDirectives() { return StringRef(Directives).trim(); } protected: InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} MemoryBufferRef MB; std::string Directives; private: const Kind FileKind; }; // .lib or .a file. class ArchiveFile : public InputFile { public: explicit ArchiveFile(MemoryBufferRef M); static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } void parse() override; // Enqueues an archive member load for the given symbol. If we've already // enqueued a load for the same archive member, this function does nothing, // which ensures that we don't load the same member more than once. void addMember(const Archive::Symbol *Sym); private: std::unique_ptr File; std::string Filename; llvm::DenseSet Seen; }; // .obj or .o file. This may be a member of an archive file. class ObjectFile : public InputFile { public: explicit ObjectFile(MemoryBufferRef M) : InputFile(ObjectKind, M) {} static bool classof(const InputFile *F) { return F->kind() == ObjectKind; } void parse() override; MachineTypes getMachineType() override; std::vector &getChunks() { return Chunks; } std::vector &getDebugChunks() { return DebugChunks; } std::vector &getSymbols() { return SymbolBodies; } // Returns a SymbolBody object for the SymbolIndex'th symbol in the // underlying object file. SymbolBody *getSymbolBody(uint32_t SymbolIndex) { return SparseSymbolBodies[SymbolIndex]; } // Returns the underying COFF file. COFFObjectFile *getCOFFObj() { return COFFObj.get(); } // True if this object file is compatible with SEH. // COFF-specific and x86-only. bool SEHCompat = false; // The list of safe exception handlers listed in .sxdata section. // COFF-specific and x86-only. std::set SEHandlers; private: void initializeChunks(); void initializeSymbols(); void initializeSEH(); SymbolBody *createDefined(COFFSymbolRef Sym, const void *Aux, bool IsFirst); SymbolBody *createUndefined(COFFSymbolRef Sym); std::unique_ptr COFFObj; llvm::BumpPtrAllocator Alloc; const coff_section *SXData = nullptr; // List of all chunks defined by this file. This includes both section // chunks and non-section chunks for common symbols. std::vector Chunks; // CodeView debug info sections. std::vector DebugChunks; // This vector contains the same chunks as Chunks, but they are // indexed such that you can get a SectionChunk by section index. // Nonexistent section indices are filled with null pointers. // (Because section number is 1-based, the first slot is always a // null pointer.) std::vector SparseChunks; // List of all symbols referenced or defined by this file. std::vector SymbolBodies; // This vector contains the same symbols as SymbolBodies, but they // are indexed such that you can get a SymbolBody by symbol // index. Nonexistent indices (which are occupied by auxiliary // symbols in the real symbol table) are filled with null pointers. std::vector SparseSymbolBodies; }; // This type represents import library members that contain DLL names // and symbols exported from the DLLs. See Microsoft PE/COFF spec. 7 // for details about the format. class ImportFile : public InputFile { public: explicit ImportFile(MemoryBufferRef M) : InputFile(ImportKind, M), StringAlloc(StringAllocAux) {} static bool classof(const InputFile *F) { return F->kind() == ImportKind; } DefinedImportData *ImpSym = nullptr; DefinedImportThunk *ThunkSym = nullptr; std::string DLLName; private: void parse() override; llvm::BumpPtrAllocator Alloc; llvm::BumpPtrAllocator StringAllocAux; llvm::StringSaver StringAlloc; public: StringRef ExternalName; const coff_import_header *Hdr; Chunk *Location = nullptr; }; // Used for LTO. class BitcodeFile : public InputFile { public: explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {} static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; } std::vector &getSymbols() { return SymbolBodies; } MachineTypes getMachineType() override; std::unique_ptr takeModule() { return std::move(M); } static llvm::LLVMContext Context; private: void parse() override; std::vector SymbolBodies; llvm::BumpPtrAllocator Alloc; std::unique_ptr M; }; - -std::string toString(InputFile *File); - } // namespace coff + +std::string toString(coff::InputFile *File); } // namespace lld #endif Index: vendor/lld/dist/COFF/Symbols.cpp =================================================================== --- vendor/lld/dist/COFF/Symbols.cpp (revision 311539) +++ vendor/lld/dist/COFF/Symbols.cpp (revision 311540) @@ -1,85 +1,84 @@ //===- Symbols.cpp --------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Symbols.h" #include "Error.h" #include "InputFiles.h" #include "Memory.h" #include "Strings.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::object; +// Returns a symbol name for an error message. +std::string lld::toString(coff::SymbolBody &B) { + if (Optional S = coff::demangle(B.getName())) + return ("\"" + *S + "\" (" + B.getName() + ")").str(); + return B.getName(); +} + namespace lld { namespace coff { StringRef SymbolBody::getName() { // DefinedCOFF names are read lazily for a performance reason. // Non-external symbol names are never used by the linker except for logging // or debugging. Their internal references are resolved not by name but by // symbol index. And because they are not external, no one can refer them by // name. Object files contain lots of non-external symbols, and creating // StringRefs for them (which involves lots of strlen() on the string table) // is a waste of time. if (Name.empty()) { auto *D = cast(this); D->File->getCOFFObj()->getSymbolName(D->Sym, Name); } return Name; } InputFile *SymbolBody::getFile() { if (auto *Sym = dyn_cast(this)) return Sym->File; if (auto *Sym = dyn_cast(this)) return Sym->File; if (auto *Sym = dyn_cast(this)) return Sym->File; return nullptr; } COFFSymbolRef DefinedCOFF::getCOFFSymbol() { size_t SymSize = File->getCOFFObj()->getSymbolTableEntrySize(); if (SymSize == sizeof(coff_symbol16)) return COFFSymbolRef(reinterpret_cast(Sym)); assert(SymSize == sizeof(coff_symbol32)); return COFFSymbolRef(reinterpret_cast(Sym)); } DefinedImportThunk::DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine) : Defined(DefinedImportThunkKind, Name) { switch (Machine) { case AMD64: Data = make(S); return; case I386: Data = make(S); return; case ARMNT: Data = make(S); return; default: llvm_unreachable("unknown machine type"); } } Defined *Undefined::getWeakAlias() { // A weak alias may be a weak alias to another symbol, so check recursively. for (SymbolBody *A = WeakAlias; A; A = cast(A)->WeakAlias) if (auto *D = dyn_cast(A)) return D; return nullptr; } - -// Returns a symbol name for an error message. -std::string toString(SymbolBody &B) { - if (Optional S = demangle(B.getName())) - return ("\"" + *S + "\" (" + B.getName() + ")").str(); - return B.getName(); -} - } // namespace coff } // namespace lld Index: vendor/lld/dist/COFF/Symbols.h =================================================================== --- vendor/lld/dist/COFF/Symbols.h (revision 311539) +++ vendor/lld/dist/COFF/Symbols.h (revision 311540) @@ -1,437 +1,436 @@ //===- Symbols.h ------------------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_COFF_SYMBOLS_H #define LLD_COFF_SYMBOLS_H #include "Chunks.h" #include "Config.h" #include "Memory.h" #include "lld/Core/LLVM.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" #include #include #include namespace lld { namespace coff { using llvm::object::Archive; using llvm::object::COFFSymbolRef; using llvm::object::coff_import_header; using llvm::object::coff_symbol_generic; class ArchiveFile; class BitcodeFile; class InputFile; class ObjectFile; struct Symbol; class SymbolTable; // The base class for real symbol classes. class SymbolBody { public: enum Kind { // The order of these is significant. We start with the regular defined // symbols as those are the most prevelant and the zero tag is the cheapest // to set. Among the defined kinds, the lower the kind is preferred over // the higher kind when testing wether one symbol should take precedence // over another. DefinedRegularKind = 0, DefinedCommonKind, DefinedLocalImportKind, DefinedImportThunkKind, DefinedImportDataKind, DefinedAbsoluteKind, DefinedRelativeKind, DefinedBitcodeKind, UndefinedKind, LazyKind, LastDefinedCOFFKind = DefinedCommonKind, LastDefinedKind = DefinedBitcodeKind, }; Kind kind() const { return static_cast(SymbolKind); } // Returns true if this is an external symbol. bool isExternal() { return IsExternal; } // Returns the symbol name. StringRef getName(); // Returns the file from which this symbol was created. InputFile *getFile(); Symbol *symbol(); const Symbol *symbol() const { return const_cast(this)->symbol(); } protected: friend SymbolTable; explicit SymbolBody(Kind K, StringRef N = "") : SymbolKind(K), IsExternal(true), IsCOMDAT(false), IsReplaceable(false), WrittenToSymtab(false), Name(N) {} const unsigned SymbolKind : 8; unsigned IsExternal : 1; // This bit is used by the \c DefinedRegular subclass. unsigned IsCOMDAT : 1; // This bit is used by the \c DefinedBitcode subclass. unsigned IsReplaceable : 1; public: // This bit is used by Writer::createSymbolAndStringTable(). unsigned WrittenToSymtab : 1; protected: StringRef Name; }; // The base class for any defined symbols, including absolute symbols, // etc. class Defined : public SymbolBody { public: Defined(Kind K, StringRef N = "") : SymbolBody(K, N) {} static bool classof(const SymbolBody *S) { return S->kind() <= LastDefinedKind; } // Returns the RVA (relative virtual address) of this symbol. The // writer sets and uses RVAs. uint64_t getRVA(); // Returns the RVA relative to the beginning of the output section. // Used to implement SECREL relocation type. uint64_t getSecrel(); // Returns the output section index. // Used to implement SECTION relocation type. uint64_t getSectionIndex(); // Returns true if this symbol points to an executable (e.g. .text) section. // Used to implement ARM relocations. bool isExecutable(); }; // Symbols defined via a COFF object file. class DefinedCOFF : public Defined { friend SymbolBody; public: DefinedCOFF(Kind K, ObjectFile *F, COFFSymbolRef S) : Defined(K), File(F), Sym(S.getGeneric()) {} static bool classof(const SymbolBody *S) { return S->kind() <= LastDefinedCOFFKind; } ObjectFile *getFile() { return File; } COFFSymbolRef getCOFFSymbol(); ObjectFile *File; protected: const coff_symbol_generic *Sym; }; // Regular defined symbols read from object file symbol tables. class DefinedRegular : public DefinedCOFF { public: DefinedRegular(ObjectFile *F, COFFSymbolRef S, SectionChunk *C) : DefinedCOFF(DefinedRegularKind, F, S), Data(&C->Repl) { IsExternal = S.isExternal(); IsCOMDAT = C->isCOMDAT(); } static bool classof(const SymbolBody *S) { return S->kind() == DefinedRegularKind; } uint64_t getRVA() { return (*Data)->getRVA() + Sym->Value; } bool isCOMDAT() { return IsCOMDAT; } SectionChunk *getChunk() { return *Data; } uint32_t getValue() { return Sym->Value; } private: SectionChunk **Data; }; class DefinedCommon : public DefinedCOFF { public: DefinedCommon(ObjectFile *F, COFFSymbolRef S, CommonChunk *C) : DefinedCOFF(DefinedCommonKind, F, S), Data(C) { IsExternal = S.isExternal(); } static bool classof(const SymbolBody *S) { return S->kind() == DefinedCommonKind; } uint64_t getRVA() { return Data->getRVA(); } private: friend SymbolTable; uint64_t getSize() { return Sym->Value; } CommonChunk *Data; }; // Absolute symbols. class DefinedAbsolute : public Defined { public: DefinedAbsolute(StringRef N, COFFSymbolRef S) : Defined(DefinedAbsoluteKind, N), VA(S.getValue()) { IsExternal = S.isExternal(); } DefinedAbsolute(StringRef N, uint64_t V) : Defined(DefinedAbsoluteKind, N), VA(V) {} static bool classof(const SymbolBody *S) { return S->kind() == DefinedAbsoluteKind; } uint64_t getRVA() { return VA - Config->ImageBase; } void setVA(uint64_t V) { VA = V; } private: uint64_t VA; }; // This is a kind of absolute symbol but relative to the image base. // Unlike absolute symbols, relocations referring this kind of symbols // are subject of the base relocation. This type is used rarely -- // mainly for __ImageBase. class DefinedRelative : public Defined { public: explicit DefinedRelative(StringRef Name, uint64_t V = 0) : Defined(DefinedRelativeKind, Name), RVA(V) {} static bool classof(const SymbolBody *S) { return S->kind() == DefinedRelativeKind; } uint64_t getRVA() { return RVA; } void setRVA(uint64_t V) { RVA = V; } private: uint64_t RVA; }; // This class represents a symbol defined in an archive file. It is // created from an archive file header, and it knows how to load an // object file from an archive to replace itself with a defined // symbol. If the resolver finds both Undefined and Lazy for // the same name, it will ask the Lazy to load a file. class Lazy : public SymbolBody { public: Lazy(ArchiveFile *F, const Archive::Symbol S) : SymbolBody(LazyKind, S.getName()), File(F), Sym(S) {} static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; } ArchiveFile *File; private: friend SymbolTable; private: const Archive::Symbol Sym; }; // Undefined symbols. class Undefined : public SymbolBody { public: explicit Undefined(StringRef N) : SymbolBody(UndefinedKind, N) {} static bool classof(const SymbolBody *S) { return S->kind() == UndefinedKind; } // An undefined symbol can have a fallback symbol which gives an // undefined symbol a second chance if it would remain undefined. // If it remains undefined, it'll be replaced with whatever the // Alias pointer points to. SymbolBody *WeakAlias = nullptr; // If this symbol is external weak, try to resolve it to a defined // symbol by searching the chain of fallback symbols. Returns the symbol if // successful, otherwise returns null. Defined *getWeakAlias(); }; // Windows-specific classes. // This class represents a symbol imported from a DLL. This has two // names for internal use and external use. The former is used for // name resolution, and the latter is used for the import descriptor // table in an output. The former has "__imp_" prefix. class DefinedImportData : public Defined { public: DefinedImportData(StringRef N, ImportFile *F) : Defined(DefinedImportDataKind, N), File(F) { } static bool classof(const SymbolBody *S) { return S->kind() == DefinedImportDataKind; } uint64_t getRVA() { return File->Location->getRVA(); } StringRef getDLLName() { return File->DLLName; } StringRef getExternalName() { return File->ExternalName; } void setLocation(Chunk *AddressTable) { File->Location = AddressTable; } uint16_t getOrdinal() { return File->Hdr->OrdinalHint; } private: ImportFile *File; }; // This class represents a symbol for a jump table entry which jumps // to a function in a DLL. Linker are supposed to create such symbols // without "__imp_" prefix for all function symbols exported from // DLLs, so that you can call DLL functions as regular functions with // a regular name. A function pointer is given as a DefinedImportData. class DefinedImportThunk : public Defined { public: DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine); static bool classof(const SymbolBody *S) { return S->kind() == DefinedImportThunkKind; } uint64_t getRVA() { return Data->getRVA(); } Chunk *getChunk() { return Data; } private: Chunk *Data; }; // If you have a symbol "__imp_foo" in your object file, a symbol name // "foo" becomes automatically available as a pointer to "__imp_foo". // This class is for such automatically-created symbols. // Yes, this is an odd feature. We didn't intend to implement that. // This is here just for compatibility with MSVC. class DefinedLocalImport : public Defined { public: DefinedLocalImport(StringRef N, Defined *S) : Defined(DefinedLocalImportKind, N), Data(make(S)) {} static bool classof(const SymbolBody *S) { return S->kind() == DefinedLocalImportKind; } uint64_t getRVA() { return Data->getRVA(); } Chunk *getChunk() { return Data; } private: LocalImportChunk *Data; }; class DefinedBitcode : public Defined { friend SymbolBody; public: DefinedBitcode(BitcodeFile *F, StringRef N, bool IsReplaceable) : Defined(DefinedBitcodeKind, N), File(F) { // IsReplaceable tracks whether the bitcode symbol may be replaced with some // other (defined, common or bitcode) symbol. This is the case for common, // comdat and weak external symbols. We try to replace bitcode symbols with // "real" symbols (see SymbolTable::add{Regular,Bitcode}), and resolve the // result against the real symbol from the combined LTO object. this->IsReplaceable = IsReplaceable; } static bool classof(const SymbolBody *S) { return S->kind() == DefinedBitcodeKind; } BitcodeFile *File; }; inline uint64_t Defined::getRVA() { switch (kind()) { case DefinedAbsoluteKind: return cast(this)->getRVA(); case DefinedRelativeKind: return cast(this)->getRVA(); case DefinedImportDataKind: return cast(this)->getRVA(); case DefinedImportThunkKind: return cast(this)->getRVA(); case DefinedLocalImportKind: return cast(this)->getRVA(); case DefinedCommonKind: return cast(this)->getRVA(); case DefinedRegularKind: return cast(this)->getRVA(); case DefinedBitcodeKind: llvm_unreachable("There is no address for a bitcode symbol."); case LazyKind: case UndefinedKind: llvm_unreachable("Cannot get the address for an undefined symbol."); } llvm_unreachable("unknown symbol kind"); } // A real symbol object, SymbolBody, is usually stored within a Symbol. There's // always one Symbol for each symbol name. The resolver updates the SymbolBody // stored in the Body field of this object as it resolves symbols. Symbol also // holds computed properties of symbol names. struct Symbol { // True if this symbol was referenced by a regular (non-bitcode) object. unsigned IsUsedInRegularObj : 1; // True if we've seen both a lazy and an undefined symbol with this symbol // name, which means that we have enqueued an archive member load and should // not load any more archive members to resolve the same symbol. unsigned PendingArchiveLoad : 1; // This field is used to store the Symbol's SymbolBody. This instantiation of // AlignedCharArrayUnion gives us a struct with a char array field that is // large and aligned enough to store any derived class of SymbolBody. llvm::AlignedCharArrayUnion Body; SymbolBody *body() { return reinterpret_cast(Body.buffer); } const SymbolBody *body() const { return const_cast(this)->body(); } }; template void replaceBody(Symbol *S, ArgT &&... Arg) { static_assert(sizeof(T) <= sizeof(S->Body), "Body too small"); static_assert(alignof(T) <= alignof(decltype(S->Body)), "Body not aligned enough"); assert(static_cast(static_cast(nullptr)) == nullptr && "Not a SymbolBody"); new (S->Body.buffer) T(std::forward(Arg)...); } inline Symbol *SymbolBody::symbol() { assert(isExternal()); return reinterpret_cast(reinterpret_cast(this) - offsetof(Symbol, Body)); } - -std::string toString(SymbolBody &B); - } // namespace coff + +std::string toString(coff::SymbolBody &B); } // namespace lld #endif Index: vendor/lld/dist/ELF/Driver.cpp =================================================================== --- vendor/lld/dist/ELF/Driver.cpp (revision 311539) +++ vendor/lld/dist/ELF/Driver.cpp (revision 311540) @@ -1,839 +1,842 @@ //===- Driver.cpp ---------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Driver.h" #include "Config.h" #include "Error.h" #include "ICF.h" #include "InputFiles.h" #include "InputSection.h" #include "LinkerScript.h" #include "Memory.h" #include "Strings.h" #include "SymbolTable.h" #include "Target.h" #include "Threads.h" #include "Writer.h" #include "lld/Config/Version.h" #include "lld/Driver/Driver.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Path.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include #include using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; using namespace llvm::sys; using namespace lld; using namespace lld::elf; Configuration *elf::Config; LinkerDriver *elf::Driver; BumpPtrAllocator elf::BAlloc; StringSaver elf::Saver{BAlloc}; std::vector elf::SpecificAllocBase::Instances; bool elf::link(ArrayRef Args, bool CanExitEarly, raw_ostream &Error) { ErrorCount = 0; ErrorOS = &Error; Argv0 = Args[0]; Config = make(); Driver = make(); ScriptConfig = make(); Driver->main(Args, CanExitEarly); freeArena(); return !ErrorCount; } // Parses a linker -m option. static std::tuple parseEmulation(StringRef Emul) { uint8_t OSABI = 0; StringRef S = Emul; if (S.endswith("_fbsd")) { S = S.drop_back(5); OSABI = ELFOSABI_FREEBSD; } std::pair Ret = StringSwitch>(S) .Cases("aarch64elf", "aarch64linux", {ELF64LEKind, EM_AARCH64}) .Case("armelf_linux_eabi", {ELF32LEKind, EM_ARM}) .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64}) .Case("elf32btsmip", {ELF32BEKind, EM_MIPS}) .Case("elf32ltsmip", {ELF32LEKind, EM_MIPS}) .Case("elf32btsmipn32", {ELF32BEKind, EM_MIPS}) .Case("elf32ltsmipn32", {ELF32LEKind, EM_MIPS}) .Case("elf32ppc", {ELF32BEKind, EM_PPC}) .Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) .Case("elf64ppc", {ELF64BEKind, EM_PPC64}) .Cases("elf_amd64", "elf_x86_64", {ELF64LEKind, EM_X86_64}) .Case("elf_i386", {ELF32LEKind, EM_386}) .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU}) .Default({ELFNoneKind, EM_NONE}); if (Ret.first == ELFNoneKind) { if (S == "i386pe" || S == "i386pep" || S == "thumb2pe") error("Windows targets are not supported on the ELF frontend: " + Emul); else error("unknown emulation: " + Emul); } return std::make_tuple(Ret.first, Ret.second, OSABI); } // Returns slices of MB by parsing MB as an archive file. // Each slice consists of a member file in the archive. std::vector LinkerDriver::getArchiveMembers(MemoryBufferRef MB) { std::unique_ptr File = check(Archive::create(MB), MB.getBufferIdentifier() + ": failed to parse archive"); std::vector V; Error Err = Error::success(); for (const ErrorOr &COrErr : File->children(Err)) { Archive::Child C = check(COrErr, MB.getBufferIdentifier() + ": could not get the child of the archive"); MemoryBufferRef MBRef = check(C.getMemoryBufferRef(), MB.getBufferIdentifier() + ": could not get the buffer for a child of the archive"); V.push_back(MBRef); } if (Err) fatal(MB.getBufferIdentifier() + ": Archive::children failed: " + toString(std::move(Err))); // Take ownership of memory buffers created for members of thin archives. for (std::unique_ptr &MB : File->takeThinBuffers()) make>(std::move(MB)); return V; } // Opens and parses a file. Path has to be resolved already. // Newly created memory buffers are owned by this driver. void LinkerDriver::addFile(StringRef Path) { using namespace sys::fs; Optional Buffer = readFile(Path); if (!Buffer.hasValue()) return; MemoryBufferRef MBRef = *Buffer; if (InBinary) { Files.push_back(make(MBRef)); return; } switch (identify_magic(MBRef.getBuffer())) { case file_magic::unknown: readLinkerScript(MBRef); return; case file_magic::archive: if (InWholeArchive) { for (MemoryBufferRef MB : getArchiveMembers(MBRef)) Files.push_back(createObjectFile(MB, Path)); return; } Files.push_back(make(MBRef)); return; case file_magic::elf_shared_object: if (Config->Relocatable) { error("attempted static link of dynamic object " + Path); return; } Files.push_back(createSharedFile(MBRef)); return; default: if (InLib) Files.push_back(make(MBRef)); else Files.push_back(createObjectFile(MBRef)); } } Optional LinkerDriver::readFile(StringRef Path) { if (Config->Verbose) outs() << Path << "\n"; auto MBOrErr = MemoryBuffer::getFile(Path); if (auto EC = MBOrErr.getError()) { error(EC, "cannot open " + Path); return None; } std::unique_ptr &MB = *MBOrErr; MemoryBufferRef MBRef = MB->getMemBufferRef(); make>(std::move(MB)); // take MB ownership - if (Cpio) - Cpio->append(relativeToRoot(Path), MBRef.getBuffer()); + if (Tar) + Tar->append(relativeToRoot(Path), MBRef.getBuffer()); return MBRef; } // Add a given library by searching it from input search paths. void LinkerDriver::addLibrary(StringRef Name) { if (Optional Path = searchLibrary(Name)) addFile(*Path); else error("unable to find library -l" + Name); } // This function is called on startup. We need this for LTO since // LTO calls LLVM functions to compile bitcode files to native code. // Technically this can be delayed until we read bitcode files, but // we don't bother to do lazily because the initialization is fast. static void initLLVM(opt::InputArgList &Args) { InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); InitializeAllAsmParsers(); // Parse and evaluate -mllvm options. std::vector V; V.push_back("lld (LLVM option parsing)"); for (auto *Arg : Args.filtered(OPT_mllvm)) V.push_back(Arg->getValue()); cl::ParseCommandLineOptions(V.size(), V.data()); } // Some command line options or some combinations of them are not allowed. // This function checks for such errors. static void checkOptions(opt::InputArgList &Args) { // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup // table which is a relatively new feature. if (Config->EMachine == EM_MIPS && Config->GnuHash) error("the .gnu.hash section is not compatible with the MIPS target."); if (Config->Pie && Config->Shared) error("-shared and -pie may not be used together"); if (Config->Relocatable) { if (Config->Shared) error("-r and -shared may not be used together"); if (Config->GcSections) error("-r and --gc-sections may not be used together"); if (Config->ICF) error("-r and --icf may not be used together"); if (Config->Pie) error("-r and -pie may not be used together"); } } static StringRef getString(opt::InputArgList &Args, unsigned Key, StringRef Default = "") { if (auto *Arg = Args.getLastArg(Key)) return Arg->getValue(); return Default; } static int getInteger(opt::InputArgList &Args, unsigned Key, int Default) { int V = Default; if (auto *Arg = Args.getLastArg(Key)) { StringRef S = Arg->getValue(); if (S.getAsInteger(10, V)) error(Arg->getSpelling() + ": number expected, but got " + S); } return V; } static const char *getReproduceOption(opt::InputArgList &Args) { if (auto *Arg = Args.getLastArg(OPT_reproduce)) return Arg->getValue(); return getenv("LLD_REPRODUCE"); } static bool hasZOption(opt::InputArgList &Args, StringRef Key) { for (auto *Arg : Args.filtered(OPT_z)) if (Key == Arg->getValue()) return true; return false; } static uint64_t getZOptionValue(opt::InputArgList &Args, StringRef Key, uint64_t Default) { for (auto *Arg : Args.filtered(OPT_z)) { StringRef Value = Arg->getValue(); size_t Pos = Value.find("="); if (Pos != StringRef::npos && Key == Value.substr(0, Pos)) { Value = Value.substr(Pos + 1); uint64_t Result; if (Value.getAsInteger(0, Result)) error("invalid " + Key + ": " + Value); return Result; } } return Default; } void LinkerDriver::main(ArrayRef ArgsArr, bool CanExitEarly) { ELFOptTable Parser; opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); // Interpret this flag early because error() depends on them. Config->ErrorLimit = getInteger(Args, OPT_error_limit, 20); // Handle -help if (Args.hasArg(OPT_help)) { printHelp(ArgsArr[0]); return; } // GNU linkers disagree here. Though both -version and -v are mentioned // in help to print the version information, GNU ld just normally exits, // while gold can continue linking. We are compatible with ld.bfd here. if (Args.hasArg(OPT_version) || Args.hasArg(OPT_v)) outs() << getLLDVersion() << "\n"; if (Args.hasArg(OPT_version)) return; Config->ExitEarly = CanExitEarly && !Args.hasArg(OPT_full_shutdown); if (const char *Path = getReproduceOption(Args)) { // Note that --reproduce is a debug option so you can ignore it // if you are trying to understand the whole picture of the code. - ErrorOr F = CpioFile::create(Path); - if (F) { - Cpio.reset(*F); - Cpio->append("response.txt", createResponseFile(Args)); - Cpio->append("version.txt", getLLDVersion() + "\n"); - } else - error(F.getError(), - Twine("--reproduce: failed to open ") + Path + ".cpio"); + Expected> ErrOrWriter = + TarWriter::create(Path, path::stem(Path)); + if (ErrOrWriter) { + Tar = std::move(*ErrOrWriter); + Tar->append("response.txt", createResponseFile(Args)); + Tar->append("version.txt", getLLDVersion() + "\n"); + } else { + error(Twine("--reproduce: failed to open ") + Path + ": " + + toString(ErrOrWriter.takeError())); + } } readConfigs(Args); initLLVM(Args); createFiles(Args); inferMachineType(); checkOptions(Args); if (ErrorCount) return; switch (Config->EKind) { case ELF32LEKind: link(Args); return; case ELF32BEKind: link(Args); return; case ELF64LEKind: link(Args); return; case ELF64BEKind: link(Args); return; default: llvm_unreachable("unknown Config->EKind"); } } static UnresolvedPolicy getUnresolvedSymbolOption(opt::InputArgList &Args) { if (Args.hasArg(OPT_noinhibit_exec)) return UnresolvedPolicy::Warn; if (Args.hasArg(OPT_no_undefined) || hasZOption(Args, "defs")) return UnresolvedPolicy::NoUndef; if (Config->Relocatable) return UnresolvedPolicy::Ignore; if (auto *Arg = Args.getLastArg(OPT_unresolved_symbols)) { StringRef S = Arg->getValue(); if (S == "ignore-all" || S == "ignore-in-object-files") return UnresolvedPolicy::Ignore; if (S == "ignore-in-shared-libs" || S == "report-all") return UnresolvedPolicy::ReportError; error("unknown --unresolved-symbols value: " + S); } return UnresolvedPolicy::ReportError; } static Target2Policy getTarget2Option(opt::InputArgList &Args) { if (auto *Arg = Args.getLastArg(OPT_target2)) { StringRef S = Arg->getValue(); if (S == "rel") return Target2Policy::Rel; if (S == "abs") return Target2Policy::Abs; if (S == "got-rel") return Target2Policy::GotRel; error("unknown --target2 option: " + S); } return Target2Policy::GotRel; } static bool isOutputFormatBinary(opt::InputArgList &Args) { if (auto *Arg = Args.getLastArg(OPT_oformat)) { StringRef S = Arg->getValue(); if (S == "binary") return true; error("unknown --oformat value: " + S); } return false; } static bool getArg(opt::InputArgList &Args, unsigned K1, unsigned K2, bool Default) { if (auto *Arg = Args.getLastArg(K1, K2)) return Arg->getOption().getID() == K1; return Default; } static DiscardPolicy getDiscardOption(opt::InputArgList &Args) { if (Config->Relocatable) return DiscardPolicy::None; auto *Arg = Args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none); if (!Arg) return DiscardPolicy::Default; if (Arg->getOption().getID() == OPT_discard_all) return DiscardPolicy::All; if (Arg->getOption().getID() == OPT_discard_locals) return DiscardPolicy::Locals; return DiscardPolicy::None; } static StripPolicy getStripOption(opt::InputArgList &Args) { if (auto *Arg = Args.getLastArg(OPT_strip_all, OPT_strip_debug)) { if (Arg->getOption().getID() == OPT_strip_all) return StripPolicy::All; return StripPolicy::Debug; } return StripPolicy::None; } static uint64_t parseSectionAddress(StringRef S, opt::Arg *Arg) { uint64_t VA = 0; if (S.startswith("0x")) S = S.drop_front(2); if (S.getAsInteger(16, VA)) - error("invalid argument: " + stringize(Arg)); + error("invalid argument: " + toString(Arg)); return VA; } static StringMap getSectionStartMap(opt::InputArgList &Args) { StringMap Ret; for (auto *Arg : Args.filtered(OPT_section_start)) { StringRef Name; StringRef Addr; std::tie(Name, Addr) = StringRef(Arg->getValue()).split('='); Ret[Name] = parseSectionAddress(Addr, Arg); } if (auto *Arg = Args.getLastArg(OPT_Ttext)) Ret[".text"] = parseSectionAddress(Arg->getValue(), Arg); if (auto *Arg = Args.getLastArg(OPT_Tdata)) Ret[".data"] = parseSectionAddress(Arg->getValue(), Arg); if (auto *Arg = Args.getLastArg(OPT_Tbss)) Ret[".bss"] = parseSectionAddress(Arg->getValue(), Arg); return Ret; } static SortSectionPolicy getSortKind(opt::InputArgList &Args) { StringRef S = getString(Args, OPT_sort_section); if (S == "alignment") return SortSectionPolicy::Alignment; if (S == "name") return SortSectionPolicy::Name; if (!S.empty()) error("unknown --sort-section rule: " + S); return SortSectionPolicy::Default; } static std::vector getLines(MemoryBufferRef MB) { SmallVector Arr; MB.getBuffer().split(Arr, '\n'); std::vector Ret; for (StringRef S : Arr) { S = S.trim(); if (!S.empty()) Ret.push_back(S); } return Ret; } // Initializes Config members by the command line options. void LinkerDriver::readConfigs(opt::InputArgList &Args) { for (auto *Arg : Args.filtered(OPT_L)) Config->SearchPaths.push_back(Arg->getValue()); std::vector RPaths; for (auto *Arg : Args.filtered(OPT_rpath)) RPaths.push_back(Arg->getValue()); if (!RPaths.empty()) Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":"); if (auto *Arg = Args.getLastArg(OPT_m)) { // Parse ELF{32,64}{LE,BE} and CPU type. StringRef S = Arg->getValue(); std::tie(Config->EKind, Config->EMachine, Config->OSABI) = parseEmulation(S); Config->MipsN32Abi = (S == "elf32btsmipn32" || S == "elf32ltsmipn32"); Config->Emulation = S; } Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition); Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic); Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions); Config->Demangle = getArg(Args, OPT_demangle, OPT_no_demangle, true); Config->DisableVerify = Args.hasArg(OPT_disable_verify); Config->EhFrameHdr = Args.hasArg(OPT_eh_frame_hdr); Config->EnableNewDtags = !Args.hasArg(OPT_disable_new_dtags); Config->ExportDynamic = Args.hasArg(OPT_export_dynamic); Config->FatalWarnings = Args.hasArg(OPT_fatal_warnings); Config->GcSections = getArg(Args, OPT_gc_sections, OPT_no_gc_sections, false); Config->GdbIndex = Args.hasArg(OPT_gdb_index); Config->ICF = Args.hasArg(OPT_icf); Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique); Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version); Config->Nostdlib = Args.hasArg(OPT_nostdlib); Config->OMagic = Args.hasArg(OPT_omagic); Config->Pie = getArg(Args, OPT_pie, OPT_nopie, false); Config->PrintGcSections = Args.hasArg(OPT_print_gc_sections); Config->Relocatable = Args.hasArg(OPT_relocatable); Config->Discard = getDiscardOption(Args); Config->SaveTemps = Args.hasArg(OPT_save_temps); Config->SingleRoRx = Args.hasArg(OPT_no_rosegment); Config->Shared = Args.hasArg(OPT_shared); Config->Target1Rel = getArg(Args, OPT_target1_rel, OPT_target1_abs, false); Config->Threads = getArg(Args, OPT_threads, OPT_no_threads, true); Config->Trace = Args.hasArg(OPT_trace); Config->Verbose = Args.hasArg(OPT_verbose); Config->WarnCommon = Args.hasArg(OPT_warn_common); Config->DynamicLinker = getString(Args, OPT_dynamic_linker); Config->Entry = getString(Args, OPT_entry); Config->Fini = getString(Args, OPT_fini, "_fini"); Config->Init = getString(Args, OPT_init, "_init"); Config->LTOAAPipeline = getString(Args, OPT_lto_aa_pipeline); Config->LTONewPmPasses = getString(Args, OPT_lto_newpm_passes); Config->OutputFile = getString(Args, OPT_o); Config->SoName = getString(Args, OPT_soname); Config->Sysroot = getString(Args, OPT_sysroot); Config->Optimize = getInteger(Args, OPT_O, 1); Config->LTOO = getInteger(Args, OPT_lto_O, 2); if (Config->LTOO > 3) error("invalid optimization level for LTO: " + getString(Args, OPT_lto_O)); Config->LTOPartitions = getInteger(Args, OPT_lto_partitions, 1); if (Config->LTOPartitions == 0) error("--lto-partitions: number of threads must be > 0"); Config->ThinLTOJobs = getInteger(Args, OPT_thinlto_jobs, -1u); if (Config->ThinLTOJobs == 0) error("--thinlto-jobs: number of threads must be > 0"); Config->ZCombreloc = !hasZOption(Args, "nocombreloc"); Config->ZExecstack = hasZOption(Args, "execstack"); Config->ZNodelete = hasZOption(Args, "nodelete"); Config->ZNow = hasZOption(Args, "now"); Config->ZOrigin = hasZOption(Args, "origin"); Config->ZRelro = !hasZOption(Args, "norelro"); Config->ZStackSize = getZOptionValue(Args, "stack-size", -1); Config->ZWxneeded = hasZOption(Args, "wxneeded"); Config->OFormatBinary = isOutputFormatBinary(Args); Config->SectionStartMap = getSectionStartMap(Args); Config->SortSection = getSortKind(Args); Config->Target2 = getTarget2Option(Args); Config->UnresolvedSymbols = getUnresolvedSymbolOption(Args); // --omagic is an option to create old-fashioned executables in which // .text segments are writable. Today, the option is still in use to // create special-purpose programs such as boot loaders. It doesn't // make sense to create PT_GNU_RELRO for such executables. if (Config->OMagic) Config->ZRelro = false; if (!Config->Relocatable) Config->Strip = getStripOption(Args); // Config->Pic is true if we are generating position-independent code. Config->Pic = Config->Pie || Config->Shared; if (auto *Arg = Args.getLastArg(OPT_hash_style)) { StringRef S = Arg->getValue(); if (S == "gnu") { Config->GnuHash = true; Config->SysvHash = false; } else if (S == "both") { Config->GnuHash = true; } else if (S != "sysv") error("unknown hash style: " + S); } // Parse --build-id or --build-id=