1 //===- tools/dsymutil/DwarfLinker.cpp - Dwarf debug info linker -----------===//
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 #include "BinaryHolder.h"
14 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
15 #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
23 /// \brief Stores all information relating to a compile unit, be it in
24 /// its original instance in the object file to its brand new cloned
25 /// and linked DIE tree.
28 /// \brief Information gathered about a DIE in the object file.
33 CompileUnit(DWARFUnit &OrigUnit) : OrigUnit(OrigUnit) {
34 Info.resize(OrigUnit.getNumDIEs());
37 DWARFUnit &getOrigUnit() { return OrigUnit; }
39 DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
40 const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; }
44 std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
47 /// \brief The core of the Dwarf linking logic.
50 DwarfLinker(StringRef OutputFilename, bool Verbose)
51 : OutputFilename(OutputFilename), Verbose(Verbose), BinHolder(Verbose) {}
53 /// \brief Link the contents of the DebugMap.
54 bool link(const DebugMap &);
57 /// \brief Called at the start of a debug object link.
58 void startDebugObject(DWARFContext &);
60 /// \brief Called at the end of a debug object link.
61 void endDebugObject();
64 std::string OutputFilename;
66 BinaryHolder BinHolder;
68 /// The units of the current debug map object.
69 std::vector<CompileUnit> Units;
72 /// \brief Recursive helper to gather the child->parent relationships in the
73 /// original compile unit.
74 void GatherDIEParents(const DWARFDebugInfoEntryMinimal *DIE, unsigned ParentIdx,
76 unsigned MyIdx = CU.getOrigUnit().getDIEIndex(DIE);
77 CU.getInfo(MyIdx).ParentIdx = ParentIdx;
79 if (DIE->hasChildren())
80 for (auto *Child = DIE->getFirstChild(); Child && !Child->isNULL();
81 Child = Child->getSibling())
82 GatherDIEParents(Child, MyIdx, CU);
85 void DwarfLinker::startDebugObject(DWARFContext &Dwarf) {
86 Units.reserve(Dwarf.getNumCompileUnits());
89 void DwarfLinker::endDebugObject() { Units.clear(); }
91 bool DwarfLinker::link(const DebugMap &Map) {
93 if (Map.begin() == Map.end()) {
94 errs() << "Empty debug map.\n";
98 for (const auto &Obj : Map.objects()) {
100 outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n";
101 auto ErrOrObj = BinHolder.GetObjectFile(Obj->getObjectFilename());
102 if (std::error_code EC = ErrOrObj.getError()) {
103 errs() << Obj->getObjectFilename() << ": " << EC.message() << "\n";
107 // Setup access to the debug info.
108 DWARFContextInMemory DwarfContext(*ErrOrObj);
109 startDebugObject(DwarfContext);
111 // In a first phase, just read in the debug info and store the DIE
112 // parent links that we will use during the next phase.
113 for (const auto &CU : DwarfContext.compile_units()) {
114 auto *CUDie = CU->getCompileUnitDIE(false);
116 outs() << "Input compilation unit:";
117 CUDie->dump(outs(), CU.get(), 0);
119 Units.emplace_back(*CU);
120 GatherDIEParents(CUDie, 0, Units.back());
123 // Clean-up before starting working on the next object.
131 bool linkDwarf(StringRef OutputFilename, const DebugMap &DM, bool Verbose) {
132 DwarfLinker Linker(OutputFilename, Verbose);
133 return Linker.link(DM);