Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -30,10 +30,15 @@ ELF64BEKind }; +// For --build-id. enum class BuildIdKind { None, Fnv1, Md5, Sha1, Hexstring, Uuid }; +// For --unresolved-symbols. enum class UnresolvedPolicy { NoUndef, Error, Warn, Ignore }; +// For --discard-{all,locals,none}. +enum class DiscardPolicy { Default, All, Locals, None }; + struct SymbolVersion { llvm::StringRef Name; bool IsExternCpp; @@ -79,9 +84,6 @@ bool BsymbolicFunctions; bool Demangle = true; bool DisableVerify; - bool DiscardAll; - bool DiscardLocals; - bool DiscardNone; bool EhFrameHdr; bool EnableNewDtags; bool ExportDynamic; @@ -115,6 +117,7 @@ bool ZNow; bool ZOrigin; bool ZRelro; + DiscardPolicy Discard; UnresolvedPolicy UnresolvedSymbols; BuildIdKind BuildId = BuildIdKind::None; ELFKind EKind = ELFNoneKind; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -344,6 +344,24 @@ return false; } +static DiscardPolicy getDiscardOption(opt::InputArgList &Args) { + auto *Arg = + Args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none); + if (!Arg) + return DiscardPolicy::Default; + + switch (Arg->getOption().getID()) { + case OPT_discard_all: + return DiscardPolicy::All; + case OPT_discard_locals: + return DiscardPolicy::Locals; + case OPT_discard_none: + return DiscardPolicy::None; + default: + llvm_unreachable("unknown discard option"); + } +} + // Initializes Config members by the command line options. void LinkerDriver::readConfigs(opt::InputArgList &Args) { for (auto *Arg : Args.filtered(OPT_L)) @@ -367,9 +385,7 @@ Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions); Config->Demangle = !Args.hasArg(OPT_no_demangle); Config->DisableVerify = Args.hasArg(OPT_disable_verify); - Config->DiscardAll = Args.hasArg(OPT_discard_all); - Config->DiscardLocals = Args.hasArg(OPT_discard_locals); - Config->DiscardNone = Args.hasArg(OPT_discard_none); + Config->Discard = getDiscardOption(Args); Config->EhFrameHdr = Args.hasArg(OPT_eh_frame_hdr); Config->EnableNewDtags = !Args.hasArg(OPT_disable_new_dtags); Config->ExportDynamic = Args.hasArg(OPT_export_dynamic); Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -1373,7 +1373,7 @@ // All symbols with STB_LOCAL binding precede the weak and global symbols. // .dynsym only contains global symbols. - if (!Config->DiscardAll && !StrTabSec.isDynamic()) + if (Config->Discard != DiscardPolicy::All && !StrTabSec.isDynamic()) writeLocalSymbols(Buf); writeGlobalSymbols(Buf); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -240,7 +240,7 @@ // The main function of the writer. template void Writer::run() { - if (!Config->DiscardAll) + if (Config->Discard != DiscardPolicy::All) copyLocalSymbols(); addReservedSymbols(); @@ -329,7 +329,7 @@ if (Sec == &InputSection::Discarded) return false; - if (Config->DiscardNone) + if (Config->Discard == DiscardPolicy::None) return true; // In ELF assembly .L symbols are normally discarded by the assembler. @@ -340,7 +340,7 @@ if (!SymName.startswith(".L") && !SymName.empty()) return true; - if (Config->DiscardLocals) + if (Config->Discard == DiscardPolicy::Locals) return false; return !(Sec->getSectionHdr()->sh_flags & SHF_MERGE);