diff options
Diffstat (limited to 'contrib/llvm/tools/lld/ELF/Driver.cpp')
-rw-r--r-- | contrib/llvm/tools/lld/ELF/Driver.cpp | 616 |
1 files changed, 500 insertions, 116 deletions
diff --git a/contrib/llvm/tools/lld/ELF/Driver.cpp b/contrib/llvm/tools/lld/ELF/Driver.cpp index 44cfa56c94ce..693dba64ab5a 100644 --- a/contrib/llvm/tools/lld/ELF/Driver.cpp +++ b/contrib/llvm/tools/lld/ELF/Driver.cpp @@ -30,9 +30,9 @@ #include "InputFiles.h" #include "InputSection.h" #include "LinkerScript.h" +#include "MarkLive.h" #include "OutputSections.h" #include "ScriptParser.h" -#include "Strings.h" #include "SymbolTable.h" #include "Symbols.h" #include "SyntheticSections.h" @@ -42,12 +42,16 @@ #include "lld/Common/Driver.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" +#include "lld/Common/Strings.h" +#include "lld/Common/TargetOptionsCommandFlags.h" #include "lld/Common/Threads.h" #include "lld/Common/Version.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compression.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/Path.h" #include "llvm/Support/TarWriter.h" #include "llvm/Support/TargetSelect.h" @@ -66,16 +70,18 @@ using namespace lld::elf; Configuration *elf::Config; LinkerDriver *elf::Driver; -static void setConfigs(); +static void setConfigs(opt::InputArgList &Args); bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Error) { - errorHandler().LogName = Args[0]; + errorHandler().LogName = sys::path::filename(Args[0]); errorHandler().ErrorLimitExceededMsg = "too many errors emitted, stopping now (use " "-error-limit=0 to see all errors)"; errorHandler().ErrorOS = &Error; + errorHandler().ExitEarly = CanExitEarly; errorHandler().ColorDiagnostics = Error.has_colors(); + InputSections.clear(); OutputSections.clear(); Tar = nullptr; @@ -88,14 +94,14 @@ bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly, Driver = make<LinkerDriver>(); Script = make<LinkerScript>(); Symtab = make<SymbolTable>(); - Config->Argv = {Args.begin(), Args.end()}; + Config->ProgName = Args[0]; - Driver->main(Args, CanExitEarly); + Driver->main(Args); // Exit immediately if we don't need to return to the caller. // This saves time because the overhead of calling destructors // for all globally-allocated objects is not negligible. - if (Config->ExitEarly) + if (CanExitEarly) exitLld(errorCount() ? 1 : 0); freeArena(); @@ -113,7 +119,8 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) { std::pair<ELFKind, uint16_t> Ret = StringSwitch<std::pair<ELFKind, uint16_t>>(S) - .Cases("aarch64elf", "aarch64linux", {ELF64LEKind, EM_AARCH64}) + .Cases("aarch64elf", "aarch64linux", "aarch64_elf64_le_vec", + {ELF64LEKind, EM_AARCH64}) .Cases("armelf", "armelf_linux_eabi", {ELF32LEKind, EM_ARM}) .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64}) .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) @@ -122,6 +129,7 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) { .Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) .Case("elf64ppc", {ELF64BEKind, EM_PPC64}) + .Case("elf64lppc", {ELF64LEKind, EM_PPC64}) .Cases("elf_amd64", "elf_x86_64", {ELF64LEKind, EM_X86_64}) .Case("elf_i386", {ELF32LEKind, EM_386}) .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU}) @@ -228,11 +236,15 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { Files.push_back( createSharedFile(MBRef, WithLOption ? path::filename(Path) : Path)); return; - default: + case file_magic::bitcode: + case file_magic::elf_relocatable: if (InLib) Files.push_back(make<LazyObjFile>(MBRef, "", 0)); else Files.push_back(createObjectFile(MBRef)); + break; + default: + error(Path + ": unknown file type"); } } @@ -248,18 +260,11 @@ void LinkerDriver::addLibrary(StringRef Name) { // 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) { +static void initLLVM() { InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); InitializeAllAsmParsers(); - - // Parse and evaluate -mllvm options. - std::vector<const char *> 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. @@ -290,11 +295,21 @@ static void checkOptions(opt::InputArgList &Args) { 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) + if (Config->GdbIndex) + error("-r and --gdb-index may not be used together"); + if (Config->ICF != ICFLevel::None) error("-r and --icf may not be used together"); if (Config->Pie) error("-r and -pie may not be used together"); } + + if (Config->ExecuteOnly) { + if (Config->EMachine != EM_AARCH64) + error("-execute-only is only supported on AArch64 targets"); + + if (Config->SingleRoRx && !Script->HasSectionsCommand) + error("-execute-only and -no-rosegment cannot be used together"); + } } static const char *getReproduceOption(opt::InputArgList &Args) { @@ -310,7 +325,37 @@ static bool hasZOption(opt::InputArgList &Args, StringRef Key) { return false; } -void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) { +static bool getZFlag(opt::InputArgList &Args, StringRef K1, StringRef K2, + bool Default) { + for (auto *Arg : Args.filtered_reverse(OPT_z)) { + if (K1 == Arg->getValue()) + return true; + if (K2 == Arg->getValue()) + return false; + } + return Default; +} + +static bool isKnown(StringRef S) { + return S == "combreloc" || S == "copyreloc" || S == "defs" || + S == "execstack" || S == "hazardplt" || S == "initfirst" || + S == "keep-text-section-prefix" || S == "lazy" || S == "muldefs" || + S == "nocombreloc" || S == "nocopyreloc" || S == "nodelete" || + S == "nodlopen" || S == "noexecstack" || + S == "nokeep-text-section-prefix" || S == "norelro" || S == "notext" || + S == "now" || S == "origin" || S == "relro" || S == "retpolineplt" || + S == "rodynamic" || S == "text" || S == "wxneeded" || + S.startswith("max-page-size=") || S.startswith("stack-size="); +} + +// Report an error for an unknown -z option. +static void checkZOptions(opt::InputArgList &Args) { + for (auto *Arg : Args.filtered(OPT_z)) + if (!isKnown(Arg->getValue())) + error("unknown -z value: " + StringRef(Arg->getValue())); +} + +void LinkerDriver::main(ArrayRef<const char *> ArgsArr) { ELFOptTable Parser; opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); @@ -319,7 +364,7 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) { // Handle -help if (Args.hasArg(OPT_help)) { - printHelp(ArgsArr[0]); + printHelp(); return; } @@ -348,9 +393,6 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) { if (Args.hasArg(OPT_version)) return; - Config->ExitEarly = CanExitEarly && !Args.hasArg(OPT_full_shutdown); - errorHandler().ExitEarly = Config->ExitEarly; - 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. @@ -368,10 +410,14 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) { } readConfigs(Args); - initLLVM(Args); + checkZOptions(Args); + initLLVM(); createFiles(Args); + if (errorCount()) + return; + inferMachineType(); - setConfigs(); + setConfigs(Args); checkOptions(Args); if (errorCount()) return; @@ -455,6 +501,8 @@ static bool isOutputFormatBinary(opt::InputArgList &Args) { StringRef S = Arg->getValue(); if (S == "binary") return true; + if (S.startswith("elf")) + return false; error("unknown --oformat value: " + S); } return false; @@ -482,6 +530,15 @@ static StringRef getDynamicLinker(opt::InputArgList &Args) { return Arg->getValue(); } +static ICFLevel getICF(opt::InputArgList &Args) { + auto *Arg = Args.getLastArg(OPT_icf_none, OPT_icf_safe, OPT_icf_all); + if (!Arg || Arg->getOption().getID() == OPT_icf_none) + return ICFLevel::None; + if (Arg->getOption().getID() == OPT_icf_safe) + return ICFLevel::Safe; + return ICFLevel::All; +} + static StripPolicy getStrip(opt::InputArgList &Args) { if (Args.hasArg(OPT_relocatable)) return StripPolicy::None; @@ -556,6 +613,8 @@ getBuildId(opt::InputArgList &Args) { return {BuildIdKind::Fast, {}}; StringRef S = Arg->getValue(); + if (S == "fast") + return {BuildIdKind::Fast, {}}; if (S == "md5") return {BuildIdKind::Md5, {}}; if (S == "sha1" || S == "tree") @@ -570,6 +629,57 @@ getBuildId(opt::InputArgList &Args) { return {BuildIdKind::None, {}}; } +static std::pair<bool, bool> getPackDynRelocs(opt::InputArgList &Args) { + StringRef S = Args.getLastArgValue(OPT_pack_dyn_relocs, "none"); + if (S == "android") + return {true, false}; + if (S == "relr") + return {false, true}; + if (S == "android+relr") + return {true, true}; + + if (S != "none") + error("unknown -pack-dyn-relocs format: " + S); + return {false, false}; +} + +static void readCallGraph(MemoryBufferRef MB) { + // Build a map from symbol name to section + DenseMap<StringRef, const Symbol *> SymbolNameToSymbol; + for (InputFile *File : ObjectFiles) + for (Symbol *Sym : File->getSymbols()) + SymbolNameToSymbol[Sym->getName()] = Sym; + + for (StringRef L : args::getLines(MB)) { + SmallVector<StringRef, 3> Fields; + L.split(Fields, ' '); + uint64_t Count; + if (Fields.size() != 3 || !to_integer(Fields[2], Count)) + fatal(MB.getBufferIdentifier() + ": parse error"); + const Symbol *FromSym = SymbolNameToSymbol.lookup(Fields[0]); + const Symbol *ToSym = SymbolNameToSymbol.lookup(Fields[1]); + if (Config->WarnSymbolOrdering) { + if (!FromSym) + warn(MB.getBufferIdentifier() + ": no such symbol: " + Fields[0]); + if (!ToSym) + warn(MB.getBufferIdentifier() + ": no such symbol: " + Fields[1]); + } + if (!FromSym || !ToSym || Count == 0) + continue; + warnUnorderableSymbol(FromSym); + warnUnorderableSymbol(ToSym); + const Defined *FromSymD = dyn_cast<Defined>(FromSym); + const Defined *ToSymD = dyn_cast<Defined>(ToSym); + if (!FromSymD || !ToSymD) + continue; + const auto *FromSB = dyn_cast_or_null<InputSectionBase>(FromSymD->Section); + const auto *ToSB = dyn_cast_or_null<InputSectionBase>(ToSymD->Section); + if (!FromSB || !ToSB) + continue; + Config->CallGraphProfile[std::make_pair(FromSB, ToSB)] += Count; + } +} + static bool getCompressDebugSections(opt::InputArgList &Args) { StringRef S = Args.getLastArgValue(OPT_compress_debug_sections, "none"); if (S == "none") @@ -581,54 +691,100 @@ static bool getCompressDebugSections(opt::InputArgList &Args) { return true; } -static int parseInt(StringRef S, opt::Arg *Arg) { - int V = 0; - if (!to_integer(S, V, 10)) - error(Arg->getSpelling() + ": number expected, but got '" + S + "'"); - return V; +static std::pair<StringRef, StringRef> getOldNewOptions(opt::InputArgList &Args, + unsigned Id) { + auto *Arg = Args.getLastArg(Id); + if (!Arg) + return {"", ""}; + + StringRef S = Arg->getValue(); + std::pair<StringRef, StringRef> Ret = S.split(';'); + if (Ret.second.empty()) + error(Arg->getSpelling() + " expects 'old;new' format, but got " + S); + return Ret; +} + +// Parse the symbol ordering file and warn for any duplicate entries. +static std::vector<StringRef> getSymbolOrderingFile(MemoryBufferRef MB) { + SetVector<StringRef> Names; + for (StringRef S : args::getLines(MB)) + if (!Names.insert(S) && Config->WarnSymbolOrdering) + warn(MB.getBufferIdentifier() + ": duplicate ordered symbol: " + S); + + return Names.takeVector(); +} + +static void parseClangOption(StringRef Opt, const Twine &Msg) { + std::string Err; + raw_string_ostream OS(Err); + + const char *Argv[] = {Config->ProgName.data(), Opt.data()}; + if (cl::ParseCommandLineOptions(2, Argv, "", &OS)) + return; + OS.flush(); + error(Msg + ": " + StringRef(Err).trim()); } // Initializes Config members by the command line options. void LinkerDriver::readConfigs(opt::InputArgList &Args) { + errorHandler().Verbose = Args.hasArg(OPT_verbose); + errorHandler().FatalWarnings = + Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); + ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); + Config->AllowMultipleDefinition = - Args.hasArg(OPT_allow_multiple_definition) || hasZOption(Args, "muldefs"); + Args.hasFlag(OPT_allow_multiple_definition, + OPT_no_allow_multiple_definition, false) || + hasZOption(Args, "muldefs"); Config->AuxiliaryList = args::getStrings(Args, OPT_auxiliary); Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic); Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions); + Config->CheckSections = + Args.hasFlag(OPT_check_sections, OPT_no_check_sections, true); Config->Chroot = Args.getLastArgValue(OPT_chroot); Config->CompressDebugSections = getCompressDebugSections(Args); + Config->Cref = Args.hasFlag(OPT_cref, OPT_no_cref, false); Config->DefineCommon = Args.hasFlag(OPT_define_common, OPT_no_define_common, !Args.hasArg(OPT_relocatable)); Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true); Config->DisableVerify = Args.hasArg(OPT_disable_verify); Config->Discard = getDiscard(Args); + Config->DwoDir = Args.getLastArgValue(OPT_plugin_opt_dwo_dir_eq); Config->DynamicLinker = getDynamicLinker(Args); Config->EhFrameHdr = Args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, false); Config->EmitRelocs = Args.hasArg(OPT_emit_relocs); - Config->EnableNewDtags = !Args.hasArg(OPT_disable_new_dtags); + Config->EnableNewDtags = + Args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true); Config->Entry = Args.getLastArgValue(OPT_entry); + Config->ExecuteOnly = + Args.hasFlag(OPT_execute_only, OPT_no_execute_only, false); Config->ExportDynamic = Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false); - errorHandler().FatalWarnings = - Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); Config->FilterList = args::getStrings(Args, OPT_filter); Config->Fini = Args.getLastArgValue(OPT_fini, "_fini"); Config->FixCortexA53Errata843419 = Args.hasArg(OPT_fix_cortex_a53_843419); Config->GcSections = Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false); + Config->GnuUnique = Args.hasFlag(OPT_gnu_unique, OPT_no_gnu_unique, true); Config->GdbIndex = Args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false); - Config->ICF = Args.hasFlag(OPT_icf_all, OPT_icf_none, false); - Config->ICFData = Args.hasArg(OPT_icf_data); + Config->ICF = getICF(Args); + Config->IgnoreDataAddressEquality = + Args.hasArg(OPT_ignore_data_address_equality); + Config->IgnoreFunctionAddressEquality = + Args.hasArg(OPT_ignore_function_address_equality); Config->Init = Args.getLastArgValue(OPT_init, "_init"); Config->LTOAAPipeline = Args.getLastArgValue(OPT_lto_aa_pipeline); + Config->LTODebugPassManager = Args.hasArg(OPT_lto_debug_pass_manager); + Config->LTONewPassManager = Args.hasArg(OPT_lto_new_pass_manager); Config->LTONewPmPasses = Args.getLastArgValue(OPT_lto_newpm_passes); Config->LTOO = args::getInteger(Args, OPT_lto_O, 2); + Config->LTOObjPath = Args.getLastArgValue(OPT_plugin_opt_obj_path_eq); Config->LTOPartitions = args::getInteger(Args, OPT_lto_partitions, 1); + Config->LTOSampleProfile = Args.getLastArgValue(OPT_lto_sample_profile); Config->MapFile = Args.getLastArgValue(OPT_Map); - Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique); + Config->MipsGotSize = args::getInteger(Args, OPT_mips_got_size, 0xfff0); Config->MergeArmExidx = Args.hasFlag(OPT_merge_exidx_entries, OPT_no_merge_exidx_entries, true); - Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version); Config->NoinhibitExec = Args.hasArg(OPT_noinhibit_exec); Config->Nostdlib = Args.hasArg(OPT_nostdlib); Config->OFormatBinary = isOutputFormatBinary(Args); @@ -638,7 +794,9 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { Config->Optimize = args::getInteger(Args, OPT_O, 1); Config->OrphanHandling = getOrphanHandling(Args); Config->OutputFile = Args.getLastArgValue(OPT_o); - Config->Pie = Args.hasFlag(OPT_pie, OPT_nopie, false); + Config->Pie = Args.hasFlag(OPT_pie, OPT_no_pie, false); + Config->PrintIcfSections = + Args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false); Config->PrintGcSections = Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false); Config->Rpath = getRpath(Args); @@ -658,48 +816,58 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { Config->ThinLTOCachePolicy = CHECK( parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)), "--thinlto-cache-policy: invalid cache policy"); + Config->ThinLTOEmitImportsFiles = + Args.hasArg(OPT_plugin_opt_thinlto_emit_imports_files); + Config->ThinLTOIndexOnly = Args.hasArg(OPT_plugin_opt_thinlto_index_only) || + Args.hasArg(OPT_plugin_opt_thinlto_index_only_eq); + Config->ThinLTOIndexOnlyArg = + Args.getLastArgValue(OPT_plugin_opt_thinlto_index_only_eq); Config->ThinLTOJobs = args::getInteger(Args, OPT_thinlto_jobs, -1u); - ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); + Config->ThinLTOObjectSuffixReplace = + getOldNewOptions(Args, OPT_plugin_opt_thinlto_object_suffix_replace_eq); + Config->ThinLTOPrefixReplace = + getOldNewOptions(Args, OPT_plugin_opt_thinlto_prefix_replace_eq); Config->Trace = Args.hasArg(OPT_trace); Config->Undefined = args::getStrings(Args, OPT_undefined); + Config->UndefinedVersion = + Args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, true); + Config->UseAndroidRelrTags = Args.hasFlag( + OPT_use_android_relr_tags, OPT_no_use_android_relr_tags, false); Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args); - Config->Verbose = Args.hasArg(OPT_verbose); - errorHandler().Verbose = Config->Verbose; - Config->WarnCommon = Args.hasArg(OPT_warn_common); - Config->ZCombreloc = !hasZOption(Args, "nocombreloc"); - Config->ZExecstack = hasZOption(Args, "execstack"); + Config->WarnBackrefs = + Args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false); + Config->WarnCommon = Args.hasFlag(OPT_warn_common, OPT_no_warn_common, false); + Config->WarnSymbolOrdering = + Args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true); + Config->ZCombreloc = getZFlag(Args, "combreloc", "nocombreloc", true); + Config->ZCopyreloc = getZFlag(Args, "copyreloc", "nocopyreloc", true); + Config->ZExecstack = getZFlag(Args, "execstack", "noexecstack", false); Config->ZHazardplt = hasZOption(Args, "hazardplt"); - Config->ZNocopyreloc = hasZOption(Args, "nocopyreloc"); + Config->ZInitfirst = hasZOption(Args, "initfirst"); + Config->ZKeepTextSectionPrefix = getZFlag( + Args, "keep-text-section-prefix", "nokeep-text-section-prefix", false); Config->ZNodelete = hasZOption(Args, "nodelete"); Config->ZNodlopen = hasZOption(Args, "nodlopen"); - Config->ZNow = hasZOption(Args, "now"); + Config->ZNow = getZFlag(Args, "now", "lazy", false); Config->ZOrigin = hasZOption(Args, "origin"); - Config->ZRelro = !hasZOption(Args, "norelro"); + Config->ZRelro = getZFlag(Args, "relro", "norelro", true); Config->ZRetpolineplt = hasZOption(Args, "retpolineplt"); Config->ZRodynamic = hasZOption(Args, "rodynamic"); Config->ZStackSize = args::getZOptionValue(Args, OPT_z, "stack-size", 0); - Config->ZText = !hasZOption(Args, "notext"); + Config->ZText = getZFlag(Args, "text", "notext", true); Config->ZWxneeded = hasZOption(Args, "wxneeded"); - // Parse LTO plugin-related options for compatibility with gold. - for (auto *Arg : Args.filtered(OPT_plugin_opt, OPT_plugin_opt_eq)) { - StringRef S = Arg->getValue(); - if (S == "disable-verify") - Config->DisableVerify = true; - else if (S == "save-temps") - Config->SaveTemps = true; - else if (S.startswith("O")) - Config->LTOO = parseInt(S.substr(1), Arg); - else if (S.startswith("lto-partitions=")) - Config->LTOPartitions = parseInt(S.substr(15), Arg); - else if (S.startswith("jobs=")) - Config->ThinLTOJobs = parseInt(S.substr(5), Arg); - else if (!S.startswith("/") && !S.startswith("-fresolution=") && - !S.startswith("-pass-through=") && !S.startswith("mcpu=") && - !S.startswith("thinlto") && S != "-function-sections" && - S != "-data-sections") - error(Arg->getSpelling() + ": unknown option: " + S); - } + // Parse LTO options. + if (auto *Arg = Args.getLastArg(OPT_plugin_opt_mcpu_eq)) + parseClangOption(Saver.save("-mcpu=" + StringRef(Arg->getValue())), + Arg->getSpelling()); + + for (auto *Arg : Args.filtered(OPT_plugin_opt)) + parseClangOption(Arg->getValue(), Arg->getSpelling()); + + // Parse -mllvm options. + for (auto *Arg : Args.filtered(OPT_mllvm)) + parseClangOption(Arg->getValue(), Arg->getSpelling()); if (Config->LTOO > 3) error("invalid optimization level for LTO: " + Twine(Config->LTOO)); @@ -742,17 +910,12 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { std::tie(Config->BuildId, Config->BuildIdVector) = getBuildId(Args); - if (auto *Arg = Args.getLastArg(OPT_pack_dyn_relocs_eq)) { - StringRef S = Arg->getValue(); - if (S == "android") - Config->AndroidPackDynRelocs = true; - else if (S != "none") - error("unknown -pack-dyn-relocs format: " + S); - } + std::tie(Config->AndroidPackDynRelocs, Config->RelrPackDynRelocs) = + getPackDynRelocs(Args); if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file)) if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) - Config->SymbolOrderingFile = args::getLines(*Buffer); + Config->SymbolOrderingFile = getSymbolOrderingFile(*Buffer); // If --retain-symbol-file is used, we'll keep only the symbols listed in // the file and discard all others. @@ -780,32 +943,67 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { {Arg->getValue(), /*IsExternCpp*/ false, /*HasWildcard*/ false}); } + // If --export-dynamic-symbol=foo is given and symbol foo is defined in + // an object file in an archive file, that object file should be pulled + // out and linked. (It doesn't have to behave like that from technical + // point of view, but this is needed for compatibility with GNU.) + for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol)) + Config->Undefined.push_back(Arg->getValue()); + for (auto *Arg : Args.filtered(OPT_version_script)) - if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) - readVersionScript(*Buffer); + if (Optional<std::string> Path = searchScript(Arg->getValue())) { + if (Optional<MemoryBufferRef> Buffer = readFile(*Path)) + readVersionScript(*Buffer); + } else { + error(Twine("cannot find version script ") + Arg->getValue()); + } } // Some Config members do not directly correspond to any particular // command line options, but computed based on other Config values. // This function initialize such members. See Config.h for the details // of these values. -static void setConfigs() { +static void setConfigs(opt::InputArgList &Args) { ELFKind Kind = Config->EKind; uint16_t Machine = Config->EMachine; - // There is an ILP32 ABI for x86-64, although it's not very popular. - // It is called the x32 ABI. - bool IsX32 = (Kind == ELF32LEKind && Machine == EM_X86_64); - Config->CopyRelocs = (Config->Relocatable || Config->EmitRelocs); Config->Is64 = (Kind == ELF64LEKind || Kind == ELF64BEKind); Config->IsLE = (Kind == ELF32LEKind || Kind == ELF64LEKind); Config->Endianness = Config->IsLE ? support::endianness::little : support::endianness::big; Config->IsMips64EL = (Kind == ELF64LEKind && Machine == EM_MIPS); - Config->IsRela = Config->Is64 || IsX32 || Config->MipsN32Abi; Config->Pic = Config->Pie || Config->Shared; Config->Wordsize = Config->Is64 ? 8 : 4; + + // There is an ILP32 ABI for x86-64, although it's not very popular. + // It is called the x32 ABI. + bool IsX32 = (Kind == ELF32LEKind && Machine == EM_X86_64); + + // ELF defines two different ways to store relocation addends as shown below: + // + // Rel: Addends are stored to the location where relocations are applied. + // Rela: Addends are stored as part of relocation entry. + // + // In other words, Rela makes it easy to read addends at the price of extra + // 4 or 8 byte for each relocation entry. We don't know why ELF defined two + // different mechanisms in the first place, but this is how the spec is + // defined. + // + // You cannot choose which one, Rel or Rela, you want to use. Instead each + // ABI defines which one you need to use. The following expression expresses + // that. + Config->IsRela = + (Config->Is64 || IsX32 || Machine == EM_PPC) && Machine != EM_MIPS; + + // If the output uses REL relocations we must store the dynamic relocation + // addends to the output sections. We also store addends for RELA relocations + // if --apply-dynamic-relocs is used. + // We default to not writing the addends when using RELA relocations since + // any standard conforming tool can find it in r_addend. + Config->WriteAddends = Args.hasFlag(OPT_apply_dynamic_relocs, + OPT_no_apply_dynamic_relocs, false) || + !Config->IsRela; } // Returns a value of "-format" option. @@ -820,6 +1018,10 @@ static bool getBinaryOption(StringRef S) { } void LinkerDriver::createFiles(opt::InputArgList &Args) { + // For --{push,pop}-state. + std::vector<std::tuple<bool, bool, bool>> Stack; + + // Iterate over argv to process input files and positional arguments. for (auto *Arg : Args) { switch (Arg->getOption().getUnaliasedOption().getID()) { case OPT_library: @@ -828,8 +1030,15 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) { case OPT_INPUT: addFile(Arg->getValue(), /*WithLOption=*/false); break; + case OPT_defsym: { + StringRef From; + StringRef To; + std::tie(From, To) = StringRef(Arg->getValue()).split('='); + readDefsym(From, MemoryBufferRef(To, "-defsym")); + break; + } case OPT_script: - if (Optional<std::string> Path = searchLinkerScript(Arg->getValue())) { + if (Optional<std::string> Path = searchScript(Arg->getValue())) { if (Optional<MemoryBufferRef> MB = readFile(*Path)) readLinkerScript(*MB); break; @@ -857,11 +1066,48 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) { case OPT_no_whole_archive: InWholeArchive = false; break; + case OPT_just_symbols: + if (Optional<MemoryBufferRef> MB = readFile(Arg->getValue())) { + Files.push_back(createObjectFile(*MB)); + Files.back()->JustSymbols = true; + } + break; + case OPT_start_group: + if (InputFile::IsInGroup) + error("nested --start-group"); + InputFile::IsInGroup = true; + break; + case OPT_end_group: + if (!InputFile::IsInGroup) + error("stray --end-group"); + InputFile::IsInGroup = false; + ++InputFile::NextGroupId; + break; case OPT_start_lib: + if (InLib) + error("nested --start-lib"); + if (InputFile::IsInGroup) + error("may not nest --start-lib in --start-group"); InLib = true; + InputFile::IsInGroup = true; break; case OPT_end_lib: + if (!InLib) + error("stray --end-lib"); InLib = false; + InputFile::IsInGroup = false; + ++InputFile::NextGroupId; + break; + case OPT_push_state: + Stack.emplace_back(Config->AsNeeded, Config->Static, InWholeArchive); + break; + case OPT_pop_state: + if (Stack.empty()) { + error("unbalanced --push-state/--pop-state"); + break; + } + std::tie(Config->AsNeeded, Config->Static, InWholeArchive) = Stack.back(); + Stack.pop_back(); break; } } @@ -934,14 +1180,6 @@ static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &Args) { return Ret; } -static Optional<StringRef> getArchiveName(InputFile *File) { - if (isa<ArchiveFile>(File)) - return File->getName(); - if (!File->ArchiveName.empty()) - return File->ArchiveName; - return None; -} - // Handles the -exclude-libs option. If a static library file is specified // by the -exclude-libs option, all public symbols from the archive become // private unless otherwise specified by version scripts or something. @@ -949,18 +1187,140 @@ static Optional<StringRef> getArchiveName(InputFile *File) { // // This is not a popular option, but some programs such as bionic libc use it. template <class ELFT> -static void excludeLibs(opt::InputArgList &Args, ArrayRef<InputFile *> Files) { +static void excludeLibs(opt::InputArgList &Args) { DenseSet<StringRef> Libs = getExcludeLibs(Args); bool All = Libs.count("ALL"); - for (InputFile *File : Files) - if (Optional<StringRef> Archive = getArchiveName(File)) - if (All || Libs.count(path::filename(*Archive))) + auto Visit = [&](InputFile *File) { + if (!File->ArchiveName.empty()) + if (All || Libs.count(path::filename(File->ArchiveName))) for (Symbol *Sym : File->getSymbols()) - if (!Sym->isLocal()) + if (!Sym->isLocal() && Sym->File == File) Sym->VersionId = VER_NDX_LOCAL; + }; + + for (InputFile *File : ObjectFiles) + Visit(File); + + for (BitcodeFile *File : BitcodeFiles) + Visit(File); +} + +// Force Sym to be entered in the output. Used for -u or equivalent. +template <class ELFT> static void handleUndefined(StringRef Name) { + Symbol *Sym = Symtab->find(Name); + if (!Sym) + return; + + // Since symbol S may not be used inside the program, LTO may + // eliminate it. Mark the symbol as "used" to prevent it. + Sym->IsUsedInRegularObj = true; + + if (Sym->isLazy()) + Symtab->fetchLazy<ELFT>(Sym); +} + +template <class ELFT> static bool shouldDemote(Symbol &Sym) { + // If all references to a DSO happen to be weak, the DSO is not added to + // DT_NEEDED. If that happens, we need to eliminate shared symbols created + // from the DSO. Otherwise, they become dangling references that point to a + // non-existent DSO. + if (auto *S = dyn_cast<SharedSymbol>(&Sym)) + return !S->getFile<ELFT>().IsNeeded; + + // We are done processing archives, so lazy symbols that were used but not + // found can be converted to undefined. We could also just delete the other + // lazy symbols, but that seems to be more work than it is worth. + return Sym.isLazy() && Sym.IsUsedInRegularObj; } +// Some files, such as .so or files between -{start,end}-lib may be removed +// after their symbols are added to the symbol table. If that happens, we +// need to remove symbols that refer files that no longer exist, so that +// they won't appear in the symbol table of the output file. +// +// We remove symbols by demoting them to undefined symbol. +template <class ELFT> static void demoteSymbols() { + for (Symbol *Sym : Symtab->getSymbols()) { + if (shouldDemote<ELFT>(*Sym)) { + bool Used = Sym->Used; + replaceSymbol<Undefined>(Sym, nullptr, Sym->getName(), Sym->Binding, + Sym->StOther, Sym->Type); + Sym->Used = Used; + } + } +} + +// The section referred to by S is considered address-significant. Set the +// KeepUnique flag on the section if appropriate. +static void markAddrsig(Symbol *S) { + if (auto *D = dyn_cast_or_null<Defined>(S)) + if (D->Section) + // We don't need to keep text sections unique under --icf=all even if they + // are address-significant. + if (Config->ICF == ICFLevel::Safe || !(D->Section->Flags & SHF_EXECINSTR)) + D->Section->KeepUnique = true; +} + +// Record sections that define symbols mentioned in --keep-unique <symbol> +// and symbols referred to by address-significance tables. These sections are +// ineligible for ICF. +template <class ELFT> +static void findKeepUniqueSections(opt::InputArgList &Args) { + for (auto *Arg : Args.filtered(OPT_keep_unique)) { + StringRef Name = Arg->getValue(); + auto *D = dyn_cast_or_null<Defined>(Symtab->find(Name)); + if (!D || !D->Section) { + warn("could not find symbol " + Name + " to keep unique"); + continue; + } + D->Section->KeepUnique = true; + } + + // --icf=all --ignore-data-address-equality means that we can ignore + // the dynsym and address-significance tables entirely. + if (Config->ICF == ICFLevel::All && Config->IgnoreDataAddressEquality) + return; + + // Symbols in the dynsym could be address-significant in other executables + // or DSOs, so we conservatively mark them as address-significant. + for (Symbol *S : Symtab->getSymbols()) + if (S->includeInDynsym()) + markAddrsig(S); + + // Visit the address-significance table in each object file and mark each + // referenced symbol as address-significant. + for (InputFile *F : ObjectFiles) { + auto *Obj = cast<ObjFile<ELFT>>(F); + ArrayRef<Symbol *> Syms = Obj->getSymbols(); + if (Obj->AddrsigSec) { + ArrayRef<uint8_t> Contents = + check(Obj->getObj().getSectionContents(Obj->AddrsigSec)); + const uint8_t *Cur = Contents.begin(); + while (Cur != Contents.end()) { + unsigned Size; + const char *Err; + uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err); + if (Err) + fatal(toString(F) + ": could not decode addrsig section: " + Err); + markAddrsig(Syms[SymIndex]); + Cur += Size; + } + } else { + // If an object file does not have an address-significance table, + // conservatively mark all of its symbols as address-significant. + for (Symbol *S : Syms) + markAddrsig(S); + } + } +} + +static const char *LibcallRoutineNames[] = { +#define HANDLE_LIBCALL(code, name) name, +#include "llvm/IR/RuntimeLibcalls.def" +#undef HANDLE_LIBCALL +}; + // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { @@ -1009,14 +1369,6 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { for (InputFile *F : Files) Symtab->addFile<ELFT>(F); - // Process -defsym option. - for (auto *Arg : Args.filtered(OPT_defsym)) { - StringRef From; - StringRef To; - std::tie(From, To) = StringRef(Arg->getValue()).split('='); - readDefsym(From, MemoryBufferRef(To, "-defsym")); - } - // Now that we have every file, we can decide if we will need a // dynamic symbol table. // We need one if we were asked to export dynamic symbols or if we are @@ -1033,24 +1385,39 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { // Handle the `--undefined <sym>` options. for (StringRef S : Config->Undefined) - Symtab->fetchIfLazy<ELFT>(S); + handleUndefined<ELFT>(S); - // If an entry symbol is in a static archive, pull out that file now - // to complete the symbol table. After this, no new names except a - // few linker-synthesized ones will be added to the symbol table. - Symtab->fetchIfLazy<ELFT>(Config->Entry); + // If an entry symbol is in a static archive, pull out that file now. + handleUndefined<ELFT>(Config->Entry); + + // If any of our inputs are bitcode files, the LTO code generator may create + // references to certain library functions that might not be explicit in the + // bitcode file's symbol table. If any of those library functions are defined + // in a bitcode file in an archive member, we need to arrange to use LTO to + // compile those archive members by adding them to the link beforehand. + // + // With this the symbol table should be complete. After this, no new names + // except a few linker-synthesized ones will be added to the symbol table. + if (!BitcodeFiles.empty()) + for (const char *S : LibcallRoutineNames) + handleUndefined<ELFT>(S); // Return if there were name resolution errors. if (errorCount()) return; - // Handle undefined symbols in DSOs. - if (!Config->Shared) - Symtab->scanShlibUndefined<ELFT>(); + // Now when we read all script files, we want to finalize order of linker + // script commands, which can be not yet final because of INSERT commands. + Script->processInsertCommands(); + + // We want to declare linker script's symbols early, + // so that we can version them. + // They also might be exported if referenced by DSOs. + Script->declareSymbols(); // Handle the -exclude-libs option. if (Args.hasArg(OPT_exclude_libs)) - excludeLibs<ELFT>(Args, Files); + excludeLibs<ELFT>(Args); // Create ElfHeader early. We need a dummy section in // addReservedSymbols to mark the created symbols as not absolute. @@ -1073,10 +1440,18 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { for (auto *Arg : Args.filtered(OPT_wrap)) Symtab->addSymbolWrap<ELFT>(Arg->getValue()); + // Do link-time optimization if given files are LLVM bitcode files. + // This compiles bitcode files into real object files. Symtab->addCombinedLTOObject<ELFT>(); if (errorCount()) return; + // If -thinlto-index-only is given, we should create only "index + // files" and not object files. Index file creation is already done + // in addCombinedLTOObject, so we are done if that's the case. + if (Config->ThinLTOIndexOnly) + return; + // Apply symbol renames for -wrap. Symtab->applySymbolWrap(); @@ -1123,11 +1498,20 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { // Do size optimizations: garbage collection, merging of SHF_MERGE sections // and identical code folding. - markLive<ELFT>(); decompressSections(); + splitSections<ELFT>(); + markLive<ELFT>(); + demoteSymbols<ELFT>(); mergeSections(); - if (Config->ICF) + if (Config->ICF != ICFLevel::None) { + findKeepUniqueSections<ELFT>(Args); doIcf<ELFT>(); + } + + // Read the callgraph now that we know what was gced or icfed + if (auto *Arg = Args.getLastArg(OPT_call_graph_ordering_file)) + if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) + readCallGraph(*Buffer); // Write the result to the file. writeResult<ELFT>(); |