blob: 7f6d69cc7de5cdd98e2d5bfa8b590ba611a4920d [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
11#include "BinaryHolder.h"
12#include "DebugMap.h"
Frederic Riss231f7142014-12-12 17:31:24 +000013#include "dsymutil.h"
Frederic Rissd3455182015-01-28 18:27:01 +000014#include "llvm/DebugInfo/DWARFContext.h"
15#include "llvm/DebugInfo/DWARFDebugInfoEntry.h"
16#include <string>
Frederic Riss231f7142014-12-12 17:31:24 +000017
18namespace llvm {
19namespace dsymutil {
20
Frederic Rissd3455182015-01-28 18:27:01 +000021namespace {
22
Frederic Riss563cba62015-01-28 22:15:14 +000023/// \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.
26class CompileUnit {
27public:
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
42private:
43 DWARFUnit &OrigUnit;
44 std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
45};
46
Frederic Rissd3455182015-01-28 18:27:01 +000047/// \brief The core of the Dwarf linking logic.
48class DwarfLinker {
49public:
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
56private:
Frederic Riss563cba62015-01-28 22:15:14 +000057 /// \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
63private:
Frederic Rissd3455182015-01-28 18:27:01 +000064 std::string OutputFilename;
65 bool Verbose;
66 BinaryHolder BinHolder;
Frederic Riss563cba62015-01-28 22:15:14 +000067
68 /// The units of the current debug map object.
69 std::vector<CompileUnit> Units;
Frederic Rissd3455182015-01-28 18:27:01 +000070};
71
Frederic Riss563cba62015-01-28 22:15:14 +000072/// \brief Recursive helper to gather the child->parent relationships in the
73/// original compile unit.
74void 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
85void DwarfLinker::startDebugObject(DWARFContext &Dwarf) {
86 Units.reserve(Dwarf.getNumCompileUnits());
87}
88
89void DwarfLinker::endDebugObject() { Units.clear(); }
90
Frederic Rissd3455182015-01-28 18:27:01 +000091bool 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
Frederic Riss563cba62015-01-28 22:15:14 +0000107 // Setup access to the debug info.
Frederic Rissd3455182015-01-28 18:27:01 +0000108 DWARFContextInMemory DwarfContext(*ErrOrObj);
Frederic Riss563cba62015-01-28 22:15:14 +0000109 startDebugObject(DwarfContext);
Frederic Rissd3455182015-01-28 18:27:01 +0000110
Frederic Riss563cba62015-01-28 22:15:14 +0000111 // 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.
Frederic Rissd3455182015-01-28 18:27:01 +0000113 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 }
Frederic Riss563cba62015-01-28 22:15:14 +0000119 Units.emplace_back(*CU);
120 GatherDIEParents(CUDie, 0, Units.back());
Frederic Rissd3455182015-01-28 18:27:01 +0000121 }
Frederic Riss563cba62015-01-28 22:15:14 +0000122
123 // Clean-up before starting working on the next object.
124 endDebugObject();
Frederic Rissd3455182015-01-28 18:27:01 +0000125 }
126
Frederic Riss231f7142014-12-12 17:31:24 +0000127 return true;
128}
129}
Frederic Rissd3455182015-01-28 18:27:01 +0000130
131bool linkDwarf(StringRef OutputFilename, const DebugMap &DM, bool Verbose) {
132 DwarfLinker Linker(OutputFilename, Verbose);
133 return Linker.link(DM);
134}
135}
Frederic Riss231f7142014-12-12 17:31:24 +0000136}