From 88c2137b6d49f88186d0957a4e2d8030a3967334 Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Tue, 7 Apr 2020 00:42:40 +0300 Subject: [PATCH] [DWARFLinker][dsymutil][NFC] Move DwarfStreamer into DWARFLinker. For implementing "remove obsolete debug info in lld", it is neccesary to have DWARF generation code implementation. dsymutil uses DwarfStreamer for that purpose. DwarfStreamer uses AsmPrinter. It is considered OK to use AsmPrinter based code in lld(D74169). This patch moves DwarfStreamer implementation into DWARFLinker, so that it could be reused from lld. Generally, a better place for such a common DWARF generation code would be not DWARFLinker but an additional separate library. Such a library could contain a single version of DWARF generation routines and could also be independent of AsmPrinter. At the current moment, DwarfStreamer does not pretend to be such a general implementation of DWARF generation. So I decided to put it into DWARFLinker since it is the only user of DwarfStreamer. Testing: it passes "check-all" lit testing. MD5 checksum for clang .dSYM bundle matches for the dsymutil with/without that patch. Reviewed By: JDevlieghere Differential revision: https://reviews.llvm.org/D77169 --- .../llvm/DWARFLinker/DWARFStreamer.h} | 72 +++++++++++++--------- llvm/lib/DWARFLinker/CMakeLists.txt | 1 + .../DWARFLinker/DWARFStreamer.cpp} | 60 +++++++++--------- llvm/tools/dsymutil/CMakeLists.txt | 1 - llvm/tools/dsymutil/DwarfLinkerForBinary.cpp | 21 +++++-- llvm/tools/dsymutil/DwarfLinkerForBinary.h | 2 +- llvm/tools/dsymutil/LinkUtils.h | 6 +- 7 files changed, 91 insertions(+), 72 deletions(-) rename llvm/{tools/dsymutil/DwarfStreamer.h => include/llvm/DWARFLinker/DWARFStreamer.h} (81%) rename llvm/{tools/dsymutil/DwarfStreamer.cpp => lib/DWARFLinker/DWARFStreamer.cpp} (97%) diff --git a/llvm/tools/dsymutil/DwarfStreamer.h b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h similarity index 81% rename from llvm/tools/dsymutil/DwarfStreamer.h rename to llvm/include/llvm/DWARFLinker/DWARFStreamer.h index 1084a28..de58f5d 100644 --- a/llvm/tools/dsymutil/DwarfStreamer.h +++ b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h @@ -1,4 +1,4 @@ -//===- tools/dsymutil/DwarfStreamer.h - Dwarf Streamer ----------*- C++ -*-===// +//===- DwarfStreamer.h ------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,37 +6,35 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_DSYMUTIL_DWARFSTREAMER_H -#define LLVM_TOOLS_DSYMUTIL_DWARFSTREAMER_H +#ifndef LLVM_DWARFLINKER_DWARFSTREAMER_H +#define LLVM_DWARFLINKER_DWARFSTREAMER_H -#include "DebugMap.h" -#include "LinkUtils.h" #include "llvm/CodeGen/AccelTable.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/NonRelocatableStringpool.h" #include "llvm/DWARFLinker/DWARFLinker.h" -#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" -#include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCTargetOptions.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" namespace llvm { -namespace dsymutil { + +enum class OutputFileType { + Object, + Assembly, +}; + +/// User of DwarfStreamer should call initialization code +/// for AsmPrinter: +/// +/// InitializeAllTargetInfos(); +/// InitializeAllTargetMCs(); +/// InitializeAllTargets(); +/// InitializeAllAsmPrinters(); + +class MCCodeEmitter; /// The Dwarf streaming logic. /// @@ -44,13 +42,16 @@ namespace dsymutil { /// information binary representation are handled in this class. class DwarfStreamer : public DwarfEmitter { public: - DwarfStreamer(raw_fd_ostream &OutFile, LinkOptions Options) - : OutFile(OutFile), Options(std::move(Options)) {} + DwarfStreamer(OutputFileType OutFileType, raw_pwrite_stream &OutFile, + std::function Translator, + bool Minimize, messageHandler Error, messageHandler Warning) + : OutFile(OutFile), OutFileType(OutFileType), Translator(Translator), + Minimize(Minimize), ErrorHandler(Error), WarningHandler(Warning) {} bool init(Triple TheTriple); /// Dump the file to the disk. - bool finish(const DebugMap &, SymbolMapTranslator &T); + void finish(); AsmPrinter &getAsmPrinter() const { return *Asm; } @@ -158,6 +159,16 @@ public: } private: + inline void error(const Twine &Error, StringRef Context = "") { + if (ErrorHandler) + ErrorHandler(Error, Context, nullptr); + } + + inline void warn(const Twine &Warning, StringRef Context = "") { + if (WarningHandler) + WarningHandler(Warning, Context, nullptr); + } + /// \defgroup MCObjects MC layer objects constructed by the streamer /// @{ std::unique_ptr MRI; @@ -174,10 +185,11 @@ private: std::unique_ptr Asm; /// @} - /// The file we stream the linked Dwarf to. - raw_fd_ostream &OutFile; - - LinkOptions Options; + /// The output file we stream the linked Dwarf to. + raw_pwrite_stream &OutFile; + OutputFileType OutFileType = OutputFileType::Object; + std::function Translator; + bool Minimize = true; uint64_t RangesSectionSize = 0; uint64_t LocSectionSize = 0; @@ -197,9 +209,11 @@ private: void emitPubSectionForUnit(MCSection *Sec, StringRef Name, const CompileUnit &Unit, const std::vector &Names); + + messageHandler ErrorHandler = nullptr; + messageHandler WarningHandler = nullptr; }; -} // end namespace dsymutil } // end namespace llvm -#endif // LLVM_TOOLS_DSYMUTIL_DWARFSTREAMER_H +#endif // LLVM_DWARFLINKER_DWARFSTREAMER_H diff --git a/llvm/lib/DWARFLinker/CMakeLists.txt b/llvm/lib/DWARFLinker/CMakeLists.txt index f8c6133..724ed76 100644 --- a/llvm/lib/DWARFLinker/CMakeLists.txt +++ b/llvm/lib/DWARFLinker/CMakeLists.txt @@ -2,6 +2,7 @@ add_llvm_component_library(LLVMDWARFLinker DWARFLinkerCompileUnit.cpp DWARFLinkerDeclContext.cpp DWARFLinker.cpp + DWARFStreamer.cpp DEPENDS intrinsics_gen diff --git a/llvm/tools/dsymutil/DwarfStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp similarity index 97% rename from llvm/tools/dsymutil/DwarfStreamer.cpp rename to llvm/lib/DWARFLinker/DWARFStreamer.cpp index c53d5d5..5b38b58 100644 --- a/llvm/tools/dsymutil/DwarfStreamer.cpp +++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp @@ -1,4 +1,4 @@ -//===- tools/dsymutil/DwarfStreamer.cpp - Dwarf Streamer ------------------===// +//===- DwarfStreamer.cpp --------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,25 +6,29 @@ // //===----------------------------------------------------------------------===// -#include "DwarfStreamer.h" -#include "LinkUtils.h" -#include "MachOUtils.h" +#include "llvm/DWARFLinker/DWARFStreamer.h" #include "llvm/ADT/Triple.h" +#include "llvm/CodeGen/NonRelocatableStringpool.h" #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/MCTargetOptionsCommandFlags.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/TargetRegistry.h" -#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" namespace llvm { static mc::RegisterMCTargetOptionsFlags MOF; -namespace dsymutil { - bool DwarfStreamer::init(Triple TheTriple) { std::string ErrorStr; std::string TripleName; @@ -34,18 +38,19 @@ bool DwarfStreamer::init(Triple TheTriple) { const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr); if (!TheTarget) - return error(ErrorStr, Context); + return error(ErrorStr, Context), false; 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); + return error(Twine("no register info for target ") + TripleName, Context), + false; MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags(); MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); if (!MAI) - return error("no asm info for target " + TripleName, Context); + return error("no asm info for target " + TripleName, Context), false; MOFI.reset(new MCObjectFileInfo); MC.reset(new MCContext(MAI.get(), MRI.get(), MOFI.get())); @@ -53,21 +58,21 @@ bool DwarfStreamer::init(Triple TheTriple) { MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", "")); if (!MSTI) - return error("no subtarget info for target " + TripleName, Context); + return error("no subtarget info for target " + TripleName, Context), false; MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions); if (!MAB) - return error("no asm backend for target " + TripleName, Context); + return error("no asm backend for target " + TripleName, Context), false; MII.reset(TheTarget->createMCInstrInfo()); if (!MII) - return error("no instr info info for target " + TripleName, Context); + return error("no instr info info for target " + TripleName, Context), false; MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, *MC); if (!MCE) - return error("no code emitter for target " + TripleName, Context); + return error("no code emitter for target " + TripleName, Context), false; - switch (Options.FileType) { + switch (OutFileType) { case OutputFileType::Assembly: { MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(), *MAI, *MII, *MRI); @@ -88,17 +93,17 @@ bool DwarfStreamer::init(Triple TheTriple) { } if (!MS) - return error("no object streamer for target " + TripleName, Context); + return error("no object streamer for target " + TripleName, Context), false; // Finally create the AsmPrinter we'll use to emit the DIEs. TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(), None)); if (!TM) - return error("no target machine for target " + TripleName, Context); + return error("no target machine for target " + TripleName, Context), false; Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr(MS))); if (!Asm) - return error("no asm printer for target " + TripleName, Context); + return error("no asm printer for target " + TripleName, Context), false; RangesSectionSize = 0; LocSectionSize = 0; @@ -109,15 +114,7 @@ bool DwarfStreamer::init(Triple TheTriple) { return true; } -bool DwarfStreamer::finish(const DebugMap &DM, SymbolMapTranslator &T) { - bool Result = true; - if (DM.getTriple().isOSDarwin() && !DM.getBinaryPath().empty() && - Options.FileType == OutputFileType::Object) - Result = MachOUtils::generateDsymCompanion(DM, T, *MS, OutFile); - else - MS->Finish(); - return Result; -} +void DwarfStreamer::finish() { MS->Finish(); } void DwarfStreamer::switchToDebugInfoSection(unsigned DwarfVersion) { MS->SwitchSection(MOFI->getDwarfInfoSection()); @@ -660,7 +657,7 @@ void DwarfStreamer::translateLineTable(DataExtractor Data, uint64_t Offset) { if (Dir[0] == 0) break; - StringRef Translated = Options.Translator(Dir); + StringRef Translated = Translator(Dir); Asm->OutStreamer->emitBytes(Translated); Asm->emitInt8(0); LineSectionSize += Translated.size() + 1; @@ -672,7 +669,7 @@ void DwarfStreamer::translateLineTable(DataExtractor Data, uint64_t Offset) { if (File[0] == 0) break; - StringRef Translated = Options.Translator(File); + StringRef Translated = Translator(File); Asm->OutStreamer->emitBytes(Translated); Asm->emitInt8(0); LineSectionSize += Translated.size() + 1; @@ -740,7 +737,7 @@ void DwarfStreamer::emitPubSectionForUnit( /// Emit .debug_pubnames for \p Unit. void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) { - if (Options.Minimize) + if (Minimize) return; emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(), "names", Unit, Unit.getPubnames()); @@ -748,7 +745,7 @@ void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) { /// Emit .debug_pubtypes for \p Unit. void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) { - if (Options.Minimize) + if (Minimize) return; emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(), "types", Unit, Unit.getPubtypes()); @@ -776,5 +773,4 @@ void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize, FrameSectionSize += FDEBytes.size() + 8 + AddrSize; } -} // namespace dsymutil } // namespace llvm diff --git a/llvm/tools/dsymutil/CMakeLists.txt b/llvm/tools/dsymutil/CMakeLists.txt index dc31b86..a42e1a9 100644 --- a/llvm/tools/dsymutil/CMakeLists.txt +++ b/llvm/tools/dsymutil/CMakeLists.txt @@ -24,7 +24,6 @@ add_llvm_tool(dsymutil CFBundle.cpp DebugMap.cpp DwarfLinkerForBinary.cpp - DwarfStreamer.cpp MachODebugMapParser.cpp MachOUtils.cpp SymbolMap.cpp diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp index c1c247d..4e99e5f 100644 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -9,7 +9,6 @@ #include "DwarfLinkerForBinary.h" #include "BinaryHolder.h" #include "DebugMap.h" -#include "DwarfStreamer.h" #include "MachOUtils.h" #include "dsymutil.h" #include "llvm/ADT/ArrayRef.h" @@ -163,7 +162,14 @@ bool DwarfLinkerForBinary::createStreamer(const Triple &TheTriple, if (Options.NoOutput) return true; - Streamer = std::make_unique(OutFile, Options); + Streamer = std::make_unique( + Options.FileType, OutFile, Options.Translator, Options.Minimize, + [&](const Twine &Error, StringRef Context, const DWARFDie *) { + error(Error, Context); + }, + [&](const Twine &Warning, StringRef Context, const DWARFDie *) { + warn(Warning, Context); + }); return Streamer->init(TheTriple); } @@ -318,7 +324,7 @@ bool DwarfLinkerForBinary::link(const DebugMap &Map) { reportWarning(Warning, Context, DIE); }); GeneralLinker.setErrorHandler( - [&](const Twine &Error, StringRef Context, const DWARFDie *DIE) { + [&](const Twine &Error, StringRef Context, const DWARFDie *) { error(Error, Context); }); GeneralLinker.setObjFileLoader( @@ -442,7 +448,14 @@ bool DwarfLinkerForBinary::link(const DebugMap &Map) { return error(toString(std::move(E))); } - return Streamer->finish(Map, Options.Translator); + if (Map.getTriple().isOSDarwin() && !Map.getBinaryPath().empty() && + Options.FileType == OutputFileType::Object) + return MachOUtils::generateDsymCompanion( + Map, Options.Translator, *Streamer->getAsmPrinter().OutStreamer, + OutFile); + + Streamer->finish(); + return true; } static bool isMachOPairedReloc(uint64_t RelocType, uint64_t Arch) { diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.h b/llvm/tools/dsymutil/DwarfLinkerForBinary.h index 9b7d9c5..7cabacb 100644 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.h +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.h @@ -11,11 +11,11 @@ #include "BinaryHolder.h" #include "DebugMap.h" -#include "DwarfStreamer.h" #include "LinkUtils.h" #include "llvm/DWARFLinker/DWARFLinker.h" #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h" #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h" +#include "llvm/DWARFLinker/DWARFStreamer.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/Remarks/RemarkFormat.h" #include "llvm/Remarks/RemarkLinker.h" diff --git a/llvm/tools/dsymutil/LinkUtils.h b/llvm/tools/dsymutil/LinkUtils.h index 0339f44..c630be3 100644 --- a/llvm/tools/dsymutil/LinkUtils.h +++ b/llvm/tools/dsymutil/LinkUtils.h @@ -16,16 +16,12 @@ #include "llvm/Support/WithColor.h" #include "llvm/DWARFLinker/DWARFLinker.h" +#include "llvm/DWARFLinker/DWARFStreamer.h" #include namespace llvm { namespace dsymutil { -enum class OutputFileType { - Object, - Assembly, -}; - struct LinkOptions { /// Verbosity bool Verbose = false; -- 2.7.4