diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/test/tools/dsymutil/X86/basic-linking-x86.test | 8 | ||||
| -rw-r--r-- | llvm/test/tools/dsymutil/X86/lit.local.cfg | 2 | ||||
| -rw-r--r-- | llvm/test/tools/dsymutil/basic-linking.test | 6 | ||||
| -rw-r--r-- | llvm/tools/dsymutil/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | llvm/tools/dsymutil/DwarfLinker.cpp | 139 | ||||
| -rw-r--r-- | llvm/tools/dsymutil/LLVMBuild.txt | 2 | ||||
| -rw-r--r-- | llvm/tools/dsymutil/Makefile | 2 | ||||
| -rw-r--r-- | llvm/tools/dsymutil/dsymutil.cpp | 11 | ||||
| -rw-r--r-- | llvm/tools/dsymutil/dsymutil.h | 5 |
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. |
