Move DebugInfo to DebugInfo/DWARF.
[oota-llvm.git] / tools / dsymutil / DwarfLinker.cpp
1 //===- tools/dsymutil/DwarfLinker.cpp - Dwarf debug info linker -----------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "DebugMap.h"
10
11 #include "BinaryHolder.h"
12 #include "DebugMap.h"
13 #include "dsymutil.h"
14 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
15 #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
16 #include <string>
17
18 namespace llvm {
19 namespace dsymutil {
20
21 namespace {
22
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.
26 class CompileUnit {
27 public:
28   /// \brief Information gathered about a DIE in the object file.
29   struct DIEInfo {
30     uint32_t ParentIdx;
31   };
32
33   CompileUnit(DWARFUnit &OrigUnit) : OrigUnit(OrigUnit) {
34     Info.resize(OrigUnit.getNumDIEs());
35   }
36
37   DWARFUnit &getOrigUnit() { return OrigUnit; }
38
39   DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
40   const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; }
41
42 private:
43   DWARFUnit &OrigUnit;
44   std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
45 };
46
47 /// \brief The core of the Dwarf linking logic.
48 class DwarfLinker {
49 public:
50   DwarfLinker(StringRef OutputFilename, bool Verbose)
51       : OutputFilename(OutputFilename), Verbose(Verbose), BinHolder(Verbose) {}
52
53   /// \brief Link the contents of the DebugMap.
54   bool link(const DebugMap &);
55
56 private:
57   /// \brief Called at the start of a debug object link.
58   void startDebugObject(DWARFContext &);
59
60   /// \brief Called at the end of a debug object link.
61   void endDebugObject();
62
63 private:
64   std::string OutputFilename;
65   bool Verbose;
66   BinaryHolder BinHolder;
67
68   /// The units of the current debug map object.
69   std::vector<CompileUnit> Units;
70 };
71
72 /// \brief Recursive helper to gather the child->parent relationships in the
73 /// original compile unit.
74 void GatherDIEParents(const DWARFDebugInfoEntryMinimal *DIE, unsigned ParentIdx,
75                       CompileUnit &CU) {
76   unsigned MyIdx = CU.getOrigUnit().getDIEIndex(DIE);
77   CU.getInfo(MyIdx).ParentIdx = ParentIdx;
78
79   if (DIE->hasChildren())
80     for (auto *Child = DIE->getFirstChild(); Child && !Child->isNULL();
81          Child = Child->getSibling())
82       GatherDIEParents(Child, MyIdx, CU);
83 }
84
85 void DwarfLinker::startDebugObject(DWARFContext &Dwarf) {
86   Units.reserve(Dwarf.getNumCompileUnits());
87 }
88
89 void DwarfLinker::endDebugObject() { Units.clear(); }
90
91 bool DwarfLinker::link(const DebugMap &Map) {
92
93   if (Map.begin() == Map.end()) {
94     errs() << "Empty debug map.\n";
95     return false;
96   }
97
98   for (const auto &Obj : Map.objects()) {
99     if (Verbose)
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";
104       continue;
105     }
106
107     // Setup access to the debug info.
108     DWARFContextInMemory DwarfContext(*ErrOrObj);
109     startDebugObject(DwarfContext);
110
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);
115       if (Verbose) {
116         outs() << "Input compilation unit:";
117         CUDie->dump(outs(), CU.get(), 0);
118       }
119       Units.emplace_back(*CU);
120       GatherDIEParents(CUDie, 0, Units.back());
121     }
122
123     // Clean-up before starting working on the next object.
124     endDebugObject();
125   }
126
127   return true;
128 }
129 }
130
131 bool linkDwarf(StringRef OutputFilename, const DebugMap &DM, bool Verbose) {
132   DwarfLinker Linker(OutputFilename, Verbose);
133   return Linker.link(DM);
134 }
135 }
136 }