From: Eric Christopher Date: Tue, 5 Feb 2013 07:29:57 +0000 (+0000) Subject: Driver and option support for -gsplit-dwarf. This is a part of X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c706c8e440abf61910c042380e19c67932998395;p=clang Driver and option support for -gsplit-dwarf. This is a part of the DWARF5 split dwarf proposal. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174349 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h index 4057e48f69..62f4aad49b 100644 --- a/include/clang/Driver/Action.h +++ b/include/clang/Driver/Action.h @@ -46,9 +46,10 @@ public: LipoJobClass, DsymutilJobClass, VerifyJobClass, + SplitDebugJobClass, JobClassFirst=PreprocessJobClass, - JobClassLast=VerifyJobClass + JobClassLast=SplitDebugJobClass }; static const char *getClassName(ActionClass AC); @@ -233,6 +234,15 @@ public: } }; +class SplitDebugJobAction : public JobAction { + virtual void anchor(); +public: + SplitDebugJobAction(ActionList &Inputs, types::ID Type); + static bool classof(const Action *A) { + return A->getKind() == SplitDebugJobClass; + } +}; + } // end namespace driver } // end namespace clang diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index f84f177197..b84f96bbe6 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -134,6 +134,8 @@ def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">; def dwarf_column_info : Flag<["-"], "dwarf-column-info">, HelpText<"Turn on column location information.">; +def split_dwarf : Flag<["-"], "split-dwarf">, + HelpText<"Split out the dwarf .dwo sections">; def fforbid_guard_variables : Flag<["-"], "fforbid-guard-variables">, HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; def no_implicit_float : Flag<["-"], "no-implicit-float">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 2aeffad382..1e56e7f575 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -760,6 +760,7 @@ def gno_record_gcc_switches : Flag<["-"], "gno-record-gcc-switches">, def gstrict_dwarf : Flag<["-"], "gstrict-dwarf">, Group; def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group; def gcolumn_info : Flag<["-"], "gcolumn-info">, Group; +def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group; def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">; def help : Flag<["-", "--"], "help">, Flags<[CC1Option]>, HelpText<"Display available options">; diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp index 2b5bbee3db..29f7ad2993 100644 --- a/lib/Driver/Action.cpp +++ b/lib/Driver/Action.cpp @@ -33,6 +33,7 @@ const char *Action::getClassName(ActionClass AC) { case LipoJobClass: return "lipo"; case DsymutilJobClass: return "dsymutil"; case VerifyJobClass: return "verify"; + case SplitDebugJobClass: return "split-debug"; } llvm_unreachable("invalid class"); @@ -119,3 +120,9 @@ void VerifyJobAction::anchor() {} VerifyJobAction::VerifyJobAction(ActionList &Inputs, types::ID Type) : JobAction(VerifyJobClass, Inputs, Type) { } + +void SplitDebugJobAction::anchor() {} + +SplitDebugJobAction::SplitDebugJobAction(ActionList &Inputs, types::ID Type) + : JobAction(SplitDebugJobClass, Inputs, Type) { +} diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 8a2804a9ad..1e23f565b6 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -25,6 +25,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringSet.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -1036,6 +1037,7 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, // Construct the actions to perform. ActionList LinkerInputs; + ActionList SplitInputs; unsigned NumSteps = 0; for (unsigned i = 0, e = Inputs.size(); i != e; ++i) { types::ID InputType = Inputs[i].first; @@ -1105,6 +1107,12 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, Current.reset(ConstructPhaseAction(Args, Phase, Current.take())); if (Current->getType() == types::TY_Nothing) break; + else if (Current->getType() == types::TY_Object && + Args.hasArg(options::OPT_gsplit_dwarf)) { + ActionList Input; + Input.push_back(Current.take()); + Current.reset(new SplitDebugJobAction(Input, types::TY_Object)); + } } // If we ended with something, add to the output list. @@ -1112,6 +1120,16 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, Actions.push_back(Current.take()); } + if (!SplitInputs.empty()) { + for (ActionList::iterator i = SplitInputs.begin(), e = SplitInputs.end(); + i != e; ++i) { + Action *Act = *i; + ActionList Inputs; + Inputs.push_back(Act); + Actions.push_back(new SplitDebugJobAction(Inputs, types::TY_Object)); + } + } + // Add a link action if necessary. if (!LinkerInputs.empty()) Actions.push_back(new LinkJobAction(LinkerInputs, types::TY_Image)); @@ -1396,12 +1414,13 @@ void Driver::BuildJobsForAction(Compilation &C, BaseInput = InputInfos[0].getFilename(); // Determine the place to write output to, if any. - if (JA->getType() == types::TY_Nothing) { + if (JA->getType() == types::TY_Nothing) Result = InputInfo(A->getType(), BaseInput); - } else { + else if (isa(A)) + Result = InputInfos[0]; + else Result = InputInfo(GetNamedOutputPath(C, *JA, BaseInput, AtTopLevel), A->getType(), BaseInput); - } if (CCCPrintBindings && !CCGenDiagnostics) { llvm::errs() << "# \"" << T.getToolChain().getTripleString() << '"' diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index d1072d5a37..367041ef86 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -189,6 +189,7 @@ Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, Tool *&T = Tools[Key]; if (!T) { switch (Key) { + case Action::SplitDebugJobClass: case Action::InputClass: case Action::BindArchClass: llvm_unreachable("Invalid tool kind."); @@ -1388,6 +1389,7 @@ Tool &Generic_GCC::SelectTool(const Compilation &C, Tool *&T = Tools[Key]; if (!T) { switch (Key) { + case Action::SplitDebugJobClass: case Action::InputClass: case Action::BindArchClass: llvm_unreachable("Invalid tool kind."); @@ -2450,6 +2452,8 @@ Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA, break; case Action::LinkJobClass: T = new tools::linuxtools::Link(*this); break; + case Action::SplitDebugJobClass: + T = new tools::linuxtools::SplitDebug(*this); break; default: T = &Generic_GCC::SelectTool(C, JA, Inputs); } diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index dbd25dfbea..71e50a5c9e 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -2250,16 +2250,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, D.CCLogDiagnosticsFilename : "-"); } - // Use the last option from "-g" group. "-gline-tables-only" is - // preserved, all other debug options are substituted with "-g". + // Use the last option from "-g" group. "-gline-tables-only" + // is preserved, all other debug options are substituted with "-g". Args.ClaimAllArgs(options::OPT_g_Group); if (Arg *A = Args.getLastArg(options::OPT_g_Group)) { - if (A->getOption().matches(options::OPT_gline_tables_only)) { + if (A->getOption().matches(options::OPT_gline_tables_only)) CmdArgs.push_back("-gline-tables-only"); - } else if (!A->getOption().matches(options::OPT_g0) && - !A->getOption().matches(options::OPT_ggdb0)) { + else if (!A->getOption().matches(options::OPT_g0) && + !A->getOption().matches(options::OPT_ggdb0)) CmdArgs.push_back("-g"); - } } // We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now. @@ -2267,6 +2266,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_gcolumn_info)) CmdArgs.push_back("-dwarf-column-info"); + // -gsplit-dwarf should turn on -g and enable the backend dwarf + // splitting and extraction. + if (Args.hasArg(options::OPT_gsplit_dwarf)) { + CmdArgs.push_back("-g"); + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-split-dwarf=Enable"); + } + Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections); Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections); @@ -5829,6 +5836,42 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs)); } +void linuxtools::SplitDebug::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + // Assert some invariants. + assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); + const InputInfo &Input = Inputs[0]; + assert(Input.isFilename() && "Unexpected verify input"); + + ArgStringList ExtractArgs; + ExtractArgs.push_back("--extract-dwo"); + + ArgStringList StripArgs; + StripArgs.push_back("--strip-dwo"); + + // Grabbing the output of the earlier compile step. + StripArgs.push_back(Input.getFilename()); + ExtractArgs.push_back(Input.getFilename()); + + // Add an output for the extract. + SmallString<128> T(Inputs[0].getBaseInput()); + llvm::sys::path::replace_extension(T, "dwo"); + const char *OutFile = Args.MakeArgString(T); + ExtractArgs.push_back(OutFile); + + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath("objcopy")); + + // First extract the dwo sections. + C.addCommand(new Command(JA, *this, Exec, ExtractArgs)); + + // Then remove them from the original .o file. + C.addCommand(new Command(JA, *this, Exec, StripArgs)); +} + void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h index f4aebd8bd2..6c1f71fcc7 100644 --- a/lib/Driver/Tools.h +++ b/lib/Driver/Tools.h @@ -454,6 +454,20 @@ namespace linuxtools { const ArgList &TCArgs, const char *LinkingOutput) const; }; + + class LLVM_LIBRARY_VISIBILITY SplitDebug : public Tool { + public: + SplitDebug(const ToolChain &TC) : Tool("linuxtools::SplitDebug", + "objcopy", TC) {} + + virtual bool hasIntegratedCPP() const { return false; } + + virtual void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; } /// minix -- Directly call GNU Binutils assembler and linker namespace minix { diff --git a/lib/Driver/WindowsToolChain.cpp b/lib/Driver/WindowsToolChain.cpp index 454d2c132b..323765adb0 100644 --- a/lib/Driver/WindowsToolChain.cpp +++ b/lib/Driver/WindowsToolChain.cpp @@ -54,6 +54,7 @@ Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA, case Action::LipoJobClass: case Action::DsymutilJobClass: case Action::VerifyJobClass: + case Action::SplitDebugJobClass: llvm_unreachable("Invalid tool kind."); case Action::PreprocessJobClass: case Action::PrecompileJobClass: diff --git a/test/Driver/split-debug.c b/test/Driver/split-debug.c new file mode 100644 index 0000000000..c3903eaaa7 --- /dev/null +++ b/test/Driver/split-debug.c @@ -0,0 +1,19 @@ +// Check that we split debug output properly +// +// REQUIRES: asserts +// RUN: %clang -target x86_64-unknown-linux-gnu -ccc-print-phases \ +// RUN: -gsplit-dwarf -arch x86_64 %s 2> %t +// RUN: FileCheck -check-prefix=CHECK-ACTIONS < %t %s +// +// CHECK-ACTIONS: 0: input, "{{.*}}split-debug.c", c +// CHECK-ACTIONS: 4: split-debug, {3}, object + +// Check output name derivation. +// +// RUN: %clang -target x86_64-unknown-linux-gnu -ccc-print-bindings \ +// RUN: -gsplit-dwarf -arch x86_64 -c %s 2> %t +// RUN: FileCheck -check-prefix=CHECK-OUTPUT-NAME < %t %s +// +// CHECK-OUTPUT-NAME:# "x86_64-unknown-linux-gnu" - "clang", inputs: ["{{.*}}split-debug.c"], output: "{{.*}}split-debug{{.*}}.o" +// CHECK-OUTPUT-NAME:# "x86_64-unknown-linux-gnu" - "linuxtools::SplitDebug", inputs: ["{{.*}}split-debug{{.*}}.o"], output: "{{.*}}split-debug{{.*}}.o" +