aboutsummaryrefslogtreecommitdiff
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/test/tools/dsymutil/X86/basic-linking-x86.test8
-rw-r--r--llvm/test/tools/dsymutil/X86/lit.local.cfg2
-rw-r--r--llvm/test/tools/dsymutil/basic-linking.test6
-rw-r--r--llvm/tools/dsymutil/CMakeLists.txt3
-rw-r--r--llvm/tools/dsymutil/DwarfLinker.cpp139
-rw-r--r--llvm/tools/dsymutil/LLVMBuild.txt2
-rw-r--r--llvm/tools/dsymutil/Makefile2
-rw-r--r--llvm/tools/dsymutil/dsymutil.cpp11
-rw-r--r--llvm/tools/dsymutil/dsymutil.h5
9 files changed, 169 insertions, 9 deletions
diff --git a/llvm/test/tools/dsymutil/X86/basic-linking-x86.test b/llvm/test/tools/dsymutil/X86/basic-linking-x86.test
new file mode 100644
index 0000000..8f604001
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/basic-linking-x86.test
@@ -0,0 +1,8 @@
+RUN: cat %p/../Inputs/basic.macho.x86_64 > %t1
+RUN: llvm-dsymutil -oso-prepend-path=%p/.. %t1
+RUN: llvm-dwarfdump %t1.dwarf | FileCheck %s
+RUN: llvm-dsymutil -o %t2 -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_64
+RUN: llvm-dwarfdump %t2 | FileCheck %s
+RUN: llvm-dsymutil -o - -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_64 | llvm-dwarfdump - | FileCheck %s
+
+CHECK: file format Mach-O 64-bit x86-64
diff --git a/llvm/test/tools/dsymutil/X86/lit.local.cfg b/llvm/test/tools/dsymutil/X86/lit.local.cfg
new file mode 100644
index 0000000..c8625f4
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/lit.local.cfg
@@ -0,0 +1,2 @@
+if not 'X86' in config.root.targets:
+ config.unsupported = True
diff --git a/llvm/test/tools/dsymutil/basic-linking.test b/llvm/test/tools/dsymutil/basic-linking.test
index 5de6c13..ec6a5b7 100644
--- a/llvm/test/tools/dsymutil/basic-linking.test
+++ b/llvm/test/tools/dsymutil/basic-linking.test
@@ -1,6 +1,6 @@
-RUN: llvm-dsymutil -v -oso-prepend-path=%p %p/Inputs/basic.macho.x86_64 | FileCheck %s
-RUN: llvm-dsymutil -v -oso-prepend-path=%p %p/Inputs/basic-lto.macho.x86_64 | FileCheck %s --check-prefix=CHECK-LTO
-RUN: llvm-dsymutil -v -oso-prepend-path=%p %p/Inputs/basic-archive.macho.x86_64 | FileCheck %s --check-prefix=CHECK-ARCHIVE
+RUN: llvm-dsymutil -no-output -v -oso-prepend-path=%p %p/Inputs/basic.macho.x86_64 | FileCheck %s
+RUN: llvm-dsymutil -no-output -v -oso-prepend-path=%p %p/Inputs/basic-lto.macho.x86_64 | FileCheck %s --check-prefix=CHECK-LTO
+RUN: llvm-dsymutil -no-output -v -oso-prepend-path=%p %p/Inputs/basic-archive.macho.x86_64 | FileCheck %s --check-prefix=CHECK-ARCHIVE
This test check the basic Dwarf linking process through the debug dumps.
diff --git a/llvm/tools/dsymutil/CMakeLists.txt b/llvm/tools/dsymutil/CMakeLists.txt
index 5e1f37f6..59b37a9 100644
--- a/llvm/tools/dsymutil/CMakeLists.txt
+++ b/llvm/tools/dsymutil/CMakeLists.txt
@@ -1,5 +1,8 @@
set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ AsmPrinter
DebugInfoDWARF
+ MC
Object
Support
)
diff --git a/llvm/tools/dsymutil/DwarfLinker.cpp b/llvm/tools/dsymutil/DwarfLinker.cpp
index e44797d..7571753 100644
--- a/llvm/tools/dsymutil/DwarfLinker.cpp
+++ b/llvm/tools/dsymutil/DwarfLinker.cpp
@@ -10,12 +10,24 @@
#include "BinaryHolder.h"
#include "DebugMap.h"
#include "dsymutil.h"
+#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/LEB128.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
#include <string>
namespace llvm {
@@ -28,6 +40,12 @@ void warn(const Twine &Warning, const Twine &Context) {
errs() << Twine("warning: ") + Warning + "\n";
}
+bool error(const Twine &Error, const Twine &Context) {
+ errs() << Twine("while processing ") + Context + ":\n";
+ errs() << Twine("error: ") + Error + "\n";
+ return false;
+}
+
/// \brief Stores all information relating to a compile unit, be it in
/// its original instance in the object file to its brand new cloned
/// and linked DIE tree.
@@ -55,6 +73,110 @@ private:
std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
};
+/// \brief The Dwarf streaming logic
+///
+/// All interactions with the MC layer that is used to build the debug
+/// information binary representation are handled in this class.
+class DwarfStreamer {
+ /// \defgroup MCObjects MC layer objects constructed by the streamer
+ /// @{
+ std::unique_ptr<MCRegisterInfo> MRI;
+ std::unique_ptr<MCAsmInfo> MAI;
+ std::unique_ptr<MCObjectFileInfo> MOFI;
+ std::unique_ptr<MCContext> MC;
+ MCAsmBackend *MAB; // Owned by MCStreamer
+ std::unique_ptr<MCInstrInfo> MII;
+ std::unique_ptr<MCSubtargetInfo> MSTI;
+ MCCodeEmitter *MCE; // Owned by MCStreamer
+ MCStreamer *MS; // Owned by AsmPrinter
+ std::unique_ptr<TargetMachine> TM;
+ std::unique_ptr<AsmPrinter> Asm;
+ /// @}
+
+ /// \brief the file we stream the linked Dwarf to.
+ std::unique_ptr<raw_fd_ostream> OutFile;
+
+public:
+ /// \brief Actually create the streamer and the ouptut file.
+ ///
+ /// This could be done directly in the constructor, but it feels
+ /// more natural to handle errors through return value.
+ bool init(Triple TheTriple, StringRef OutputFilename);
+
+ ///\brief Dump the file to the disk.
+ bool finish();
+};
+
+bool DwarfStreamer::init(Triple TheTriple, StringRef OutputFilename) {
+ std::string ErrorStr;
+ std::string TripleName;
+ StringRef Context = "dwarf streamer init";
+
+ // Get the target.
+ const Target *TheTarget =
+ TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
+ if (!TheTarget)
+ return error(ErrorStr, Context);
+ TripleName = TheTriple.getTriple();
+
+ // Create all the MC Objects.
+ MRI.reset(TheTarget->createMCRegInfo(TripleName));
+ if (!MRI)
+ return error(Twine("no register info for target ") + TripleName, Context);
+
+ MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName));
+ if (!MAI)
+ return error("no asm info for target " + TripleName, Context);
+
+ MOFI.reset(new MCObjectFileInfo);
+ MC.reset(new MCContext(MAI.get(), MRI.get(), MOFI.get()));
+ MOFI->InitMCObjectFileInfo(TripleName, Reloc::Default, CodeModel::Default,
+ *MC);
+
+ MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, "");
+ if (!MAB)
+ return error("no asm backend for target " + TripleName, Context);
+
+ MII.reset(TheTarget->createMCInstrInfo());
+ if (!MII)
+ return error("no instr info info for target " + TripleName, Context);
+
+ MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
+ if (!MSTI)
+ return error("no subtarget info for target " + TripleName, Context);
+
+ MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, *MSTI, *MC);
+ if (!MCE)
+ return error("no code emitter for target " + TripleName, Context);
+
+ // Create the output file.
+ std::error_code EC;
+ OutFile = make_unique<raw_fd_ostream>(OutputFilename, EC, sys::fs::F_None);
+ if (EC)
+ return error(Twine(OutputFilename) + ": " + EC.message(), Context);
+
+ MS = TheTarget->createMCObjectStreamer(TripleName, *MC, *MAB, *OutFile, MCE,
+ *MSTI, false);
+ if (!MS)
+ return error("no object streamer for target " + TripleName, Context);
+
+ // Finally create the AsmPrinter we'll use to emit the DIEs.
+ TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions()));
+ if (!TM)
+ return error("no target machine for target " + TripleName, Context);
+
+ Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
+ if (!Asm)
+ return error("no asm printer for target " + TripleName, Context);
+
+ return true;
+}
+
+bool DwarfStreamer::finish() {
+ MS->Finish();
+ return true;
+}
+
/// \brief The core of the Dwarf linking logic.
///
/// The link of the dwarf information from the object files will be
@@ -178,12 +300,15 @@ private:
void reportWarning(const Twine &Warning, const DWARFUnit *Unit = nullptr,
const DWARFDebugInfoEntryMinimal *DIE = nullptr);
+
+ bool createStreamer(Triple TheTriple, StringRef OutputFilename);
/// @}
private:
std::string OutputFilename;
LinkOptions Options;
BinaryHolder BinHolder;
+ std::unique_ptr<DwarfStreamer> Streamer;
/// The units of the current debug map object.
std::vector<CompileUnit> Units;
@@ -238,6 +363,14 @@ void DwarfLinker::reportWarning(const Twine &Warning, const DWARFUnit *Unit,
6 /* Indent */);
}
+bool DwarfLinker::createStreamer(Triple TheTriple, StringRef OutputFilename) {
+ if (Options.NoOutput)
+ return true;
+
+ Streamer = make_unique<DwarfStreamer>();
+ return Streamer->init(TheTriple, OutputFilename);
+}
+
/// \brief Recursive helper to gather the child->parent relationships in the
/// original compile unit.
static void gatherDIEParents(const DWARFDebugInfoEntryMinimal *DIE,
@@ -509,7 +642,6 @@ unsigned DwarfLinker::shouldKeepDIE(const DWARFDebugInfoEntryMinimal &DIE,
return Flags;
}
-
/// \brief Mark the passed DIE as well as all the ones it depends on
/// as kept.
///
@@ -614,6 +746,9 @@ bool DwarfLinker::link(const DebugMap &Map) {
return false;
}
+ if (!createStreamer(Map.getTriple(), OutputFilename))
+ return false;
+
for (const auto &Obj : Map.objects()) {
CurrentDebugObject = Obj.get();
@@ -661,7 +796,7 @@ bool DwarfLinker::link(const DebugMap &Map) {
endDebugObject();
}
- return true;
+ return Options.NoOutput ? true : Streamer->finish();
}
}
diff --git a/llvm/tools/dsymutil/LLVMBuild.txt b/llvm/tools/dsymutil/LLVMBuild.txt
index c995291..99b0b44 100644
--- a/llvm/tools/dsymutil/LLVMBuild.txt
+++ b/llvm/tools/dsymutil/LLVMBuild.txt
@@ -19,4 +19,4 @@
type = Tool
name = llvm-dsymutil
parent = Tools
-required_libraries = DebugInfoDWARF Object Support
+required_libraries = AsmPrinter DebugInfoDWARF MC Object Support all-targets
diff --git a/llvm/tools/dsymutil/Makefile b/llvm/tools/dsymutil/Makefile
index e8dc569..c4365e0 100644
--- a/llvm/tools/dsymutil/Makefile
+++ b/llvm/tools/dsymutil/Makefile
@@ -9,7 +9,7 @@
LEVEL := ../..
TOOLNAME := llvm-dsymutil
-LINK_COMPONENTS := DebugInfoDWARF Object Support
+LINK_COMPONENTS := all-targets AsmPrinter DebugInfoDWARF MC Object Support
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS := 1
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index d9899be..4fc91b0 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -19,6 +19,7 @@
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/TargetSelect.h"
#include <string>
using namespace llvm::dsymutil;
@@ -40,6 +41,10 @@ static opt<std::string> OsoPrependPath("oso-prepend-path",
static opt<bool> Verbose("v", desc("Verbosity level"), init(false));
+static opt<bool> NoOutput("no-output", desc("Do the link in memory, but do "
+ "not emit the result file."),
+ init(false));
+
static opt<bool>
ParseOnly("parse-only",
desc("Only parse the debug map, do not actaully link "
@@ -57,6 +62,12 @@ int main(int argc, char **argv) {
auto DebugMapPtrOrErr = parseDebugMap(InputFile, OsoPrependPath, Verbose);
Options.Verbose = Verbose;
+ Options.NoOutput = NoOutput;
+
+ llvm::InitializeAllTargetInfos();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllAsmPrinters();
if (auto EC = DebugMapPtrOrErr.getError()) {
llvm::errs() << "error: cannot parse the debug map for \"" << InputFile
diff --git a/llvm/tools/dsymutil/dsymutil.h b/llvm/tools/dsymutil/dsymutil.h
index 9130693..e9f7cd9 100644
--- a/llvm/tools/dsymutil/dsymutil.h
+++ b/llvm/tools/dsymutil/dsymutil.h
@@ -25,9 +25,10 @@ namespace llvm {
namespace dsymutil {
struct LinkOptions {
- bool Verbose;
+ bool Verbose; ///< Verbosity
+ bool NoOutput; ///< Skip emitting output
- LinkOptions() : Verbose(false) {}
+ LinkOptions() : Verbose(false), NoOutput(false) {}
};
/// \brief Extract the DebugMap from the given file.