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 //===----------------------------------------------------------------------===//
10 #include "BinaryHolder.h"
13 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
14 #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
22 /// \brief Stores all information relating to a compile unit, be it in
23 /// its original instance in the object file to its brand new cloned
24 /// and linked DIE tree.
27 /// \brief Information gathered about a DIE in the object file.
32 CompileUnit(DWARFUnit &OrigUnit) : OrigUnit(OrigUnit) {
33 Info.resize(OrigUnit.getNumDIEs());
36 DWARFUnit &getOrigUnit() { return OrigUnit; }
38 DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
39 const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; }
43 std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
46 /// \brief The core of the Dwarf linking logic.
49 DwarfLinker(StringRef OutputFilename, bool Verbose)
50 : OutputFilename(OutputFilename), Verbose(Verbose), BinHolder(Verbose) {}
52 /// \brief Link the contents of the DebugMap.
53 bool link(const DebugMap &);
56 /// \brief Called at the start of a debug object link.
57 void startDebugObject(DWARFContext &);
59 /// \brief Called at the end of a debug object link.
60 void endDebugObject();
63 std::string OutputFilename;
65 BinaryHolder BinHolder;
67 /// The units of the current debug map object.
68 std::vector<CompileUnit> Units;
71 /// \brief Recursive helper to gather the child->parent relationships in the
72 /// original compile unit.
73 void GatherDIEParents(const DWARFDebugInfoEntryMinimal *DIE, unsigned ParentIdx,
75 unsigned MyIdx = CU.getOrigUnit().getDIEIndex(DIE);
76 CU.getInfo(MyIdx).ParentIdx = ParentIdx;
78 if (DIE->hasChildren())
79 for (auto *Child = DIE->getFirstChild(); Child && !Child->isNULL();
80 Child = Child->getSibling())
81 GatherDIEParents(Child, MyIdx, CU);
84 void DwarfLinker::startDebugObject(DWARFContext &Dwarf) {
85 Units.reserve(Dwarf.getNumCompileUnits());
88 void DwarfLinker::endDebugObject() { Units.clear(); }
90 bool DwarfLinker::link(const DebugMap &Map) {
92 if (Map.begin() == Map.end()) {
93 errs() << "Empty debug map.\n";
97 for (const auto &Obj : Map.objects()) {
99 outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n";
100 auto ErrOrObj = BinHolder.GetObjectFile(Obj->getObjectFilename());
101 if (std::error_code EC = ErrOrObj.getError()) {
102 errs() << Obj->getObjectFilename() << ": " << EC.message() << "\n";
106 // Setup access to the debug info.
107 DWARFContextInMemory DwarfContext(*ErrOrObj);
108 startDebugObject(DwarfContext);
110 // In a first phase, just read in the debug info and store the DIE
111 // parent links that we will use during the next phase.
112 for (const auto &CU : DwarfContext.compile_units()) {
113 auto *CUDie = CU->getCompileUnitDIE(false);
115 outs() << "Input compilation unit:";
116 CUDie->dump(outs(), CU.get(), 0);
118 Units.emplace_back(*CU);
119 GatherDIEParents(CUDie, 0, Units.back());
122 // Clean-up before starting working on the next object.
130 bool linkDwarf(StringRef OutputFilename, const DebugMap &DM, bool Verbose) {
131 DwarfLinker Linker(OutputFilename, Verbose);
132 return Linker.link(DM);