blob: 71af214e434c9d3f92ecdef3e04e1793790e5361 [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 Riss1b9da422015-02-13 23:18:29 +000015#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
Frederic Riss1036e642015-02-13 23:18:22 +000016#include "llvm/Object/MachO.h"
Frederic Riss84c09a52015-02-13 23:18:34 +000017#include "llvm/Support/Dwarf.h"
18#include "llvm/Support/LEB128.h"
Frederic Rissd3455182015-01-28 18:27:01 +000019#include <string>
Frederic Riss231f7142014-12-12 17:31:24 +000020
21namespace llvm {
22namespace dsymutil {
23
Frederic Rissd3455182015-01-28 18:27:01 +000024namespace {
25
Frederic Rissdef4fb72015-02-28 00:29:01 +000026void warn(const Twine &Warning, const Twine &Context) {
27 errs() << Twine("while processing ") + Context + ":\n";
28 errs() << Twine("warning: ") + Warning + "\n";
29}
30
Frederic Riss563cba62015-01-28 22:15:14 +000031/// \brief Stores all information relating to a compile unit, be it in
32/// its original instance in the object file to its brand new cloned
33/// and linked DIE tree.
34class CompileUnit {
35public:
36 /// \brief Information gathered about a DIE in the object file.
37 struct DIEInfo {
Frederic Riss84c09a52015-02-13 23:18:34 +000038 uint64_t Address; ///< Linked address of the described entity.
39 uint32_t ParentIdx; ///< The index of this DIE's parent.
40 bool Keep; ///< Is the DIE part of the linked output?
41 bool InDebugMap; ///< Was this DIE's entity found in the map?
Frederic Riss563cba62015-01-28 22:15:14 +000042 };
43
44 CompileUnit(DWARFUnit &OrigUnit) : OrigUnit(OrigUnit) {
45 Info.resize(OrigUnit.getNumDIEs());
46 }
47
Frederic Rissc3349d42015-02-13 23:18:27 +000048 DWARFUnit &getOrigUnit() const { return OrigUnit; }
Frederic Riss563cba62015-01-28 22:15:14 +000049
50 DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
51 const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; }
52
53private:
54 DWARFUnit &OrigUnit;
55 std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
56};
57
Frederic Rissd3455182015-01-28 18:27:01 +000058/// \brief The core of the Dwarf linking logic.
Frederic Riss1036e642015-02-13 23:18:22 +000059///
60/// The link of the dwarf information from the object files will be
61/// driven by the selection of 'root DIEs', which are DIEs that
62/// describe variables or functions that are present in the linked
63/// binary (and thus have entries in the debug map). All the debug
64/// information that will be linked (the DIEs, but also the line
65/// tables, ranges, ...) is derived from that set of root DIEs.
66///
67/// The root DIEs are identified because they contain relocations that
68/// correspond to a debug map entry at specific places (the low_pc for
69/// a function, the location for a variable). These relocations are
70/// called ValidRelocs in the DwarfLinker and are gathered as a very
71/// first step when we start processing a DebugMapObject.
Frederic Rissd3455182015-01-28 18:27:01 +000072class DwarfLinker {
73public:
74 DwarfLinker(StringRef OutputFilename, bool Verbose)
75 : OutputFilename(OutputFilename), Verbose(Verbose), BinHolder(Verbose) {}
76
77 /// \brief Link the contents of the DebugMap.
78 bool link(const DebugMap &);
79
80private:
Frederic Riss563cba62015-01-28 22:15:14 +000081 /// \brief Called at the start of a debug object link.
82 void startDebugObject(DWARFContext &);
83
84 /// \brief Called at the end of a debug object link.
85 void endDebugObject();
86
Frederic Riss1036e642015-02-13 23:18:22 +000087 /// \defgroup FindValidRelocations Translate debug map into a list
88 /// of relevant relocations
89 ///
90 /// @{
91 struct ValidReloc {
92 uint32_t Offset;
93 uint32_t Size;
94 uint64_t Addend;
95 const DebugMapObject::DebugMapEntry *Mapping;
96
97 ValidReloc(uint32_t Offset, uint32_t Size, uint64_t Addend,
98 const DebugMapObject::DebugMapEntry *Mapping)
99 : Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {}
100
101 bool operator<(const ValidReloc &RHS) const { return Offset < RHS.Offset; }
102 };
103
104 /// \brief The valid relocations for the current DebugMapObject.
105 /// This vector is sorted by relocation offset.
106 std::vector<ValidReloc> ValidRelocs;
107
108 /// \brief Index into ValidRelocs of the next relocation to
109 /// consider. As we walk the DIEs in acsending file offset and as
110 /// ValidRelocs is sorted by file offset, keeping this index
111 /// uptodate is all we have to do to have a cheap lookup during the
112 /// root DIE selection.
113 unsigned NextValidReloc;
114
115 bool findValidRelocsInDebugInfo(const object::ObjectFile &Obj,
116 const DebugMapObject &DMO);
117
118 bool findValidRelocs(const object::SectionRef &Section,
119 const object::ObjectFile &Obj,
120 const DebugMapObject &DMO);
121
122 void findValidRelocsMachO(const object::SectionRef &Section,
123 const object::MachOObjectFile &Obj,
124 const DebugMapObject &DMO);
125 /// @}
Frederic Riss1b9da422015-02-13 23:18:29 +0000126
Frederic Riss84c09a52015-02-13 23:18:34 +0000127 /// \defgroup FindRootDIEs Find DIEs corresponding to debug map entries.
128 ///
129 /// @{
130 /// \brief Recursively walk the \p DIE tree and look for DIEs to
131 /// keep. Store that information in \p CU's DIEInfo.
132 void lookForDIEsToKeep(const DWARFDebugInfoEntryMinimal &DIE,
133 const DebugMapObject &DMO, CompileUnit &CU,
134 unsigned Flags);
135
136 /// \brief Flags passed to DwarfLinker::lookForDIEsToKeep
137 enum TravesalFlags {
138 TF_Keep = 1 << 0, ///< Mark the traversed DIEs as kept.
139 TF_InFunctionScope = 1 << 1, ///< Current scope is a fucntion scope.
140 TF_DependencyWalk = 1 << 2, ///< Walking the dependencies of a kept DIE.
141 TF_ParentWalk = 1 << 3, ///< Walking up the parents of a kept DIE.
142 };
143
144 /// \brief Mark the passed DIE as well as all the ones it depends on
145 /// as kept.
146 void keepDIEAndDenpendencies(const DWARFDebugInfoEntryMinimal &DIE,
147 CompileUnit::DIEInfo &MyInfo,
148 const DebugMapObject &DMO, CompileUnit &CU,
149 unsigned Flags);
150
151 unsigned shouldKeepDIE(const DWARFDebugInfoEntryMinimal &DIE,
152 CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
153 unsigned Flags);
154
155 unsigned shouldKeepVariableDIE(const DWARFDebugInfoEntryMinimal &DIE,
156 CompileUnit &Unit,
157 CompileUnit::DIEInfo &MyInfo, unsigned Flags);
158
159 unsigned shouldKeepSubprogramDIE(const DWARFDebugInfoEntryMinimal &DIE,
160 CompileUnit &Unit,
161 CompileUnit::DIEInfo &MyInfo,
162 unsigned Flags);
163
164 bool hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
165 CompileUnit::DIEInfo &Info);
166 /// @}
167
Frederic Riss1b9da422015-02-13 23:18:29 +0000168 /// \defgroup Helpers Various helper methods.
169 ///
170 /// @{
171 const DWARFDebugInfoEntryMinimal *
172 resolveDIEReference(DWARFFormValue &RefValue, const DWARFUnit &Unit,
173 const DWARFDebugInfoEntryMinimal &DIE,
174 CompileUnit *&ReferencedCU);
175
176 CompileUnit *getUnitForOffset(unsigned Offset);
177
178 void reportWarning(const Twine &Warning, const DWARFUnit *Unit = nullptr,
179 const DWARFDebugInfoEntryMinimal *DIE = nullptr);
180 /// @}
181
Frederic Riss563cba62015-01-28 22:15:14 +0000182private:
Frederic Rissd3455182015-01-28 18:27:01 +0000183 std::string OutputFilename;
184 bool Verbose;
185 BinaryHolder BinHolder;
Frederic Riss563cba62015-01-28 22:15:14 +0000186
187 /// The units of the current debug map object.
188 std::vector<CompileUnit> Units;
Frederic Riss1b9da422015-02-13 23:18:29 +0000189
190 /// The debug map object curently under consideration.
191 DebugMapObject *CurrentDebugObject;
Frederic Rissd3455182015-01-28 18:27:01 +0000192};
193
Frederic Riss1b9da422015-02-13 23:18:29 +0000194/// \brief Similar to DWARFUnitSection::getUnitForOffset(), but
195/// returning our CompileUnit object instead.
196CompileUnit *DwarfLinker::getUnitForOffset(unsigned Offset) {
197 auto CU =
198 std::upper_bound(Units.begin(), Units.end(), Offset,
199 [](uint32_t LHS, const CompileUnit &RHS) {
200 return LHS < RHS.getOrigUnit().getNextUnitOffset();
201 });
202 return CU != Units.end() ? &*CU : nullptr;
203}
204
205/// \brief Resolve the DIE attribute reference that has been
206/// extracted in \p RefValue. The resulting DIE migh be in another
207/// CompileUnit which is stored into \p ReferencedCU.
208/// \returns null if resolving fails for any reason.
209const DWARFDebugInfoEntryMinimal *DwarfLinker::resolveDIEReference(
210 DWARFFormValue &RefValue, const DWARFUnit &Unit,
211 const DWARFDebugInfoEntryMinimal &DIE, CompileUnit *&RefCU) {
212 assert(RefValue.isFormClass(DWARFFormValue::FC_Reference));
213 uint64_t RefOffset = *RefValue.getAsReference(&Unit);
214
215 if ((RefCU = getUnitForOffset(RefOffset)))
216 if (const auto *RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset))
217 return RefDie;
218
219 reportWarning("could not find referenced DIE", &Unit, &DIE);
220 return nullptr;
221}
222
223/// \brief Report a warning to the user, optionaly including
224/// information about a specific \p DIE related to the warning.
225void DwarfLinker::reportWarning(const Twine &Warning, const DWARFUnit *Unit,
226 const DWARFDebugInfoEntryMinimal *DIE) {
Frederic Rissdef4fb72015-02-28 00:29:01 +0000227 StringRef Context = "<debug map>";
Frederic Riss1b9da422015-02-13 23:18:29 +0000228 if (CurrentDebugObject)
Frederic Rissdef4fb72015-02-28 00:29:01 +0000229 Context = CurrentDebugObject->getObjectFilename();
230 warn(Warning, Context);
Frederic Riss1b9da422015-02-13 23:18:29 +0000231
232 if (!Verbose || !DIE)
233 return;
234
235 errs() << " in DIE:\n";
236 DIE->dump(errs(), const_cast<DWARFUnit *>(Unit), 0 /* RecurseDepth */,
237 6 /* Indent */);
238}
239
Frederic Riss563cba62015-01-28 22:15:14 +0000240/// \brief Recursive helper to gather the child->parent relationships in the
241/// original compile unit.
Frederic Riss9aa725b2015-02-13 23:18:31 +0000242static void gatherDIEParents(const DWARFDebugInfoEntryMinimal *DIE,
243 unsigned ParentIdx, CompileUnit &CU) {
Frederic Riss563cba62015-01-28 22:15:14 +0000244 unsigned MyIdx = CU.getOrigUnit().getDIEIndex(DIE);
245 CU.getInfo(MyIdx).ParentIdx = ParentIdx;
246
247 if (DIE->hasChildren())
248 for (auto *Child = DIE->getFirstChild(); Child && !Child->isNULL();
249 Child = Child->getSibling())
Frederic Riss9aa725b2015-02-13 23:18:31 +0000250 gatherDIEParents(Child, MyIdx, CU);
Frederic Riss563cba62015-01-28 22:15:14 +0000251}
252
Frederic Riss84c09a52015-02-13 23:18:34 +0000253static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag) {
254 switch (Tag) {
255 default:
256 return false;
257 case dwarf::DW_TAG_subprogram:
258 case dwarf::DW_TAG_lexical_block:
259 case dwarf::DW_TAG_subroutine_type:
260 case dwarf::DW_TAG_structure_type:
261 case dwarf::DW_TAG_class_type:
262 case dwarf::DW_TAG_union_type:
263 return true;
264 }
265 llvm_unreachable("Invalid Tag");
266}
267
Frederic Riss563cba62015-01-28 22:15:14 +0000268void DwarfLinker::startDebugObject(DWARFContext &Dwarf) {
269 Units.reserve(Dwarf.getNumCompileUnits());
Frederic Riss1036e642015-02-13 23:18:22 +0000270 NextValidReloc = 0;
Frederic Riss563cba62015-01-28 22:15:14 +0000271}
272
Frederic Riss1036e642015-02-13 23:18:22 +0000273void DwarfLinker::endDebugObject() {
274 Units.clear();
275 ValidRelocs.clear();
276}
277
278/// \brief Iterate over the relocations of the given \p Section and
279/// store the ones that correspond to debug map entries into the
280/// ValidRelocs array.
281void DwarfLinker::findValidRelocsMachO(const object::SectionRef &Section,
282 const object::MachOObjectFile &Obj,
283 const DebugMapObject &DMO) {
284 StringRef Contents;
285 Section.getContents(Contents);
286 DataExtractor Data(Contents, Obj.isLittleEndian(), 0);
287
288 for (const object::RelocationRef &Reloc : Section.relocations()) {
289 object::DataRefImpl RelocDataRef = Reloc.getRawDataRefImpl();
290 MachO::any_relocation_info MachOReloc = Obj.getRelocation(RelocDataRef);
291 unsigned RelocSize = 1 << Obj.getAnyRelocationLength(MachOReloc);
292 uint64_t Offset64;
293 if ((RelocSize != 4 && RelocSize != 8) || Reloc.getOffset(Offset64)) {
Frederic Riss1b9da422015-02-13 23:18:29 +0000294 reportWarning(" unsupported relocation in debug_info section.");
Frederic Riss1036e642015-02-13 23:18:22 +0000295 continue;
296 }
297 uint32_t Offset = Offset64;
298 // Mach-o uses REL relocations, the addend is at the relocation offset.
299 uint64_t Addend = Data.getUnsigned(&Offset, RelocSize);
300
301 auto Sym = Reloc.getSymbol();
302 if (Sym != Obj.symbol_end()) {
303 StringRef SymbolName;
304 if (Sym->getName(SymbolName)) {
Frederic Riss1b9da422015-02-13 23:18:29 +0000305 reportWarning("error getting relocation symbol name.");
Frederic Riss1036e642015-02-13 23:18:22 +0000306 continue;
307 }
308 if (const auto *Mapping = DMO.lookupSymbol(SymbolName))
309 ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping);
310 } else if (const auto *Mapping = DMO.lookupObjectAddress(Addend)) {
311 // Do not store the addend. The addend was the address of the
312 // symbol in the object file, the address in the binary that is
313 // stored in the debug map doesn't need to be offseted.
314 ValidRelocs.emplace_back(Offset64, RelocSize, 0, Mapping);
315 }
316 }
317}
318
319/// \brief Dispatch the valid relocation finding logic to the
320/// appropriate handler depending on the object file format.
321bool DwarfLinker::findValidRelocs(const object::SectionRef &Section,
322 const object::ObjectFile &Obj,
323 const DebugMapObject &DMO) {
324 // Dispatch to the right handler depending on the file type.
325 if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Obj))
326 findValidRelocsMachO(Section, *MachOObj, DMO);
327 else
Frederic Riss1b9da422015-02-13 23:18:29 +0000328 reportWarning(Twine("unsupported object file type: ") + Obj.getFileName());
Frederic Riss1036e642015-02-13 23:18:22 +0000329
330 if (ValidRelocs.empty())
331 return false;
332
333 // Sort the relocations by offset. We will walk the DIEs linearly in
334 // the file, this allows us to just keep an index in the relocation
335 // array that we advance during our walk, rather than resorting to
336 // some associative container. See DwarfLinker::NextValidReloc.
337 std::sort(ValidRelocs.begin(), ValidRelocs.end());
338 return true;
339}
340
341/// \brief Look for relocations in the debug_info section that match
342/// entries in the debug map. These relocations will drive the Dwarf
343/// link by indicating which DIEs refer to symbols present in the
344/// linked binary.
345/// \returns wether there are any valid relocations in the debug info.
346bool DwarfLinker::findValidRelocsInDebugInfo(const object::ObjectFile &Obj,
347 const DebugMapObject &DMO) {
348 // Find the debug_info section.
349 for (const object::SectionRef &Section : Obj.sections()) {
350 StringRef SectionName;
351 Section.getName(SectionName);
352 SectionName = SectionName.substr(SectionName.find_first_not_of("._"));
353 if (SectionName != "debug_info")
354 continue;
355 return findValidRelocs(Section, Obj, DMO);
356 }
357 return false;
358}
Frederic Riss563cba62015-01-28 22:15:14 +0000359
Frederic Riss84c09a52015-02-13 23:18:34 +0000360/// \brief Checks that there is a relocation against an actual debug
361/// map entry between \p StartOffset and \p NextOffset.
362///
363/// This function must be called with offsets in strictly ascending
364/// order because it never looks back at relocations it already 'went past'.
365/// \returns true and sets Info.InDebugMap if it is the case.
366bool DwarfLinker::hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
367 CompileUnit::DIEInfo &Info) {
368 assert(NextValidReloc == 0 ||
369 StartOffset > ValidRelocs[NextValidReloc - 1].Offset);
370 if (NextValidReloc >= ValidRelocs.size())
371 return false;
372
373 uint64_t RelocOffset = ValidRelocs[NextValidReloc].Offset;
374
375 // We might need to skip some relocs that we didn't consider. For
376 // example the high_pc of a discarded DIE might contain a reloc that
377 // is in the list because it actually corresponds to the start of a
378 // function that is in the debug map.
379 while (RelocOffset < StartOffset && NextValidReloc < ValidRelocs.size() - 1)
380 RelocOffset = ValidRelocs[++NextValidReloc].Offset;
381
382 if (RelocOffset < StartOffset || RelocOffset >= EndOffset)
383 return false;
384
385 const auto &ValidReloc = ValidRelocs[NextValidReloc++];
386 if (Verbose)
387 outs() << "Found valid debug map entry: " << ValidReloc.Mapping->getKey()
388 << " " << format("\t%016" PRIx64 " => %016" PRIx64,
389 ValidReloc.Mapping->getValue().ObjectAddress,
390 ValidReloc.Mapping->getValue().BinaryAddress);
391
392 Info.Address =
393 ValidReloc.Mapping->getValue().BinaryAddress + ValidReloc.Addend;
394 Info.InDebugMap = true;
395 return true;
396}
397
398/// \brief Get the starting and ending (exclusive) offset for the
399/// attribute with index \p Idx descibed by \p Abbrev. \p Offset is
400/// supposed to point to the position of the first attribute described
401/// by \p Abbrev.
402/// \return [StartOffset, EndOffset) as a pair.
403static std::pair<uint32_t, uint32_t>
404getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx,
405 unsigned Offset, const DWARFUnit &Unit) {
406 DataExtractor Data = Unit.getDebugInfoExtractor();
407
408 for (unsigned i = 0; i < Idx; ++i)
409 DWARFFormValue::skipValue(Abbrev->getFormByIndex(i), Data, &Offset, &Unit);
410
411 uint32_t End = Offset;
412 DWARFFormValue::skipValue(Abbrev->getFormByIndex(Idx), Data, &End, &Unit);
413
414 return std::make_pair(Offset, End);
415}
416
417/// \brief Check if a variable describing DIE should be kept.
418/// \returns updated TraversalFlags.
419unsigned DwarfLinker::shouldKeepVariableDIE(
420 const DWARFDebugInfoEntryMinimal &DIE, CompileUnit &Unit,
421 CompileUnit::DIEInfo &MyInfo, unsigned Flags) {
422 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
423
424 // Global variables with constant value can always be kept.
425 if (!(Flags & TF_InFunctionScope) &&
426 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value) != -1U) {
427 MyInfo.InDebugMap = true;
428 return Flags | TF_Keep;
429 }
430
431 uint32_t LocationIdx = Abbrev->findAttributeIndex(dwarf::DW_AT_location);
432 if (LocationIdx == -1U)
433 return Flags;
434
435 uint32_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode());
436 const DWARFUnit &OrigUnit = Unit.getOrigUnit();
437 uint32_t LocationOffset, LocationEndOffset;
438 std::tie(LocationOffset, LocationEndOffset) =
439 getAttributeOffsets(Abbrev, LocationIdx, Offset, OrigUnit);
440
441 // See if there is a relocation to a valid debug map entry inside
442 // this variable's location. The order is important here. We want to
443 // always check in the variable has a valid relocation, so that the
444 // DIEInfo is filled. However, we don't want a static variable in a
445 // function to force us to keep the enclosing function.
446 if (!hasValidRelocation(LocationOffset, LocationEndOffset, MyInfo) ||
447 (Flags & TF_InFunctionScope))
448 return Flags;
449
450 if (Verbose)
451 DIE.dump(outs(), const_cast<DWARFUnit *>(&OrigUnit), 0, 8 /* Indent */);
452
453 return Flags | TF_Keep;
454}
455
456/// \brief Check if a function describing DIE should be kept.
457/// \returns updated TraversalFlags.
458unsigned DwarfLinker::shouldKeepSubprogramDIE(
459 const DWARFDebugInfoEntryMinimal &DIE, CompileUnit &Unit,
460 CompileUnit::DIEInfo &MyInfo, unsigned Flags) {
461 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
462
463 Flags |= TF_InFunctionScope;
464
465 uint32_t LowPcIdx = Abbrev->findAttributeIndex(dwarf::DW_AT_low_pc);
466 if (LowPcIdx == -1U)
467 return Flags;
468
469 uint32_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode());
470 const DWARFUnit &OrigUnit = Unit.getOrigUnit();
471 uint32_t LowPcOffset, LowPcEndOffset;
472 std::tie(LowPcOffset, LowPcEndOffset) =
473 getAttributeOffsets(Abbrev, LowPcIdx, Offset, OrigUnit);
474
475 uint64_t LowPc =
476 DIE.getAttributeValueAsAddress(&OrigUnit, dwarf::DW_AT_low_pc, -1ULL);
477 assert(LowPc != -1ULL && "low_pc attribute is not an address.");
478 if (LowPc == -1ULL ||
479 !hasValidRelocation(LowPcOffset, LowPcEndOffset, MyInfo))
480 return Flags;
481
482 if (Verbose)
483 DIE.dump(outs(), const_cast<DWARFUnit *>(&OrigUnit), 0, 8 /* Indent */);
484
485 return Flags | TF_Keep;
486}
487
488/// \brief Check if a DIE should be kept.
489/// \returns updated TraversalFlags.
490unsigned DwarfLinker::shouldKeepDIE(const DWARFDebugInfoEntryMinimal &DIE,
491 CompileUnit &Unit,
492 CompileUnit::DIEInfo &MyInfo,
493 unsigned Flags) {
494 switch (DIE.getTag()) {
495 case dwarf::DW_TAG_constant:
496 case dwarf::DW_TAG_variable:
497 return shouldKeepVariableDIE(DIE, Unit, MyInfo, Flags);
498 case dwarf::DW_TAG_subprogram:
499 return shouldKeepSubprogramDIE(DIE, Unit, MyInfo, Flags);
500 case dwarf::DW_TAG_module:
501 case dwarf::DW_TAG_imported_module:
502 case dwarf::DW_TAG_imported_declaration:
503 case dwarf::DW_TAG_imported_unit:
504 // We always want to keep these.
505 return Flags | TF_Keep;
506 }
507
508 return Flags;
509}
510
511
512/// \brief Mark the passed DIE as well as all the ones it depends on
513/// as kept.
514///
515/// This function is called by lookForDIEsToKeep on DIEs that are
516/// newly discovered to be needed in the link. It recursively calls
517/// back to lookForDIEsToKeep while adding TF_DependencyWalk to the
518/// TraversalFlags to inform it that it's not doing the primary DIE
519/// tree walk.
520void DwarfLinker::keepDIEAndDenpendencies(const DWARFDebugInfoEntryMinimal &DIE,
521 CompileUnit::DIEInfo &MyInfo,
522 const DebugMapObject &DMO,
523 CompileUnit &CU, unsigned Flags) {
524 const DWARFUnit &Unit = CU.getOrigUnit();
525 MyInfo.Keep = true;
526
527 // First mark all the parent chain as kept.
528 unsigned AncestorIdx = MyInfo.ParentIdx;
529 while (!CU.getInfo(AncestorIdx).Keep) {
530 lookForDIEsToKeep(*Unit.getDIEAtIndex(AncestorIdx), DMO, CU,
531 TF_ParentWalk | TF_Keep | TF_DependencyWalk);
532 AncestorIdx = CU.getInfo(AncestorIdx).ParentIdx;
533 }
534
535 // Then we need to mark all the DIEs referenced by this DIE's
536 // attributes as kept.
537 DataExtractor Data = Unit.getDebugInfoExtractor();
538 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
539 uint32_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode());
540
541 // Mark all DIEs referenced through atttributes as kept.
542 for (const auto &AttrSpec : Abbrev->attributes()) {
543 DWARFFormValue Val(AttrSpec.Form);
544
545 if (!Val.isFormClass(DWARFFormValue::FC_Reference)) {
546 DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, &Unit);
547 continue;
548 }
549
550 Val.extractValue(Data, &Offset, &Unit);
551 CompileUnit *ReferencedCU;
552 if (const auto *RefDIE = resolveDIEReference(Val, Unit, DIE, ReferencedCU))
553 lookForDIEsToKeep(*RefDIE, DMO, *ReferencedCU,
554 TF_Keep | TF_DependencyWalk);
555 }
556}
557
558/// \brief Recursively walk the \p DIE tree and look for DIEs to
559/// keep. Store that information in \p CU's DIEInfo.
560///
561/// This function is the entry point of the DIE selection
562/// algorithm. It is expected to walk the DIE tree in file order and
563/// (though the mediation of its helper) call hasValidRelocation() on
564/// each DIE that might be a 'root DIE' (See DwarfLinker class
565/// comment).
566/// While walking the dependencies of root DIEs, this function is
567/// also called, but during these dependency walks the file order is
568/// not respected. The TF_DependencyWalk flag tells us which kind of
569/// traversal we are currently doing.
570void DwarfLinker::lookForDIEsToKeep(const DWARFDebugInfoEntryMinimal &DIE,
571 const DebugMapObject &DMO, CompileUnit &CU,
572 unsigned Flags) {
573 unsigned Idx = CU.getOrigUnit().getDIEIndex(&DIE);
574 CompileUnit::DIEInfo &MyInfo = CU.getInfo(Idx);
575 bool AlreadyKept = MyInfo.Keep;
576
577 // If the Keep flag is set, we are marking a required DIE's
578 // dependencies. If our target is already marked as kept, we're all
579 // set.
580 if ((Flags & TF_DependencyWalk) && AlreadyKept)
581 return;
582
583 // We must not call shouldKeepDIE while called from keepDIEAndDenpendencies,
584 // because it would screw up the relocation finding logic.
585 if (!(Flags & TF_DependencyWalk))
586 Flags = shouldKeepDIE(DIE, CU, MyInfo, Flags);
587
588 // If it is a newly kept DIE mark it as well as all its dependencies as kept.
589 if (!AlreadyKept && (Flags & TF_Keep))
590 keepDIEAndDenpendencies(DIE, MyInfo, DMO, CU, Flags);
591
592 // The TF_ParentWalk flag tells us that we are currently walking up
593 // the parent chain of a required DIE, and we don't want to mark all
594 // the children of the parents as kept (consider for example a
595 // DW_TAG_namespace node in the parent chain). There are however a
596 // set of DIE types for which we want to ignore that directive and still
597 // walk their children.
598 if (dieNeedsChildrenToBeMeaningful(DIE.getTag()))
599 Flags &= ~TF_ParentWalk;
600
601 if (!DIE.hasChildren() || (Flags & TF_ParentWalk))
602 return;
603
604 for (auto *Child = DIE.getFirstChild(); Child && !Child->isNULL();
605 Child = Child->getSibling())
606 lookForDIEsToKeep(*Child, DMO, CU, Flags);
607}
608
Frederic Rissd3455182015-01-28 18:27:01 +0000609bool DwarfLinker::link(const DebugMap &Map) {
610
611 if (Map.begin() == Map.end()) {
612 errs() << "Empty debug map.\n";
613 return false;
614 }
615
616 for (const auto &Obj : Map.objects()) {
Frederic Riss1b9da422015-02-13 23:18:29 +0000617 CurrentDebugObject = Obj.get();
618
Frederic Rissd3455182015-01-28 18:27:01 +0000619 if (Verbose)
620 outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n";
621 auto ErrOrObj = BinHolder.GetObjectFile(Obj->getObjectFilename());
622 if (std::error_code EC = ErrOrObj.getError()) {
Frederic Riss1b9da422015-02-13 23:18:29 +0000623 reportWarning(Twine(Obj->getObjectFilename()) + ": " + EC.message());
Frederic Rissd3455182015-01-28 18:27:01 +0000624 continue;
625 }
626
Frederic Riss1036e642015-02-13 23:18:22 +0000627 // Look for relocations that correspond to debug map entries.
628 if (!findValidRelocsInDebugInfo(*ErrOrObj, *Obj)) {
629 if (Verbose)
630 outs() << "No valid relocations found. Skipping.\n";
631 continue;
632 }
633
Frederic Riss563cba62015-01-28 22:15:14 +0000634 // Setup access to the debug info.
Frederic Rissd3455182015-01-28 18:27:01 +0000635 DWARFContextInMemory DwarfContext(*ErrOrObj);
Frederic Riss563cba62015-01-28 22:15:14 +0000636 startDebugObject(DwarfContext);
Frederic Rissd3455182015-01-28 18:27:01 +0000637
Frederic Riss563cba62015-01-28 22:15:14 +0000638 // In a first phase, just read in the debug info and store the DIE
639 // parent links that we will use during the next phase.
Frederic Rissd3455182015-01-28 18:27:01 +0000640 for (const auto &CU : DwarfContext.compile_units()) {
641 auto *CUDie = CU->getCompileUnitDIE(false);
642 if (Verbose) {
643 outs() << "Input compilation unit:";
644 CUDie->dump(outs(), CU.get(), 0);
645 }
Frederic Riss563cba62015-01-28 22:15:14 +0000646 Units.emplace_back(*CU);
Frederic Riss9aa725b2015-02-13 23:18:31 +0000647 gatherDIEParents(CUDie, 0, Units.back());
Frederic Rissd3455182015-01-28 18:27:01 +0000648 }
Frederic Riss563cba62015-01-28 22:15:14 +0000649
Frederic Riss84c09a52015-02-13 23:18:34 +0000650 // Then mark all the DIEs that need to be present in the linked
651 // output and collect some information about them. Note that this
652 // loop can not be merged with the previous one becaue cross-cu
653 // references require the ParentIdx to be setup for every CU in
654 // the object file before calling this.
655 for (auto &CurrentUnit : Units)
656 lookForDIEsToKeep(*CurrentUnit.getOrigUnit().getCompileUnitDIE(), *Obj,
657 CurrentUnit, 0);
658
Frederic Riss563cba62015-01-28 22:15:14 +0000659 // Clean-up before starting working on the next object.
660 endDebugObject();
Frederic Rissd3455182015-01-28 18:27:01 +0000661 }
662
Frederic Riss231f7142014-12-12 17:31:24 +0000663 return true;
664}
665}
Frederic Rissd3455182015-01-28 18:27:01 +0000666
667bool linkDwarf(StringRef OutputFilename, const DebugMap &DM, bool Verbose) {
668 DwarfLinker Linker(OutputFilename, Verbose);
669 return Linker.link(DM);
670}
671}
Frederic Riss231f7142014-12-12 17:31:24 +0000672}