blob: 51520884a4ec8efdc82badca776458c080eb7c53 [file] [log] [blame]
Frederic Riss231f7142014-12-12 17:31:24 +00001//===- 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"
Frederic Rissd3455182015-01-28 18:27:01 +000010#include "BinaryHolder.h"
11#include "DebugMap.h"
Frederic Riss231f7142014-12-12 17:31:24 +000012#include "dsymutil.h"
Zachary Turner82af9432015-01-30 18:07:45 +000013#include "llvm/DebugInfo/DWARF/DWARFContext.h"
14#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
Frederic Rissd3455182015-01-28 18:27:01 +000015#include <string>
Frederic Riss231f7142014-12-12 17:31:24 +000016
17namespace llvm {
18namespace dsymutil {
19
Frederic Rissd3455182015-01-28 18:27:01 +000020namespace {
21
Frederic Riss563cba62015-01-28 22:15:14 +000022/// \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.
25class CompileUnit {
26public:
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
41private:
42 DWARFUnit &OrigUnit;
43 std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
44};
45
Frederic Rissd3455182015-01-28 18:27:01 +000046/// \brief The core of the Dwarf linking logic.
47class DwarfLinker {
48public:
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
55private:
Frederic Riss563cba62015-01-28 22:15:14 +000056 /// \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
62private:
Frederic Rissd3455182015-01-28 18:27:01 +000063 std::string OutputFilename;
64 bool Verbose;
65 BinaryHolder BinHolder;
Frederic Riss563cba62015-01-28 22:15:14 +000066
67 /// The units of the current debug map object.
68 std::vector<CompileUnit> Units;
Frederic Rissd3455182015-01-28 18:27:01 +000069};
70
Frederic Riss563cba62015-01-28 22:15:14 +000071/// \brief Recursive helper to gather the child->parent relationships in the
72/// original compile unit.
73void 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
84void DwarfLinker::startDebugObject(DWARFContext &Dwarf) {
85 Units.reserve(Dwarf.getNumCompileUnits());
86}
87
88void DwarfLinker::endDebugObject() { Units.clear(); }
89
Frederic Rissd3455182015-01-28 18:27:01 +000090bool 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
Frederic Riss563cba62015-01-28 22:15:14 +0000106 // Setup access to the debug info.
Frederic Rissd3455182015-01-28 18:27:01 +0000107 DWARFContextInMemory DwarfContext(*ErrOrObj);
Frederic Riss563cba62015-01-28 22:15:14 +0000108 startDebugObject(DwarfContext);
Frederic Rissd3455182015-01-28 18:27:01 +0000109
Frederic Riss563cba62015-01-28 22:15:14 +0000110 // 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.
Frederic Rissd3455182015-01-28 18:27:01 +0000112 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 }
Frederic Riss563cba62015-01-28 22:15:14 +0000118 Units.emplace_back(*CU);
119 GatherDIEParents(CUDie, 0, Units.back());
Frederic Rissd3455182015-01-28 18:27:01 +0000120 }
Frederic Riss563cba62015-01-28 22:15:14 +0000121
122 // Clean-up before starting working on the next object.
123 endDebugObject();
Frederic Rissd3455182015-01-28 18:27:01 +0000124 }
125
Frederic Riss231f7142014-12-12 17:31:24 +0000126 return true;
127}
128}
Frederic Rissd3455182015-01-28 18:27:01 +0000129
130bool linkDwarf(StringRef OutputFilename, const DebugMap &DM, bool Verbose) {
131 DwarfLinker Linker(OutputFilename, Verbose);
132 return Linker.link(DM);
133}
134}
Frederic Riss231f7142014-12-12 17:31:24 +0000135}