Index: vendor/lld/dist/COFF/Driver.cpp =================================================================== --- vendor/lld/dist/COFF/Driver.cpp (revision 320020) +++ vendor/lld/dist/COFF/Driver.cpp (revision 320021) @@ -1,1134 +1,1141 @@ //===- 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/BinaryFormat/Magic.h" #include "llvm/Object/ArchiveWriter.h" #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/COFFModuleDefinition.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 "llvm/ToolDrivers/llvm-lib/LibDriver.h" #include #include #include using namespace llvm; using namespace llvm::object; using namespace llvm::COFF; using llvm::sys::Process; namespace lld { namespace coff { Configuration *Config; LinkerDriver *Driver; BumpPtrAllocator BAlloc; StringSaver Saver{BAlloc}; std::vector SpecificAllocBase::Instances; bool link(ArrayRef Args, raw_ostream &Diag) { ErrorCount = 0; ErrorOS = &Diag; Argv0 = Args[0]; Config = make(); Config->ColorDiagnostics = (ErrorOS == &llvm::errs() && Process::StandardErrHasColors()); Driver = make(); Driver->link(Args); return !ErrorCount; } // 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; make>(std::move(MB)); // take ownership 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) error(MBRef.getBufferIdentifier() + ": is not a native COFF file. " "Recompile without /GL"); else 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) error("could not open " + PathStr + ": " + MBOrErr.second.message()); else Driver->addBuffer(std::move(MBOrErr.first)); }); } 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 { error("unknown file type: " + MB.getBufferIdentifier()); return; } Obj->ParentName = ParentName; Symtab.addFile(Obj); log("Loaded " + toString(Obj) + " for " + SymName); } 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: error(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 << 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)) .Default(0); 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(); } static std::string getImplibPath() { if (!Config->Implib.empty()) return Config->Implib; SmallString<128> Out = StringRef(Config->OutputFile); sys::path::replace_extension(Out, ".lib"); return Out.str(); } -std::vector createCOFFShortExportFromConfig() { +static void createImportLibrary() { std::vector Exports; for (Export &E1 : Config->Exports) { COFFShortExport E2; // Use SymbolName, which will have any stdcall or fastcall qualifiers. E2.Name = E1.SymbolName; E2.ExtName = E1.ExtName; E2.Ordinal = E1.Ordinal; E2.Noname = E1.Noname; E2.Data = E1.Data; E2.Private = E1.Private; E2.Constant = E1.Constant; Exports.push_back(E2); } - return Exports; -} -static void createImportLibrary() { - std::vector Exports = createCOFFShortExportFromConfig(); std::string DLLName = sys::path::filename(Config->OutputFile); std::string Path = getImplibPath(); writeImportLibrary(DLLName, Path, Exports, Config->Machine); } static void parseModuleDefs(StringRef Path) { std::unique_ptr MB = check( MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path); COFFModuleDefinition M = check(parseCOFFModuleDefinition(MB->getMemBufferRef(), Config->Machine)); if (Config->OutputFile.empty()) Config->OutputFile = Saver.save(M.OutputFile); if (M.ImageBase) Config->ImageBase = M.ImageBase; if (M.StackReserve) Config->StackReserve = M.StackReserve; if (M.StackCommit) Config->StackCommit = M.StackCommit; if (M.HeapReserve) Config->HeapReserve = M.HeapReserve; if (M.HeapCommit) Config->HeapCommit = M.HeapCommit; if (M.MajorImageVersion) Config->MajorImageVersion = M.MajorImageVersion; if (M.MinorImageVersion) Config->MinorImageVersion = M.MinorImageVersion; if (M.MajorOSVersion) Config->MajorOSVersion = M.MajorOSVersion; if (M.MinorOSVersion) Config->MinorOSVersion = M.MinorOSVersion; for (COFFShortExport E1 : M.Exports) { Export E2; E2.Name = Saver.save(E1.Name); if (E1.isWeak()) E2.ExtName = Saver.save(E1.ExtName); E2.Ordinal = E1.Ordinal; E2.Noname = E1.Noname; E2.Data = E1.Data; E2.Private = E1.Private; E2.Constant = E1.Constant; Config->Exports.push_back(E2); } } std::vector getArchiveMembers(Archive *File) { std::vector V; Error Err = Error::success(); for (const ErrorOr &COrErr : File->children(Err)) { Archive::Child C = check(COrErr, File->getFileName() + ": could not get the child of the archive"); MemoryBufferRef MBRef = check(C.getMemoryBufferRef(), File->getFileName() + ": could not get the buffer for a child of the archive"); V.push_back(MBRef); } if (Err) fatal(File->getFileName() + ": Archive::children failed: " + toString(std::move(Err))); return V; } // A helper function for filterBitcodeFiles. static bool needsRebuilding(MemoryBufferRef MB) { // The MSVC linker doesn't support thin archives, so if it's a thin // archive, we always need to rebuild it. std::unique_ptr File = check(Archive::create(MB), "Failed to read " + MB.getBufferIdentifier()); if (File->isThin()) return true; // Returns true if the archive contains at least one bitcode file. for (MemoryBufferRef Member : getArchiveMembers(File.get())) if (identify_magic(Member.getBuffer()) == file_magic::bitcode) return true; return false; } // Opens a given path as an archive file and removes bitcode files // from them if exists. This function is to appease the MSVC linker as // their linker doesn't like archive files containing non-native // object files. // // If a given archive doesn't contain bitcode files, the archive path // is returned as-is. Otherwise, a new temporary file is created and // its path is returned. static Optional filterBitcodeFiles(StringRef Path, std::vector &TemporaryFiles) { std::unique_ptr MB = check( MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path); MemoryBufferRef MBRef = MB->getMemBufferRef(); file_magic Magic = identify_magic(MBRef.getBuffer()); if (Magic == file_magic::bitcode) return None; if (Magic != file_magic::archive) return Path.str(); if (!needsRebuilding(MBRef)) return Path.str(); std::unique_ptr File = check(Archive::create(MBRef), MBRef.getBufferIdentifier() + ": failed to parse archive"); std::vector New; for (MemoryBufferRef Member : getArchiveMembers(File.get())) if (identify_magic(Member.getBuffer()) != file_magic::bitcode) New.emplace_back(Member); if (New.empty()) return None; log("Creating a temporary archive for " + Path + " to remove bitcode files"); SmallString<128> S; if (auto EC = sys::fs::createTemporaryFile("lld-" + sys::path::stem(Path), ".lib", S)) fatal(EC, "cannot create a temporary file"); std::string Temp = S.str(); TemporaryFiles.push_back(Temp); std::pair Ret = llvm::writeArchive(Temp, New, /*WriteSymtab=*/true, Archive::Kind::K_GNU, /*Deterministics=*/true, /*Thin=*/false); if (Ret.second) error("failed to create a new archive " + S.str() + ": " + Ret.first); return Temp; } // Create response file contents and invoke the MSVC linker. void LinkerDriver::invokeMSVC(opt::InputArgList &Args) { std::string Rsp = "/nologo\n"; std::vector Temps; // Write out archive members that we used in symbol resolution and pass these // to MSVC before any archives, so that MSVC uses the same objects to satisfy // references. for (const auto *O : Symtab.ObjectFiles) { if (O->ParentName.empty()) continue; SmallString<128> S; int Fd; if (auto EC = sys::fs::createTemporaryFile( "lld-" + sys::path::filename(O->ParentName), ".obj", Fd, S)) fatal(EC, "cannot create a temporary file"); raw_fd_ostream OS(Fd, /*shouldClose*/ true); OS << O->MB.getBuffer(); Temps.push_back(S.str()); Rsp += quote(S) + "\n"; } for (auto *Arg : Args) { switch (Arg->getOption().getID()) { case OPT_linkrepro: case OPT_lldmap: case OPT_lldmap_file: case OPT_lldsavetemps: case OPT_msvclto: // LLD-specific options are stripped. break; case OPT_opt: if (!StringRef(Arg->getValue()).startswith("lld")) Rsp += toString(Arg) + " "; break; case OPT_INPUT: { if (Optional Path = doFindFile(Arg->getValue())) { if (Optional S = filterBitcodeFiles(*Path, Temps)) Rsp += quote(*S) + "\n"; continue; } Rsp += quote(Arg->getValue()) + "\n"; break; } default: Rsp += toString(Arg) + "\n"; } } std::vector ObjectFiles = Symtab.compileBitcodeFiles(); runMSVCLinker(Rsp, ObjectFiles); for (StringRef Path : Temps) sys::fs::remove(Path); } 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)); // Parse and evaluate -mllvm options. std::vector V; V.push_back("lld-link (LLVM option parsing)"); for (auto *Arg : Args.filtered(OPT_mllvm)) V.push_back(Arg->getValue()); cl::ParseCommandLineOptions(V.size(), V.data()); // Handle /errorlimit early, because error() depends on it. if (auto *Arg = Args.getLastArg(OPT_errorlimit)) { int N = 20; StringRef S = Arg->getValue(); if (S.getAsInteger(10, N)) error(Arg->getSpelling() + " number expected, but got " + S); Config->ErrorLimit = N; } // 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.tar"); Expected> ErrOrWriter = TarWriter::create(Path, "repro"); if (ErrOrWriter) { Tar = std::move(*ErrOrWriter); } else { error("/linkrepro: failed to open " + Path + ": " + toString(ErrOrWriter.takeError())); } } - if (!Args.hasArgNoClaim(OPT_INPUT)) - fatal("no input files"); + if (!Args.hasArgNoClaim(OPT_INPUT)) { + if (Args.hasArgNoClaim(OPT_deffile)) + Config->NoEntry = true; + else + 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)) Config->NoEntry = true; else error("/noentry must be specified with /dll"); } // 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)) { error("/fixed must not be specified with /dynamicbase"); } else { Config->Relocatable = false; Config->DynamicBase = false; } } if (Args.hasArg(OPT_appcontainer)) Config->AppContainer = true; // 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) error("/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) error("/opt:lldltojobs: invalid job count: " + Jobs); continue; } if (StringRef(S).startswith("lldltopartitions=")) { StringRef N = StringRef(S).substr(17); if (N.getAsInteger(10, Config->LTOPartitions) || Config->LTOPartitions == 0) error("/opt:lldltopartitions: invalid partition count: " + N); continue; } if (S != "ref" && S != "lbr" && S != "nolbr") error("/opt: unknown option: " + S); } } // Handle /lldsavetemps if (Args.hasArg(OPT_lldsavetemps)) Config->SaveTemps = true; // 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_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->MapFile = getMapFile(Args); if (ErrorCount) return; // 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) { warn("/machine is not specified. x64 is assumed"); 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 (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); log("Entry name inferred: " + S); } // 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(Arg->getValue()); + } + + // Handle generation of import library from a def file. + if (!Args.hasArgNoClaim(OPT_INPUT)) { + fixupExports(); + createImportLibrary(); + exit(0); } // 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 name if neither /out or /def set it. if (Config->OutputFile.empty()) { Config->OutputFile = getOutputPath((*Args.filtered(OPT_INPUT).begin())->getValue()); } // Put the PDB next to the image if no /pdb flag was passed. if (Config->Debug && Config->PDBPath.empty()) { Config->PDBPath = Config->OutputFile; sys::path::replace_extension(Config->PDBPath, ".pdb"); } // Disable PDB generation if the user requested it. if (Args.hasArg(OPT_nopdb)) Config->PDBPath = ""; // 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()); if (ErrorCount) return; // If /msvclto is given, we use the MSVC linker to link LTO output files. // This is useful because MSVC link.exe can generate complete PDBs. if (Args.hasArg(OPT_msvclto)) { invokeMSVC(Args); exit(0); } // 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) error("/safeseh: " + File->getName() + " is not compatible with SEH"); if (ErrorCount) return; } // Windows specific -- when we are creating a .dll file, we also // need to create a .lib file. if (!Config->Exports.empty() || Config->DLL) { fixupExports(); createImportLibrary(); 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); // Call exit to avoid calling destructors. exit(0); } } // namespace coff } // namespace lld Index: vendor/lld/dist/COFF/DriverUtils.cpp =================================================================== --- vendor/lld/dist/COFF/DriverUtils.cpp (revision 320020) +++ vendor/lld/dist/COFF/DriverUtils.cpp (revision 320021) @@ -1,737 +1,737 @@ //===- DriverUtils.cpp ----------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file contains utility functions for the driver. Because there // are so many small functions, we created this separate file to make // Driver.cpp less cluttered. // //===----------------------------------------------------------------------===// #include "Config.h" #include "Driver.h" #include "Error.h" #include "Memory.h" #include "Symbols.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Object/COFF.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" #include using namespace llvm::COFF; using namespace llvm; using llvm::cl::ExpandResponseFiles; using llvm::cl::TokenizeWindowsCommandLine; using llvm::sys::Process; namespace lld { namespace coff { namespace { class Executor { public: explicit Executor(StringRef S) : Prog(Saver.save(S)) {} void add(StringRef S) { Args.push_back(Saver.save(S)); } void add(std::string &S) { Args.push_back(Saver.save(S)); } void add(Twine S) { Args.push_back(Saver.save(S)); } void add(const char *S) { Args.push_back(Saver.save(S)); } void run() { ErrorOr ExeOrErr = sys::findProgramByName(Prog); if (auto EC = ExeOrErr.getError()) fatal(EC, "unable to find " + Prog + " in PATH: "); StringRef Exe = Saver.save(*ExeOrErr); Args.insert(Args.begin(), Exe); std::vector Vec; for (StringRef S : Args) Vec.push_back(S.data()); Vec.push_back(nullptr); if (sys::ExecuteAndWait(Args[0], Vec.data()) != 0) fatal("ExecuteAndWait failed: " + llvm::join(Args.begin(), Args.end(), " ")); } private: StringRef Prog; std::vector Args; }; } // anonymous namespace // Returns /machine's value. MachineTypes getMachineType(StringRef S) { MachineTypes MT = StringSwitch(S.lower()) .Cases("x64", "amd64", AMD64) .Cases("x86", "i386", I386) .Case("arm", ARMNT) .Default(IMAGE_FILE_MACHINE_UNKNOWN); if (MT != IMAGE_FILE_MACHINE_UNKNOWN) return MT; fatal("unknown /machine argument: " + S); } StringRef machineToStr(MachineTypes MT) { switch (MT) { case ARMNT: return "arm"; case AMD64: return "x64"; case I386: return "x86"; default: llvm_unreachable("unknown machine type"); } } // Parses a string in the form of "[,]". void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size) { StringRef S1, S2; std::tie(S1, S2) = Arg.split(','); if (S1.getAsInteger(0, *Addr)) fatal("invalid number: " + S1); if (Size && !S2.empty() && S2.getAsInteger(0, *Size)) fatal("invalid number: " + S2); } // Parses a string in the form of "[.]". // If second number is not present, Minor is set to 0. void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor) { StringRef S1, S2; std::tie(S1, S2) = Arg.split('.'); if (S1.getAsInteger(0, *Major)) fatal("invalid number: " + S1); *Minor = 0; if (!S2.empty() && S2.getAsInteger(0, *Minor)) fatal("invalid number: " + S2); } // Parses a string in the form of "[,[.]]". void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major, uint32_t *Minor) { StringRef SysStr, Ver; std::tie(SysStr, Ver) = Arg.split(','); *Sys = StringSwitch(SysStr.lower()) .Case("boot_application", IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION) .Case("console", IMAGE_SUBSYSTEM_WINDOWS_CUI) .Case("efi_application", IMAGE_SUBSYSTEM_EFI_APPLICATION) .Case("efi_boot_service_driver", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) .Case("efi_rom", IMAGE_SUBSYSTEM_EFI_ROM) .Case("efi_runtime_driver", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) .Case("native", IMAGE_SUBSYSTEM_NATIVE) .Case("posix", IMAGE_SUBSYSTEM_POSIX_CUI) .Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI) .Default(IMAGE_SUBSYSTEM_UNKNOWN); if (*Sys == IMAGE_SUBSYSTEM_UNKNOWN) fatal("unknown subsystem: " + SysStr); if (!Ver.empty()) parseVersion(Ver, Major, Minor); } // Parse a string of the form of "=". // Results are directly written to Config. void parseAlternateName(StringRef S) { StringRef From, To; std::tie(From, To) = S.split('='); if (From.empty() || To.empty()) fatal("/alternatename: invalid argument: " + S); auto It = Config->AlternateNames.find(From); if (It != Config->AlternateNames.end() && It->second != To) fatal("/alternatename: conflicts: " + S); Config->AlternateNames.insert(It, std::make_pair(From, To)); } // Parse a string of the form of "=". // Results are directly written to Config. void parseMerge(StringRef S) { StringRef From, To; std::tie(From, To) = S.split('='); if (From.empty() || To.empty()) fatal("/merge: invalid argument: " + S); auto Pair = Config->Merge.insert(std::make_pair(From, To)); bool Inserted = Pair.second; if (!Inserted) { StringRef Existing = Pair.first->second; if (Existing != To) warn(S + ": already merged into " + Existing); } } static uint32_t parseSectionAttributes(StringRef S) { uint32_t Ret = 0; for (char C : S.lower()) { switch (C) { case 'd': Ret |= IMAGE_SCN_MEM_DISCARDABLE; break; case 'e': Ret |= IMAGE_SCN_MEM_EXECUTE; break; case 'k': Ret |= IMAGE_SCN_MEM_NOT_CACHED; break; case 'p': Ret |= IMAGE_SCN_MEM_NOT_PAGED; break; case 'r': Ret |= IMAGE_SCN_MEM_READ; break; case 's': Ret |= IMAGE_SCN_MEM_SHARED; break; case 'w': Ret |= IMAGE_SCN_MEM_WRITE; break; default: fatal("/section: invalid argument: " + S); } } return Ret; } // Parses /section option argument. void parseSection(StringRef S) { StringRef Name, Attrs; std::tie(Name, Attrs) = S.split(','); if (Name.empty() || Attrs.empty()) fatal("/section: invalid argument: " + S); Config->Section[Name] = parseSectionAttributes(Attrs); } // Parses a string in the form of "EMBED[,=]|NO". // Results are directly written to Config. void parseManifest(StringRef Arg) { if (Arg.equals_lower("no")) { Config->Manifest = Configuration::No; return; } if (!Arg.startswith_lower("embed")) fatal("invalid option " + Arg); Config->Manifest = Configuration::Embed; Arg = Arg.substr(strlen("embed")); if (Arg.empty()) return; if (!Arg.startswith_lower(",id=")) fatal("invalid option " + Arg); Arg = Arg.substr(strlen(",id=")); if (Arg.getAsInteger(0, Config->ManifestID)) fatal("invalid option " + Arg); } // Parses a string in the form of "level=|uiAccess=|NO". // Results are directly written to Config. void parseManifestUAC(StringRef Arg) { if (Arg.equals_lower("no")) { Config->ManifestUAC = false; return; } for (;;) { Arg = Arg.ltrim(); if (Arg.empty()) return; if (Arg.startswith_lower("level=")) { Arg = Arg.substr(strlen("level=")); std::tie(Config->ManifestLevel, Arg) = Arg.split(" "); continue; } if (Arg.startswith_lower("uiaccess=")) { Arg = Arg.substr(strlen("uiaccess=")); std::tie(Config->ManifestUIAccess, Arg) = Arg.split(" "); continue; } fatal("invalid option " + Arg); } } // Quote each line with "". Existing double-quote is converted // to two double-quotes. static void quoteAndPrint(raw_ostream &Out, StringRef S) { while (!S.empty()) { StringRef Line; std::tie(Line, S) = S.split("\n"); if (Line.empty()) continue; Out << '\"'; for (int I = 0, E = Line.size(); I != E; ++I) { if (Line[I] == '\"') { Out << "\"\""; } else { Out << Line[I]; } } Out << "\"\n"; } } // An RAII temporary file class that automatically removes a temporary file. namespace { class TemporaryFile { public: TemporaryFile(StringRef Prefix, StringRef Extn, StringRef Contents = "") { SmallString<128> S; if (auto EC = sys::fs::createTemporaryFile("lld-" + Prefix, Extn, S)) fatal(EC, "cannot create a temporary file"); Path = S.str(); if (!Contents.empty()) { std::error_code EC; raw_fd_ostream OS(Path, EC, sys::fs::F_None); if (EC) fatal(EC, "failed to open " + Path); OS << Contents; } } TemporaryFile(TemporaryFile &&Obj) { std::swap(Path, Obj.Path); } ~TemporaryFile() { if (Path.empty()) return; if (sys::fs::remove(Path)) fatal("failed to remove " + Path); } // Returns a memory buffer of this temporary file. // Note that this function does not leave the file open, // so it is safe to remove the file immediately after this function // is called (you cannot remove an opened file on Windows.) std::unique_ptr getMemoryBuffer() { // IsVolatileSize=true forces MemoryBuffer to not use mmap(). return check(MemoryBuffer::getFile(Path, /*FileSize=*/-1, /*RequiresNullTerminator=*/false, /*IsVolatileSize=*/true), "could not open " + Path); } std::string Path; }; } // Create the default manifest file as a temporary file. TemporaryFile createDefaultXml() { // Create a temporary file. TemporaryFile File("defaultxml", "manifest"); // Open the temporary file for writing. std::error_code EC; raw_fd_ostream OS(File.Path, EC, sys::fs::F_Text); if (EC) fatal(EC, "failed to open " + File.Path); // Emit the XML. Note that we do *not* verify that the XML attributes are // syntactically correct. This is intentional for link.exe compatibility. OS << "\n" << "\n"; if (Config->ManifestUAC) { OS << " \n" << " \n" << " \n" << " \n" << " \n" << " \n" << " \n"; if (!Config->ManifestDependency.empty()) { OS << " \n" << " \n" << " ManifestDependency << " />\n" << " \n" << " \n"; } } OS << "\n"; OS.close(); return File; } static std::string readFile(StringRef Path) { std::unique_ptr MB = check(MemoryBuffer::getFile(Path), "could not open " + Path); return MB->getBuffer(); } static std::string createManifestXml() { // Create the default manifest file. TemporaryFile File1 = createDefaultXml(); if (Config->ManifestInput.empty()) return readFile(File1.Path); // If manifest files are supplied by the user using /MANIFESTINPUT // option, we need to merge them with the default manifest. TemporaryFile File2("user", "manifest"); Executor E("mt.exe"); E.add("/manifest"); E.add(File1.Path); for (StringRef Filename : Config->ManifestInput) { E.add("/manifest"); E.add(Filename); } E.add("/nologo"); E.add("/out:" + StringRef(File2.Path)); E.run(); return readFile(File2.Path); } // Create a resource file containing a manifest XML. std::unique_ptr createManifestRes() { // Create a temporary file for the resource script file. TemporaryFile RCFile("manifest", "rc"); // Open the temporary file for writing. std::error_code EC; raw_fd_ostream Out(RCFile.Path, EC, sys::fs::F_Text); if (EC) fatal(EC, "failed to open " + RCFile.Path); // Write resource script to the RC file. Out << "#define LANG_ENGLISH 9\n" << "#define SUBLANG_DEFAULT 1\n" << "#define APP_MANIFEST " << Config->ManifestID << "\n" << "#define RT_MANIFEST 24\n" << "LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT\n" << "APP_MANIFEST RT_MANIFEST {\n"; quoteAndPrint(Out, createManifestXml()); Out << "}\n"; Out.close(); // Create output resource file. TemporaryFile ResFile("output-resource", "res"); Executor E("rc.exe"); E.add("/fo"); E.add(ResFile.Path); E.add("/nologo"); E.add(RCFile.Path); E.run(); return ResFile.getMemoryBuffer(); } void createSideBySideManifest() { std::string Path = Config->ManifestFile; if (Path == "") Path = Config->OutputFile + ".manifest"; std::error_code EC; raw_fd_ostream Out(Path, EC, sys::fs::F_Text); if (EC) fatal(EC, "failed to create manifest"); Out << createManifestXml(); } // Parse a string in the form of // "[=][,@ordinal[,NONAME]][,DATA][,PRIVATE]" // or "=.". // Used for parsing /export arguments. Export parseExport(StringRef Arg) { Export E; StringRef Rest; std::tie(E.Name, Rest) = Arg.split(","); if (E.Name.empty()) goto err; if (E.Name.find('=') != StringRef::npos) { StringRef X, Y; std::tie(X, Y) = E.Name.split("="); // If "=.". if (Y.find(".") != StringRef::npos) { E.Name = X; E.ForwardTo = Y; return E; } E.ExtName = X; E.Name = Y; if (E.Name.empty()) goto err; } // If "=[,@ordinal[,NONAME]][,DATA][,PRIVATE]" while (!Rest.empty()) { StringRef Tok; std::tie(Tok, Rest) = Rest.split(","); if (Tok.equals_lower("noname")) { if (E.Ordinal == 0) goto err; E.Noname = true; continue; } if (Tok.equals_lower("data")) { E.Data = true; continue; } if (Tok.equals_lower("constant")) { E.Constant = true; continue; } if (Tok.equals_lower("private")) { E.Private = true; continue; } if (Tok.startswith("@")) { int32_t Ord; if (Tok.substr(1).getAsInteger(0, Ord)) goto err; if (Ord <= 0 || 65535 < Ord) goto err; E.Ordinal = Ord; continue; } goto err; } return E; err: fatal("invalid /export: " + Arg); } static StringRef undecorate(StringRef Sym) { if (Config->Machine != I386) return Sym; return Sym.startswith("_") ? Sym.substr(1) : Sym; } // Performs error checking on all /export arguments. // It also sets ordinals. void fixupExports() { // Symbol ordinals must be unique. std::set Ords; for (Export &E : Config->Exports) { if (E.Ordinal == 0) continue; if (!Ords.insert(E.Ordinal).second) fatal("duplicate export ordinal: " + E.Name); } for (Export &E : Config->Exports) { SymbolBody *Sym = E.Sym; - if (!E.ForwardTo.empty()) { + if (!E.ForwardTo.empty() || !Sym) { E.SymbolName = E.Name; } else { if (auto *U = dyn_cast(Sym)) if (U->WeakAlias) Sym = U->WeakAlias; E.SymbolName = Sym->getName(); } } for (Export &E : Config->Exports) { if (!E.ForwardTo.empty()) { E.ExportName = undecorate(E.Name); } else { E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName); } } // Uniquefy by name. std::map Map; std::vector V; for (Export &E : Config->Exports) { auto Pair = Map.insert(std::make_pair(E.ExportName, &E)); bool Inserted = Pair.second; if (Inserted) { V.push_back(E); continue; } Export *Existing = Pair.first->second; if (E == *Existing || E.Name != Existing->Name) continue; warn("duplicate /export option: " + E.Name); } Config->Exports = std::move(V); // Sort by name. std::sort(Config->Exports.begin(), Config->Exports.end(), [](const Export &A, const Export &B) { return A.ExportName < B.ExportName; }); } void assignExportOrdinals() { // Assign unique ordinals if default (= 0). uint16_t Max = 0; for (Export &E : Config->Exports) Max = std::max(Max, E.Ordinal); for (Export &E : Config->Exports) if (E.Ordinal == 0) E.Ordinal = ++Max; } // Parses a string in the form of "key=value" and check // if value matches previous values for the same key. void checkFailIfMismatch(StringRef Arg) { StringRef K, V; std::tie(K, V) = Arg.split('='); if (K.empty() || V.empty()) fatal("/failifmismatch: invalid argument: " + Arg); StringRef Existing = Config->MustMatch[K]; if (!Existing.empty() && V != Existing) fatal("/failifmismatch: mismatch detected: " + Existing + " and " + V + " for key " + K); Config->MustMatch[K] = V; } // Convert Windows resource files (.res files) to a .obj file // using cvtres.exe. std::unique_ptr convertResToCOFF(const std::vector &MBs) { // Create an output file path. TemporaryFile File("resource-file", "obj"); // Execute cvtres.exe. Executor E("cvtres.exe"); E.add("/machine:" + machineToStr(Config->Machine)); E.add("/readonly"); E.add("/nologo"); E.add("/out:" + Twine(File.Path)); // We must create new files because the memory buffers we have may have no // underlying file still existing on the disk. // It happens if it was created from a TemporaryFile, which usually delete // the file just after creating the MemoryBuffer. std::vector ResFiles; ResFiles.reserve(MBs.size()); for (MemoryBufferRef MB : MBs) { // We store the temporary file in a vector to avoid deletion // before running cvtres ResFiles.emplace_back("resource-file", "res"); TemporaryFile& ResFile = ResFiles.back(); // Write the content of the resource in a temporary file std::error_code EC; raw_fd_ostream OS(ResFile.Path, EC, sys::fs::F_None); if (EC) fatal(EC, "failed to open " + ResFile.Path); OS << MB.getBuffer(); OS.close(); E.add(ResFile.Path); } E.run(); return File.getMemoryBuffer(); } // Run MSVC link.exe for given in-memory object files. // Command line options are copied from those given to LLD. // This is for the /msvclto option. void runMSVCLinker(std::string Rsp, ArrayRef Objects) { // Write the in-memory object files to disk. std::vector Temps; for (StringRef S : Objects) { Temps.emplace_back("lto", "obj", S); Rsp += quote(Temps.back().Path) + "\n"; } log("link.exe " + Rsp); // Run MSVC link.exe. Temps.emplace_back("lto", "rsp", Rsp); Executor E("link.exe"); E.add(Twine("@" + Temps.back().Path)); E.run(); } // Create OptTable // Create prefix string literals used in Options.td #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; #include "Options.inc" #undef PREFIX // Create table mapping all options defined in Options.td static const llvm::opt::OptTable::Info infoTable[] = { #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \ { \ X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \ OPT_##GROUP, OPT_##ALIAS, X6 \ }, #include "Options.inc" #undef OPTION }; class COFFOptTable : public llvm::opt::OptTable { public: COFFOptTable() : OptTable(infoTable, true) {} }; // Parses a given list of options. opt::InputArgList ArgParser::parse(ArrayRef ArgsArr) { // First, replace respnose files (@-style options). std::vector Argv = replaceResponseFiles(ArgsArr); // Make InputArgList from string vectors. COFFOptTable Table; unsigned MissingIndex; unsigned MissingCount; opt::InputArgList Args = Table.ParseArgs(Argv, MissingIndex, MissingCount); // Print the real command line if response files are expanded. if (Args.hasArg(OPT_verbose) && ArgsArr.size() != Argv.size()) { std::string Msg = "Command line:"; for (const char *S : Argv) Msg += " " + std::string(S); message(Msg); } if (MissingCount) fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); for (auto *Arg : Args.filtered(OPT_UNKNOWN)) warn("ignoring unknown argument: " + Arg->getSpelling()); return Args; } // link.exe has an interesting feature. If LINK or _LINK_ environment // variables exist, their contents are handled as command line strings. // So you can pass extra arguments using them. opt::InputArgList ArgParser::parseLINK(std::vector Args) { // Concatenate LINK env and command line arguments, and then parse them. if (Optional S = Process::GetEnv("LINK")) { std::vector V = tokenize(*S); Args.insert(Args.begin(), V.begin(), V.end()); } if (Optional S = Process::GetEnv("_LINK_")) { std::vector V = tokenize(*S); Args.insert(Args.begin(), V.begin(), V.end()); } return parse(Args); } std::vector ArgParser::tokenize(StringRef S) { SmallVector Tokens; cl::TokenizeWindowsCommandLine(S, Saver, Tokens); return std::vector(Tokens.begin(), Tokens.end()); } // Creates a new command line by replacing options starting with '@' // character. '@' is replaced by the file's contents. std::vector ArgParser::replaceResponseFiles(std::vector Argv) { SmallVector Tokens(Argv.data(), Argv.data() + Argv.size()); ExpandResponseFiles(Saver, TokenizeWindowsCommandLine, Tokens); return std::vector(Tokens.begin(), Tokens.end()); } void printHelp(const char *Argv0) { COFFOptTable Table; Table.PrintHelp(outs(), Argv0, "LLVM Linker", false); } } // namespace coff } // namespace lld Index: vendor/lld/dist/COFF/InputFiles.h =================================================================== --- vendor/lld/dist/COFF/InputFiles.h (revision 320020) +++ vendor/lld/dist/COFF/InputFiles.h (revision 320021) @@ -1,211 +1,223 @@ //===- 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 "Config.h" #include "lld/Core/LLVM.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/LTO/LTO.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" #include "llvm/Support/StringSaver.h" #include #include #include +namespace llvm { +namespace pdb { +class DbiModuleDescriptorBuilder; +} +} + namespace lld { namespace coff { 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; } MemoryBufferRef MB; // 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) {} 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; + + // Pointer to the PDB module descriptor builder. Various debug info records + // will reference object files by "module index", which is here. Things like + // source files and section contributions are also recorded here. Will be null + // if we are not producing a PDB. + llvm::pdb::DbiModuleDescriptorBuilder *ModuleDBI = nullptr; private: void initializeChunks(); void initializeSymbols(); void initializeSEH(); SymbolBody *createDefined(COFFSymbolRef Sym, const void *Aux, bool IsFirst); SymbolBody *createUndefined(COFFSymbolRef Sym); std::unique_ptr COFFObj; 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), Live(!Config->DoGC) {} static bool classof(const InputFile *F) { return F->kind() == ImportKind; } DefinedImportData *ImpSym = nullptr; DefinedImportData *ConstSym = nullptr; DefinedImportThunk *ThunkSym = nullptr; std::string DLLName; private: void parse() override; public: StringRef ExternalName; const coff_import_header *Hdr; Chunk *Location = nullptr; // We want to eliminate dllimported symbols if no one actually refers them. // This "Live" bit is used to keep track of which import library members // are actually in use. // // If the Live bit is turned off by MarkLive, Writer will ignore dllimported // symbols provided by this import library member. bool Live; }; // 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 Obj; private: void parse() override; std::vector SymbolBodies; }; } // namespace coff std::string toString(coff::InputFile *File); } // namespace lld #endif Index: vendor/lld/dist/COFF/PDB.cpp =================================================================== --- vendor/lld/dist/COFF/PDB.cpp (revision 320020) +++ vendor/lld/dist/COFF/PDB.cpp (revision 320021) @@ -1,233 +1,245 @@ //===- PDB.cpp ------------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "PDB.h" #include "Chunks.h" #include "Config.h" #include "Error.h" #include "SymbolTable.h" #include "Symbols.h" #include "llvm/DebugInfo/CodeView/CVDebugRecord.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/SymbolDumper.h" #include "llvm/DebugInfo/CodeView/TypeDatabase.h" #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" #include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" #include "llvm/Object/COFF.h" #include "llvm/Support/BinaryByteStream.h" #include "llvm/Support/Endian.h" #include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/ScopedPrinter.h" #include using namespace lld; using namespace lld::coff; using namespace llvm; using namespace llvm::codeview; using namespace llvm::support; using namespace llvm::support::endian; using llvm::object::coff_section; static ExitOnError ExitOnErr; // Returns a list of all SectionChunks. -static std::vector getInputSections(SymbolTable *Symtab) { - std::vector V; +static void addSectionContribs(SymbolTable *Symtab, pdb::DbiStreamBuilder &DbiBuilder) { for (Chunk *C : Symtab->getChunks()) if (auto *SC = dyn_cast(C)) - V.push_back(*SC->Header); - return V; + DbiBuilder.addSectionContrib(SC->File->ModuleDBI, SC->Header); } static SectionChunk *findByName(std::vector &Sections, StringRef Name) { for (SectionChunk *C : Sections) if (C->getSectionName() == Name) return C; return nullptr; } static ArrayRef getDebugSection(ObjectFile *File, StringRef SecName) { SectionChunk *Sec = findByName(File->getDebugChunks(), SecName); if (!Sec) return {}; // First 4 bytes are section magic. ArrayRef Data = Sec->getContents(); if (Data.size() < 4) fatal(SecName + " too short"); if (read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC) fatal(SecName + " has an invalid magic"); return Data.slice(4); } static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder, codeview::TypeTableBuilder &TypeTable) { // Start the TPI or IPI stream header. TpiBuilder.setVersionHeader(pdb::PdbTpiV80); // Flatten the in memory type table. TypeTable.ForEachRecord([&](TypeIndex TI, ArrayRef Rec) { // FIXME: Hash types. TpiBuilder.addTypeRecord(Rec, None); }); } -// Merge .debug$T sections into IpiData and TpiData. -static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder, - codeview::TypeTableBuilder &TypeTable, - codeview::TypeTableBuilder &IDTable) { +// Add all object files to the PDB. Merge .debug$T sections into IpiData and +// TpiData. +static void addObjectsToPDB(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder, + codeview::TypeTableBuilder &TypeTable, + codeview::TypeTableBuilder &IDTable) { // Follow type servers. If the same type server is encountered more than // once for this instance of `PDBTypeServerHandler` (for example if many // object files reference the same TypeServer), the types from the // TypeServer will only be visited once. pdb::PDBTypeServerHandler Handler; // Visit all .debug$T sections to add them to Builder. for (ObjectFile *File : Symtab->ObjectFiles) { + // Add a module descriptor for every object file. We need to put an absolute + // path to the object into the PDB. If this is a plain object, we make its + // path absolute. If it's an object in an archive, we make the archive path + // absolute. + bool InArchive = !File->ParentName.empty(); + SmallString<128> Path = InArchive ? File->ParentName : File->getName(); + sys::fs::make_absolute(Path); + StringRef Name = InArchive ? File->getName() : StringRef(Path); + File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name)); + File->ModuleDBI->setObjFileName(Path); + + // FIXME: Walk the .debug$S sections and add them. Do things like recording + // source files. + ArrayRef Data = getDebugSection(File, ".debug$T"); if (Data.empty()) continue; BinaryByteStream Stream(Data, support::little); codeview::CVTypeArray Types; BinaryStreamReader Reader(Stream); SmallVector SourceToDest; Handler.addSearchPath(llvm::sys::path::parent_path(File->getName())); if (auto EC = Reader.readArray(Types, Reader.getLength())) fatal(EC, "Reader::readArray failed"); if (auto Err = codeview::mergeTypeAndIdRecords( IDTable, TypeTable, SourceToDest, &Handler, Types)) fatal(Err, "codeview::mergeTypeStreams failed"); } // Construct TPI stream contents. addTypeInfo(Builder.getTpiBuilder(), TypeTable); // Construct IPI stream contents. addTypeInfo(Builder.getIpiBuilder(), IDTable); } static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) { ListScope LS(W, "DebugT"); ArrayRef Data = getDebugSection(File, ".debug$T"); if (Data.empty()) return; LazyRandomTypeCollection Types(Data, 100); TypeDumpVisitor TDV(Types, &W, false); // Use a default implementation that does not follow type servers and instead // just dumps the contents of the TypeServer2 record. if (auto EC = codeview::visitTypeStream(Types, TDV)) fatal(EC, "CVTypeDumper::dump failed"); } static void dumpDebugS(ScopedPrinter &W, ObjectFile *File) { ListScope LS(W, "DebugS"); ArrayRef Data = getDebugSection(File, ".debug$S"); if (Data.empty()) return; BinaryByteStream Stream(Data, llvm::support::little); CVSymbolArray Symbols; BinaryStreamReader Reader(Stream); if (auto EC = Reader.readArray(Symbols, Reader.getLength())) fatal(EC, "StreamReader.readArray failed"); TypeDatabase TDB(0); CVSymbolDumper SymbolDumper(W, TDB, CodeViewContainer::ObjectFile, nullptr, false); if (auto EC = SymbolDumper.dump(Symbols)) fatal(EC, "CVSymbolDumper::dump failed"); } // Dump CodeView debug info. This is for debugging. static void dumpCodeView(SymbolTable *Symtab) { ScopedPrinter W(outs()); for (ObjectFile *File : Symtab->ObjectFiles) { dumpDebugT(W, File); dumpDebugS(W, File); } } // Creates a PDB file. void coff::createPDB(StringRef Path, SymbolTable *Symtab, ArrayRef SectionTable, const llvm::codeview::DebugInfo *DI) { if (Config->DumpPdb) dumpCodeView(Symtab); BumpPtrAllocator Alloc; pdb::PDBFileBuilder Builder(Alloc); ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize // Create streams in MSF for predefined streams, namely // PDB, TPI, DBI and IPI. for (int I = 0; I < (int)pdb::kSpecialStreamCount; ++I) ExitOnErr(Builder.getMsfBuilder().addStream(0)); // Add an Info stream. auto &InfoBuilder = Builder.getInfoBuilder(); InfoBuilder.setAge(DI ? DI->PDB70.Age : 0); pdb::PDB_UniqueId uuid{}; if (DI) memcpy(&uuid, &DI->PDB70.Signature, sizeof(uuid)); InfoBuilder.setGuid(uuid); // Should be the current time, but set 0 for reproducibilty. InfoBuilder.setSignature(0); InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70); // Add an empty DPI stream. - auto &DbiBuilder = Builder.getDbiBuilder(); + pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); DbiBuilder.setVersionHeader(pdb::PdbDbiV110); codeview::TypeTableBuilder TypeTable(BAlloc); codeview::TypeTableBuilder IDTable(BAlloc); - mergeDebugT(Symtab, Builder, TypeTable, IDTable); + addObjectsToPDB(Symtab, Builder, TypeTable, IDTable); // Add Section Contributions. - std::vector Contribs = - pdb::DbiStreamBuilder::createSectionContribs(getInputSections(Symtab)); - DbiBuilder.setSectionContribs(Contribs); + addSectionContribs(Symtab, DbiBuilder); // Add Section Map stream. ArrayRef Sections = { (const object::coff_section *)SectionTable.data(), SectionTable.size() / sizeof(object::coff_section)}; std::vector SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections); DbiBuilder.setSectionMap(SectionMap); ExitOnErr(DbiBuilder.addModuleInfo("* Linker *")); // Add COFF section header stream. ExitOnErr( DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable)); // Write to a file. ExitOnErr(Builder.commit(Path)); } Index: vendor/lld/dist/ELF/Arch/AArch64.cpp =================================================================== --- vendor/lld/dist/ELF/Arch/AArch64.cpp (nonexistent) +++ vendor/lld/dist/ELF/Arch/AArch64.cpp (revision 320021) @@ -0,0 +1,374 @@ +//===- AArch64.cpp --------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "Memory.h" +#include "Symbols.h" +#include "SyntheticSections.h" +#include "Target.h" +#include "Thunks.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::support::endian; +using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; + +// Page(Expr) is the page address of the expression Expr, defined +// as (Expr & ~0xFFF). (This applies even if the machine page size +// supported by the platform has a different value.) +uint64_t elf::getAArch64Page(uint64_t Expr) { + return Expr & ~static_cast(0xFFF); +} + +namespace { +class AArch64 final : public TargetInfo { +public: + AArch64(); + RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const override; + bool isPicRel(uint32_t Type) const override; + void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; + void writePltHeader(uint8_t *Buf) const override; + void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, + int32_t Index, unsigned RelOff) const override; + bool usesOnlyLowPageBits(uint32_t Type) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, + RelExpr Expr) const override; + void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; +}; +} // namespace + +AArch64::AArch64() { + CopyRel = R_AARCH64_COPY; + RelativeRel = R_AARCH64_RELATIVE; + IRelativeRel = R_AARCH64_IRELATIVE; + GotRel = R_AARCH64_GLOB_DAT; + PltRel = R_AARCH64_JUMP_SLOT; + TlsDescRel = R_AARCH64_TLSDESC; + TlsGotRel = R_AARCH64_TLS_TPREL64; + GotEntrySize = 8; + GotPltEntrySize = 8; + PltEntrySize = 16; + PltHeaderSize = 32; + DefaultMaxPageSize = 65536; + + // It doesn't seem to be documented anywhere, but tls on aarch64 uses variant + // 1 of the tls structures and the tcb size is 16. + TcbSize = 16; +} + +RelExpr AArch64::getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const { + switch (Type) { + default: + return R_ABS; + case R_AARCH64_TLSDESC_ADR_PAGE21: + return R_TLSDESC_PAGE; + case R_AARCH64_TLSDESC_LD64_LO12: + case R_AARCH64_TLSDESC_ADD_LO12: + return R_TLSDESC; + case R_AARCH64_TLSDESC_CALL: + return R_TLSDESC_CALL; + case R_AARCH64_TLSLE_ADD_TPREL_HI12: + case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + return R_TLS; + case R_AARCH64_CALL26: + case R_AARCH64_CONDBR19: + case R_AARCH64_JUMP26: + case R_AARCH64_TSTBR14: + return R_PLT_PC; + case R_AARCH64_PREL16: + case R_AARCH64_PREL32: + case R_AARCH64_PREL64: + case R_AARCH64_ADR_PREL_LO21: + return R_PC; + case R_AARCH64_ADR_PREL_PG_HI21: + return R_PAGE_PC; + case R_AARCH64_LD64_GOT_LO12_NC: + case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + return R_GOT; + case R_AARCH64_ADR_GOT_PAGE: + case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: + return R_GOT_PAGE_PC; + case R_AARCH64_NONE: + return R_NONE; + } +} + +RelExpr AArch64::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, + RelExpr Expr) const { + if (Expr == R_RELAX_TLS_GD_TO_IE) { + if (Type == R_AARCH64_TLSDESC_ADR_PAGE21) + return R_RELAX_TLS_GD_TO_IE_PAGE_PC; + return R_RELAX_TLS_GD_TO_IE_ABS; + } + return Expr; +} + +bool AArch64::usesOnlyLowPageBits(uint32_t Type) const { + switch (Type) { + default: + return false; + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LD64_GOT_LO12_NC: + case R_AARCH64_LDST128_ABS_LO12_NC: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_TLSDESC_ADD_LO12: + case R_AARCH64_TLSDESC_LD64_LO12: + case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + return true; + } +} + +bool AArch64::isPicRel(uint32_t Type) const { + return Type == R_AARCH64_ABS32 || Type == R_AARCH64_ABS64; +} + +void AArch64::writeGotPlt(uint8_t *Buf, const SymbolBody &) const { + write64le(Buf, InX::Plt->getVA()); +} + +void AArch64::writePltHeader(uint8_t *Buf) const { + const uint8_t PltData[] = { + 0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]! + 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[2])) + 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[2]))] + 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.plt.got[2])) + 0x20, 0x02, 0x1f, 0xd6, // br x17 + 0x1f, 0x20, 0x03, 0xd5, // nop + 0x1f, 0x20, 0x03, 0xd5, // nop + 0x1f, 0x20, 0x03, 0xd5 // nop + }; + memcpy(Buf, PltData, sizeof(PltData)); + + uint64_t Got = InX::GotPlt->getVA(); + uint64_t Plt = InX::Plt->getVA(); + relocateOne(Buf + 4, R_AARCH64_ADR_PREL_PG_HI21, + getAArch64Page(Got + 16) - getAArch64Page(Plt + 4)); + relocateOne(Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, Got + 16); + relocateOne(Buf + 12, R_AARCH64_ADD_ABS_LO12_NC, Got + 16); +} + +void AArch64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const { + const uint8_t Inst[] = { + 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[n])) + 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[n]))] + 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.plt.got[n])) + 0x20, 0x02, 0x1f, 0xd6 // br x17 + }; + memcpy(Buf, Inst, sizeof(Inst)); + + relocateOne(Buf, R_AARCH64_ADR_PREL_PG_HI21, + getAArch64Page(GotPltEntryAddr) - getAArch64Page(PltEntryAddr)); + relocateOne(Buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, GotPltEntryAddr); + relocateOne(Buf + 8, R_AARCH64_ADD_ABS_LO12_NC, GotPltEntryAddr); +} + +static void write32AArch64Addr(uint8_t *L, uint64_t Imm) { + uint32_t ImmLo = (Imm & 0x3) << 29; + uint32_t ImmHi = (Imm & 0x1FFFFC) << 3; + uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3); + write32le(L, (read32le(L) & ~Mask) | ImmLo | ImmHi); +} + +// Return the bits [Start, End] from Val shifted Start bits. +// For instance, getBits(0xF0, 4, 8) returns 0xF. +static uint64_t getBits(uint64_t Val, int Start, int End) { + uint64_t Mask = ((uint64_t)1 << (End + 1 - Start)) - 1; + return (Val >> Start) & Mask; +} + +static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); } + +// Update the immediate field in a AARCH64 ldr, str, and add instruction. +static void or32AArch64Imm(uint8_t *L, uint64_t Imm) { + or32le(L, (Imm & 0xFFF) << 10); +} + +void AArch64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + switch (Type) { + case R_AARCH64_ABS16: + case R_AARCH64_PREL16: + checkIntUInt<16>(Loc, Val, Type); + write16le(Loc, Val); + break; + case R_AARCH64_ABS32: + case R_AARCH64_PREL32: + checkIntUInt<32>(Loc, Val, Type); + write32le(Loc, Val); + break; + case R_AARCH64_ABS64: + case R_AARCH64_GLOB_DAT: + case R_AARCH64_PREL64: + write64le(Loc, Val); + break; + case R_AARCH64_ADD_ABS_LO12_NC: + or32AArch64Imm(Loc, Val); + break; + case R_AARCH64_ADR_GOT_PAGE: + case R_AARCH64_ADR_PREL_PG_HI21: + case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: + case R_AARCH64_TLSDESC_ADR_PAGE21: + checkInt<33>(Loc, Val, Type); + write32AArch64Addr(Loc, Val >> 12); + break; + case R_AARCH64_ADR_PREL_LO21: + checkInt<21>(Loc, Val, Type); + write32AArch64Addr(Loc, Val); + break; + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + checkInt<28>(Loc, Val, Type); + or32le(Loc, (Val & 0x0FFFFFFC) >> 2); + break; + case R_AARCH64_CONDBR19: + checkInt<21>(Loc, Val, Type); + or32le(Loc, (Val & 0x1FFFFC) << 3); + break; + case R_AARCH64_LD64_GOT_LO12_NC: + case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + case R_AARCH64_TLSDESC_LD64_LO12: + checkAlignment<8>(Loc, Val, Type); + or32le(Loc, (Val & 0xFF8) << 7); + break; + case R_AARCH64_LDST8_ABS_LO12_NC: + or32AArch64Imm(Loc, getBits(Val, 0, 11)); + break; + case R_AARCH64_LDST16_ABS_LO12_NC: + or32AArch64Imm(Loc, getBits(Val, 1, 11)); + break; + case R_AARCH64_LDST32_ABS_LO12_NC: + or32AArch64Imm(Loc, getBits(Val, 2, 11)); + break; + case R_AARCH64_LDST64_ABS_LO12_NC: + or32AArch64Imm(Loc, getBits(Val, 3, 11)); + break; + case R_AARCH64_LDST128_ABS_LO12_NC: + or32AArch64Imm(Loc, getBits(Val, 4, 11)); + break; + case R_AARCH64_MOVW_UABS_G0_NC: + or32le(Loc, (Val & 0xFFFF) << 5); + break; + case R_AARCH64_MOVW_UABS_G1_NC: + or32le(Loc, (Val & 0xFFFF0000) >> 11); + break; + case R_AARCH64_MOVW_UABS_G2_NC: + or32le(Loc, (Val & 0xFFFF00000000) >> 27); + break; + case R_AARCH64_MOVW_UABS_G3: + or32le(Loc, (Val & 0xFFFF000000000000) >> 43); + break; + case R_AARCH64_TSTBR14: + checkInt<16>(Loc, Val, Type); + or32le(Loc, (Val & 0xFFFC) << 3); + break; + case R_AARCH64_TLSLE_ADD_TPREL_HI12: + checkInt<24>(Loc, Val, Type); + or32AArch64Imm(Loc, Val >> 12); + break; + case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + case R_AARCH64_TLSDESC_ADD_LO12: + or32AArch64Imm(Loc, Val); + break; + default: + error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); + } +} + +void AArch64::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + // TLSDESC Global-Dynamic relocation are in the form: + // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21] + // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12] + // add x0, x0, :tlsdesc_los:v [R_AARCH64_TLSDESC_ADD_LO12] + // .tlsdesccall [R_AARCH64_TLSDESC_CALL] + // blr x1 + // And it can optimized to: + // movz x0, #0x0, lsl #16 + // movk x0, #0x10 + // nop + // nop + checkUInt<32>(Loc, Val, Type); + + switch (Type) { + case R_AARCH64_TLSDESC_ADD_LO12: + case R_AARCH64_TLSDESC_CALL: + write32le(Loc, 0xd503201f); // nop + return; + case R_AARCH64_TLSDESC_ADR_PAGE21: + write32le(Loc, 0xd2a00000 | (((Val >> 16) & 0xffff) << 5)); // movz + return; + case R_AARCH64_TLSDESC_LD64_LO12: + write32le(Loc, 0xf2800000 | ((Val & 0xffff) << 5)); // movk + return; + default: + llvm_unreachable("unsupported relocation for TLS GD to LE relaxation"); + } +} + +void AArch64::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + // TLSDESC Global-Dynamic relocation are in the form: + // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21] + // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12] + // add x0, x0, :tlsdesc_los:v [R_AARCH64_TLSDESC_ADD_LO12] + // .tlsdesccall [R_AARCH64_TLSDESC_CALL] + // blr x1 + // And it can optimized to: + // adrp x0, :gottprel:v + // ldr x0, [x0, :gottprel_lo12:v] + // nop + // nop + + switch (Type) { + case R_AARCH64_TLSDESC_ADD_LO12: + case R_AARCH64_TLSDESC_CALL: + write32le(Loc, 0xd503201f); // nop + break; + case R_AARCH64_TLSDESC_ADR_PAGE21: + write32le(Loc, 0x90000000); // adrp + relocateOne(Loc, R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, Val); + break; + case R_AARCH64_TLSDESC_LD64_LO12: + write32le(Loc, 0xf9400000); // ldr + relocateOne(Loc, R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, Val); + break; + default: + llvm_unreachable("unsupported relocation for TLS GD to LE relaxation"); + } +} + +void AArch64::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + checkUInt<32>(Loc, Val, Type); + + if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) { + // Generate MOVZ. + uint32_t RegNo = read32le(Loc) & 0x1f; + write32le(Loc, (0xd2a00000 | RegNo) | (((Val >> 16) & 0xffff) << 5)); + return; + } + if (Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) { + // Generate MOVK. + uint32_t RegNo = read32le(Loc) & 0x1f; + write32le(Loc, (0xf2800000 | RegNo) | ((Val & 0xffff) << 5)); + return; + } + llvm_unreachable("invalid relocation for TLS IE to LE relaxation"); +} + +TargetInfo *elf::createAArch64TargetInfo() { return make(); } Property changes on: vendor/lld/dist/ELF/Arch/AArch64.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/ELF/Arch/AMDGPU.cpp =================================================================== --- vendor/lld/dist/ELF/Arch/AMDGPU.cpp (nonexistent) +++ vendor/lld/dist/ELF/Arch/AMDGPU.cpp (revision 320021) @@ -0,0 +1,82 @@ +//===- AMDGPU.cpp ---------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "InputFiles.h" +#include "Memory.h" +#include "Symbols.h" +#include "Target.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::support::endian; +using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; + +namespace { +class AMDGPU final : public TargetInfo { +public: + AMDGPU(); + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const override; +}; +} // namespace + +AMDGPU::AMDGPU() { + RelativeRel = R_AMDGPU_REL64; + GotRel = R_AMDGPU_ABS64; + GotEntrySize = 8; +} + +void AMDGPU::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + switch (Type) { + case R_AMDGPU_ABS32: + case R_AMDGPU_GOTPCREL: + case R_AMDGPU_GOTPCREL32_LO: + case R_AMDGPU_REL32: + case R_AMDGPU_REL32_LO: + write32le(Loc, Val); + break; + case R_AMDGPU_ABS64: + write64le(Loc, Val); + break; + case R_AMDGPU_GOTPCREL32_HI: + case R_AMDGPU_REL32_HI: + write32le(Loc, Val >> 32); + break; + default: + error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); + } +} + +RelExpr AMDGPU::getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const { + switch (Type) { + case R_AMDGPU_ABS32: + case R_AMDGPU_ABS64: + return R_ABS; + case R_AMDGPU_REL32: + case R_AMDGPU_REL32_LO: + case R_AMDGPU_REL32_HI: + return R_PC; + case R_AMDGPU_GOTPCREL: + case R_AMDGPU_GOTPCREL32_LO: + case R_AMDGPU_GOTPCREL32_HI: + return R_GOT_PC; + default: + error(toString(S.File) + ": unknown relocation type: " + toString(Type)); + return R_HINT; + } +} + +TargetInfo *elf::createAMDGPUTargetInfo() { return make(); } Property changes on: vendor/lld/dist/ELF/Arch/AMDGPU.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/ELF/Arch/ARM.cpp =================================================================== --- vendor/lld/dist/ELF/Arch/ARM.cpp (nonexistent) +++ vendor/lld/dist/ELF/Arch/ARM.cpp (revision 320021) @@ -0,0 +1,432 @@ +//===- ARM.cpp ------------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "InputFiles.h" +#include "Memory.h" +#include "Symbols.h" +#include "SyntheticSections.h" +#include "Target.h" +#include "Thunks.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::support::endian; +using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; + +namespace { +class ARM final : public TargetInfo { +public: + ARM(); + RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const override; + bool isPicRel(uint32_t Type) const override; + uint32_t getDynRel(uint32_t Type) const override; + int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; + void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; + void writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const override; + void writePltHeader(uint8_t *Buf) const override; + void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, + int32_t Index, unsigned RelOff) const override; + void addPltSymbols(InputSectionBase *IS, uint64_t Off) const override; + void addPltHeaderSymbols(InputSectionBase *ISD) const override; + bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, + const SymbolBody &S) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; +}; +} // namespace + +ARM::ARM() { + CopyRel = R_ARM_COPY; + RelativeRel = R_ARM_RELATIVE; + IRelativeRel = R_ARM_IRELATIVE; + GotRel = R_ARM_GLOB_DAT; + PltRel = R_ARM_JUMP_SLOT; + TlsGotRel = R_ARM_TLS_TPOFF32; + TlsModuleIndexRel = R_ARM_TLS_DTPMOD32; + TlsOffsetRel = R_ARM_TLS_DTPOFF32; + GotEntrySize = 4; + GotPltEntrySize = 4; + PltEntrySize = 16; + PltHeaderSize = 20; + // ARM uses Variant 1 TLS + TcbSize = 8; + NeedsThunks = true; +} + +RelExpr ARM::getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const { + switch (Type) { + default: + return R_ABS; + case R_ARM_THM_JUMP11: + return R_PC; + case R_ARM_CALL: + case R_ARM_JUMP24: + case R_ARM_PC24: + case R_ARM_PLT32: + case R_ARM_PREL31: + case R_ARM_THM_JUMP19: + case R_ARM_THM_JUMP24: + case R_ARM_THM_CALL: + return R_PLT_PC; + case R_ARM_GOTOFF32: + // (S + A) - GOT_ORG + return R_GOTREL; + case R_ARM_GOT_BREL: + // GOT(S) + A - GOT_ORG + return R_GOT_OFF; + case R_ARM_GOT_PREL: + case R_ARM_TLS_IE32: + // GOT(S) + A - P + return R_GOT_PC; + case R_ARM_SBREL32: + return R_ARM_SBREL; + case R_ARM_TARGET1: + return Config->Target1Rel ? R_PC : R_ABS; + case R_ARM_TARGET2: + if (Config->Target2 == Target2Policy::Rel) + return R_PC; + if (Config->Target2 == Target2Policy::Abs) + return R_ABS; + return R_GOT_PC; + case R_ARM_TLS_GD32: + return R_TLSGD_PC; + case R_ARM_TLS_LDM32: + return R_TLSLD_PC; + case R_ARM_BASE_PREL: + // B(S) + A - P + // FIXME: currently B(S) assumed to be .got, this may not hold for all + // platforms. + return R_GOTONLY_PC; + case R_ARM_MOVW_PREL_NC: + case R_ARM_MOVT_PREL: + case R_ARM_REL32: + case R_ARM_THM_MOVW_PREL_NC: + case R_ARM_THM_MOVT_PREL: + return R_PC; + case R_ARM_NONE: + return R_NONE; + case R_ARM_TLS_LE32: + return R_TLS; + } +} + +bool ARM::isPicRel(uint32_t Type) const { + return (Type == R_ARM_TARGET1 && !Config->Target1Rel) || + (Type == R_ARM_ABS32); +} + +uint32_t ARM::getDynRel(uint32_t Type) const { + if (Type == R_ARM_TARGET1 && !Config->Target1Rel) + return R_ARM_ABS32; + if (Type == R_ARM_ABS32) + return Type; + // Keep it going with a dummy value so that we can find more reloc errors. + return R_ARM_ABS32; +} + +void ARM::writeGotPlt(uint8_t *Buf, const SymbolBody &) const { + write32le(Buf, InX::Plt->getVA()); +} + +void ARM::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const { + // An ARM entry is the address of the ifunc resolver function. + write32le(Buf, S.getVA()); +} + +void ARM::writePltHeader(uint8_t *Buf) const { + const uint8_t PltData[] = { + 0x04, 0xe0, 0x2d, 0xe5, // str lr, [sp,#-4]! + 0x04, 0xe0, 0x9f, 0xe5, // ldr lr, L2 + 0x0e, 0xe0, 0x8f, 0xe0, // L1: add lr, pc, lr + 0x08, 0xf0, 0xbe, 0xe5, // ldr pc, [lr, #8] + 0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8 + }; + memcpy(Buf, PltData, sizeof(PltData)); + uint64_t GotPlt = InX::GotPlt->getVA(); + uint64_t L1 = InX::Plt->getVA() + 8; + write32le(Buf + 16, GotPlt - L1 - 8); +} + +void ARM::addPltHeaderSymbols(InputSectionBase *ISD) const { + auto *IS = cast(ISD); + addSyntheticLocal("$a", STT_NOTYPE, 0, 0, IS); + addSyntheticLocal("$d", STT_NOTYPE, 16, 0, IS); +} + +void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const { + // FIXME: Using simple code sequence with simple relocations. + // There is a more optimal sequence but it requires support for the group + // relocations. See ELF for the ARM Architecture Appendix A.3 + const uint8_t PltData[] = { + 0x04, 0xc0, 0x9f, 0xe5, // ldr ip, L2 + 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc + 0x00, 0xf0, 0x9c, 0xe5, // ldr pc, [ip] + 0x00, 0x00, 0x00, 0x00, // L2: .word Offset(&(.plt.got) - L1 - 8 + }; + memcpy(Buf, PltData, sizeof(PltData)); + uint64_t L1 = PltEntryAddr + 4; + write32le(Buf + 12, GotPltEntryAddr - L1 - 8); +} + +void ARM::addPltSymbols(InputSectionBase *ISD, uint64_t Off) const { + auto *IS = cast(ISD); + addSyntheticLocal("$a", STT_NOTYPE, Off, 0, IS); + addSyntheticLocal("$d", STT_NOTYPE, Off + 12, 0, IS); +} + +bool ARM::needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, + const SymbolBody &S) const { + // If S is an undefined weak symbol in an executable we don't need a Thunk. + // In a DSO calls to undefined symbols, including weak ones get PLT entries + // which may need a thunk. + if (S.isUndefined() && !S.isLocal() && S.symbol()->isWeak() && + !Config->Shared) + return false; + // A state change from ARM to Thumb and vice versa must go through an + // interworking thunk if the relocation type is not R_ARM_CALL or + // R_ARM_THM_CALL. + switch (RelocType) { + case R_ARM_PC24: + case R_ARM_PLT32: + case R_ARM_JUMP24: + // Source is ARM, all PLT entries are ARM so no interworking required. + // Otherwise we need to interwork if Symbol has bit 0 set (Thumb). + if (Expr == R_PC && ((S.getVA() & 1) == 1)) + return true; + break; + case R_ARM_THM_JUMP19: + case R_ARM_THM_JUMP24: + // Source is Thumb, all PLT entries are ARM so interworking is required. + // Otherwise we need to interwork if Symbol has bit 0 clear (ARM). + if (Expr == R_PLT_PC || ((S.getVA() & 1) == 0)) + return true; + break; + } + return false; +} + +void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + switch (Type) { + case R_ARM_ABS32: + case R_ARM_BASE_PREL: + case R_ARM_GLOB_DAT: + case R_ARM_GOTOFF32: + case R_ARM_GOT_BREL: + case R_ARM_GOT_PREL: + case R_ARM_REL32: + case R_ARM_RELATIVE: + case R_ARM_SBREL32: + case R_ARM_TARGET1: + case R_ARM_TARGET2: + case R_ARM_TLS_GD32: + case R_ARM_TLS_IE32: + case R_ARM_TLS_LDM32: + case R_ARM_TLS_LDO32: + case R_ARM_TLS_LE32: + case R_ARM_TLS_TPOFF32: + case R_ARM_TLS_DTPOFF32: + write32le(Loc, Val); + break; + case R_ARM_TLS_DTPMOD32: + write32le(Loc, 1); + break; + case R_ARM_PREL31: + checkInt<31>(Loc, Val, Type); + write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000)); + break; + case R_ARM_CALL: + // R_ARM_CALL is used for BL and BLX instructions, depending on the + // value of bit 0 of Val, we must select a BL or BLX instruction + if (Val & 1) { + // If bit 0 of Val is 1 the target is Thumb, we must select a BLX. + // The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1' + checkInt<26>(Loc, Val, Type); + write32le(Loc, 0xfa000000 | // opcode + ((Val & 2) << 23) | // H + ((Val >> 2) & 0x00ffffff)); // imm24 + break; + } + if ((read32le(Loc) & 0xfe000000) == 0xfa000000) + // BLX (always unconditional) instruction to an ARM Target, select an + // unconditional BL. + write32le(Loc, 0xeb000000 | (read32le(Loc) & 0x00ffffff)); + // fall through as BL encoding is shared with B + LLVM_FALLTHROUGH; + case R_ARM_JUMP24: + case R_ARM_PC24: + case R_ARM_PLT32: + checkInt<26>(Loc, Val, Type); + write32le(Loc, (read32le(Loc) & ~0x00ffffff) | ((Val >> 2) & 0x00ffffff)); + break; + case R_ARM_THM_JUMP11: + checkInt<12>(Loc, Val, Type); + write16le(Loc, (read32le(Loc) & 0xf800) | ((Val >> 1) & 0x07ff)); + break; + case R_ARM_THM_JUMP19: + // Encoding T3: Val = S:J2:J1:imm6:imm11:0 + checkInt<21>(Loc, Val, Type); + write16le(Loc, + (read16le(Loc) & 0xfbc0) | // opcode cond + ((Val >> 10) & 0x0400) | // S + ((Val >> 12) & 0x003f)); // imm6 + write16le(Loc + 2, + 0x8000 | // opcode + ((Val >> 8) & 0x0800) | // J2 + ((Val >> 5) & 0x2000) | // J1 + ((Val >> 1) & 0x07ff)); // imm11 + break; + case R_ARM_THM_CALL: + // R_ARM_THM_CALL is used for BL and BLX instructions, depending on the + // value of bit 0 of Val, we must select a BL or BLX instruction + if ((Val & 1) == 0) { + // Ensure BLX destination is 4-byte aligned. As BLX instruction may + // only be two byte aligned. This must be done before overflow check + Val = alignTo(Val, 4); + } + // Bit 12 is 0 for BLX, 1 for BL + write16le(Loc + 2, (read16le(Loc + 2) & ~0x1000) | (Val & 1) << 12); + // Fall through as rest of encoding is the same as B.W + LLVM_FALLTHROUGH; + case R_ARM_THM_JUMP24: + // Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0 + // FIXME: Use of I1 and I2 require v6T2ops + checkInt<25>(Loc, Val, Type); + write16le(Loc, + 0xf000 | // opcode + ((Val >> 14) & 0x0400) | // S + ((Val >> 12) & 0x03ff)); // imm10 + write16le(Loc + 2, + (read16le(Loc + 2) & 0xd000) | // opcode + (((~(Val >> 10)) ^ (Val >> 11)) & 0x2000) | // J1 + (((~(Val >> 11)) ^ (Val >> 13)) & 0x0800) | // J2 + ((Val >> 1) & 0x07ff)); // imm11 + break; + case R_ARM_MOVW_ABS_NC: + case R_ARM_MOVW_PREL_NC: + write32le(Loc, (read32le(Loc) & ~0x000f0fff) | ((Val & 0xf000) << 4) | + (Val & 0x0fff)); + break; + case R_ARM_MOVT_ABS: + case R_ARM_MOVT_PREL: + checkInt<32>(Loc, Val, Type); + write32le(Loc, (read32le(Loc) & ~0x000f0fff) | + (((Val >> 16) & 0xf000) << 4) | ((Val >> 16) & 0xfff)); + break; + case R_ARM_THM_MOVT_ABS: + case R_ARM_THM_MOVT_PREL: + // Encoding T1: A = imm4:i:imm3:imm8 + checkInt<32>(Loc, Val, Type); + write16le(Loc, + 0xf2c0 | // opcode + ((Val >> 17) & 0x0400) | // i + ((Val >> 28) & 0x000f)); // imm4 + write16le(Loc + 2, + (read16le(Loc + 2) & 0x8f00) | // opcode + ((Val >> 12) & 0x7000) | // imm3 + ((Val >> 16) & 0x00ff)); // imm8 + break; + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVW_PREL_NC: + // Encoding T3: A = imm4:i:imm3:imm8 + write16le(Loc, + 0xf240 | // opcode + ((Val >> 1) & 0x0400) | // i + ((Val >> 12) & 0x000f)); // imm4 + write16le(Loc + 2, + (read16le(Loc + 2) & 0x8f00) | // opcode + ((Val << 4) & 0x7000) | // imm3 + (Val & 0x00ff)); // imm8 + break; + default: + error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); + } +} + +int64_t ARM::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { + switch (Type) { + default: + return 0; + case R_ARM_ABS32: + case R_ARM_BASE_PREL: + case R_ARM_GOTOFF32: + case R_ARM_GOT_BREL: + case R_ARM_GOT_PREL: + case R_ARM_REL32: + case R_ARM_TARGET1: + case R_ARM_TARGET2: + case R_ARM_TLS_GD32: + case R_ARM_TLS_LDM32: + case R_ARM_TLS_LDO32: + case R_ARM_TLS_IE32: + case R_ARM_TLS_LE32: + return SignExtend64<32>(read32le(Buf)); + case R_ARM_PREL31: + return SignExtend64<31>(read32le(Buf)); + case R_ARM_CALL: + case R_ARM_JUMP24: + case R_ARM_PC24: + case R_ARM_PLT32: + return SignExtend64<26>(read32le(Buf) << 2); + case R_ARM_THM_JUMP11: + return SignExtend64<12>(read16le(Buf) << 1); + case R_ARM_THM_JUMP19: { + // Encoding T3: A = S:J2:J1:imm10:imm6:0 + uint16_t Hi = read16le(Buf); + uint16_t Lo = read16le(Buf + 2); + return SignExtend64<20>(((Hi & 0x0400) << 10) | // S + ((Lo & 0x0800) << 8) | // J2 + ((Lo & 0x2000) << 5) | // J1 + ((Hi & 0x003f) << 12) | // imm6 + ((Lo & 0x07ff) << 1)); // imm11:0 + } + case R_ARM_THM_CALL: + case R_ARM_THM_JUMP24: { + // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0 + // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S) + // FIXME: I1 and I2 require v6T2ops + uint16_t Hi = read16le(Buf); + uint16_t Lo = read16le(Buf + 2); + return SignExtend64<24>(((Hi & 0x0400) << 14) | // S + (~((Lo ^ (Hi << 3)) << 10) & 0x00800000) | // I1 + (~((Lo ^ (Hi << 1)) << 11) & 0x00400000) | // I2 + ((Hi & 0x003ff) << 12) | // imm0 + ((Lo & 0x007ff) << 1)); // imm11:0 + } + // ELF for the ARM Architecture 4.6.1.1 the implicit addend for MOVW and + // MOVT is in the range -32768 <= A < 32768 + case R_ARM_MOVW_ABS_NC: + case R_ARM_MOVT_ABS: + case R_ARM_MOVW_PREL_NC: + case R_ARM_MOVT_PREL: { + uint64_t Val = read32le(Buf) & 0x000f0fff; + return SignExtend64<16>(((Val & 0x000f0000) >> 4) | (Val & 0x00fff)); + } + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVT_ABS: + case R_ARM_THM_MOVW_PREL_NC: + case R_ARM_THM_MOVT_PREL: { + // Encoding T3: A = imm4:i:imm3:imm8 + uint16_t Hi = read16le(Buf); + uint16_t Lo = read16le(Buf + 2); + return SignExtend64<16>(((Hi & 0x000f) << 12) | // imm4 + ((Hi & 0x0400) << 1) | // i + ((Lo & 0x7000) >> 4) | // imm3 + (Lo & 0x00ff)); // imm8 + } + } +} + +TargetInfo *elf::createARMTargetInfo() { return make(); } Property changes on: vendor/lld/dist/ELF/Arch/ARM.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/ELF/Arch/AVR.cpp =================================================================== --- vendor/lld/dist/ELF/Arch/AVR.cpp (nonexistent) +++ vendor/lld/dist/ELF/Arch/AVR.cpp (revision 320021) @@ -0,0 +1,78 @@ +//===- AVR.cpp ------------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// AVR is a Harvard-architecture 8-bit micrcontroller designed for small +// baremetal programs. All AVR-family processors have 32 8-bit registers. +// The tiniest AVR has 32 byte RAM and 1 KiB program memory, and the largest +// one supports up to 2^24 data address space and 2^22 code address space. +// +// Since it is a baremetal programming, there's usually no loader to load +// ELF files on AVRs. You are expected to link your program against address +// 0 and pull out a .text section from the result using objcopy, so that you +// can write the linked code to on-chip flush memory. You can do that with +// the following commands: +// +// ld.lld -Ttext=0 -o foo foo.o +// objcopy -O binary --only-section=.text foo output.bin +// +// Note that the current AVR support is very preliminary so you can't +// link any useful program yet, though. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "InputFiles.h" +#include "Memory.h" +#include "Symbols.h" +#include "Target.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::support::endian; +using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; + +namespace { +class AVR final : public TargetInfo { +public: + RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; +}; +} // namespace + +RelExpr AVR::getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const { + switch (Type) { + case R_AVR_CALL: + return R_ABS; + default: + error(toString(S.File) + ": unknown relocation type: " + toString(Type)); + return R_HINT; + } +} + +void AVR::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + switch (Type) { + case R_AVR_CALL: { + uint16_t Hi = Val >> 17; + uint16_t Lo = Val >> 1; + write16le(Loc, read16le(Loc) | ((Hi >> 1) << 4) | (Hi & 1)); + write16le(Loc + 2, Lo); + break; + } + default: + error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type)); + } +} + +TargetInfo *elf::createAVRTargetInfo() { return make(); } Property changes on: vendor/lld/dist/ELF/Arch/AVR.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/ELF/Arch/Mips.cpp =================================================================== --- vendor/lld/dist/ELF/Arch/Mips.cpp (nonexistent) +++ vendor/lld/dist/ELF/Arch/Mips.cpp (revision 320021) @@ -0,0 +1,422 @@ +//===- MIPS.cpp -----------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "InputFiles.h" +#include "Memory.h" +#include "OutputSections.h" +#include "Symbols.h" +#include "SyntheticSections.h" +#include "Target.h" +#include "Thunks.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::support::endian; +using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; + +namespace { +template class MIPS final : public TargetInfo { +public: + MIPS(); + RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const override; + int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; + bool isPicRel(uint32_t Type) const override; + uint32_t getDynRel(uint32_t Type) const override; + void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; + void writePltHeader(uint8_t *Buf) const override; + void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, + int32_t Index, unsigned RelOff) const override; + bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, + const SymbolBody &S) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + bool usesOnlyLowPageBits(uint32_t Type) const override; +}; +} // namespace + +template MIPS::MIPS() { + GotPltHeaderEntriesNum = 2; + DefaultMaxPageSize = 65536; + GotEntrySize = sizeof(typename ELFT::uint); + GotPltEntrySize = sizeof(typename ELFT::uint); + PltEntrySize = 16; + PltHeaderSize = 32; + CopyRel = R_MIPS_COPY; + PltRel = R_MIPS_JUMP_SLOT; + NeedsThunks = true; + + if (ELFT::Is64Bits) { + RelativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32; + TlsGotRel = R_MIPS_TLS_TPREL64; + TlsModuleIndexRel = R_MIPS_TLS_DTPMOD64; + TlsOffsetRel = R_MIPS_TLS_DTPREL64; + } else { + RelativeRel = R_MIPS_REL32; + TlsGotRel = R_MIPS_TLS_TPREL32; + TlsModuleIndexRel = R_MIPS_TLS_DTPMOD32; + TlsOffsetRel = R_MIPS_TLS_DTPREL32; + } +} + +template +RelExpr MIPS::getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const { + // See comment in the calculateMipsRelChain. + if (ELFT::Is64Bits || Config->MipsN32Abi) + Type &= 0xff; + switch (Type) { + default: + return R_ABS; + case R_MIPS_JALR: + return R_HINT; + case R_MIPS_GPREL16: + case R_MIPS_GPREL32: + return R_MIPS_GOTREL; + case R_MIPS_26: + return R_PLT; + case R_MIPS_HI16: + case R_MIPS_LO16: + // R_MIPS_HI16/R_MIPS_LO16 relocations against _gp_disp calculate + // offset between start of function and 'gp' value which by default + // equal to the start of .got section. In that case we consider these + // relocations as relative. + if (&S == ElfSym::MipsGpDisp) + return R_MIPS_GOT_GP_PC; + if (&S == ElfSym::MipsLocalGp) + return R_MIPS_GOT_GP; + LLVM_FALLTHROUGH; + case R_MIPS_GOT_OFST: + return R_ABS; + case R_MIPS_PC32: + case R_MIPS_PC16: + case R_MIPS_PC19_S2: + case R_MIPS_PC21_S2: + case R_MIPS_PC26_S2: + case R_MIPS_PCHI16: + case R_MIPS_PCLO16: + return R_PC; + case R_MIPS_GOT16: + if (S.isLocal()) + return R_MIPS_GOT_LOCAL_PAGE; + LLVM_FALLTHROUGH; + case R_MIPS_CALL16: + case R_MIPS_GOT_DISP: + case R_MIPS_TLS_GOTTPREL: + return R_MIPS_GOT_OFF; + case R_MIPS_CALL_HI16: + case R_MIPS_CALL_LO16: + case R_MIPS_GOT_HI16: + case R_MIPS_GOT_LO16: + return R_MIPS_GOT_OFF32; + case R_MIPS_GOT_PAGE: + return R_MIPS_GOT_LOCAL_PAGE; + case R_MIPS_TLS_GD: + return R_MIPS_TLSGD; + case R_MIPS_TLS_LDM: + return R_MIPS_TLSLD; + } +} + +template bool MIPS::isPicRel(uint32_t Type) const { + return Type == R_MIPS_32 || Type == R_MIPS_64; +} + +template uint32_t MIPS::getDynRel(uint32_t Type) const { + return RelativeRel; +} + +template +void MIPS::writeGotPlt(uint8_t *Buf, const SymbolBody &) const { + write32(Buf, InX::Plt->getVA()); +} + +template +static int64_t getPcRelocAddend(const uint8_t *Loc) { + uint32_t Instr = read32(Loc); + uint32_t Mask = 0xffffffff >> (32 - BSIZE); + return SignExtend64((Instr & Mask) << SHIFT); +} + +template +static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t V) { + uint32_t Mask = 0xffffffff >> (32 - BSIZE); + uint32_t Instr = read32(Loc); + if (SHIFT > 0) + checkAlignment<(1 << SHIFT)>(Loc, V, Type); + checkInt(Loc, V, Type); + write32(Loc, (Instr & ~Mask) | ((V >> SHIFT) & Mask)); +} + +template static void writeMipsHi16(uint8_t *Loc, uint64_t V) { + uint32_t Instr = read32(Loc); + uint16_t Res = ((V + 0x8000) >> 16) & 0xffff; + write32(Loc, (Instr & 0xffff0000) | Res); +} + +template static void writeMipsHigher(uint8_t *Loc, uint64_t V) { + uint32_t Instr = read32(Loc); + uint16_t Res = ((V + 0x80008000) >> 32) & 0xffff; + write32(Loc, (Instr & 0xffff0000) | Res); +} + +template static void writeMipsHighest(uint8_t *Loc, uint64_t V) { + uint32_t Instr = read32(Loc); + uint16_t Res = ((V + 0x800080008000) >> 48) & 0xffff; + write32(Loc, (Instr & 0xffff0000) | Res); +} + +template static void writeMipsLo16(uint8_t *Loc, uint64_t V) { + uint32_t Instr = read32(Loc); + write32(Loc, (Instr & 0xffff0000) | (V & 0xffff)); +} + +template static bool isMipsR6() { + const auto &FirstObj = cast>(*Config->FirstElf); + uint32_t Arch = FirstObj.getObj().getHeader()->e_flags & EF_MIPS_ARCH; + return Arch == EF_MIPS_ARCH_32R6 || Arch == EF_MIPS_ARCH_64R6; +} + +template void MIPS::writePltHeader(uint8_t *Buf) const { + const endianness E = ELFT::TargetEndianness; + if (Config->MipsN32Abi) { + write32(Buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) + write32(Buf + 4, 0x8dd90000); // lw $25, %lo(&GOTPLT[0])($14) + write32(Buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) + write32(Buf + 12, 0x030ec023); // subu $24, $24, $14 + } else { + write32(Buf, 0x3c1c0000); // lui $28, %hi(&GOTPLT[0]) + write32(Buf + 4, 0x8f990000); // lw $25, %lo(&GOTPLT[0])($28) + write32(Buf + 8, 0x279c0000); // addiu $28, $28, %lo(&GOTPLT[0]) + write32(Buf + 12, 0x031cc023); // subu $24, $24, $28 + } + + write32(Buf + 16, 0x03e07825); // move $15, $31 + write32(Buf + 20, 0x0018c082); // srl $24, $24, 2 + write32(Buf + 24, 0x0320f809); // jalr $25 + write32(Buf + 28, 0x2718fffe); // subu $24, $24, 2 + + uint64_t GotPlt = InX::GotPlt->getVA(); + writeMipsHi16(Buf, GotPlt); + writeMipsLo16(Buf + 4, GotPlt); + writeMipsLo16(Buf + 8, GotPlt); +} + +template +void MIPS::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const { + const endianness E = ELFT::TargetEndianness; + write32(Buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry) + write32(Buf + 4, 0x8df90000); // l[wd] $25, %lo(.got.plt entry)($15) + // jr $25 + write32(Buf + 8, isMipsR6() ? 0x03200009 : 0x03200008); + write32(Buf + 12, 0x25f80000); // addiu $24, $15, %lo(.got.plt entry) + writeMipsHi16(Buf, GotPltEntryAddr); + writeMipsLo16(Buf + 4, GotPltEntryAddr); + writeMipsLo16(Buf + 12, GotPltEntryAddr); +} + +template +bool MIPS::needsThunk(RelExpr Expr, uint32_t Type, const InputFile *File, + const SymbolBody &S) const { + // Any MIPS PIC code function is invoked with its address in register $t9. + // So if we have a branch instruction from non-PIC code to the PIC one + // we cannot make the jump directly and need to create a small stubs + // to save the target function address. + // See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf + if (Type != R_MIPS_26) + return false; + auto *F = dyn_cast_or_null>(File); + if (!F) + return false; + // If current file has PIC code, LA25 stub is not required. + if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC) + return false; + auto *D = dyn_cast(&S); + // LA25 is required if target file has PIC code + // or target symbol is a PIC symbol. + return D && D->isMipsPIC(); +} + +template +int64_t MIPS::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { + const endianness E = ELFT::TargetEndianness; + switch (Type) { + default: + return 0; + case R_MIPS_32: + case R_MIPS_GPREL32: + case R_MIPS_TLS_DTPREL32: + case R_MIPS_TLS_TPREL32: + return SignExtend64<32>(read32(Buf)); + case R_MIPS_26: + // FIXME (simon): If the relocation target symbol is not a PLT entry + // we should use another expression for calculation: + // ((A << 2) | (P & 0xf0000000)) >> 2 + return SignExtend64<28>((read32(Buf) & 0x3ffffff) << 2); + case R_MIPS_GPREL16: + case R_MIPS_LO16: + case R_MIPS_PCLO16: + case R_MIPS_TLS_DTPREL_HI16: + case R_MIPS_TLS_DTPREL_LO16: + case R_MIPS_TLS_TPREL_HI16: + case R_MIPS_TLS_TPREL_LO16: + return SignExtend64<16>(read32(Buf)); + case R_MIPS_PC16: + return getPcRelocAddend(Buf); + case R_MIPS_PC19_S2: + return getPcRelocAddend(Buf); + case R_MIPS_PC21_S2: + return getPcRelocAddend(Buf); + case R_MIPS_PC26_S2: + return getPcRelocAddend(Buf); + case R_MIPS_PC32: + return getPcRelocAddend(Buf); + } +} + +static std::pair +calculateMipsRelChain(uint8_t *Loc, uint32_t Type, uint64_t Val) { + // MIPS N64 ABI packs multiple relocations into the single relocation + // record. In general, all up to three relocations can have arbitrary + // types. In fact, Clang and GCC uses only a few combinations. For now, + // we support two of them. That is allow to pass at least all LLVM + // test suite cases. + // / R_MIPS_SUB / R_MIPS_HI16 | R_MIPS_LO16 + // / R_MIPS_64 / R_MIPS_NONE + // The first relocation is a 'real' relocation which is calculated + // using the corresponding symbol's value. The second and the third + // relocations used to modify result of the first one: extend it to + // 64-bit, extract high or low part etc. For details, see part 2.9 Relocation + // at the https://dmz-portal.mips.com/mw/images/8/82/007-4658-001.pdf + uint32_t Type2 = (Type >> 8) & 0xff; + uint32_t Type3 = (Type >> 16) & 0xff; + if (Type2 == R_MIPS_NONE && Type3 == R_MIPS_NONE) + return std::make_pair(Type, Val); + if (Type2 == R_MIPS_64 && Type3 == R_MIPS_NONE) + return std::make_pair(Type2, Val); + if (Type2 == R_MIPS_SUB && (Type3 == R_MIPS_HI16 || Type3 == R_MIPS_LO16)) + return std::make_pair(Type3, -Val); + error(getErrorLocation(Loc) + "unsupported relocations combination " + + Twine(Type)); + return std::make_pair(Type & 0xff, Val); +} + +template +void MIPS::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + const endianness E = ELFT::TargetEndianness; + // Thread pointer and DRP offsets from the start of TLS data area. + // https://www.linux-mips.org/wiki/NPTL + if (Type == R_MIPS_TLS_DTPREL_HI16 || Type == R_MIPS_TLS_DTPREL_LO16 || + Type == R_MIPS_TLS_DTPREL32 || Type == R_MIPS_TLS_DTPREL64) + Val -= 0x8000; + else if (Type == R_MIPS_TLS_TPREL_HI16 || Type == R_MIPS_TLS_TPREL_LO16 || + Type == R_MIPS_TLS_TPREL32 || Type == R_MIPS_TLS_TPREL64) + Val -= 0x7000; + if (ELFT::Is64Bits || Config->MipsN32Abi) + std::tie(Type, Val) = calculateMipsRelChain(Loc, Type, Val); + switch (Type) { + case R_MIPS_32: + case R_MIPS_GPREL32: + case R_MIPS_TLS_DTPREL32: + case R_MIPS_TLS_TPREL32: + write32(Loc, Val); + break; + case R_MIPS_64: + case R_MIPS_TLS_DTPREL64: + case R_MIPS_TLS_TPREL64: + write64(Loc, Val); + break; + case R_MIPS_26: + write32(Loc, (read32(Loc) & ~0x3ffffff) | ((Val >> 2) & 0x3ffffff)); + break; + case R_MIPS_GOT16: + // The R_MIPS_GOT16 relocation's value in "relocatable" linking mode + // is updated addend (not a GOT index). In that case write high 16 bits + // to store a correct addend value. + if (Config->Relocatable) + writeMipsHi16(Loc, Val); + else { + checkInt<16>(Loc, Val, Type); + writeMipsLo16(Loc, Val); + } + break; + case R_MIPS_GOT_DISP: + case R_MIPS_GOT_PAGE: + case R_MIPS_GPREL16: + case R_MIPS_TLS_GD: + case R_MIPS_TLS_LDM: + checkInt<16>(Loc, Val, Type); + LLVM_FALLTHROUGH; + case R_MIPS_CALL16: + case R_MIPS_CALL_LO16: + case R_MIPS_GOT_LO16: + case R_MIPS_GOT_OFST: + case R_MIPS_LO16: + case R_MIPS_PCLO16: + case R_MIPS_TLS_DTPREL_LO16: + case R_MIPS_TLS_GOTTPREL: + case R_MIPS_TLS_TPREL_LO16: + writeMipsLo16(Loc, Val); + break; + case R_MIPS_CALL_HI16: + case R_MIPS_GOT_HI16: + case R_MIPS_HI16: + case R_MIPS_PCHI16: + case R_MIPS_TLS_DTPREL_HI16: + case R_MIPS_TLS_TPREL_HI16: + writeMipsHi16(Loc, Val); + break; + case R_MIPS_HIGHER: + writeMipsHigher(Loc, Val); + break; + case R_MIPS_HIGHEST: + writeMipsHighest(Loc, Val); + break; + case R_MIPS_JALR: + // Ignore this optimization relocation for now + break; + case R_MIPS_PC16: + applyMipsPcReloc(Loc, Type, Val); + break; + case R_MIPS_PC19_S2: + applyMipsPcReloc(Loc, Type, Val); + break; + case R_MIPS_PC21_S2: + applyMipsPcReloc(Loc, Type, Val); + break; + case R_MIPS_PC26_S2: + applyMipsPcReloc(Loc, Type, Val); + break; + case R_MIPS_PC32: + applyMipsPcReloc(Loc, Type, Val); + break; + default: + error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); + } +} + +template +bool MIPS::usesOnlyLowPageBits(uint32_t Type) const { + return Type == R_MIPS_LO16 || Type == R_MIPS_GOT_OFST; +} + +template TargetInfo *elf::createMipsTargetInfo() { + return make>(); +} + +template TargetInfo *elf::createMipsTargetInfo(); +template TargetInfo *elf::createMipsTargetInfo(); +template TargetInfo *elf::createMipsTargetInfo(); +template TargetInfo *elf::createMipsTargetInfo(); Property changes on: vendor/lld/dist/ELF/Arch/Mips.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/ELF/Arch/PPC.cpp =================================================================== --- vendor/lld/dist/ELF/Arch/PPC.cpp (nonexistent) +++ vendor/lld/dist/ELF/Arch/PPC.cpp (revision 320021) @@ -0,0 +1,63 @@ +//===- PPC.cpp ------------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "Memory.h" +#include "Symbols.h" +#include "Target.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::support::endian; +using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; + +namespace { +class PPC final : public TargetInfo { +public: + PPC() {} + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const override; +}; +} // namespace + +void PPC::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + switch (Type) { + case R_PPC_ADDR16_HA: + write16be(Loc, (Val + 0x8000) >> 16); + break; + case R_PPC_ADDR16_LO: + write16be(Loc, Val); + break; + case R_PPC_ADDR32: + case R_PPC_REL32: + write32be(Loc, Val); + break; + case R_PPC_REL24: + write32be(Loc, read32be(Loc) | (Val & 0x3FFFFFC)); + break; + default: + error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); + } +} + +RelExpr PPC::getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const { + switch (Type) { + case R_PPC_REL24: + case R_PPC_REL32: + return R_PC; + default: + return R_ABS; + } +} + +TargetInfo *elf::createPPCTargetInfo() { return make(); } Property changes on: vendor/lld/dist/ELF/Arch/PPC.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/ELF/Arch/PPC64.cpp =================================================================== --- vendor/lld/dist/ELF/Arch/PPC64.cpp (nonexistent) +++ vendor/lld/dist/ELF/Arch/PPC64.cpp (revision 320021) @@ -0,0 +1,215 @@ +//===- PPC64.cpp ----------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "Memory.h" +#include "Symbols.h" +#include "SyntheticSections.h" +#include "Target.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::support::endian; +using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; + +static uint64_t PPC64TocOffset = 0x8000; + +uint64_t elf::getPPC64TocBase() { + // The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The + // TOC starts where the first of these sections starts. We always create a + // .got when we see a relocation that uses it, so for us the start is always + // the .got. + uint64_t TocVA = InX::Got->getVA(); + + // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000 + // thus permitting a full 64 Kbytes segment. Note that the glibc startup + // code (crt1.o) assumes that you can get from the TOC base to the + // start of the .toc section with only a single (signed) 16-bit relocation. + return TocVA + PPC64TocOffset; +} + +namespace { +class PPC64 final : public TargetInfo { +public: + PPC64(); + RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const override; + void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, + int32_t Index, unsigned RelOff) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; +}; +} // namespace + +// Relocation masks following the #lo(value), #hi(value), #ha(value), +// #higher(value), #highera(value), #highest(value), and #highesta(value) +// macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi +// document. +static uint16_t applyPPCLo(uint64_t V) { return V; } +static uint16_t applyPPCHi(uint64_t V) { return V >> 16; } +static uint16_t applyPPCHa(uint64_t V) { return (V + 0x8000) >> 16; } +static uint16_t applyPPCHigher(uint64_t V) { return V >> 32; } +static uint16_t applyPPCHighera(uint64_t V) { return (V + 0x8000) >> 32; } +static uint16_t applyPPCHighest(uint64_t V) { return V >> 48; } +static uint16_t applyPPCHighesta(uint64_t V) { return (V + 0x8000) >> 48; } + +PPC64::PPC64() { + PltRel = GotRel = R_PPC64_GLOB_DAT; + RelativeRel = R_PPC64_RELATIVE; + GotEntrySize = 8; + GotPltEntrySize = 8; + PltEntrySize = 32; + PltHeaderSize = 0; + + // We need 64K pages (at least under glibc/Linux, the loader won't + // set different permissions on a finer granularity than that). + DefaultMaxPageSize = 65536; + + // The PPC64 ELF ABI v1 spec, says: + // + // It is normally desirable to put segments with different characteristics + // in separate 256 Mbyte portions of the address space, to give the + // operating system full paging flexibility in the 64-bit address space. + // + // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers + // use 0x10000000 as the starting address. + DefaultImageBase = 0x10000000; +} + +RelExpr PPC64::getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const { + switch (Type) { + default: + return R_ABS; + case R_PPC64_TOC16: + case R_PPC64_TOC16_DS: + case R_PPC64_TOC16_HA: + case R_PPC64_TOC16_HI: + case R_PPC64_TOC16_LO: + case R_PPC64_TOC16_LO_DS: + return R_GOTREL; + case R_PPC64_TOC: + return R_PPC_TOC; + case R_PPC64_REL24: + return R_PPC_PLT_OPD; + } +} + +void PPC64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const { + uint64_t Off = GotPltEntryAddr - getPPC64TocBase(); + + // FIXME: What we should do, in theory, is get the offset of the function + // descriptor in the .opd section, and use that as the offset from %r2 (the + // TOC-base pointer). Instead, we have the GOT-entry offset, and that will + // be a pointer to the function descriptor in the .opd section. Using + // this scheme is simpler, but requires an extra indirection per PLT dispatch. + + write32be(Buf, 0xf8410028); // std %r2, 40(%r1) + write32be(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha + write32be(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11) + write32be(Buf + 12, 0xe96c0000); // ld %r11,0(%r12) + write32be(Buf + 16, 0x7d6903a6); // mtctr %r11 + write32be(Buf + 20, 0xe84c0008); // ld %r2,8(%r12) + write32be(Buf + 24, 0xe96c0010); // ld %r11,16(%r12) + write32be(Buf + 28, 0x4e800420); // bctr +} + +static std::pair toAddr16Rel(uint32_t Type, uint64_t Val) { + uint64_t V = Val - PPC64TocOffset; + switch (Type) { + case R_PPC64_TOC16: + return {R_PPC64_ADDR16, V}; + case R_PPC64_TOC16_DS: + return {R_PPC64_ADDR16_DS, V}; + case R_PPC64_TOC16_HA: + return {R_PPC64_ADDR16_HA, V}; + case R_PPC64_TOC16_HI: + return {R_PPC64_ADDR16_HI, V}; + case R_PPC64_TOC16_LO: + return {R_PPC64_ADDR16_LO, V}; + case R_PPC64_TOC16_LO_DS: + return {R_PPC64_ADDR16_LO_DS, V}; + default: + return {Type, Val}; + } +} + +void PPC64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + // For a TOC-relative relocation, proceed in terms of the corresponding + // ADDR16 relocation type. + std::tie(Type, Val) = toAddr16Rel(Type, Val); + + switch (Type) { + case R_PPC64_ADDR14: { + checkAlignment<4>(Loc, Val, Type); + // Preserve the AA/LK bits in the branch instruction + uint8_t AALK = Loc[3]; + write16be(Loc + 2, (AALK & 3) | (Val & 0xfffc)); + break; + } + case R_PPC64_ADDR16: + checkInt<16>(Loc, Val, Type); + write16be(Loc, Val); + break; + case R_PPC64_ADDR16_DS: + checkInt<16>(Loc, Val, Type); + write16be(Loc, (read16be(Loc) & 3) | (Val & ~3)); + break; + case R_PPC64_ADDR16_HA: + case R_PPC64_REL16_HA: + write16be(Loc, applyPPCHa(Val)); + break; + case R_PPC64_ADDR16_HI: + case R_PPC64_REL16_HI: + write16be(Loc, applyPPCHi(Val)); + break; + case R_PPC64_ADDR16_HIGHER: + write16be(Loc, applyPPCHigher(Val)); + break; + case R_PPC64_ADDR16_HIGHERA: + write16be(Loc, applyPPCHighera(Val)); + break; + case R_PPC64_ADDR16_HIGHEST: + write16be(Loc, applyPPCHighest(Val)); + break; + case R_PPC64_ADDR16_HIGHESTA: + write16be(Loc, applyPPCHighesta(Val)); + break; + case R_PPC64_ADDR16_LO: + write16be(Loc, applyPPCLo(Val)); + break; + case R_PPC64_ADDR16_LO_DS: + case R_PPC64_REL16_LO: + write16be(Loc, (read16be(Loc) & 3) | (applyPPCLo(Val) & ~3)); + break; + case R_PPC64_ADDR32: + case R_PPC64_REL32: + checkInt<32>(Loc, Val, Type); + write32be(Loc, Val); + break; + case R_PPC64_ADDR64: + case R_PPC64_REL64: + case R_PPC64_TOC: + write64be(Loc, Val); + break; + case R_PPC64_REL24: { + uint32_t Mask = 0x03FFFFFC; + checkInt<24>(Loc, Val, Type); + write32be(Loc, (read32be(Loc) & ~Mask) | (Val & Mask)); + break; + } + default: + error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); + } +} + +TargetInfo *elf::createPPC64TargetInfo() { return make(); } Property changes on: vendor/lld/dist/ELF/Arch/PPC64.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/ELF/Arch/X86.cpp =================================================================== --- vendor/lld/dist/ELF/Arch/X86.cpp (nonexistent) +++ vendor/lld/dist/ELF/Arch/X86.cpp (revision 320021) @@ -0,0 +1,363 @@ +//===- X86.cpp ------------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "InputFiles.h" +#include "Memory.h" +#include "Symbols.h" +#include "SyntheticSections.h" +#include "Target.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::support::endian; +using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; + +namespace { +class X86 final : public TargetInfo { +public: + X86(); + RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const override; + int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; + void writeGotPltHeader(uint8_t *Buf) const override; + uint32_t getDynRel(uint32_t Type) const override; + void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; + void writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const override; + void writePltHeader(uint8_t *Buf) const override; + void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, + int32_t Index, unsigned RelOff) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + + RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, + RelExpr Expr) const override; + void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; +}; +} // namespace + +X86::X86() { + CopyRel = R_386_COPY; + GotRel = R_386_GLOB_DAT; + PltRel = R_386_JUMP_SLOT; + IRelativeRel = R_386_IRELATIVE; + RelativeRel = R_386_RELATIVE; + TlsGotRel = R_386_TLS_TPOFF; + TlsModuleIndexRel = R_386_TLS_DTPMOD32; + TlsOffsetRel = R_386_TLS_DTPOFF32; + GotEntrySize = 4; + GotPltEntrySize = 4; + PltEntrySize = 16; + PltHeaderSize = 16; + TlsGdRelaxSkip = 2; + + // 0xCC is the "int3" (call debug exception handler) instruction. + TrapInstr = 0xcccccccc; +} + +RelExpr X86::getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const { + switch (Type) { + case R_386_8: + case R_386_16: + case R_386_32: + case R_386_TLS_LDO_32: + return R_ABS; + case R_386_TLS_GD: + return R_TLSGD; + case R_386_TLS_LDM: + return R_TLSLD; + case R_386_PLT32: + return R_PLT_PC; + case R_386_PC8: + case R_386_PC16: + case R_386_PC32: + return R_PC; + case R_386_GOTPC: + return R_GOTONLY_PC_FROM_END; + case R_386_TLS_IE: + return R_GOT; + case R_386_GOT32: + case R_386_GOT32X: + // These relocations can be calculated in two different ways. + // Usual calculation is G + A - GOT what means an offset in GOT table + // (R_GOT_FROM_END). When instruction pointed by relocation has no base + // register, then relocations can be used when PIC code is disabled. In that + // case calculation is G + A, it resolves to an address of entry in GOT + // (R_GOT) and not an offset. + // + // To check that instruction has no base register we scan ModR/M byte. + // See "Table 2-2. 32-Bit Addressing Forms with the ModR/M Byte" + // (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/ + // 64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf) + if ((Loc[-1] & 0xc7) != 0x5) + return R_GOT_FROM_END; + if (Config->Pic) + error(toString(S.File) + ": relocation " + toString(Type) + " against '" + + S.getName() + + "' without base register can not be used when PIC enabled"); + return R_GOT; + case R_386_TLS_GOTIE: + return R_GOT_FROM_END; + case R_386_GOTOFF: + return R_GOTREL_FROM_END; + case R_386_TLS_LE: + return R_TLS; + case R_386_TLS_LE_32: + return R_NEG_TLS; + case R_386_NONE: + return R_NONE; + default: + error(toString(S.File) + ": unknown relocation type: " + toString(Type)); + return R_HINT; + } +} + +RelExpr X86::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, + RelExpr Expr) const { + switch (Expr) { + default: + return Expr; + case R_RELAX_TLS_GD_TO_IE: + return R_RELAX_TLS_GD_TO_IE_END; + case R_RELAX_TLS_GD_TO_LE: + return R_RELAX_TLS_GD_TO_LE_NEG; + } +} + +void X86::writeGotPltHeader(uint8_t *Buf) const { + write32le(Buf, InX::Dynamic->getVA()); +} + +void X86::writeGotPlt(uint8_t *Buf, const SymbolBody &S) const { + // Entries in .got.plt initially points back to the corresponding + // PLT entries with a fixed offset to skip the first instruction. + write32le(Buf, S.getPltVA() + 6); +} + +void X86::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const { + // An x86 entry is the address of the ifunc resolver function. + write32le(Buf, S.getVA()); +} + +uint32_t X86::getDynRel(uint32_t Type) const { + if (Type == R_386_TLS_LE) + return R_386_TLS_TPOFF; + if (Type == R_386_TLS_LE_32) + return R_386_TLS_TPOFF32; + return Type; +} + +void X86::writePltHeader(uint8_t *Buf) const { + if (Config->Pic) { + const uint8_t V[] = { + 0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl GOTPLT+4(%ebx) + 0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *GOTPLT+8(%ebx) + 0x90, 0x90, 0x90, 0x90 // nop + }; + memcpy(Buf, V, sizeof(V)); + + uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize(); + uint32_t GotPlt = InX::GotPlt->getVA() - Ebx; + write32le(Buf + 2, GotPlt + 4); + write32le(Buf + 8, GotPlt + 8); + return; + } + + const uint8_t PltData[] = { + 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushl (GOTPLT+4) + 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *(GOTPLT+8) + 0x90, 0x90, 0x90, 0x90 // nop + }; + memcpy(Buf, PltData, sizeof(PltData)); + uint32_t GotPlt = InX::GotPlt->getVA(); + write32le(Buf + 2, GotPlt + 4); + write32le(Buf + 8, GotPlt + 8); +} + +void X86::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const { + const uint8_t Inst[] = { + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, // jmp *foo_in_GOT|*foo@GOT(%ebx) + 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $reloc_offset + 0xe9, 0x00, 0x00, 0x00, 0x00 // jmp .PLT0@PC + }; + memcpy(Buf, Inst, sizeof(Inst)); + + if (Config->Pic) { + // jmp *foo@GOT(%ebx) + uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize(); + Buf[1] = 0xa3; + write32le(Buf + 2, GotPltEntryAddr - Ebx); + } else { + // jmp *foo_in_GOT + Buf[1] = 0x25; + write32le(Buf + 2, GotPltEntryAddr); + } + + write32le(Buf + 7, RelOff); + write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16); +} + +int64_t X86::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { + switch (Type) { + default: + return 0; + case R_386_8: + case R_386_PC8: + return SignExtend64<8>(*Buf); + case R_386_16: + case R_386_PC16: + return SignExtend64<16>(read16le(Buf)); + case R_386_32: + case R_386_GOT32: + case R_386_GOT32X: + case R_386_GOTOFF: + case R_386_GOTPC: + case R_386_PC32: + case R_386_PLT32: + case R_386_TLS_LDO_32: + case R_386_TLS_LE: + return SignExtend64<32>(read32le(Buf)); + } +} + +void X86::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + // R_386_{PC,}{8,16} are not part of the i386 psABI, but they are + // being used for some 16-bit programs such as boot loaders, so + // we want to support them. + switch (Type) { + case R_386_8: + checkUInt<8>(Loc, Val, Type); + *Loc = Val; + break; + case R_386_PC8: + checkInt<8>(Loc, Val, Type); + *Loc = Val; + break; + case R_386_16: + checkUInt<16>(Loc, Val, Type); + write16le(Loc, Val); + break; + case R_386_PC16: + // R_386_PC16 is normally used with 16 bit code. In that situation + // the PC is 16 bits, just like the addend. This means that it can + // point from any 16 bit address to any other if the possibility + // of wrapping is included. + // The only restriction we have to check then is that the destination + // address fits in 16 bits. That is impossible to do here. The problem is + // that we are passed the final value, which already had the + // current location subtracted from it. + // We just check that Val fits in 17 bits. This misses some cases, but + // should have no false positives. + checkInt<17>(Loc, Val, Type); + write16le(Loc, Val); + break; + default: + checkInt<32>(Loc, Val, Type); + write32le(Loc, Val); + } +} + +void X86::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + // Convert + // leal x@tlsgd(, %ebx, 1), + // call __tls_get_addr@plt + // to + // movl %gs:0,%eax + // subl $x@ntpoff,%eax + const uint8_t Inst[] = { + 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax + 0x81, 0xe8, 0x00, 0x00, 0x00, 0x00 // subl 0(%ebx), %eax + }; + memcpy(Loc - 3, Inst, sizeof(Inst)); + write32le(Loc + 5, Val); +} + +void X86::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + // Convert + // leal x@tlsgd(, %ebx, 1), + // call __tls_get_addr@plt + // to + // movl %gs:0, %eax + // addl x@gotntpoff(%ebx), %eax + const uint8_t Inst[] = { + 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax + 0x03, 0x83, 0x00, 0x00, 0x00, 0x00 // addl 0(%ebx), %eax + }; + memcpy(Loc - 3, Inst, sizeof(Inst)); + write32le(Loc + 5, Val); +} + +// In some conditions, relocations can be optimized to avoid using GOT. +// This function does that for Initial Exec to Local Exec case. +void X86::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + // Ulrich's document section 6.2 says that @gotntpoff can + // be used with MOVL or ADDL instructions. + // @indntpoff is similar to @gotntpoff, but for use in + // position dependent code. + uint8_t Reg = (Loc[-1] >> 3) & 7; + + if (Type == R_386_TLS_IE) { + if (Loc[-1] == 0xa1) { + // "movl foo@indntpoff,%eax" -> "movl $foo,%eax" + // This case is different from the generic case below because + // this is a 5 byte instruction while below is 6 bytes. + Loc[-1] = 0xb8; + } else if (Loc[-2] == 0x8b) { + // "movl foo@indntpoff,%reg" -> "movl $foo,%reg" + Loc[-2] = 0xc7; + Loc[-1] = 0xc0 | Reg; + } else { + // "addl foo@indntpoff,%reg" -> "addl $foo,%reg" + Loc[-2] = 0x81; + Loc[-1] = 0xc0 | Reg; + } + } else { + assert(Type == R_386_TLS_GOTIE); + if (Loc[-2] == 0x8b) { + // "movl foo@gottpoff(%rip),%reg" -> "movl $foo,%reg" + Loc[-2] = 0xc7; + Loc[-1] = 0xc0 | Reg; + } else { + // "addl foo@gotntpoff(%rip),%reg" -> "leal foo(%reg),%reg" + Loc[-2] = 0x8d; + Loc[-1] = 0x80 | (Reg << 3) | Reg; + } + } + write32le(Loc, Val); +} + +void X86::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { + if (Type == R_386_TLS_LDO_32) { + write32le(Loc, Val); + return; + } + + // Convert + // leal foo(%reg),%eax + // call ___tls_get_addr + // to + // movl %gs:0,%eax + // nop + // leal 0(%esi,1),%esi + const uint8_t Inst[] = { + 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax + 0x90, // nop + 0x8d, 0x74, 0x26, 0x00 // leal 0(%esi,1),%esi + }; + memcpy(Loc - 2, Inst, sizeof(Inst)); +} + +TargetInfo *elf::createX86TargetInfo() { return make(); } Property changes on: vendor/lld/dist/ELF/Arch/X86.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/ELF/Arch/X86_64.cpp =================================================================== --- vendor/lld/dist/ELF/Arch/X86_64.cpp (nonexistent) +++ vendor/lld/dist/ELF/Arch/X86_64.cpp (revision 320021) @@ -0,0 +1,468 @@ +//===- X86_64.cpp ---------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "InputFiles.h" +#include "Memory.h" +#include "Symbols.h" +#include "SyntheticSections.h" +#include "Target.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::support::endian; +using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; + +namespace { +template class X86_64 final : public TargetInfo { +public: + X86_64(); + RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const override; + bool isPicRel(uint32_t Type) const override; + void writeGotPltHeader(uint8_t *Buf) const override; + void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; + void writePltHeader(uint8_t *Buf) const override; + void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, + int32_t Index, unsigned RelOff) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + + RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, + RelExpr Expr) const override; + void relaxGot(uint8_t *Loc, uint64_t Val) const override; + void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + +private: + void relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op, + uint8_t ModRm) const; +}; +} // namespace + +template X86_64::X86_64() { + CopyRel = R_X86_64_COPY; + GotRel = R_X86_64_GLOB_DAT; + PltRel = R_X86_64_JUMP_SLOT; + RelativeRel = R_X86_64_RELATIVE; + IRelativeRel = R_X86_64_IRELATIVE; + TlsGotRel = R_X86_64_TPOFF64; + TlsModuleIndexRel = R_X86_64_DTPMOD64; + TlsOffsetRel = R_X86_64_DTPOFF64; + GotEntrySize = 8; + GotPltEntrySize = 8; + PltEntrySize = 16; + PltHeaderSize = 16; + TlsGdRelaxSkip = 2; + + // Align to the large page size (known as a superpage or huge page). + // FreeBSD automatically promotes large, superpage-aligned allocations. + DefaultImageBase = 0x200000; + + // 0xCC is the "int3" (call debug exception handler) instruction. + TrapInstr = 0xcccccccc; +} + +template +RelExpr X86_64::getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const { + switch (Type) { + case R_X86_64_8: + case R_X86_64_16: + case R_X86_64_32: + case R_X86_64_32S: + case R_X86_64_64: + case R_X86_64_DTPOFF32: + case R_X86_64_DTPOFF64: + return R_ABS; + case R_X86_64_TPOFF32: + return R_TLS; + case R_X86_64_TLSLD: + return R_TLSLD_PC; + case R_X86_64_TLSGD: + return R_TLSGD_PC; + case R_X86_64_SIZE32: + case R_X86_64_SIZE64: + return R_SIZE; + case R_X86_64_PLT32: + return R_PLT_PC; + case R_X86_64_PC32: + case R_X86_64_PC64: + return R_PC; + case R_X86_64_GOT32: + case R_X86_64_GOT64: + return R_GOT_FROM_END; + case R_X86_64_GOTPCREL: + case R_X86_64_GOTPCRELX: + case R_X86_64_REX_GOTPCRELX: + case R_X86_64_GOTTPOFF: + return R_GOT_PC; + case R_X86_64_NONE: + return R_NONE; + default: + error(toString(S.File) + ": unknown relocation type: " + toString(Type)); + return R_HINT; + } +} + +template void X86_64::writeGotPltHeader(uint8_t *Buf) const { + // The first entry holds the value of _DYNAMIC. It is not clear why that is + // required, but it is documented in the psabi and the glibc dynamic linker + // seems to use it (note that this is relevant for linking ld.so, not any + // other program). + write64le(Buf, InX::Dynamic->getVA()); +} + +template +void X86_64::writeGotPlt(uint8_t *Buf, const SymbolBody &S) const { + // See comments in X86TargetInfo::writeGotPlt. + write32le(Buf, S.getPltVA() + 6); +} + +template void X86_64::writePltHeader(uint8_t *Buf) const { + const uint8_t PltData[] = { + 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushq GOTPLT+8(%rip) + 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *GOTPLT+16(%rip) + 0x0f, 0x1f, 0x40, 0x00 // nop + }; + memcpy(Buf, PltData, sizeof(PltData)); + uint64_t GotPlt = InX::GotPlt->getVA(); + uint64_t Plt = InX::Plt->getVA(); + write32le(Buf + 2, GotPlt - Plt + 2); // GOTPLT+8 + write32le(Buf + 8, GotPlt - Plt + 4); // GOTPLT+16 +} + +template +void X86_64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const { + const uint8_t Inst[] = { + 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip) + 0x68, 0x00, 0x00, 0x00, 0x00, // pushq + 0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[0] + }; + memcpy(Buf, Inst, sizeof(Inst)); + + write32le(Buf + 2, GotPltEntryAddr - PltEntryAddr - 6); + write32le(Buf + 7, Index); + write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16); +} + +template bool X86_64::isPicRel(uint32_t Type) const { + return Type != R_X86_64_PC32 && Type != R_X86_64_32 && + Type != R_X86_64_TPOFF32; +} + +template +void X86_64::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { + // Convert + // .byte 0x66 + // leaq x@tlsgd(%rip), %rdi + // .word 0x6666 + // rex64 + // call __tls_get_addr@plt + // to + // mov %fs:0x0,%rax + // lea x@tpoff,%rax + const uint8_t Inst[] = { + 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax + 0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 // lea x@tpoff,%rax + }; + memcpy(Loc - 4, Inst, sizeof(Inst)); + + // The original code used a pc relative relocation and so we have to + // compensate for the -4 in had in the addend. + write32le(Loc + 8, Val + 4); +} + +template +void X86_64::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { + // Convert + // .byte 0x66 + // leaq x@tlsgd(%rip), %rdi + // .word 0x6666 + // rex64 + // call __tls_get_addr@plt + // to + // mov %fs:0x0,%rax + // addq x@tpoff,%rax + const uint8_t Inst[] = { + 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax + 0x48, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00 // addq x@tpoff,%rax + }; + memcpy(Loc - 4, Inst, sizeof(Inst)); + + // Both code sequences are PC relatives, but since we are moving the constant + // forward by 8 bytes we have to subtract the value by 8. + write32le(Loc + 8, Val - 8); +} + +// In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to +// R_X86_64_TPOFF32 so that it does not use GOT. +template +void X86_64::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { + uint8_t *Inst = Loc - 3; + uint8_t Reg = Loc[-1] >> 3; + uint8_t *RegSlot = Loc - 1; + + // Note that ADD with RSP or R12 is converted to ADD instead of LEA + // because LEA with these registers needs 4 bytes to encode and thus + // wouldn't fit the space. + + if (memcmp(Inst, "\x48\x03\x25", 3) == 0) { + // "addq foo@gottpoff(%rip),%rsp" -> "addq $foo,%rsp" + memcpy(Inst, "\x48\x81\xc4", 3); + } else if (memcmp(Inst, "\x4c\x03\x25", 3) == 0) { + // "addq foo@gottpoff(%rip),%r12" -> "addq $foo,%r12" + memcpy(Inst, "\x49\x81\xc4", 3); + } else if (memcmp(Inst, "\x4c\x03", 2) == 0) { + // "addq foo@gottpoff(%rip),%r[8-15]" -> "leaq foo(%r[8-15]),%r[8-15]" + memcpy(Inst, "\x4d\x8d", 2); + *RegSlot = 0x80 | (Reg << 3) | Reg; + } else if (memcmp(Inst, "\x48\x03", 2) == 0) { + // "addq foo@gottpoff(%rip),%reg -> "leaq foo(%reg),%reg" + memcpy(Inst, "\x48\x8d", 2); + *RegSlot = 0x80 | (Reg << 3) | Reg; + } else if (memcmp(Inst, "\x4c\x8b", 2) == 0) { + // "movq foo@gottpoff(%rip),%r[8-15]" -> "movq $foo,%r[8-15]" + memcpy(Inst, "\x49\xc7", 2); + *RegSlot = 0xc0 | Reg; + } else if (memcmp(Inst, "\x48\x8b", 2) == 0) { + // "movq foo@gottpoff(%rip),%reg" -> "movq $foo,%reg" + memcpy(Inst, "\x48\xc7", 2); + *RegSlot = 0xc0 | Reg; + } else { + error(getErrorLocation(Loc - 3) + + "R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only"); + } + + // The original code used a PC relative relocation. + // Need to compensate for the -4 it had in the addend. + write32le(Loc, Val + 4); +} + +template +void X86_64::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { + // Convert + // leaq bar@tlsld(%rip), %rdi + // callq __tls_get_addr@PLT + // leaq bar@dtpoff(%rax), %rcx + // to + // .word 0x6666 + // .byte 0x66 + // mov %fs:0,%rax + // leaq bar@tpoff(%rax), %rcx + if (Type == R_X86_64_DTPOFF64) { + write64le(Loc, Val); + return; + } + if (Type == R_X86_64_DTPOFF32) { + write32le(Loc, Val); + return; + } + + const uint8_t Inst[] = { + 0x66, 0x66, // .word 0x6666 + 0x66, // .byte 0x66 + 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 // mov %fs:0,%rax + }; + memcpy(Loc - 3, Inst, sizeof(Inst)); +} + +template +void X86_64::relocateOne(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { + switch (Type) { + case R_X86_64_8: + checkUInt<8>(Loc, Val, Type); + *Loc = Val; + break; + case R_X86_64_16: + checkUInt<16>(Loc, Val, Type); + write16le(Loc, Val); + break; + case R_X86_64_32: + checkUInt<32>(Loc, Val, Type); + write32le(Loc, Val); + break; + case R_X86_64_32S: + case R_X86_64_TPOFF32: + case R_X86_64_GOT32: + case R_X86_64_GOTPCREL: + case R_X86_64_GOTPCRELX: + case R_X86_64_REX_GOTPCRELX: + case R_X86_64_PC32: + case R_X86_64_GOTTPOFF: + case R_X86_64_PLT32: + case R_X86_64_TLSGD: + case R_X86_64_TLSLD: + case R_X86_64_DTPOFF32: + case R_X86_64_SIZE32: + checkInt<32>(Loc, Val, Type); + write32le(Loc, Val); + break; + case R_X86_64_64: + case R_X86_64_DTPOFF64: + case R_X86_64_GLOB_DAT: + case R_X86_64_PC64: + case R_X86_64_SIZE64: + case R_X86_64_GOT64: + write64le(Loc, Val); + break; + default: + llvm_unreachable("unexpected relocation"); + } +} + +template +RelExpr X86_64::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, + RelExpr RelExpr) const { + if (Type != R_X86_64_GOTPCRELX && Type != R_X86_64_REX_GOTPCRELX) + return RelExpr; + const uint8_t Op = Data[-2]; + const uint8_t ModRm = Data[-1]; + + // FIXME: When PIC is disabled and foo is defined locally in the + // lower 32 bit address space, memory operand in mov can be converted into + // immediate operand. Otherwise, mov must be changed to lea. We support only + // latter relaxation at this moment. + if (Op == 0x8b) + return R_RELAX_GOT_PC; + + // Relax call and jmp. + if (Op == 0xff && (ModRm == 0x15 || ModRm == 0x25)) + return R_RELAX_GOT_PC; + + // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor. + // If PIC then no relaxation is available. + // We also don't relax test/binop instructions without REX byte, + // they are 32bit operations and not common to have. + assert(Type == R_X86_64_REX_GOTPCRELX); + return Config->Pic ? RelExpr : R_RELAX_GOT_PC_NOPIC; +} + +// A subset of relaxations can only be applied for no-PIC. This method +// handles such relaxations. Instructions encoding information was taken from: +// "Intel 64 and IA-32 Architectures Software Developer's Manual V2" +// (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/ +// 64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf) +template +void X86_64::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op, + uint8_t ModRm) const { + const uint8_t Rex = Loc[-3]; + // Convert "test %reg, foo@GOTPCREL(%rip)" to "test $foo, %reg". + if (Op == 0x85) { + // See "TEST-Logical Compare" (4-428 Vol. 2B), + // TEST r/m64, r64 uses "full" ModR / M byte (no opcode extension). + + // ModR/M byte has form XX YYY ZZZ, where + // YYY is MODRM.reg(register 2), ZZZ is MODRM.rm(register 1). + // XX has different meanings: + // 00: The operand's memory address is in reg1. + // 01: The operand's memory address is reg1 + a byte-sized displacement. + // 10: The operand's memory address is reg1 + a word-sized displacement. + // 11: The operand is reg1 itself. + // If an instruction requires only one operand, the unused reg2 field + // holds extra opcode bits rather than a register code + // 0xC0 == 11 000 000 binary. + // 0x38 == 00 111 000 binary. + // We transfer reg2 to reg1 here as operand. + // See "2.1.3 ModR/M and SIB Bytes" (Vol. 2A 2-3). + Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3; // ModR/M byte. + + // Change opcode from TEST r/m64, r64 to TEST r/m64, imm32 + // See "TEST-Logical Compare" (4-428 Vol. 2B). + Loc[-2] = 0xf7; + + // Move R bit to the B bit in REX byte. + // REX byte is encoded as 0100WRXB, where + // 0100 is 4bit fixed pattern. + // REX.W When 1, a 64-bit operand size is used. Otherwise, when 0, the + // default operand size is used (which is 32-bit for most but not all + // instructions). + // REX.R This 1-bit value is an extension to the MODRM.reg field. + // REX.X This 1-bit value is an extension to the SIB.index field. + // REX.B This 1-bit value is an extension to the MODRM.rm field or the + // SIB.base field. + // See "2.2.1.2 More on REX Prefix Fields " (2-8 Vol. 2A). + Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2; + write32le(Loc, Val); + return; + } + + // If we are here then we need to relax the adc, add, and, cmp, or, sbb, sub + // or xor operations. + + // Convert "binop foo@GOTPCREL(%rip), %reg" to "binop $foo, %reg". + // Logic is close to one for test instruction above, but we also + // write opcode extension here, see below for details. + Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3 | (Op & 0x3c); // ModR/M byte. + + // Primary opcode is 0x81, opcode extension is one of: + // 000b = ADD, 001b is OR, 010b is ADC, 011b is SBB, + // 100b is AND, 101b is SUB, 110b is XOR, 111b is CMP. + // This value was wrote to MODRM.reg in a line above. + // See "3.2 INSTRUCTIONS (A-M)" (Vol. 2A 3-15), + // "INSTRUCTION SET REFERENCE, N-Z" (Vol. 2B 4-1) for + // descriptions about each operation. + Loc[-2] = 0x81; + Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2; + write32le(Loc, Val); +} + +template +void X86_64::relaxGot(uint8_t *Loc, uint64_t Val) const { + const uint8_t Op = Loc[-2]; + const uint8_t ModRm = Loc[-1]; + + // Convert "mov foo@GOTPCREL(%rip),%reg" to "lea foo(%rip),%reg". + if (Op == 0x8b) { + Loc[-2] = 0x8d; + write32le(Loc, Val); + return; + } + + if (Op != 0xff) { + // We are relaxing a rip relative to an absolute, so compensate + // for the old -4 addend. + assert(!Config->Pic); + relaxGotNoPic(Loc, Val + 4, Op, ModRm); + return; + } + + // Convert call/jmp instructions. + if (ModRm == 0x15) { + // ABI says we can convert "call *foo@GOTPCREL(%rip)" to "nop; call foo". + // Instead we convert to "addr32 call foo" where addr32 is an instruction + // prefix. That makes result expression to be a single instruction. + Loc[-2] = 0x67; // addr32 prefix + Loc[-1] = 0xe8; // call + write32le(Loc, Val); + return; + } + + // Convert "jmp *foo@GOTPCREL(%rip)" to "jmp foo; nop". + // jmp doesn't return, so it is fine to use nop here, it is just a stub. + assert(ModRm == 0x25); + Loc[-2] = 0xe9; // jmp + Loc[3] = 0x90; // nop + write32le(Loc - 1, Val + 1); +} + +TargetInfo *elf::createX32TargetInfo() { return make>(); } +TargetInfo *elf::createX86_64TargetInfo() { return make>(); } Property changes on: vendor/lld/dist/ELF/Arch/X86_64.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/ELF/CMakeLists.txt =================================================================== --- vendor/lld/dist/ELF/CMakeLists.txt (revision 320020) +++ vendor/lld/dist/ELF/CMakeLists.txt (revision 320021) @@ -1,65 +1,74 @@ set(LLVM_TARGET_DEFINITIONS Options.td) tablegen(LLVM Options.inc -gen-opt-parser-defs) add_public_tablegen_target(ELFOptionsTableGen) if(NOT LLD_BUILT_STANDALONE) set(tablegen_deps intrinsics_gen) endif() add_lld_library(lldELF + Arch/AArch64.cpp + Arch/AMDGPU.cpp + Arch/ARM.cpp + Arch/AVR.cpp + Arch/Mips.cpp + Arch/PPC.cpp + Arch/PPC64.cpp + Arch/X86.cpp + Arch/X86_64.cpp Driver.cpp DriverUtils.cpp EhFrame.cpp Error.cpp Filesystem.cpp GdbIndex.cpp ICF.cpp InputFiles.cpp InputSection.cpp LTO.cpp LinkerScript.cpp MapFile.cpp MarkLive.cpp Mips.cpp OutputSections.cpp Relocations.cpp ScriptLexer.cpp ScriptParser.cpp Strings.cpp SymbolTable.cpp Symbols.cpp SyntheticSections.cpp Target.cpp Thunks.cpp Writer.cpp LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} Analysis BinaryFormat BitReader BitWriter Codegen Core DebugInfoDWARF Demangle IPO Linker LTO Object Option Passes MC Support Target TransformUtils LINK_LIBS lldConfig lldCore ${LLVM_PTHREAD_LIB} DEPENDS ELFOptionsTableGen ${tablegen_deps} ) Index: vendor/lld/dist/ELF/Driver.cpp =================================================================== --- vendor/lld/dist/ELF/Driver.cpp (revision 320020) +++ vendor/lld/dist/ELF/Driver.cpp (revision 320021) @@ -1,1024 +1,1012 @@ //===- Driver.cpp ---------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // The driver drives the entire linking process. It is responsible for // parsing command line options and doing whatever it is instructed to do. // // One notable thing in the LLD's driver when compared to other linkers is // that the LLD's driver is agnostic on the host operating system. // Other linkers usually have implicit default values (such as a dynamic // linker path or library paths) for each host OS. // // I don't think implicit default values are useful because they are // usually explicitly specified by the compiler driver. They can even // be harmful when you are doing cross-linking. Therefore, in LLD, we // simply trust the compiler driver to pass all required options and // don't try to make effort on our side. // //===----------------------------------------------------------------------===// #include "Driver.h" #include "Config.h" #include "Error.h" #include "Filesystem.h" #include "ICF.h" #include "InputFiles.h" #include "InputSection.h" #include "LinkerScript.h" #include "Memory.h" #include "OutputSections.h" #include "ScriptParser.h" #include "Strings.h" #include "SymbolTable.h" +#include "SyntheticSections.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/Object/Decompressor.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Path.h" #include "llvm/Support/TarWriter.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; static void setConfigs(); bool elf::link(ArrayRef Args, bool CanExitEarly, raw_ostream &Error) { ErrorCount = 0; ErrorOS = &Error; Argv0 = Args[0]; InputSections.clear(); Tar = nullptr; Config = make(); Driver = make(); Script = 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}) + .Cases("armelf", "armelf_linux_eabi", {ELF32LEKind, EM_ARM}) .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64}) .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) .Cases("elf32ltsmip", "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> static 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(std::make_pair(MBRef, C.getChildOffset())); } 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 a file and create a file object. Path has to be resolved already. void LinkerDriver::addFile(StringRef Path, bool WithLOption) { 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: { // Handle -whole-archive. if (InWholeArchive) { for (const auto &P : getArchiveMembers(MBRef)) Files.push_back(createObjectFile(P.first, Path, P.second)); return; } std::unique_ptr File = check(Archive::create(MBRef), Path + ": failed to parse archive"); // If an archive file has no symbol table, it is likely that a user // is attempting LTO and using a default ar command that doesn't // understand the LLVM bitcode file. It is a pretty common error, so // we'll handle it as if it had a symbol table. if (!File->isEmpty() && !File->hasSymbolTable()) { for (const auto &P : getArchiveMembers(MBRef)) Files.push_back(make(P.first, Path, P.second)); return; } // Handle the regular case. Files.push_back(make(std::move(File))); return; } case file_magic::elf_shared_object: if (Config->Relocatable) { error("attempted static link of dynamic object " + Path); return; } // DSOs usually have DT_SONAME tags in their ELF headers, and the // sonames are used to identify DSOs. But if they are missing, // they are identified by filenames. We don't know whether the new // file has a DT_SONAME or not because we haven't parsed it yet. // Here, we set the default soname for the file because we might // need it later. // // If a file was specified by -lfoo, the directory part is not // significant, as a user did not specify it. This behavior is // compatible with GNU. Files.push_back(createSharedFile( MBRef, WithLOption ? sys::path::filename(Path) : Path)); return; default: if (InLib) Files.push_back(make(MBRef, "", 0)); else Files.push_back(createObjectFile(MBRef)); } } // Add a given library by searching it from input search paths. void LinkerDriver::addLibrary(StringRef Name) { if (Optional Path = searchLibrary(Name)) addFile(*Path, /*WithLOption=*/true); 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->Shared && !Config->AuxiliaryList.empty()) error("-f may not be used without -shared"); 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 (!to_integer(S, V, 10)) 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); + std::pair KV = StringRef(Arg->getValue()).split('='); + if (KV.first == Key) { uint64_t Result; - if (!to_integer(Value, Result)) - error("invalid " + Key + ": " + Value); + if (!to_integer(KV.second, Result)) + error("invalid " + Key + ": " + KV.second); 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; } // Handle -v or -version. // // A note about "compatible with GNU linkers" message: this is a hack for // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and // still the newest version in March 2017) or earlier to recognize LLD as // a GNU compatible linker. As long as an output for the -v option // contains "GNU" or "with BFD", they recognize us as GNU-compatible. // // This is somewhat ugly hack, but in reality, we had no choice other // than doing this. Considering the very long release cycle of Libtool, // it is not easy to improve it to recognize LLD as a GNU compatible // linker in a timely manner. Even if we can make it, there are still a // lot of "configure" scripts out there that are generated by old version // of Libtool. We cannot convince every software developer to migrate to // the latest version and re-generate scripts. So we have this hack. if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) message(getLLDVersion() + " (compatible with GNU linkers)"); // ld.bfd always exits after printing out the version string. // ld.gold proceeds if a given option is -v. Because gold's behavior // is more permissive than ld.bfd, we chose what gold does here. 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. Expected> ErrOrWriter = TarWriter::create(Path, path::stem(Path)); if (ErrOrWriter) { Tar = ErrOrWriter->get(); Tar->append("response.txt", createResponseFile(Args)); Tar->append("version.txt", getLLDVersion() + "\n"); make>(std::move(*ErrOrWriter)); } else { error(Twine("--reproduce: failed to open ") + Path + ": " + toString(ErrOrWriter.takeError())); } } readConfigs(Args); initLLVM(Args); createFiles(Args); inferMachineType(); setConfigs(); 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 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 std::vector getArgs(opt::InputArgList &Args, int Id) { std::vector V; for (auto *Arg : Args.filtered(Id)) V.push_back(Arg->getValue()); return V; } static std::string getRpath(opt::InputArgList &Args) { std::vector V = getArgs(Args, OPT_rpath); return llvm::join(V.begin(), V.end(), ":"); } // Determines what we should do if there are remaining unresolved // symbols after the name resolution. static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &Args) { // -noinhibit-exec or -r imply some default values. if (Args.hasArg(OPT_noinhibit_exec)) return UnresolvedPolicy::WarnAll; if (Args.hasArg(OPT_relocatable)) return UnresolvedPolicy::IgnoreAll; UnresolvedPolicy ErrorOrWarn = getArg(Args, OPT_error_unresolved_symbols, OPT_warn_unresolved_symbols, true) ? UnresolvedPolicy::ReportError : UnresolvedPolicy::Warn; // Process the last of -unresolved-symbols, -no-undefined or -z defs. for (auto *Arg : llvm::reverse(Args)) { switch (Arg->getOption().getID()) { case 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 ErrorOrWarn; error("unknown --unresolved-symbols value: " + S); continue; } case OPT_no_undefined: return ErrorOrWarn; case OPT_z: if (StringRef(Arg->getValue()) == "defs") return ErrorOrWarn; continue; } } // -shared implies -unresolved-symbols=ignore-all because missing // symbols are likely to be resolved at runtime using other DSOs. if (Config->Shared) return UnresolvedPolicy::Ignore; return ErrorOrWarn; } static Target2Policy getTarget2(opt::InputArgList &Args) { - StringRef S = getString(Args, OPT_target2, "got-rel"); + StringRef S = Args.getLastArgValue(OPT_target2, "got-rel"); 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 DiscardPolicy getDiscard(opt::InputArgList &Args) { if (Args.hasArg(OPT_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 StringRef getDynamicLinker(opt::InputArgList &Args) { auto *Arg = Args.getLastArg(OPT_dynamic_linker, OPT_no_dynamic_linker); if (!Arg || Arg->getOption().getID() == OPT_no_dynamic_linker) return ""; return Arg->getValue(); } static StripPolicy getStrip(opt::InputArgList &Args) { if (Args.hasArg(OPT_relocatable)) return StripPolicy::None; auto *Arg = Args.getLastArg(OPT_strip_all, OPT_strip_debug); if (!Arg) return StripPolicy::None; if (Arg->getOption().getID() == OPT_strip_all) return StripPolicy::All; return StripPolicy::Debug; } static uint64_t parseSectionAddress(StringRef S, opt::Arg *Arg) { uint64_t VA = 0; if (S.startswith("0x")) S = S.drop_front(2); if (!to_integer(S, VA, 16)) 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 getSortSection(opt::InputArgList &Args) { - StringRef S = getString(Args, OPT_sort_section); + StringRef S = Args.getLastArgValue(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::pair getHashStyle(opt::InputArgList &Args) { - StringRef S = getString(Args, OPT_hash_style, "sysv"); + StringRef S = Args.getLastArgValue(OPT_hash_style, "sysv"); if (S == "sysv") return {true, false}; if (S == "gnu") return {false, true}; if (S != "both") error("unknown -hash-style: " + S); return {true, true}; } // Parse --build-id or --build-id= .. role:: none .. role:: partial .. role:: good =============== Windows support =============== LLD supports Windows operating system. When invoked as ``lld-link.exe`` or with ``-flavor link``, the driver for Windows operating system is used to parse command line options, and it drives further linking processes. LLD accepts almost all command line options that the linker shipped with Microsoft Visual C++ (link.exe) supports. The current status is that LLD can link itself on Windows x86/x64 using Visual C++ 2013 as the compiler. Development status ================== Driver :good:`Mostly done`. Some exotic command line options that are not usually used for application develompent, such as ``/DRIVER``, are not supported. Options for Windows 8 app store are not recognized too (e.g. ``/APPCONTAINER``). Linking against DLL :good:`Done`. LLD can read import libraries needed to link against DLL. Both export-by-name and export-by-ordinal are supported. Linking against static library :good:`Done`. The format of static library (.lib) on Windows is actually the same as on Unix (.a). LLD can read it. Creating DLL :good:`Done`. LLD creates a DLL if ``/DLL`` option is given. Exported functions can be specified either via command line (``/EXPORT``) or via module-definition file (.def). Both export-by-name and export-by-ordinal are supported. LLD uses Microsoft ``lib.exe`` tool to create an import library file. Windows resource files support - :good:`Done`. If an ``.rc`` file is given, LLD converts the file to a COFF - file using some external commands and link it. Specifically, ``rc.exe`` is - used to compile a resource file (.rc) to a compiled resource (.res) - file. ``rescvt.exe`` is then used to convert a compiled resource file to a - COFF object file section. Both tools are shipped with MSVC. + :good:`Done`. If an ``.res`` file is given, LLD converts the file to a COFF + file using ``cvtres.exe`` command and link it. Safe Structured Exception Handler (SEH) :good:`Done` for both x86 and x64. Module-definition file :partial:`Partially done`. LLD currently recognizes these directives: ``EXPORTS``, ``HEAPSIZE``, ``STACKSIZE``, ``NAME``, and ``VERSION``. Debug info :none:`No progress has been made`. Microsoft linker can interpret the CodeGen debug info (old-style debug info) and PDB to emit an .pdb file. LLD doesn't support neither. Building LLD ============ Using Visual Studio IDE/MSBuild ------------------------------- 1. Check out LLVM and LLD from the LLVM SVN repository (or Git mirror), #. run ``cmake -G "Visual Studio 12" `` from VS command prompt, #. open LLVM.sln with Visual Studio, and #. build ``lld`` target in ``lld executables`` folder Alternatively, you can use msbuild if you don't like to work in an IDE:: msbuild LLVM.sln /m /target:"lld executables\lld" MSBuild.exe had been shipped as a component of the .NET framework, but since 2013 it's part of Visual Studio. You can find it at "C:\\Program Files (x86)\\msbuild". You can build LLD as a 64 bit application. To do that, open VS2013 x64 command prompt and run cmake for "Visual Studio 12 Win64" target. Using Ninja ----------- 1. Check out LLVM and LLD from the LLVM SVN repository (or Git mirror), #. run ``cmake -G ninja `` from VS command prompt, #. run ``ninja lld`` Index: vendor/lld/dist/test/COFF/Inputs/constant-export.ll =================================================================== --- vendor/lld/dist/test/COFF/Inputs/constant-export.ll (revision 320020) +++ vendor/lld/dist/test/COFF/Inputs/constant-export.ll (revision 320021) @@ -1,10 +1,7 @@ target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" target triple = "i686-unknown-windows-msvc18.0.0" @__CFConstantStringClassReference = common global [32 x i32] zeroinitializer, align 4 -!llvm.module.flags = !{!0} - -!0 = !{i32 6, !"Linker Options", !1} -!1 = !{!2} -!2 = !{!" -export:___CFConstantStringClassReference,CONSTANT"} +!llvm.linker.options = !{!0} +!0 = !{!" -export:___CFConstantStringClassReference,CONSTANT"} Index: vendor/lld/dist/test/COFF/Inputs/library.def =================================================================== --- vendor/lld/dist/test/COFF/Inputs/library.def (nonexistent) +++ vendor/lld/dist/test/COFF/Inputs/library.def (revision 320021) @@ -0,0 +1,5 @@ +LIBRARY library +EXPORTS + function + data DATA + constant CONSTANT Index: vendor/lld/dist/test/COFF/Inputs/pdb1.yaml =================================================================== --- vendor/lld/dist/test/COFF/Inputs/pdb1.yaml (revision 320020) +++ vendor/lld/dist/test/COFF/Inputs/pdb1.yaml (revision 320021) @@ -1,172 +1,306 @@ --- !COFF header: Machine: IMAGE_FILE_MACHINE_AMD64 Characteristics: [ ] sections: - Name: .drectve Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] Alignment: 1 SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D45532220 - Name: '.debug$S' Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 - SectionData: 04000000F1000000580000001A00011100000000443A5C625C72657434322D6D61696E2E6F626A003A003C1100600000D00013000000F259000013000000F25900004D6963726F736F667420285229204F7074696D697A696E6720436F6D70696C657200F10000004E0000002A0047110000000000000000000000000E000000040000000900000005100000000000000000006D61696E001C001210280000000000000000000000000000000000000000000042110002004F110000F20000002000000000000000000000000E0000000000000001000000140000000000000002000080F400000018000000010000001001C538722F63570DF6705DDE06FE96E5D10000F30000001300000000643A5C625C72657434322D6D61696E2E630000F10000000800000006004C110E100000 + Subsections: + - !Symbols + Records: + - Kind: S_OBJNAME + ObjNameSym: + Signature: 0 + ObjectName: 'D:\b\ret42-main.obj' + - Kind: S_COMPILE3 + Compile3Sym: + Flags: [ SecurityChecks, HotPatch ] + Machine: X64 + FrontendMajor: 19 + FrontendMinor: 0 + FrontendBuild: 23026 + FrontendQFE: 0 + BackendMajor: 19 + BackendMinor: 0 + BackendBuild: 23026 + BackendQFE: 0 + Version: 'Microsoft (R) Optimizing Compiler' + - !Symbols + Records: + - Kind: S_GPROC32_ID + ProcSym: + PtrParent: 0 + PtrEnd: 0 + PtrNext: 0 + CodeSize: 14 + DbgStart: 4 + DbgEnd: 9 + FunctionType: 4101 + Segment: 0 + Flags: [ ] + DisplayName: main + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 40 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 14 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'd:\b\ret42-main.c' + Lines: + - Offset: 0 + LineStart: 2 + IsStatement: true + EndDelta: 0 + Columns: + - !FileChecksums + Checksums: + - FileName: 'd:\b\ret42-main.c' + Kind: MD5 + Checksum: C538722F63570DF6705DDE06FE96E5D1 + - !StringTable + Strings: + - 'd:\b\ret42-main.c' + - !Symbols + Records: + - Kind: S_BUILDINFO + BuildInfoSym: + BuildId: 4110 Relocations: - VirtualAddress: 140 SymbolName: main Type: IMAGE_REL_AMD64_SECREL - VirtualAddress: 144 SymbolName: main Type: IMAGE_REL_AMD64_SECTION - VirtualAddress: 196 SymbolName: main Type: IMAGE_REL_AMD64_SECREL - VirtualAddress: 200 SymbolName: main Type: IMAGE_REL_AMD64_SECTION - Name: '.debug$T' Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 - SectionData: 0400000006000112000000000E0008107400000000000000001000000A000210011000000C0001000A00011201000000000000000E0008107400000000000000031000001200011600000000041000006D61696E00F3F2F10E0001160000000001100000666F6F000E00051600000000443A5C6200F3F2F12200051600000000433A5C767331345C56435C42494E5C616D6436345C636C2E6578650002010516000000002D5A37202D63202D4D54202D49433A5C767331345C56435C494E434C554445202D49433A5C767331345C56435C41544C4D46435C494E434C554445202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C31305C696E636C7564655C31302E302E31303135302E305C7563727422202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C4E4554465853444B5C342E365C696E636C7564655C756D22202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C382E315C696E636C7564655C73686172656422000A0004160100000009100000820005160A100000202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C382E315C696E636C7564655C756D22202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C382E315C696E636C7564655C77696E727422202D5443202D5800F3F2F1160005160000000072657434322D6D61696E2E6300F3F2F11600051600000000443A5C625C76633134302E70646200F11A000316050007100000081000000C1000000D1000000B100000F2F1 + Types: + - Kind: LF_ARGLIST + ArgList: + ArgIndices: [ ] + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 116 + CallConv: NearC + Options: [ None ] + ParameterCount: 0 + ArgumentList: 4096 + - Kind: LF_POINTER + Pointer: + ReferentType: 4097 + Attrs: 65548 + - Kind: LF_ARGLIST + ArgList: + ArgIndices: [ 0 ] + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 116 + CallConv: NearC + Options: [ None ] + ParameterCount: 0 + ArgumentList: 4099 + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4100 + Name: main + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4097 + Name: foo + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'D:\b' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'C:\vs14\VC\BIN\amd64\cl.exe' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: '-Z7 -c -MT -IC:\vs14\VC\INCLUDE -IC:\vs14\VC\ATLMFC\INCLUDE -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared"' + - Kind: LF_SUBSTR_LIST + StringList: + StringIndices: [ 4105 ] + - Kind: LF_STRING_ID + StringId: + Id: 4106 + String: ' -I"C:\Program Files (x86)\Windows Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TC -X' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: ret42-main.c + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'D:\b\vc140.pdb' + - Kind: LF_BUILDINFO + BuildInfo: + ArgIndices: [ 4103, 4104, 4108, 4109, 4107 ] - Name: '.text$mn' Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] Alignment: 16 SectionData: 4883EC28E8000000004883C428C3 Relocations: - VirtualAddress: 5 SymbolName: foo Type: IMAGE_REL_AMD64_REL32 - Name: .xdata Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] Alignment: 4 SectionData: '0104010004420000' - Name: .pdata Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] Alignment: 4 SectionData: '000000000E00000000000000' Relocations: - VirtualAddress: 0 SymbolName: '$LN3' Type: IMAGE_REL_AMD64_ADDR32NB - VirtualAddress: 4 SymbolName: '$LN3' Type: IMAGE_REL_AMD64_ADDR32NB - VirtualAddress: 8 SymbolName: '$unwind$main' Type: IMAGE_REL_AMD64_ADDR32NB symbols: - Name: '@comp.id' Value: 17062386 SectionNumber: -1 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC - Name: '@feat.00' Value: 2147484048 SectionNumber: -1 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC - Name: .drectve Value: 0 SectionNumber: 1 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 47 NumberOfRelocations: 0 NumberOfLinenumbers: 0 CheckSum: 0 Number: 0 - Name: '.debug$S' Value: 0 SectionNumber: 2 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 304 NumberOfRelocations: 4 NumberOfLinenumbers: 0 CheckSum: 0 Number: 0 - Name: '.debug$T' Value: 0 SectionNumber: 3 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 636 NumberOfRelocations: 0 NumberOfLinenumbers: 0 CheckSum: 0 Number: 0 - Name: '.text$mn' Value: 0 SectionNumber: 4 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 14 NumberOfRelocations: 1 NumberOfLinenumbers: 0 CheckSum: 1682752513 Number: 0 - Name: foo Value: 0 SectionNumber: 0 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_FUNCTION StorageClass: IMAGE_SYM_CLASS_EXTERNAL - Name: main Value: 0 SectionNumber: 4 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_FUNCTION StorageClass: IMAGE_SYM_CLASS_EXTERNAL - Name: '$LN3' Value: 0 SectionNumber: 4 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_LABEL - Name: .xdata Value: 0 SectionNumber: 5 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 8 NumberOfRelocations: 0 NumberOfLinenumbers: 0 CheckSum: 264583633 Number: 0 - Name: '$unwind$main' Value: 0 SectionNumber: 5 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC - Name: .pdata Value: 0 SectionNumber: 6 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 12 NumberOfRelocations: 3 NumberOfLinenumbers: 0 CheckSum: 361370162 Number: 0 - Name: '$pdata$main' Value: 0 SectionNumber: 6 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC ... Index: vendor/lld/dist/test/COFF/Inputs/pdb2.yaml =================================================================== --- vendor/lld/dist/test/COFF/Inputs/pdb2.yaml (revision 320020) +++ vendor/lld/dist/test/COFF/Inputs/pdb2.yaml (revision 320021) @@ -1,102 +1,217 @@ --- !COFF header: Machine: IMAGE_FILE_MACHINE_AMD64 Characteristics: [ ] sections: - Name: .drectve Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] Alignment: 1 SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D45532220 - Name: '.debug$S' Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 - SectionData: 04000000F1000000570000001900011100000000443A5C625C72657434322D7375622E6F626A003A003C1100600000D00013000000F259000013000000F25900004D6963726F736F667420285229204F7074696D697A696E6720436F6D70696C65720000F10000004D000000290047110000000000000000000000000600000000000000050000000210000000000000000000666F6F001C001210000000000000000000000000000000000000000000000042110002004F11000000F2000000200000000000000000000000060000000000000001000000140000000000000001000080F400000018000000010000001001EC2D89EFF5A1FEB6B74EE4D79074072F0000F30000001200000000643A5C625C72657434322D7375622E63000000F10000000800000006004C110A100000 + Subsections: + - !Symbols + Records: + - Kind: S_OBJNAME + ObjNameSym: + Signature: 0 + ObjectName: 'D:\b\ret42-sub.obj' + - Kind: S_COMPILE3 + Compile3Sym: + Flags: [ SecurityChecks, HotPatch ] + Machine: X64 + FrontendMajor: 19 + FrontendMinor: 0 + FrontendBuild: 23026 + FrontendQFE: 0 + BackendMajor: 19 + BackendMinor: 0 + BackendBuild: 23026 + BackendQFE: 0 + Version: 'Microsoft (R) Optimizing Compiler' + - !Symbols + Records: + - Kind: S_GPROC32_ID + ProcSym: + PtrParent: 0 + PtrEnd: 0 + PtrNext: 0 + CodeSize: 6 + DbgStart: 0 + DbgEnd: 5 + FunctionType: 4098 + Segment: 0 + Flags: [ ] + DisplayName: foo + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 0 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 6 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'd:\b\ret42-sub.c' + Lines: + - Offset: 0 + LineStart: 1 + IsStatement: true + EndDelta: 0 + Columns: + - !FileChecksums + Checksums: + - FileName: 'd:\b\ret42-sub.c' + Kind: MD5 + Checksum: EC2D89EFF5A1FEB6B74EE4D79074072F + - !StringTable + Strings: + - 'd:\b\ret42-sub.c' + - !Symbols + Records: + - Kind: S_BUILDINFO + BuildInfoSym: + BuildId: 4106 Relocations: - VirtualAddress: 140 SymbolName: foo Type: IMAGE_REL_AMD64_SECREL - VirtualAddress: 144 SymbolName: foo Type: IMAGE_REL_AMD64_SECTION - VirtualAddress: 196 SymbolName: foo Type: IMAGE_REL_AMD64_SECREL - VirtualAddress: 200 SymbolName: foo Type: IMAGE_REL_AMD64_SECTION - Name: '.debug$T' Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 - SectionData: 0400000006000112000000000E0008107400000000000000001000000E0001160000000001100000666F6F000E00051600000000443A5C6200F3F2F12200051600000000433A5C767331345C56435C42494E5C616D6436345C636C2E6578650002010516000000002D5A37202D63202D4D54202D49433A5C767331345C56435C494E434C554445202D49433A5C767331345C56435C41544C4D46435C494E434C554445202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C31305C696E636C7564655C31302E302E31303135302E305C7563727422202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C4E4554465853444B5C342E365C696E636C7564655C756D22202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C382E315C696E636C7564655C73686172656422000A00041601000000051000008200051606100000202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C382E315C696E636C7564655C756D22202D4922433A5C50726F6772616D2046696C65732028783836295C57696E646F7773204B6974735C382E315C696E636C7564655C77696E727422202D5443202D5800F3F2F1120005160000000072657434322D7375622E63001600051600000000443A5C625C76633134302E70646200F11A00031605000310000004100000081000000910000007100000F2F1 + Types: + - Kind: LF_ARGLIST + ArgList: + ArgIndices: [ ] + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 116 + CallConv: NearC + Options: [ None ] + ParameterCount: 0 + ArgumentList: 4096 + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4097 + Name: foo + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'D:\b' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'C:\vs14\VC\BIN\amd64\cl.exe' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: '-Z7 -c -MT -IC:\vs14\VC\INCLUDE -IC:\vs14\VC\ATLMFC\INCLUDE -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared"' + - Kind: LF_SUBSTR_LIST + StringList: + StringIndices: [ 4101 ] + - Kind: LF_STRING_ID + StringId: + Id: 4102 + String: ' -I"C:\Program Files (x86)\Windows Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TC -X' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: ret42-sub.c + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'D:\b\vc140.pdb' + - Kind: LF_BUILDINFO + BuildInfo: + ArgIndices: [ 4099, 4100, 4104, 4105, 4103 ] - Name: '.text$mn' Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] Alignment: 16 SectionData: B82A000000C3 symbols: - Name: '@comp.id' Value: 17062386 SectionNumber: -1 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC - Name: '@feat.00' Value: 2147484048 SectionNumber: -1 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC - Name: .drectve Value: 0 SectionNumber: 1 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 47 NumberOfRelocations: 0 NumberOfLinenumbers: 0 CheckSum: 0 Number: 0 - Name: '.debug$S' Value: 0 SectionNumber: 2 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 304 NumberOfRelocations: 4 NumberOfLinenumbers: 0 CheckSum: 0 Number: 0 - Name: '.debug$T' Value: 0 SectionNumber: 3 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 572 NumberOfRelocations: 0 NumberOfLinenumbers: 0 CheckSum: 0 Number: 0 - Name: '.text$mn' Value: 0 SectionNumber: 4 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 6 NumberOfRelocations: 0 NumberOfLinenumbers: 0 CheckSum: 2139436471 Number: 0 - Name: foo Value: 0 SectionNumber: 4 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_FUNCTION StorageClass: IMAGE_SYM_CLASS_EXTERNAL ... Index: vendor/lld/dist/test/COFF/include-lto.ll =================================================================== --- vendor/lld/dist/test/COFF/include-lto.ll (revision 320020) +++ vendor/lld/dist/test/COFF/include-lto.ll (revision 320021) @@ -1,24 +1,21 @@ ; RUN: llvm-as -o %t.obj %s ; RUN: lld-link /dll /out:%t.dll %t.obj ; RUN: llvm-objdump -d %t.dll | FileCheck %s ; Checks that code for foo is emitted, as required by the /INCLUDE directive. ; CHECK: xorl %eax, %eax ; CHECK-NEXT: retq target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc" define void @_DllMainCRTStartup() { ret void } define i32 @foo() { ret i32 0 } -!llvm.module.flags = !{!0} - -!0 = !{i32 6, !"Linker Options", !1} -!1 = !{!2} -!2 = !{!"/INCLUDE:foo"} +!llvm.linker.options = !{!0} +!0 = !{!"/INCLUDE:foo"} Index: vendor/lld/dist/test/COFF/lib.test =================================================================== --- vendor/lld/dist/test/COFF/lib.test (nonexistent) +++ vendor/lld/dist/test/COFF/lib.test (revision 320021) @@ -0,0 +1,11 @@ +# RUN: lld-link /machine:x64 /def:%S/Inputs/library.def /out:%t.lib +# RUN: llvm-nm %t.lib | FileCheck %s + +CHECK: 00000000 R __imp_constant +CHECK: 00000000 R constant + +CHECK: 00000000 D __imp_data + +CHECK: 00000000 T __imp_function +CHECK: 00000000 T function + Index: vendor/lld/dist/test/COFF/lto-linker-opts.ll =================================================================== --- vendor/lld/dist/test/COFF/lto-linker-opts.ll (revision 320020) +++ vendor/lld/dist/test/COFF/lto-linker-opts.ll (revision 320021) @@ -1,11 +1,8 @@ ; RUN: llvm-as -o %T/lto-linker-opts.obj %s ; RUN: env LIB=%S/Inputs lld-link /out:%T/lto-linker-opts.exe /entry:main /subsystem:console %T/lto-linker-opts.obj target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc" -!llvm.module.flags = !{!0} - -!0 = !{i32 6, !"Linker Options", !1} -!1 = !{!2} -!2 = !{!"/DEFAULTLIB:ret42.lib"} +!llvm.linker.options = !{!0} +!0 = !{!"/DEFAULTLIB:ret42.lib"} Index: vendor/lld/dist/test/COFF/pdb-lib.s =================================================================== --- vendor/lld/dist/test/COFF/pdb-lib.s (nonexistent) +++ vendor/lld/dist/test/COFF/pdb-lib.s (revision 320021) @@ -0,0 +1,32 @@ +# RUN: rm -rf %t && mkdir -p %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o foo.obj +# RUN: llc %S/Inputs/bar.ll -filetype=obj -mtriple=i686-windows-msvc -o bar.obj +# RUN: llvm-lib bar.obj -out:bar.lib +# RUN: lld-link -debug -pdb:foo.pdb foo.obj bar.lib -out:foo.exe -entry:main +# RUN: llvm-pdbutil raw -modules %t/foo.pdb | FileCheck %s + +# Make sure that the PDB has module descriptors. foo.obj and bar.lib should be +# absolute paths, and bar.obj should be the relative path passed to llvm-lib. + +# CHECK: Modules +# CHECK-NEXT: ============================================================ +# CHECK-NEXT: Mod 0000 | Name: `{{.*pdb-lib.s.tmp[/\\]foo.obj}}`: +# CHECK-NEXT: Obj: `{{.*pdb-lib.s.tmp[/\\]foo.obj}}`: +# CHECK-NEXT: debug stream: 9, # files: 0, has ec info: false +# CHECK-NEXT: Mod 0001 | Name: `bar.obj`: +# CHECK-NEXT: Obj: `{{.*pdb-lib.s.tmp[/\\]bar.lib}}`: +# CHECK-NEXT: debug stream: 10, # files: 0, has ec info: false +# CHECK-NEXT: Mod 0002 | Name: `* Linker *`: +# CHECK-NEXT: Obj: ``: +# CHECK-NEXT: debug stream: 11, # files: 0, has ec info: false + + .def _main; + .scl 2; + .type 32; + .endef + .globl _main +_main: + calll _bar + xor %eax, %eax + retl + Property changes on: vendor/lld/dist/test/COFF/pdb-lib.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/COFF/pdb-none.test =================================================================== --- vendor/lld/dist/test/COFF/pdb-none.test (revision 320020) +++ vendor/lld/dist/test/COFF/pdb-none.test (revision 320021) @@ -1,13 +1,14 @@ # RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj # RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj # RUN: lld-link /debug /debugtype:pdata /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \ # RUN: %t1.obj %t2.obj # RUN: llvm-pdbutil pdb2yaml -pdb-stream %t.pdb | FileCheck %s # CHECK: PdbStream: # CHECK-NEXT: Age: 0 # CHECK-NEXT: Guid: '{00000000-0000-0000-0000-000000000000}' # CHECK-NEXT: Signature: 0 +# CHECK-NEXT: Features: [ VC140 ] # CHECK-NEXT: Version: VC70 Index: vendor/lld/dist/test/COFF/pdb-options.test =================================================================== --- vendor/lld/dist/test/COFF/pdb-options.test (revision 320020) +++ vendor/lld/dist/test/COFF/pdb-options.test (revision 320021) @@ -1,20 +1,21 @@ # RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj # RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj ; If /DEBUG is not specified, /pdb is ignored. +# RUN: rm -f %t.pdb # RUN: lld-link /pdb:%t.pdb /entry:main /nodefaultlib %t1.obj %t2.obj # RUN: not ls %t.pdb ; If /DEBUG and /pdb are specified, it uses the specified name. # RUN: lld-link /DEBUG /pdb:%t.pdb /entry:main /nodefaultlib %t1.obj %t2.obj # RUN: ls %t.pdb # RUN: rm %t.pdb ; If /DEBUG is specified but not /pdb, it uses a default name in the current ; directory. This is a bit hacky since but we need to be IN our test specific ; temporary directory when we run this command or we can't test this # RUN: cd %T # RUN: lld-link /DEBUG /entry:main /nodefaultlib %t1.obj %t2.obj # RUN: ls %t1.pdb # RUN: rm %t* # RUN: cd %T/.. Index: vendor/lld/dist/test/COFF/pdb.test =================================================================== --- vendor/lld/dist/test/COFF/pdb.test (revision 320020) +++ vendor/lld/dist/test/COFF/pdb.test (revision 320021) @@ -1,409 +1,199 @@ # RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj # RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj # RUN: lld-link /debug /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \ # RUN: %t1.obj %t2.obj # RUN: llvm-pdbutil pdb2yaml -stream-metadata -stream-directory -pdb-stream \ # RUN: -dbi-stream -ipi-stream -tpi-stream %t.pdb | FileCheck %s -# RUN: llvm-pdbutil raw -modules -section-map -section-headers -section-contribs \ -# RUN: -tpi-records %t.pdb | FileCheck -check-prefix RAW %s +# RUN: llvm-pdbutil raw -modules -section-map -section-contribs \ +# RUN: -types -ids %t.pdb | FileCheck -check-prefix RAW %s # CHECK: MSF: # CHECK-NEXT: SuperBlock: # CHECK-NEXT: BlockSize: 4096 # CHECK-NEXT: FreeBlockMap: 1 # CHECK-NEXT: NumBlocks: # CHECK-NEXT: NumDirectoryBytes: # CHECK-NEXT: Unknown1: 0 # CHECK-NEXT: BlockMapAddr: # CHECK-NEXT: NumDirectoryBlocks: # CHECK-NEXT: DirectoryBlocks: -# CHECK-NEXT: NumStreams: -# CHECK-NEXT: FileSize: -# CHECK-NEXT: StreamSizes: +# CHECK-NEXT: NumStreams: +# CHECK-NEXT: FileSize: +# CHECK-NEXT: StreamSizes: # CHECK-NEXT: StreamMap: # CHECK: PdbStream: # CHECK-NEXT: Age: 1 # CHECK-NEXT: Guid: # CHECK-NEXT: Signature: 0 +# CHECK-NEXT: Features: [ VC140 ] # CHECK-NEXT: Version: VC70 # CHECK-NEXT: DbiStream: # CHECK-NEXT: VerHeader: V110 # CHECK-NEXT: Age: 1 # CHECK-NEXT: BuildNumber: 0 # CHECK-NEXT: PdbDllVersion: 0 # CHECK-NEXT: PdbDllRbld: 0 # CHECK-NEXT: Flags: 0 # CHECK-NEXT: MachineType: x86 # CHECK-NEXT: TpiStream: # CHECK-NEXT: Version: VC80 # CHECK-NEXT: Records: # CHECK-NEXT: - Kind: LF_ARGLIST # CHECK-NEXT: ArgList: # CHECK-NEXT: ArgIndices: [ ] # CHECK-NEXT: - Kind: LF_PROCEDURE # CHECK-NEXT: Procedure: # CHECK-NEXT: ReturnType: 116 # CHECK-NEXT: CallConv: NearC # CHECK-NEXT: Options: [ None ] # CHECK-NEXT: ParameterCount: 0 # CHECK-NEXT: ArgumentList: 4096 # CHECK-NEXT: - Kind: LF_POINTER # CHECK-NEXT: Pointer: # CHECK-NEXT: ReferentType: 4097 # CHECK-NEXT: Attrs: 65548 # CHECK-NEXT: - Kind: LF_ARGLIST # CHECK-NEXT: ArgList: # CHECK-NEXT: ArgIndices: [ 0 ] # CHECK-NEXT: - Kind: LF_PROCEDURE # CHECK-NEXT: Procedure: # CHECK-NEXT: ReturnType: 116 # CHECK-NEXT: CallConv: NearC # CHECK-NEXT: Options: [ None ] # CHECK-NEXT: ParameterCount: 0 # CHECK-NEXT: ArgumentList: 4099 # CHECK-NEXT: IpiStream: # CHECK-NEXT: Version: VC80 # CHECK-NEXT: Records: # CHECK-NEXT: - Kind: LF_FUNC_ID # CHECK-NEXT: FuncId: # CHECK-NEXT: ParentScope: 0 # CHECK-NEXT: FunctionType: 4100 # CHECK-NEXT: Name: main # CHECK-NEXT: - Kind: LF_FUNC_ID # CHECK-NEXT: FuncId: # CHECK-NEXT: ParentScope: 0 # CHECK-NEXT: FunctionType: 4097 # CHECK-NEXT: Name: foo # CHECK-NEXT: - Kind: LF_STRING_ID # CHECK-NEXT: StringId: # CHECK-NEXT: Id: 0 # CHECK-NEXT: String: 'D:\b' # CHECK-NEXT: - Kind: LF_STRING_ID # CHECK-NEXT: StringId: # CHECK-NEXT: Id: 0 # CHECK-NEXT: String: 'C:\vs14\VC\BIN\amd64\cl.exe' # CHECK-NEXT: - Kind: LF_STRING_ID # CHECK-NEXT: StringId: # CHECK-NEXT: Id: 0 # CHECK-NEXT: String: '-Z7 -c -MT -IC:\vs14\VC\INCLUDE -IC:\vs14\VC\ATLMFC\INCLUDE -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared"' # CHECK-NEXT: - Kind: LF_SUBSTR_LIST # CHECK-NEXT: StringList: # CHECK-NEXT: StringIndices: [ 4100 ] # CHECK-NEXT: - Kind: LF_STRING_ID # CHECK-NEXT: StringId: # CHECK-NEXT: Id: 4101 # CHECK-NEXT: String: ' -I"C:\Program Files (x86)\Windows Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TC -X' # CHECK-NEXT: - Kind: LF_STRING_ID # CHECK-NEXT: StringId: # CHECK-NEXT: Id: 0 # CHECK-NEXT: String: ret42-main.c # CHECK-NEXT: - Kind: LF_STRING_ID # CHECK-NEXT: StringId: # CHECK-NEXT: Id: 0 # CHECK-NEXT: String: 'D:\b\vc140.pdb' # CHECK-NEXT: - Kind: LF_BUILDINFO # CHECK-NEXT: BuildInfo: # CHECK-NEXT: ArgIndices: [ 4098, 4099, 4103, 4104, 4102 ] # CHECK-NEXT: - Kind: LF_STRING_ID # CHECK-NEXT: StringId: # CHECK-NEXT: Id: 0 # CHECK-NEXT: String: ret42-sub.c # CHECK-NEXT: - Kind: LF_BUILDINFO # CHECK-NEXT: BuildInfo: # CHECK-NEXT: ArgIndices: [ 4098, 4099, 4106, 4104, 4102 ] -# RAW: Type Info Stream (TPI) { -# RAW-NEXT: TPI Version: 20040203 -# RAW-NEXT: Record count: 5 -# RAW-NEXT: Records [ -# RAW-NEXT: { -# RAW-NEXT: ArgList (0x1000) { -# RAW-NEXT: TypeLeafKind: LF_ARGLIST (0x1201) -# RAW-NEXT: NumArgs: 0 -# RAW-NEXT: Arguments [ -# RAW-NEXT: ] -# RAW-NEXT: } -# RAW-NEXT: } -# RAW-NEXT: { -# RAW-NEXT: Procedure (0x1001) { -# RAW-NEXT: TypeLeafKind: LF_PROCEDURE (0x1008) -# RAW-NEXT: ReturnType: int (0x74) -# RAW-NEXT: CallingConvention: NearC (0x0) -# RAW-NEXT: FunctionOptions [ (0x0) -# RAW-NEXT: ] -# RAW-NEXT: NumParameters: 0 -# RAW-NEXT: ArgListType: () (0x1000) -# RAW-NEXT: } -# RAW-NEXT: } -# RAW-NEXT: { -# RAW-NEXT: Pointer (0x1002) { -# RAW-NEXT: TypeLeafKind: LF_POINTER (0x1002) -# RAW-NEXT: PointeeType: int () (0x1001) -# RAW-NEXT: PointerAttributes: 0x1000C -# RAW-NEXT: PtrType: Near64 (0xC) -# RAW-NEXT: PtrMode: Pointer (0x0) -# RAW-NEXT: IsFlat: 0 -# RAW-NEXT: IsConst: 0 -# RAW-NEXT: IsVolatile: 0 -# RAW-NEXT: IsUnaligned: 0 -# RAW-NEXT: SizeOf: 8 -# RAW-NEXT: } -# RAW-NEXT: } -# RAW-NEXT: { -# RAW-NEXT: ArgList (0x1003) { -# RAW-NEXT: TypeLeafKind: LF_ARGLIST (0x1201) -# RAW-NEXT: NumArgs: 1 -# RAW-NEXT: Arguments [ -# RAW-NEXT: ArgType: 0x0 -# RAW-NEXT: ] -# RAW-NEXT: } -# RAW-NEXT: } -# RAW-NEXT: { -# RAW-NEXT: Procedure (0x1004) { -# RAW-NEXT: TypeLeafKind: LF_PROCEDURE (0x1008) -# RAW-NEXT: ReturnType: int (0x74) -# RAW-NEXT: CallingConvention: NearC (0x0) -# RAW-NEXT: FunctionOptions [ (0x0) -# RAW-NEXT: ] -# RAW-NEXT: NumParameters: 0 -# RAW-NEXT: ArgListType: () (0x1003) -# RAW-NEXT: } -# RAW-NEXT: } -# RAW-NEXT: TypeIndexOffsets [ -# RAW-NEXT: Index: 0x1000, Offset: 0 -# RAW-NEXT: ] -# RAW-NEXT: ] -# RAW-NEXT: } -# RAW-NEXT: DBI Stream { -# RAW-NEXT: Dbi Version: 20091201 -# RAW-NEXT: Age: 1 -# RAW-NEXT: Incremental Linking: No -# RAW-NEXT: Has CTypes: No -# RAW-NEXT: Is Stripped: No -# RAW-NEXT: Machine Type: x86 -# RAW-NEXT: Symbol Record Stream Index: 65535 -# RAW-NEXT: Public Symbol Stream Index: 65535 -# RAW-NEXT: Global Symbol Stream Index: 65535 -# RAW-NEXT: Toolchain Version: 0.0 -# RAW-NEXT: mspdb00.dll version: 0.0.0 -# RAW-NEXT: Modules [ -# RAW-NEXT: { -# RAW-NEXT: Name: * Linker * -# RAW-NEXT: Debug Stream Index: 9 -# RAW-NEXT: Object File Name: -# RAW-NEXT: Num Files: 0 -# RAW-NEXT: Source File Name Idx: 0 -# RAW-NEXT: Pdb File Name Idx: 0 -# RAW-NEXT: Line Info Byte Size: 0 -# RAW-NEXT: C13 Line Info Byte Size: 0 -# RAW-NEXT: Symbol Byte Size: 4 -# RAW-NEXT: Type Server Index: 0 -# RAW-NEXT: Has EC Info: No -# RAW-NEXT: } -# RAW-NEXT: ] -# RAW-NEXT: } -# RAW-NEXT: Section Contributions [ -# RAW-NEXT: Contribution { -# RAW-NEXT: ISect: 0 -# RAW-NEXT: Off: 1288 -# RAW-NEXT: Size: 14 -# RAW-NEXT: Characteristics [ (0x60500020) -# RAW-NEXT: IMAGE_SCN_ALIGN_16BYTES (0x500000) -# RAW-NEXT: IMAGE_SCN_CNT_CODE (0x20) -# RAW-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000) -# RAW-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -# RAW-NEXT: ] -# RAW-NEXT: Module { -# RAW-NEXT: Index: 0 -# RAW-NEXT: Name: * Linker * -# RAW-NEXT: } -# RAW-NEXT: Data CRC: 0 -# RAW-NEXT: Reloc CRC: 0 -# RAW-NEXT: } -# RAW-NEXT: Contribution { -# RAW-NEXT: ISect: 0 -# RAW-NEXT: Off: 1312 -# RAW-NEXT: Size: 8 -# RAW-NEXT: Characteristics [ (0x40300040) -# RAW-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000) -# RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -# RAW-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -# RAW-NEXT: ] -# RAW-NEXT: Module { -# RAW-NEXT: Index: 0 -# RAW-NEXT: Name: * Linker * -# RAW-NEXT: } -# RAW-NEXT: Data CRC: 0 -# RAW-NEXT: Reloc CRC: 0 -# RAW-NEXT: } -# RAW-NEXT: Contribution { -# RAW-NEXT: ISect: 0 -# RAW-NEXT: Off: 1320 -# RAW-NEXT: Size: 12 -# RAW-NEXT: Characteristics [ (0x40300040) -# RAW-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000) -# RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -# RAW-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -# RAW-NEXT: ] -# RAW-NEXT: Module { -# RAW-NEXT: Index: 0 -# RAW-NEXT: Name: * Linker * -# RAW-NEXT: } -# RAW-NEXT: Data CRC: 0 -# RAW-NEXT: Reloc CRC: 0 -# RAW-NEXT: } -# RAW-NEXT: Contribution { -# RAW-NEXT: ISect: 0 -# RAW-NEXT: Off: 1144 -# RAW-NEXT: Size: 6 -# RAW-NEXT: Characteristics [ (0x60500020) -# RAW-NEXT: IMAGE_SCN_ALIGN_16BYTES (0x500000) -# RAW-NEXT: IMAGE_SCN_CNT_CODE (0x20) -# RAW-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000) -# RAW-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -# RAW-NEXT: ] -# RAW-NEXT: Module { -# RAW-NEXT: Index: 0 -# RAW-NEXT: Name: * Linker * -# RAW-NEXT: } -# RAW-NEXT: Data CRC: 0 -# RAW-NEXT: Reloc CRC: 0 -# RAW-NEXT: } -# RAW-NEXT: ] -# RAW-NEXT: Section Map [ -# RAW-NEXT: Entry { -# RAW-NEXT: Flags [ (0x109) -# RAW-NEXT: AddressIs32Bit (0x8) -# RAW-NEXT: IsSelector (0x100) -# RAW-NEXT: Read (0x1) -# RAW-NEXT: ] -# RAW-NEXT: Ovl: 0 -# RAW-NEXT: Group: 0 -# RAW-NEXT: Frame: 1 -# RAW-NEXT: SecName: 65535 -# RAW-NEXT: ClassName: 65535 -# RAW-NEXT: Offset: 0 -# RAW-NEXT: SecByteLength: 12 -# RAW-NEXT: } -# RAW-NEXT: Entry { -# RAW-NEXT: Flags [ (0x10D) -# RAW-NEXT: AddressIs32Bit (0x8) -# RAW-NEXT: Execute (0x4) -# RAW-NEXT: IsSelector (0x100) -# RAW-NEXT: Read (0x1) -# RAW-NEXT: ] -# RAW-NEXT: Ovl: 0 -# RAW-NEXT: Group: 0 -# RAW-NEXT: Frame: 2 -# RAW-NEXT: SecName: 65535 -# RAW-NEXT: ClassName: 65535 -# RAW-NEXT: Offset: 0 -# RAW-NEXT: SecByteLength: 22 -# RAW-NEXT: } -# RAW-NEXT: Entry { -# RAW-NEXT: Flags [ (0x109) -# RAW-NEXT: AddressIs32Bit (0x8) -# RAW-NEXT: IsSelector (0x100) -# RAW-NEXT: Read (0x1) -# RAW-NEXT: ] -# RAW-NEXT: Ovl: 0 -# RAW-NEXT: Group: 0 -# RAW-NEXT: Frame: 3 -# RAW-NEXT: SecName: 65535 -# RAW-NEXT: ClassName: 65535 -# RAW-NEXT: Offset: 0 -# RAW-NEXT: SecByteLength: 8 -# RAW-NEXT: } -# RAW-NEXT: Entry { -# RAW-NEXT: Flags [ (0x109) -# RAW-NEXT: AddressIs32Bit (0x8) -# RAW-NEXT: IsSelector (0x100) -# RAW-NEXT: Read (0x1) -# RAW-NEXT: ] -# RAW-NEXT: Ovl: 0 -# RAW-NEXT: Group: 0 -# RAW-NEXT: Frame: 4 -# RAW-NEXT: SecName: 65535 -# RAW-NEXT: ClassName: 65535 -# RAW-NEXT: Offset: 0 -# RAW-NEXT: SecByteLength: -# RAW-NEXT: } -# RAW-NEXT: Entry { -# RAW-NEXT: Flags [ (0x208) -# RAW-NEXT: AddressIs32Bit (0x8) -# RAW-NEXT: IsAbsoluteAddress (0x200) -# RAW-NEXT: ] -# RAW-NEXT: Ovl: 0 -# RAW-NEXT: Group: 0 -# RAW-NEXT: Frame: 5 -# RAW-NEXT: SecName: 65535 -# RAW-NEXT: ClassName: 65535 -# RAW-NEXT: Offset: 0 -# RAW-NEXT: SecByteLength: 4294967295 -# RAW-NEXT: } -# RAW-NEXT: ] -# RAW-NEXT: Section Headers [ -# RAW-NEXT: { -# RAW-NEXT: Name: .pdata -# RAW-NEXT: Virtual Size: 12 -# RAW-NEXT: Virtual Address: 4096 -# RAW-NEXT: Size of Raw Data: 512 -# RAW-NEXT: File Pointer to Raw Data: 1024 -# RAW-NEXT: File Pointer to Relocations: 0 -# RAW-NEXT: File Pointer to Linenumbers: 0 -# RAW-NEXT: Number of Relocations: 0 -# RAW-NEXT: Number of Linenumbers: 0 -# RAW-NEXT: Characteristics [ (0x40000040) -# RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -# RAW-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -# RAW-NEXT: ] -# RAW-NEXT: } -# RAW-NEXT: { -# RAW-NEXT: Name: .text -# RAW-NEXT: Virtual Size: 22 -# RAW-NEXT: Virtual Address: 8192 -# RAW-NEXT: Size of Raw Data: 512 -# RAW-NEXT: File Pointer to Raw Data: 1536 -# RAW-NEXT: File Pointer to Relocations: 0 -# RAW-NEXT: File Pointer to Linenumbers: 0 -# RAW-NEXT: Number of Relocations: 0 -# RAW-NEXT: Number of Linenumbers: 0 -# RAW-NEXT: Characteristics [ (0x60000020) -# RAW-NEXT: IMAGE_SCN_CNT_CODE (0x20) -# RAW-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000) -# RAW-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -# RAW-NEXT: ] -# RAW-NEXT: } -# RAW-NEXT: { -# RAW-NEXT: Name: .xdata -# RAW-NEXT: Virtual Size: 8 -# RAW-NEXT: Virtual Address: 12288 -# RAW-NEXT: Size of Raw Data: 512 -# RAW-NEXT: File Pointer to Raw Data: 2048 -# RAW-NEXT: File Pointer to Relocations: 0 -# RAW-NEXT: File Pointer to Linenumbers: 0 -# RAW-NEXT: Number of Relocations: 0 -# RAW-NEXT: Number of Linenumbers: 0 -# RAW-NEXT: Characteristics [ (0x40000040) -# RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -# RAW-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -# RAW-NEXT: ] -# RAW-NEXT: } -# RAW-NEXT: { -# RAW-NEXT: Name: .rdata -# RAW-NEXT: Virtual Size: -# RAW-NEXT: Virtual Address: 16384 -# RAW-NEXT: Size of Raw Data: 512 -# RAW-NEXT: File Pointer to Raw Data: 2560 -# RAW-NEXT: File Pointer to Relocations: 0 -# RAW-NEXT: File Pointer to Linenumbers: 0 -# RAW-NEXT: Number of Relocations: 0 -# RAW-NEXT: Number of Linenumbers: 0 -# RAW-NEXT: Characteristics [ (0x40000040) -# RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -# RAW-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -# RAW-NEXT: ] -# RAW-NEXT: } -# RAW-NEXT: ] +RAW: Modules +RAW-NEXT: ============================================================ +RAW-NEXT: Mod 0000 | Name: `{{.*}}pdb.test.tmp1.obj`: +RAW-NEXT: Obj: `{{.*}}pdb.test.tmp1.obj`: +RAW-NEXT: debug stream: 9, # files: 0, has ec info: false +RAW-NEXT: Mod 0001 | Name: `{{.*}}pdb.test.tmp2.obj`: +RAW-NEXT: Obj: `{{.*}}pdb.test.tmp2.obj`: +RAW-NEXT: debug stream: 10, # files: 0, has ec info: false +RAW-NEXT: Mod 0002 | Name: `* Linker *`: +RAW-NEXT: Obj: ``: +RAW-NEXT: debug stream: 11, # files: 0, has ec info: false +RAW: Types (TPI Stream) +RAW-NEXT: ============================================================ +RAW-NEXT: Showing 5 records +RAW-NEXT: 0x1000 | LF_ARGLIST [size = 8] +RAW-NEXT: 0x1001 | LF_PROCEDURE [size = 16] +RAW-NEXT: return type = 0x0074 (int), # args = 0, param list = 0x1000 +RAW-NEXT: calling conv = cdecl, options = None +RAW-NEXT: 0x1002 | LF_POINTER [size = 12] +RAW-NEXT: referent = 0x1001, mode = pointer, opts = None, kind = ptr64 +RAW-NEXT: 0x1003 | LF_ARGLIST [size = 12] +RAW-NEXT: : `` +RAW-NEXT: 0x1004 | LF_PROCEDURE [size = 16] +RAW-NEXT: return type = 0x0074 (int), # args = 0, param list = 0x1003 +RAW-NEXT: calling conv = cdecl, options = None +RAW: Types (IPI Stream) +RAW-NEXT: ============================================================ +RAW-NEXT: Showing 12 records +RAW-NEXT: 0x1000 | LF_FUNC_ID [size = 20] +RAW-NEXT: name = main, type = 0x1004, parent scope = +RAW-NEXT: 0x1001 | LF_FUNC_ID [size = 16] +RAW-NEXT: name = foo, type = 0x1001, parent scope = +RAW-NEXT: 0x1002 | LF_STRING_ID [size = 16] ID: , String: D:\b +RAW-NEXT: 0x1003 | LF_STRING_ID [size = 36] ID: , String: C:\vs14\VC\BIN\amd64\cl.exe +RAW-NEXT: 0x1004 | LF_STRING_ID [size = 260] ID: , String: -Z7 -c -MT -IC:\vs14\VC\INCLUDE -IC:\vs14\VC\ATLMFC\INCLUDE -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" +RAW-NEXT: 0x1005 | LF_SUBSTR_LIST [size = 12] +RAW-NEXT: 0x1004: `-Z7 -c -MT -IC:\vs14\VC\INCLUDE -IC:\vs14\VC\ATLMFC\INCLUDE -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared"` +RAW-NEXT: 0x1006 | LF_STRING_ID [size = 132] ID: 0x1005, String: -I"C:\Program Files (x86)\Windows Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TC -X +RAW-NEXT: 0x1007 | LF_STRING_ID [size = 24] ID: , String: ret42-main.c +RAW-NEXT: 0x1008 | LF_STRING_ID [size = 24] ID: , String: D:\b\vc140.pdb +RAW-NEXT: 0x1009 | LF_BUILDINFO [size = 28] +RAW-NEXT: 0x1002: `D:\b` +RAW-NEXT: 0x1003: `C:\vs14\VC\BIN\amd64\cl.exe` +RAW-NEXT: 0x1007: `ret42-main.c` +RAW-NEXT: 0x1008: `D:\b\vc140.pdb` +RAW-NEXT: 0x1006: ` -I"C:\Program Files (x86)\Windows Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TC -X` +RAW-NEXT: 0x100A | LF_STRING_ID [size = 20] ID: , String: ret42-sub.c +RAW-NEXT: 0x100B | LF_BUILDINFO [size = 28] +RAW-NEXT: 0x1002: `D:\b` +RAW-NEXT: 0x1003: `C:\vs14\VC\BIN\amd64\cl.exe` +RAW-NEXT: 0x100A: `ret42-sub.c` +RAW-NEXT: 0x1008: `D:\b\vc140.pdb` +RAW-NEXT: 0x1006: ` -I"C:\Program Files (x86)\Windows Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TC -X` +RAW: Section Contributions +RAW-NEXT: ============================================================ +RAW-NEXT: SC | mod = 0, 65535:1288, size = 14, data crc = 0, reloc crc = 0 +RAW-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE | +RAW-NEXT: IMAGE_SCN_MEM_READ +RAW-NEXT: SC | mod = 0, 65535:1312, size = 8, data crc = 0, reloc crc = 0 +RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ +RAW-NEXT: SC | mod = 0, 65535:1320, size = 12, data crc = 0, reloc crc = 0 +RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ +RAW-NEXT: SC | mod = 1, 65535:1144, size = 6, data crc = 0, reloc crc = 0 +RAW-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE | +RAW-NEXT: IMAGE_SCN_MEM_READ +RAW: Section Map +RAW-NEXT: ============================================================ +RAW-NEXT: Section 0000 | ovl = 0, group = 0, frame = 0, name = 1 +RAW-NEXT: class = 65535, offset = 0, size = +RAW-NEXT: flags = read | 32 bit addr | selector +RAW-NEXT: Section 0001 | ovl = 1, group = 0, frame = 0, name = 2 +RAW-NEXT: class = 65535, offset = 0, size = +RAW-NEXT: flags = read | execute | 32 bit addr | selector +RAW-NEXT: Section 0002 | ovl = 2, group = 0, frame = 0, name = 3 +RAW-NEXT: class = 65535, offset = 0, size = +RAW-NEXT: flags = read | 32 bit addr | selector +RAW-NEXT: Section 0003 | ovl = 3, group = 0, frame = 0, name = 4 +RAW-NEXT: class = 65535, offset = 0, size = +RAW-NEXT: flags = read | 32 bit addr | selector +RAW-NEXT: Section 0004 | ovl = 4, group = 0, frame = 0, name = 5 +RAW-NEXT: class = 65535, offset = 0, size = +RAW-NEXT: flags = 32 bit addr | absolute addr Index: vendor/lld/dist/test/COFF/sort-debug.test =================================================================== --- vendor/lld/dist/test/COFF/sort-debug.test (revision 320020) +++ vendor/lld/dist/test/COFF/sort-debug.test (revision 320021) @@ -1,296 +1,335 @@ # RUN: yaml2obj < %s > %t.obj # RUN: lld-link /debug /out:%t.exe /entry:main %t.obj # RUN: llvm-readobj -sections %t.exe | FileCheck %s # CHECK: Name: .text # CHECK: Name: .debug_abbrev # CHECK: Name: .debug_info # CHECK: Name: .debug_line # CHECK: Name: .debug_pubnames # CHECK: Name: .debug_pubtypes # CHECK: Name: .reloc --- !COFF header: Machine: IMAGE_FILE_MACHINE_I386 Characteristics: [ ] sections: - Name: .text Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] Alignment: 16 SectionData: 508D0500000000C70424000000005AC3 Relocations: - VirtualAddress: 3 SymbolName: '?x@@3HA' Type: IMAGE_REL_I386_DIR32 - Name: .data Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] Alignment: 4 SectionData: '' - Name: .bss Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] Alignment: 4 SectionData: '' - Name: '.debug$S' Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 - SectionData: 04000000F1000000300000002A00471100000000000000000000000010000000000000000000000000000000000000000000006D61696E0002004F11F200000024000000000000000000010010000000000000000100000018000000000000000100000000000000F4000000080000000100000000000000F30000003C000000005C7573725C6C6F63616C5C676F6F676C655C686F6D655C6D616A6E656D65725C6C6C766D5C7372635C746F6F6C735C6C6C645C3C737464696E3E00 + Subsections: + - !Symbols + Records: + - Kind: S_GPROC32_ID + ProcSym: + PtrParent: 0 + PtrEnd: 0 + PtrNext: 0 + CodeSize: 16 + DbgStart: 0 + DbgEnd: 0 + FunctionType: 0 + Segment: 0 + Flags: [ ] + DisplayName: main + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 16 + Flags: [ HasColumnInfo ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: '\usr\local\google\home\majnemer\llvm\src\tools\lld\' + Lines: + - Offset: 0 + LineStart: 1 + IsStatement: false + EndDelta: 0 + Columns: + - StartColumn: 0 + EndColumn: 0 + - !FileChecksums + Checksums: + - FileName: '\usr\local\google\home\majnemer\llvm\src\tools\lld\' + Kind: None + Checksum: '' + - !StringTable + Strings: + - '\usr\local\google\home\majnemer\llvm\src\tools\lld\' Relocations: - VirtualAddress: 44 SymbolName: _main Type: IMAGE_REL_I386_SECREL - VirtualAddress: 48 SymbolName: _main Type: IMAGE_REL_I386_SECTION - VirtualAddress: 68 SymbolName: _main Type: IMAGE_REL_I386_SECREL - VirtualAddress: 72 SymbolName: _main Type: IMAGE_REL_I386_SECTION - Name: .debug_str Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 SectionData: '' - Name: .debug_loc Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 SectionData: '' - Name: .debug_abbrev Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 SectionData: 011101250E1305030E10171B0E110112060000023400030E49133F193A0B3B0B02186E0E0000032400030E3E0B0B0B0000042E0011011206E77F194018030E3A0B3B0B49133F19000000 - Name: .debug_info Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 SectionData: 54000000040000000000040100000000040037000000000000003F000000000000001000000002720000003B0000000101050300000000780000000374000000050404000000001000000001548000000001013B00000000 Relocations: - VirtualAddress: 6 SymbolName: .debug_abbrev Type: IMAGE_REL_I386_SECREL - VirtualAddress: 12 SymbolName: .debug_str Type: IMAGE_REL_I386_SECREL - VirtualAddress: 18 SymbolName: .debug_str Type: IMAGE_REL_I386_SECREL - VirtualAddress: 22 SymbolName: .debug_line Type: IMAGE_REL_I386_SECREL - VirtualAddress: 26 SymbolName: .debug_str Type: IMAGE_REL_I386_SECREL - VirtualAddress: 30 SymbolName: .text Type: IMAGE_REL_I386_DIR32 - VirtualAddress: 39 SymbolName: .debug_str Type: IMAGE_REL_I386_SECREL - VirtualAddress: 51 SymbolName: '?x@@3HA' Type: IMAGE_REL_I386_DIR32 - VirtualAddress: 55 SymbolName: .debug_str Type: IMAGE_REL_I386_SECREL - VirtualAddress: 60 SymbolName: .debug_str Type: IMAGE_REL_I386_SECREL - VirtualAddress: 67 SymbolName: .text Type: IMAGE_REL_I386_DIR32 - VirtualAddress: 77 SymbolName: .debug_str Type: IMAGE_REL_I386_SECREL - Name: .debug_ranges Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 SectionData: '' - Name: .debug_pubnames Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 SectionData: 1D00000002000000000058000000420000006D61696E0026000000780000000000 Relocations: - VirtualAddress: 6 SymbolName: .debug_info Type: IMAGE_REL_I386_SECREL - Name: .debug_pubtypes Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 SectionData: 16000000020000000000580000003B000000696E740000000000 Relocations: - VirtualAddress: 6 SymbolName: .debug_info Type: IMAGE_REL_I386_SECREL - Name: .debug_line Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 SectionData: 3300000002001E0000000101FB0E0D000101010100000001000001003C737464696E3E000000000000050200000000010AD60202000101 Relocations: - VirtualAddress: 43 SymbolName: .text Type: IMAGE_REL_I386_DIR32 symbols: - Name: .text Value: 0 SectionNumber: 1 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 16 NumberOfRelocations: 1 NumberOfLinenumbers: 0 CheckSum: 0 Number: 1 - Name: .data Value: 0 SectionNumber: 2 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 0 NumberOfRelocations: 0 NumberOfLinenumbers: 0 CheckSum: 0 Number: 2 - Name: .bss Value: 0 SectionNumber: 3 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 4 NumberOfRelocations: 0 NumberOfLinenumbers: 0 CheckSum: 0 Number: 3 - Name: '.debug$S' Value: 0 SectionNumber: 4 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 188 NumberOfRelocations: 4 NumberOfLinenumbers: 0 CheckSum: 0 Number: 4 - Name: .debug_str Value: 0 SectionNumber: 5 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 133 NumberOfRelocations: 0 NumberOfLinenumbers: 0 CheckSum: 0 Number: 5 - Name: .debug_loc Value: 0 SectionNumber: 6 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 0 NumberOfRelocations: 0 NumberOfLinenumbers: 0 CheckSum: 0 Number: 6 - Name: .debug_abbrev Value: 0 SectionNumber: 7 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 74 NumberOfRelocations: 0 NumberOfLinenumbers: 0 CheckSum: 0 Number: 7 - Name: .debug_info Value: 0 SectionNumber: 8 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 88 NumberOfRelocations: 12 NumberOfLinenumbers: 0 CheckSum: 0 Number: 8 - Name: .debug_ranges Value: 0 SectionNumber: 9 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 0 NumberOfRelocations: 0 NumberOfLinenumbers: 0 CheckSum: 0 Number: 9 - Name: .debug_pubnames Value: 0 SectionNumber: 10 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 33 NumberOfRelocations: 1 NumberOfLinenumbers: 0 CheckSum: 0 Number: 10 - Name: .debug_pubtypes Value: 0 SectionNumber: 11 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 26 NumberOfRelocations: 1 NumberOfLinenumbers: 0 CheckSum: 0 Number: 11 - Name: .debug_line Value: 0 SectionNumber: 12 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: Length: 55 NumberOfRelocations: 1 NumberOfLinenumbers: 0 CheckSum: 0 Number: 12 - Name: '@feat.00' Value: 1 SectionNumber: -1 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC - Name: _main Value: 0 SectionNumber: 1 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_FUNCTION StorageClass: IMAGE_SYM_CLASS_EXTERNAL - Name: '?x@@3HA' Value: 0 SectionNumber: 3 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_EXTERNAL ... Index: vendor/lld/dist/test/ELF/Inputs/icf-merge-sec.s =================================================================== --- vendor/lld/dist/test/ELF/Inputs/icf-merge-sec.s (nonexistent) +++ vendor/lld/dist/test/ELF/Inputs/icf-merge-sec.s (revision 320021) @@ -0,0 +1,9 @@ +.section .rodata.str,"aMS",@progbits,1 +.asciz "bar" +.asciz "baz" +.asciz "foo" + +.section .text.f2,"ax" +.globl f2 +f2: +.quad .rodata.str+8 Property changes on: vendor/lld/dist/test/ELF/Inputs/icf-merge-sec.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/Inputs/icf-merge.s =================================================================== --- vendor/lld/dist/test/ELF/Inputs/icf-merge.s (nonexistent) +++ vendor/lld/dist/test/ELF/Inputs/icf-merge.s (revision 320021) @@ -0,0 +1,10 @@ +.section .rodata.str,"aMS",@progbits,1 +.asciz "bar" +.asciz "baz" +foo: +.asciz "foo" + +.section .text.f2,"ax" +.globl f2 +f2: +lea foo+42(%rip), %rax Property changes on: vendor/lld/dist/test/ELF/Inputs/icf-merge.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/Inputs/icf-merge2.s =================================================================== --- vendor/lld/dist/test/ELF/Inputs/icf-merge2.s (nonexistent) +++ vendor/lld/dist/test/ELF/Inputs/icf-merge2.s (revision 320021) @@ -0,0 +1,10 @@ +.section .rodata.str,"aMS",@progbits,1 +.asciz "bar" +.asciz "baz" +boo: +.asciz "boo" + +.section .text.f2,"ax" +.globl f2 +f2: +lea boo+42(%rip), %rax Property changes on: vendor/lld/dist/test/ELF/Inputs/icf-merge2.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/Inputs/icf-merge3.s =================================================================== --- vendor/lld/dist/test/ELF/Inputs/icf-merge3.s (nonexistent) +++ vendor/lld/dist/test/ELF/Inputs/icf-merge3.s (revision 320021) @@ -0,0 +1,10 @@ +.section .rodata.str,"aMS",@progbits,1 +.asciz "bar" +.asciz "baz" +foo: +.asciz "foo" + +.section .text.f2,"ax" +.globl f2 +f2: +lea foo+43(%rip), %rax Property changes on: vendor/lld/dist/test/ELF/Inputs/icf-merge3.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/Inputs/sht-group-gold-r.elf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/x-object Property changes on: vendor/lld/dist/test/ELF/Inputs/sht-group-gold-r.elf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/x-object \ No newline at end of property Index: vendor/lld/dist/test/ELF/Inputs/sht-group-gold-r.s =================================================================== --- vendor/lld/dist/test/ELF/Inputs/sht-group-gold-r.s (nonexistent) +++ vendor/lld/dist/test/ELF/Inputs/sht-group-gold-r.s (revision 320021) @@ -0,0 +1,14 @@ +# sht-group-gold-r.elf is produced by +# +# llvm-mc -filetype=obj -triple=x86_64-pc-linux sht-group-gold-r.s -o sht-group-gold-r.o +# ld.gold -o sht-group-gold-r.elf -r sht-group-gold-r.o + +.global foo, bar + +.section .text.foo,"aG",@progbits,group_foo,comdat +foo: + nop + +.section .text.bar,"aG",@progbits,group_bar,comdat +bar: + nop Property changes on: vendor/lld/dist/test/ELF/Inputs/sht-group-gold-r.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/aarch64-undefined-weak.s =================================================================== --- vendor/lld/dist/test/ELF/aarch64-undefined-weak.s (revision 320020) +++ vendor/lld/dist/test/ELF/aarch64-undefined-weak.s (revision 320021) @@ -1,45 +1,45 @@ // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t // RUN: ld.lld %t -o %t2 2>&1 // RUN: llvm-objdump -triple=aarch64-none-linux -d %t2 | FileCheck %s // REQUIRES: aarch64 // Check that the ARM 64-bit ABI rules for undefined weak symbols are applied. // Branch instructions are resolved to the next instruction. Undefined // Symbols in relative are resolved to the place so S - P + A = A. .weak target .text .global _start _start: // R_AARCH64_JUMP26 b target // R_AARCH64_CALL26 bl target // R_AARCH64_CONDBR19 b.eq target // R_AARCH64_TSTBR14 cbz x1, target // R_AARCH64_ADR_PREL_LO21 adr x0, target // R_AARCH64_ADR_PREL_PG_HI21 adrp x0, target // R_AARCH64_PREL32 .word target - . // R_AARCH64_PREL64 .xword target - . // R_AARCH64_PREL16 .hword target - . // CHECK: Disassembly of section .text: // 131076 = 0x20004 -// CHECK: 20000: {{.*}} b #131076 -// CHECK-NEXT: 20004: {{.*}} bl #131080 -// CHECK-NEXT: 20008: {{.*}} b.eq #131084 -// CHECK-NEXT: 2000c: {{.*}} cbz x1, #131088 +// CHECK: 20000: {{.*}} b #4 +// CHECK-NEXT: 20004: {{.*}} bl #4 +// CHECK-NEXT: 20008: {{.*}} b.eq #4 +// CHECK-NEXT: 2000c: {{.*}} cbz x1, #4 // CHECK-NEXT: 20010: {{.*}} adr x0, #0 -// CHECK-NEXT: 20014: {{.*}} adrp x0, #0 +// CHECK-NEXT: 20014: {{.*}} adrp x0, #-131072 // CHECK: 20018: {{.*}} .word 0x00000000 // CHECK-NEXT: 2001c: {{.*}} .word 0x00000000 // CHECK-NEXT: 20020: {{.*}} .word 0x00000000 // CHECK-NEXT: 20024: {{.*}} .short 0x0000 Index: vendor/lld/dist/test/ELF/arm-thumb-no-undefined-thunk.s =================================================================== --- vendor/lld/dist/test/ELF/arm-thumb-no-undefined-thunk.s (revision 320020) +++ vendor/lld/dist/test/ELF/arm-thumb-no-undefined-thunk.s (revision 320021) @@ -1,24 +1,24 @@ // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o %t2 2>&1 // RUN: llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d %t2 | FileCheck %s // REQUIRES: arm // Check that no thunks are created for an undefined weak symbol .syntax unified .weak target .section .text.thumb, "ax", %progbits .thumb .global _start: bl target b target b.w target // CHECK: Disassembly of section .text: // CHECK-NEXT: _start: // 69636 = 0x11004 = next instruction -// CHECK: 11000: {{.*}} bl #69636 -// CHECK-NEXT: 11004: {{.*}} b.w #69640 -// CHECK-NEXT: 11008: {{.*}} b.w #69644 +// CHECK: 11000: {{.*}} bl #0 +// CHECK-NEXT: 11004: {{.*}} b.w #0 <_start+0x8> +// CHECK-NEXT: 11008: {{.*}} b.w #0 <_start+0xC> Index: vendor/lld/dist/test/ELF/arm-thumb-undefined-weak.s =================================================================== --- vendor/lld/dist/test/ELF/arm-thumb-undefined-weak.s (revision 320020) +++ vendor/lld/dist/test/ELF/arm-thumb-undefined-weak.s (revision 320021) @@ -1,38 +1,38 @@ // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o %t2 2>&1 // RUN: llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d %t2 | FileCheck %s // REQUIRES: arm // Check that the ARM ABI rules for undefined weak symbols are applied. // Branch instructions are resolved to the next instruction. Relative // relocations are resolved to the place. .syntax unified .weak target .text .global _start _start: // R_ARM_THM_JUMP19 beq.w target // R_ARM_THM_JUMP24 b.w target // R_ARM_THM_CALL bl target // R_ARM_THM_CALL with exchange blx target // R_ARM_THM_MOVT_PREL movt r0, :upper16:target - . // R_ARM_THM_MOVW_PREL_NC movw r0, :lower16:target - . // CHECK: Disassembly of section .text: // 69636 = 0x11004 -// CHECK: 11000: {{.*}} beq.w #69636 -// CHECK-NEXT: 11004: {{.*}} b.w #69640 -// CHECK-NEXT: 11008: {{.*}} bl #69644 +// CHECK: 11000: {{.*}} beq.w #0 <_start+0x4> +// CHECK-NEXT: 11004: {{.*}} b.w #0 <_start+0x8> +// CHECK-NEXT: 11008: {{.*}} bl #0 // blx is transformed into bl so we don't change state -// CHECK-NEXT: 1100c: {{.*}} bl #69648 +// CHECK-NEXT: 1100c: {{.*}} bl #0 // CHECK-NEXT: 11010: {{.*}} movt r0, #0 // CHECK-NEXT: 11014: {{.*}} movw r0, #0 Index: vendor/lld/dist/test/ELF/arm-undefined-weak.s =================================================================== --- vendor/lld/dist/test/ELF/arm-undefined-weak.s (revision 320020) +++ vendor/lld/dist/test/ELF/arm-undefined-weak.s (revision 320021) @@ -1,39 +1,39 @@ // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o %t2 2>&1 // RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t2 | FileCheck %s // REQUIRES: arm // Check that the ARM ABI rules for undefined weak symbols are applied. // Branch instructions are resolved to the next instruction. Undefined // Symbols in relative are resolved to the place so S - P + A = A. .syntax unified .weak target .text .global _start _start: // R_ARM_JUMP24 b target // R_ARM_CALL bl target // R_ARM_CALL with exchange blx target // R_ARM_MOVT_PREL movt r0, :upper16:target - . // R_ARM_MOVW_PREL_NC movw r0, :lower16:target - . // R_ARM_REL32 .word target - . // CHECK: Disassembly of section .text: // 69636 = 0x11004 -// CHECK: 11000: {{.*}} b #69636 -// CHECK-NEXT: 11004: {{.*}} bl #69640 +// CHECK: 11000: {{.*}} b #-4 <_start+0x4> +// CHECK-NEXT: 11004: {{.*}} bl #-4 <_start+0x8> // blx is transformed into bl so we don't change state -// CHECK-NEXT: 11008: {{.*}} bl #69644 +// CHECK-NEXT: 11008: {{.*}} bl #-4 <_start+0xC> // CHECK-NEXT: 1100c: {{.*}} movt r0, #0 // CHECK-NEXT: 11010: {{.*}} movw r0, #0 // CHECK: 11014: {{.*}} .word 0x00000000 Index: vendor/lld/dist/test/ELF/basic-avr.s =================================================================== --- vendor/lld/dist/test/ELF/basic-avr.s (nonexistent) +++ vendor/lld/dist/test/ELF/basic-avr.s (revision 320021) @@ -0,0 +1,14 @@ +# REQUIRES: avr +# RUN: llvm-mc -filetype=obj -triple=avr-unknown-linux -mcpu=atmega328p %s -o %t.o +# RUN: ld.lld %t.o -o %t.exe -Ttext=0 +# RUN: llvm-objdump -d %t.exe | FileCheck %s + +main: + call foo +foo: + jmp foo + +# CHECK: main: +# CHECK-NEXT: 0: 0e 94 02 00 +# CHECK: foo: +# CHECK-NEXT: 4: 0c 94 02 00 Property changes on: vendor/lld/dist/test/ELF/basic-avr.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/icf-merge-sec.s =================================================================== --- vendor/lld/dist/test/ELF/icf-merge-sec.s (nonexistent) +++ vendor/lld/dist/test/ELF/icf-merge-sec.s (revision 320021) @@ -0,0 +1,18 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge-sec.s -o %t2 +# RUN: ld.lld %t %t2 -o %t3 --icf=all --verbose | FileCheck %s + +# CHECK: selected .text.f1 +# CHECK: removed .text.f2 + +.section .rodata.str,"aMS",@progbits,1 +.asciz "foo" +.asciz "string 1" +.asciz "string 2" + +.section .text.f1,"ax" +.globl f1 +f1: +.quad .rodata.str Property changes on: vendor/lld/dist/test/ELF/icf-merge-sec.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/icf-merge.s =================================================================== --- vendor/lld/dist/test/ELF/icf-merge.s (nonexistent) +++ vendor/lld/dist/test/ELF/icf-merge.s (revision 320021) @@ -0,0 +1,27 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge.s -o %t1 +# RUN: ld.lld %t %t1 -o %t1.out --icf=all --verbose | FileCheck %s + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge2.s -o %t2 +# RUN: ld.lld %t %t2 -o %t3.out --icf=all --verbose | FileCheck --check-prefix=NOMERGE %s + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge3.s -o %t3 +# RUN: ld.lld %t %t3 -o %t3.out --icf=all --verbose | FileCheck --check-prefix=NOMERGE %s + +# CHECK: selected .text.f1 +# CHECK: removed .text.f2 + +# NOMERGE-NOT: selected .text.f + +.section .rodata.str,"aMS",@progbits,1 +foo: +.asciz "foo" +.asciz "string 1" +.asciz "string 2" + +.section .text.f1,"ax" +.globl f1 +f1: +lea foo+42(%rip), %rax Property changes on: vendor/lld/dist/test/ELF/icf-merge.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/linkerscript/data-commands-gc.s =================================================================== --- vendor/lld/dist/test/ELF/linkerscript/data-commands-gc.s (nonexistent) +++ vendor/lld/dist/test/ELF/linkerscript/data-commands-gc.s (revision 320021) @@ -0,0 +1,16 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { .text : { *(.text*) QUAD(bar) } }" > %t.script +# RUN: ld.lld --gc-sections -o %t %t.o --script %t.script | FileCheck -allow-empty %s + +# CHECK-NOT: unable to evaluate expression: input section .rodata.bar has no output section assigned + +.section .rodata.bar +.quad 0x1122334455667788 +.global bar +bar: + +.section .text +.global _start +_start: + nop Property changes on: vendor/lld/dist/test/ELF/linkerscript/data-commands-gc.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/linkerscript/locationcountererr2.s =================================================================== --- vendor/lld/dist/test/ELF/linkerscript/locationcountererr2.s (revision 320020) +++ vendor/lld/dist/test/ELF/linkerscript/locationcountererr2.s (revision 320021) @@ -1,9 +1,9 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o # RUN: echo "SECTIONS {" > %t.script -# RUN: echo ". = 0x20; . = 0x10; }" >> %t.script +# RUN: echo ". = 0x20; . = 0x10; .text : {} }" >> %t.script # RUN: not ld.lld %t.o --script %t.script -o %t -shared 2>&1 | FileCheck %s # CHECK: {{.*}}.script:2: unable to move location counter backward # RUN: echo "SECTIONS { . = 0x20; . = ASSERT(0x1, "foo"); }" > %t2.script # RUN: ld.lld %t.o --script %t2.script -o %t -shared Index: vendor/lld/dist/test/ELF/linkerscript/symbols-non-alloc.s =================================================================== --- vendor/lld/dist/test/ELF/linkerscript/symbols-non-alloc.s (revision 320020) +++ vendor/lld/dist/test/ELF/linkerscript/symbols-non-alloc.s (revision 320021) @@ -1,16 +1,19 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: echo "SECTIONS { . = SIZEOF_HEADERS; \ # RUN: .text : { *(.text) } \ # RUN: .nonalloc : { *(.nonalloc) } \ # RUN: Sym = .; \ # RUN: }" > %t.script # RUN: ld.lld -o %t2 --script %t.script %t # RUN: llvm-objdump -section-headers -t %t2 | FileCheck %s +# CHECK: Sections: +# CHECK: .nonalloc 00000008 0000000000000000 + # CHECK: SYMBOL TABLE: -# CHECK: 00000000000000f0 .nonalloc 00000000 Sym +# CHECK: 0000000000000008 .nonalloc 00000000 Sym .section .nonalloc,"" .quad 0 Index: vendor/lld/dist/test/ELF/sht-group-gold-r.test =================================================================== --- vendor/lld/dist/test/ELF/sht-group-gold-r.test (nonexistent) +++ vendor/lld/dist/test/ELF/sht-group-gold-r.test (revision 320021) @@ -0,0 +1,17 @@ +# GNU gold 1.14 (the newest version as of July 2017) seems to create +# non-standard-compliant SHT_GROUP sections when the -r option is given. +# +# Such SHT_GROUP sections use section names as their signatures +# instead of symbols pointed by sh_link field. Since it is prevalent, +# we accept such nonstandard sections. + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: ld.lld %p/Inputs/sht-group-gold-r.elf %t.o -o %t.exe +# RUN: llvm-objdump -t %t.exe | FileCheck %s + +# CHECK: .text 00000000 bar +# CHECK: .text 00000000 foo + +.globl _start +_start: + ret Index: vendor/lld/dist/test/lit.cfg =================================================================== --- vendor/lld/dist/test/lit.cfg (revision 320020) +++ vendor/lld/dist/test/lit.cfg (revision 320021) @@ -1,266 +1,269 @@ # -*- Python -*- import os import platform import re import subprocess import locale import lit.formats import lit.util # Configuration file for the 'lit' test runner. # name: The name of this test suite. config.name = 'lld' # Tweak PATH for Win32 if sys.platform in ['win32']: # Seek sane tools in directories and set to $PATH. path = getattr(config, 'lit_tools_dir', None) path = lit_config.getToolsPath(path, config.environment['PATH'], ['cmp.exe', 'grep.exe', 'sed.exe']) if path is not None: path = os.path.pathsep.join((path, config.environment['PATH'])) config.environment['PATH'] = path # Choose between lit's internal shell pipeline runner and a real shell. If # LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override. use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL") if use_lit_shell: # 0 is external, "" is default, and everything else is internal. execute_external = (use_lit_shell == "0") else: # Otherwise we default to internal on Windows and external elsewhere, as # bash on Windows is usually very slow. execute_external = (not sys.platform in ['win32']) # testFormat: The test format to use to interpret tests. # # For now we require '&&' between commands, until they get globally killed and # the test runner updated. config.test_format = lit.formats.ShTest(execute_external) # suffixes: A list of file extensions to treat as test files. -config.suffixes = ['.ll', '.objtxt', '.test'] +config.suffixes = ['.ll', '.s', '.objtxt', '.test'] # excludes: A list of directories to exclude from the testsuite. The 'Inputs' # subdirectories contain auxiliary inputs for various tests in their parent # directories. config.excludes = ['Inputs'] # test_source_root: The root path where tests are located. config.test_source_root = os.path.dirname(__file__) # test_exec_root: The root path where tests should be run. lld_obj_root = getattr(config, 'lld_obj_root', None) if lld_obj_root is not None: config.test_exec_root = os.path.join(lld_obj_root, 'test') # Set llvm_{src,obj}_root for use by others. config.llvm_src_root = getattr(config, 'llvm_src_root', None) config.llvm_obj_root = getattr(config, 'llvm_obj_root', None) # Tweak the PATH to include the tools dir and the scripts dir. if lld_obj_root is not None: lld_tools_dir = getattr(config, 'lld_tools_dir', None) if not lld_tools_dir: lit_config.fatal('No LLD tools dir set!') llvm_tools_dir = getattr(config, 'llvm_tools_dir', None) if not llvm_tools_dir: lit_config.fatal('No LLVM tools dir set!') path = os.path.pathsep.join((lld_tools_dir, llvm_tools_dir, config.environment['PATH'])) path = os.path.pathsep.join((os.path.join(getattr(config, 'llvm_src_root', None),'test','Scripts'),path)) config.environment['PATH'] = path lld_libs_dir = getattr(config, 'lld_libs_dir', None) if not lld_libs_dir: lit_config.fatal('No LLD libs dir set!') llvm_libs_dir = getattr(config, 'llvm_libs_dir', None) if not llvm_libs_dir: lit_config.fatal('No LLVM libs dir set!') path = os.path.pathsep.join((lld_libs_dir, llvm_libs_dir, config.environment.get('LD_LIBRARY_PATH',''))) config.environment['LD_LIBRARY_PATH'] = path # Propagate LLVM_SRC_ROOT into the environment. config.environment['LLVM_SRC_ROOT'] = getattr(config, 'llvm_src_root', '') # Propagate PYTHON_EXECUTABLE into the environment config.environment['PYTHON_EXECUTABLE'] = getattr(config, 'python_executable', '') ### # Check that the object root is known. if config.test_exec_root is None: # Otherwise, we haven't loaded the site specific configuration (the user is # probably trying to run on a test file directly, and either the site # configuration hasn't been created by the build system, or we are in an # out-of-tree build situation). # Check for 'lld_site_config' user parameter, and use that if available. site_cfg = lit_config.params.get('lld_site_config', None) if site_cfg and os.path.exists(site_cfg): lit_config.load_config(config, site_cfg) raise SystemExit # Try to detect the situation where we are using an out-of-tree build by # looking for 'llvm-config'. # # FIXME: I debated (i.e., wrote and threw away) adding logic to # automagically generate the lit.site.cfg if we are in some kind of fresh # build situation. This means knowing how to invoke the build system though, # and I decided it was too much magic. We should solve this by just having # the .cfg files generated during the configuration step. llvm_config = lit.util.which('llvm-config', config.environment['PATH']) if not llvm_config: lit_config.fatal('No site specific configuration available!') # Get the source and object roots. llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip() llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip() lld_src_root = os.path.join(llvm_src_root, "tools", "lld") lld_obj_root = os.path.join(llvm_obj_root, "tools", "lld") # Validate that we got a tree which points to here, using the standard # tools/lld layout. this_src_root = os.path.dirname(config.test_source_root) if os.path.realpath(lld_src_root) != os.path.realpath(this_src_root): lit_config.fatal('No site specific configuration available!') # Check that the site specific configuration exists. site_cfg = os.path.join(lld_obj_root, 'test', 'lit.site.cfg') if not os.path.exists(site_cfg): lit_config.fatal( 'No site specific configuration available! You may need to ' 'run "make test" in your lld build directory.') # Okay, that worked. Notify the user of the automagic, and reconfigure. lit_config.note('using out-of-tree build at %r' % lld_obj_root) lit_config.load_config(config, site_cfg) raise SystemExit # For each occurrence of a lld tool name as its own word, replace it # with the full path to the build directory holding that tool. This # ensures that we are testing the tools just built and not some random # tools that might happen to be in the user's PATH. # Regex assertions to reject neighbor hyphens/dots (seen in some tests). # For example, we want to prefix 'lld' and 'ld.lld' but not the 'lld' inside # of 'ld.lld'. NoPreJunk = r"(?