diff options
author | Will Wilson <will@indefiant.com> | 2018-09-24 15:28:03 +0000 |
---|---|---|
committer | Will Wilson <will@indefiant.com> | 2018-09-24 15:28:03 +0000 |
commit | 58898a8566a462780711073bfceb165d84cc0f73 (patch) | |
tree | 6658ae99a546435161477137fc800e9abfec6f6a /lld | |
parent | 146603d6841611b649999eda9fb868ce848ebebd (diff) |
[lld-link] Generalize handling of /debug and /debug:{none,full,fastlink,ghash,symtab}
Implement final argument precedence if multiple /debug arguments are passed on the command-line to match expected link.exe behavior.
Support /debug:none and emit warning for /debug:fastlink with automatic fallback to /debug:full.
Emit error if last /debug:option is unknown.
Emit warning if last /debugtype:option is unknown.
https://reviews.llvm.org/D50404
Diffstat (limited to 'lld')
-rw-r--r-- | lld/COFF/Driver.cpp | 91 | ||||
-rw-r--r-- | lld/COFF/Options.td | 5 | ||||
-rw-r--r-- | lld/test/COFF/debug-fastlink.test | 12 | ||||
-rw-r--r-- | lld/test/COFF/invalid-debug-type.test | 3 | ||||
-rw-r--r-- | lld/test/COFF/invalid-debug.test | 6 | ||||
-rw-r--r-- | lld/test/COFF/pdb-options.test | 5 |
6 files changed, 92 insertions, 30 deletions
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index b2fe804bce6..15ed19ba07b 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -508,26 +508,65 @@ static std::string createResponseFile(const opt::InputArgList &Args, return Data.str(); } -static unsigned getDefaultDebugType(const opt::InputArgList &Args) { - unsigned DebugTypes = static_cast<unsigned>(DebugType::CV); +enum class DebugKind { Unknown, None, Full, FastLink, GHash, Dwarf, Symtab }; + +static DebugKind parseDebugKind(const opt::InputArgList &Args) { + auto *A = Args.getLastArg(OPT_debug, OPT_debug_opt); + if (!A) + return DebugKind::None; + if (A->getNumValues() == 0) + return DebugKind::Full; + + DebugKind Debug = StringSwitch<DebugKind>(A->getValue()) + .CaseLower("none", DebugKind::None) + .CaseLower("full", DebugKind::Full) + .CaseLower("fastlink", DebugKind::FastLink) + // LLD extensions + .CaseLower("ghash", DebugKind::GHash) + .CaseLower("dwarf", DebugKind::Dwarf) + .CaseLower("symtab", DebugKind::Symtab) + .Default(DebugKind::Unknown); + + if (Debug == DebugKind::FastLink) { + warn("/debug:fastlink unsupported; using /debug:full"); + return DebugKind::Full; + } + if (Debug == DebugKind::Unknown) { + error("/debug: unknown option: " + Twine(A->getValue())); + return DebugKind::None; + } + return Debug; +} + +static unsigned parseDebugTypes(const opt::InputArgList &Args) { + unsigned DebugTypes = static_cast<unsigned>(DebugType::None); + + if (auto *A = Args.getLastArg(OPT_debugtype)) { + SmallVector<StringRef, 3> Types; + A->getSpelling().split(Types, ',', /*KeepEmpty=*/false); + + for (StringRef Type : Types) { + unsigned V = StringSwitch<unsigned>(Type.lower()) + .Case("cv", static_cast<unsigned>(DebugType::CV)) + .Case("pdata", static_cast<unsigned>(DebugType::PData)) + .Case("fixup", static_cast<unsigned>(DebugType::Fixup)) + .Default(0); + if (V == 0) { + warn("/debugtype: unknown option: " + Twine(A->getValue())); + continue; + } + DebugTypes |= V; + } + return DebugTypes; + } + + // Default debug types + DebugTypes = static_cast<unsigned>(DebugType::CV); if (Args.hasArg(OPT_driver)) DebugTypes |= static_cast<unsigned>(DebugType::PData); if (Args.hasArg(OPT_profile)) DebugTypes |= static_cast<unsigned>(DebugType::Fixup); - return DebugTypes; -} - -static unsigned parseDebugType(StringRef Arg) { - SmallVector<StringRef, 3> Types; - Arg.split(Types, ',', /*KeepEmpty=*/false); - unsigned DebugTypes = static_cast<unsigned>(DebugType::None); - for (StringRef Type : Types) - DebugTypes |= StringSwitch<unsigned>(Type.lower()) - .Case("cv", static_cast<unsigned>(DebugType::CV)) - .Case("pdata", static_cast<unsigned>(DebugType::PData)) - .Case("fixup", static_cast<unsigned>(DebugType::Fixup)) - .Default(0); return DebugTypes; } @@ -895,17 +934,19 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { Config->ForceMultiple = true; // Handle /debug - if (Args.hasArg(OPT_debug, OPT_debug_dwarf, OPT_debug_ghash)) { + DebugKind Debug = parseDebugKind(Args); + if (Debug == DebugKind::Full || Debug == DebugKind::Dwarf || + Debug == DebugKind::GHash) { Config->Debug = true; Config->Incremental = true; - if (auto *Arg = Args.getLastArg(OPT_debugtype)) - Config->DebugTypes = parseDebugType(Arg->getValue()); - else - Config->DebugTypes = getDefaultDebugType(Args); } + // Handle /debugtype + Config->DebugTypes = parseDebugTypes(Args); + // Handle /pdb - bool ShouldCreatePDB = Args.hasArg(OPT_debug, OPT_debug_ghash); + bool ShouldCreatePDB = + (Debug == DebugKind::Full || Debug == DebugKind::GHash); if (ShouldCreatePDB) { if (auto *Arg = Args.getLastArg(OPT_pdb)) Config->PDBPath = Arg->getValue(); @@ -1026,7 +1067,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { Config->Implib = Arg->getValue(); // Handle /opt. - bool DoGC = !Args.hasArg(OPT_debug) || Args.hasArg(OPT_profile); + bool DoGC = Debug == DebugKind::None || Args.hasArg(OPT_profile); unsigned ICFLevel = Args.hasArg(OPT_profile) ? 0 : 1; // 0: off, 1: limited, 2: on unsigned TailMerge = 1; @@ -1170,9 +1211,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { Config->NxCompat = Args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true); Config->TerminalServerAware = !Config->DLL && Args.hasFlag(OPT_tsaware, OPT_tsaware_no, true); - Config->DebugDwarf = Args.hasArg(OPT_debug_dwarf); - Config->DebugGHashes = Args.hasArg(OPT_debug_ghash); - Config->DebugSymtab = Args.hasArg(OPT_debug_symtab); + Config->DebugDwarf = Debug == DebugKind::Dwarf; + Config->DebugGHashes = Debug == DebugKind::GHash; + Config->DebugSymtab = Debug == DebugKind::Symtab; Config->MapFile = getMapFile(Args); diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td index 13947472054..f5dcd274089 100644 --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -85,7 +85,7 @@ def deffile : Joined<["/", "-"], "def:">, HelpText<"Use module-definition file">; def debug : F<"debug">, HelpText<"Embed a symbol table in the image">; -def debug_full : F<"debug:full">, Alias<debug>; +def debug_opt : P<"debug", "Embed a symbol table in the image with option">; def debugtype : P<"debugtype", "Debug Info Options">; def dll : F<"dll">, HelpText<"Create a DLL">; def driver : P<"driver", "Generate a Windows NT Kernel Mode Driver">; @@ -142,9 +142,6 @@ def help : F<"help">; def help_q : Flag<["/?", "-?"], "">, Alias<help>; // LLD extensions -def debug_ghash : F<"debug:ghash">; -def debug_dwarf : F<"debug:dwarf">; -def debug_symtab : F<"debug:symtab">; def export_all_symbols : F<"export-all-symbols">; def kill_at : F<"kill-at">; def lldmingw : F<"lldmingw">; diff --git a/lld/test/COFF/debug-fastlink.test b/lld/test/COFF/debug-fastlink.test new file mode 100644 index 00000000000..10b414195da --- /dev/null +++ b/lld/test/COFF/debug-fastlink.test @@ -0,0 +1,12 @@ +# RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj +# RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj + +; If /DEBUG:FASTLINK is specified, /DEBUG:FULL is used instead +# RUN: rm -f %t.pdb +# RUN: lld-link /DEBUG /pdb:%t.pdb /DEBUG:FASTLINK /entry:main /nodefaultlib %t1.obj %t2.obj \ +# RUN: 2>&1 | FileCheck %s + +# CHECK: /debug:fastlink unsupported; using /debug:full + +# RUN: ls %t.pdb + diff --git a/lld/test/COFF/invalid-debug-type.test b/lld/test/COFF/invalid-debug-type.test index 10264180314..0fa40b0312b 100644 --- a/lld/test/COFF/invalid-debug-type.test +++ b/lld/test/COFF/invalid-debug-type.test @@ -1,5 +1,6 @@ # RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj # RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj # RUN: lld-link /debug /debugtype:invalid /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \ -# RUN: %t1.obj %t2.obj +# RUN: %t1.obj %t2.obj 2>&1 | FileCheck %s +# CHECK: /debugtype: unknown option: invalid
\ No newline at end of file diff --git a/lld/test/COFF/invalid-debug.test b/lld/test/COFF/invalid-debug.test new file mode 100644 index 00000000000..67f794f8b1b --- /dev/null +++ b/lld/test/COFF/invalid-debug.test @@ -0,0 +1,6 @@ +# RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj +# RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj +# RUN: not lld-link /debug /debug:invalid /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \ +# RUN: %t1.obj %t2.obj 2>&1 | FileCheck %s + +# CHECK: /debug: unknown option: invalid diff --git a/lld/test/COFF/pdb-options.test b/lld/test/COFF/pdb-options.test index 2bd1d920ee4..f0edc2f3bc7 100644 --- a/lld/test/COFF/pdb-options.test +++ b/lld/test/COFF/pdb-options.test @@ -6,6 +6,11 @@ # RUN: lld-link /pdb:%t.pdb /entry:main /nodefaultlib %t1.obj %t2.obj # RUN: not ls %t.pdb +; If /DEBUG:NONE is specified after /DEBUG, /pdb is ignored. +# RUN: rm -f %t.pdb +# RUN: lld-link /DEBUG /pdb:%t.pdb /DEBUG:NONE /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 |