summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/clang/Driver/Action.h12
-rw-r--r--include/clang/Driver/CC1Options.td2
-rw-r--r--include/clang/Driver/Options.td1
-rw-r--r--lib/Driver/Action.cpp7
-rw-r--r--lib/Driver/Driver.cpp25
-rw-r--r--lib/Driver/ToolChains.cpp4
-rw-r--r--lib/Driver/Tools.cpp55
-rw-r--r--lib/Driver/Tools.h14
-rw-r--r--lib/Driver/WindowsToolChain.cpp1
-rw-r--r--test/Driver/split-debug.c19
10 files changed, 130 insertions, 10 deletions
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<g_flags_Group>;
def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group<g_flags_Group>;
def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>;
+def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_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<SplitDebugJobAction>(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"
+