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