blob: 64fa8d2107d5ba5b7bca93ac9c5cdc13912e7234 [file] [log] [blame]
Jonas Devlieghere928fea22018-06-27 16:13:40 +00001//===- tools/dsymutil/DwarfLinker.h - Dwarf debug info linker ---*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
11#define LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
12
13#include "BinaryHolder.h"
14#include "CompileUnit.h"
15#include "DebugMap.h"
16#include "DeclContext.h"
17#include "DwarfStreamer.h"
18#include "LinkUtils.h"
19#include "llvm/DebugInfo/DWARF/DWARFContext.h"
20
21namespace llvm {
22namespace dsymutil {
23
24/// Partial address range for debug map objects. Besides an offset, only the
25/// HighPC is stored. The structure is stored in a map where the LowPC is the
26/// key.
27struct DebugMapObjectRange {
28 /// Function HighPC.
29 uint64_t HighPC;
30 /// Offset to apply to the linked address.
31 int64_t Offset;
32
33 DebugMapObjectRange(uint64_t EndPC, int64_t Offset)
34 : HighPC(EndPC), Offset(Offset) {}
35
36 DebugMapObjectRange() : HighPC(0), Offset(0) {}
37};
38
39/// Map LowPC to DebugMapObjectRange.
40using RangesTy = std::map<uint64_t, DebugMapObjectRange>;
41using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
42
43/// The core of the Dwarf linking logic.
44///
45/// The link of the dwarf information from the object files will be
46/// driven by the selection of 'root DIEs', which are DIEs that
47/// describe variables or functions that are present in the linked
48/// binary (and thus have entries in the debug map). All the debug
49/// information that will be linked (the DIEs, but also the line
50/// tables, ranges, ...) is derived from that set of root DIEs.
51///
52/// The root DIEs are identified because they contain relocations that
53/// correspond to a debug map entry at specific places (the low_pc for
54/// a function, the location for a variable). These relocations are
55/// called ValidRelocs in the DwarfLinker and are gathered as a very
56/// first step when we start processing a DebugMapObject.
57class DwarfLinker {
58public:
Jonas Devlieghere9f33bbfe2018-06-29 16:51:52 +000059 DwarfLinker(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
Jonas Devlieghere4d3e6c12018-06-29 16:50:41 +000060 const LinkOptions &Options)
61 : OutFile(OutFile), BinHolder(BinHolder), Options(Options) {}
Jonas Devlieghere928fea22018-06-27 16:13:40 +000062
63 /// Link the contents of the DebugMap.
64 bool link(const DebugMap &);
65
66 void reportWarning(const Twine &Warning, const DebugMapObject &DMO,
67 const DWARFDie *DIE = nullptr) const;
68
69private:
Jonas Devlieghere7c767bd2018-07-25 23:01:38 +000070 /// Remembers the oldest and newest DWARF version we've seen in a unit.
71 void updateDwarfVersion(unsigned Version) {
72 MaxDwarfVersion = std::max(MaxDwarfVersion, Version);
73 MinDwarfVersion = std::min(MinDwarfVersion, Version);
Jonas Devlieghere928fea22018-06-27 16:13:40 +000074 }
75
Jonas Devlieghere7c767bd2018-07-25 23:01:38 +000076 /// Remembers the kinds of accelerator tables we've seen in a unit.
77 void updateAccelKind(DWARFContext &Dwarf);
78
Jonas Devlieghere928fea22018-06-27 16:13:40 +000079 /// Emit warnings as Dwarf compile units to leave a trail after linking.
80 bool emitPaperTrailWarnings(const DebugMapObject &DMO, const DebugMap &Map,
81 OffsetsStringPool &StringPool);
82
83 /// Keeps track of relocations.
84 class RelocationManager {
85 struct ValidReloc {
86 uint32_t Offset;
87 uint32_t Size;
88 uint64_t Addend;
89 const DebugMapObject::DebugMapEntry *Mapping;
90
91 ValidReloc(uint32_t Offset, uint32_t Size, uint64_t Addend,
92 const DebugMapObject::DebugMapEntry *Mapping)
93 : Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {}
94
95 bool operator<(const ValidReloc &RHS) const {
96 return Offset < RHS.Offset;
97 }
98 };
99
100 const DwarfLinker &Linker;
101
102 /// The valid relocations for the current DebugMapObject.
103 /// This vector is sorted by relocation offset.
104 std::vector<ValidReloc> ValidRelocs;
105
106 /// Index into ValidRelocs of the next relocation to consider. As we walk
107 /// the DIEs in acsending file offset and as ValidRelocs is sorted by file
108 /// offset, keeping this index up to date is all we have to do to have a
109 /// cheap lookup during the root DIE selection and during DIE cloning.
110 unsigned NextValidReloc = 0;
111
112 public:
113 RelocationManager(DwarfLinker &Linker) : Linker(Linker) {}
114
115 bool hasValidRelocs() const { return !ValidRelocs.empty(); }
116
117 /// Reset the NextValidReloc counter.
118 void resetValidRelocs() { NextValidReloc = 0; }
119
120 /// \defgroup FindValidRelocations Translate debug map into a list
121 /// of relevant relocations
122 ///
123 /// @{
124 bool findValidRelocsInDebugInfo(const object::ObjectFile &Obj,
125 const DebugMapObject &DMO);
126
127 bool findValidRelocs(const object::SectionRef &Section,
128 const object::ObjectFile &Obj,
129 const DebugMapObject &DMO);
130
131 void findValidRelocsMachO(const object::SectionRef &Section,
132 const object::MachOObjectFile &Obj,
133 const DebugMapObject &DMO);
134 /// @}
135
136 bool hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
137 CompileUnit::DIEInfo &Info);
138
139 bool applyValidRelocs(MutableArrayRef<char> Data, uint32_t BaseOffset,
140 bool isLittleEndian);
141 };
142
143 /// Keeps track of data associated with one object during linking.
144 struct LinkContext {
145 DebugMapObject &DMO;
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000146 const object::ObjectFile *ObjectFile;
147 RelocationManager RelocMgr;
148 std::unique_ptr<DWARFContext> DwarfContext;
149 RangesTy Ranges;
150 UnitListTy CompileUnits;
151
Jonas Devlieghere4d3e6c12018-06-29 16:50:41 +0000152 LinkContext(const DebugMap &Map, DwarfLinker &Linker, DebugMapObject &DMO)
153 : DMO(DMO), RelocMgr(Linker) {
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000154 // Swift ASTs are not object files.
155 if (DMO.getType() == MachO::N_AST) {
156 ObjectFile = nullptr;
157 return;
158 }
Jonas Devlieghere4d3e6c12018-06-29 16:50:41 +0000159 auto ErrOrObj = Linker.loadObject(DMO, Map);
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000160 ObjectFile = ErrOrObj ? &*ErrOrObj : nullptr;
161 DwarfContext = ObjectFile ? DWARFContext::create(*ObjectFile) : nullptr;
162 }
163
Jonas Devlieghere7c767bd2018-07-25 23:01:38 +0000164 /// Clear part of the context that's no longer needed when we're done with
165 /// the debug object.
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000166 void Clear() {
Jonas Devlieghere7c767bd2018-07-25 23:01:38 +0000167 DwarfContext.reset(nullptr);
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000168 CompileUnits.clear();
169 Ranges.clear();
170 }
171 };
172
173 /// Called at the start of a debug object link.
174 void startDebugObject(LinkContext &Context);
175
176 /// Called at the end of a debug object link.
177 void endDebugObject(LinkContext &Context);
178
179 /// \defgroup FindRootDIEs Find DIEs corresponding to debug map entries.
180 ///
181 /// @{
182 /// Recursively walk the \p DIE tree and look for DIEs to
183 /// keep. Store that information in \p CU's DIEInfo.
184 ///
185 /// The return value indicates whether the DIE is incomplete.
Jonas Devlieghere3289ee62018-08-01 13:24:39 +0000186 void lookForDIEsToKeep(RelocationManager &RelocMgr, RangesTy &Ranges,
Jonas Devlieghereea63d872018-06-28 15:01:42 +0000187 const UnitListTy &Units, const DWARFDie &DIE,
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000188 const DebugMapObject &DMO, CompileUnit &CU,
189 unsigned Flags);
190
191 /// If this compile unit is really a skeleton CU that points to a
192 /// clang module, register it in ClangModules and return true.
193 ///
194 /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
195 /// pointing to the module, and a DW_AT_gnu_dwo_id with the module
196 /// hash.
197 bool registerModuleReference(const DWARFDie &CUDie, const DWARFUnit &Unit,
198 DebugMap &ModuleMap, const DebugMapObject &DMO,
199 RangesTy &Ranges,
200 OffsetsStringPool &OffsetsStringPool,
201 UniquingStringPool &UniquingStringPoolStringPool,
Jonas Devlieghere60c60092018-09-07 10:29:22 +0000202 DeclContextTree &ODRContexts,
203 uint64_t ModulesEndOffset, unsigned &UnitID,
Adrian Prantl5309f162018-08-24 20:41:08 +0000204 unsigned Indent = 0, bool Quiet = false);
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000205
206 /// Recursively add the debug info in this clang module .pcm
207 /// file (and all the modules imported by it in a bottom-up fashion)
208 /// to Units.
209 Error loadClangModule(StringRef Filename, StringRef ModulePath,
210 StringRef ModuleName, uint64_t DwoId,
211 DebugMap &ModuleMap, const DebugMapObject &DMO,
212 RangesTy &Ranges, OffsetsStringPool &OffsetsStringPool,
213 UniquingStringPool &UniquingStringPool,
Jonas Devlieghere60c60092018-09-07 10:29:22 +0000214 DeclContextTree &ODRContexts, uint64_t ModulesEndOffset,
215 unsigned &UnitID, unsigned Indent = 0,
216 bool Quiet = false);
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000217
218 /// Flags passed to DwarfLinker::lookForDIEsToKeep
219 enum TraversalFlags {
220 TF_Keep = 1 << 0, ///< Mark the traversed DIEs as kept.
221 TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope.
222 TF_DependencyWalk = 1 << 2, ///< Walking the dependencies of a kept DIE.
223 TF_ParentWalk = 1 << 3, ///< Walking up the parents of a kept DIE.
224 TF_ODR = 1 << 4, ///< Use the ODR while keeping dependents.
225 TF_SkipPC = 1 << 5, ///< Skip all location attributes.
226 };
227
228 /// Mark the passed DIE as well as all the ones it depends on as kept.
229 void keepDIEAndDependencies(RelocationManager &RelocMgr, RangesTy &Ranges,
Jonas Devlieghereea63d872018-06-28 15:01:42 +0000230 const UnitListTy &Units, const DWARFDie &DIE,
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000231 CompileUnit::DIEInfo &MyInfo,
232 const DebugMapObject &DMO, CompileUnit &CU,
233 bool UseODR);
234
235 unsigned shouldKeepDIE(RelocationManager &RelocMgr, RangesTy &Ranges,
236 const DWARFDie &DIE, const DebugMapObject &DMO,
237 CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
238 unsigned Flags);
239
240 unsigned shouldKeepVariableDIE(RelocationManager &RelocMgr,
241 const DWARFDie &DIE, CompileUnit &Unit,
242 CompileUnit::DIEInfo &MyInfo, unsigned Flags);
243
244 unsigned shouldKeepSubprogramDIE(RelocationManager &RelocMgr,
245 RangesTy &Ranges, const DWARFDie &DIE,
246 const DebugMapObject &DMO, CompileUnit &Unit,
247 CompileUnit::DIEInfo &MyInfo,
248 unsigned Flags);
249
250 bool hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
251 CompileUnit::DIEInfo &Info);
252 /// @}
253
254 /// \defgroup Linking Methods used to link the debug information
255 ///
256 /// @{
257
258 class DIECloner {
259 DwarfLinker &Linker;
260 RelocationManager &RelocMgr;
261
262 /// Allocator used for all the DIEValue objects.
263 BumpPtrAllocator &DIEAlloc;
264
265 std::vector<std::unique_ptr<CompileUnit>> &CompileUnits;
266 LinkOptions Options;
267
268 public:
269 DIECloner(DwarfLinker &Linker, RelocationManager &RelocMgr,
270 BumpPtrAllocator &DIEAlloc,
271 std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
272 LinkOptions &Options)
273 : Linker(Linker), RelocMgr(RelocMgr), DIEAlloc(DIEAlloc),
274 CompileUnits(CompileUnits), Options(Options) {}
275
276 /// Recursively clone \p InputDIE into an tree of DIE objects
277 /// where useless (as decided by lookForDIEsToKeep()) bits have been
278 /// stripped out and addresses have been rewritten according to the
279 /// debug map.
280 ///
281 /// \param OutOffset is the offset the cloned DIE in the output
282 /// compile unit.
283 /// \param PCOffset (while cloning a function scope) is the offset
284 /// applied to the entry point of the function to get the linked address.
285 /// \param Die the output DIE to use, pass NULL to create one.
286 /// \returns the root of the cloned tree or null if nothing was selected.
287 DIE *cloneDIE(const DWARFDie &InputDIE, const DebugMapObject &DMO,
288 CompileUnit &U, OffsetsStringPool &StringPool,
289 int64_t PCOffset, uint32_t OutOffset, unsigned Flags,
290 DIE *Die = nullptr);
291
292 /// Construct the output DIE tree by cloning the DIEs we
293 /// chose to keep above. If there are no valid relocs, then there's
294 /// nothing to clone/emit.
295 void cloneAllCompileUnits(DWARFContext &DwarfContext,
296 const DebugMapObject &DMO, RangesTy &Ranges,
297 OffsetsStringPool &StringPool);
298
299 private:
300 using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec;
301
302 /// Information gathered and exchanged between the various
303 /// clone*Attributes helpers about the attributes of a particular DIE.
304 struct AttributesInfo {
305 /// Names.
306 DwarfStringPoolEntryRef Name, MangledName, NameWithoutTemplate;
307
308 /// Offsets in the string pool.
309 uint32_t NameOffset = 0;
310 uint32_t MangledNameOffset = 0;
311
312 /// Value of AT_low_pc in the input DIE
313 uint64_t OrigLowPc = std::numeric_limits<uint64_t>::max();
314
315 /// Value of AT_high_pc in the input DIE
316 uint64_t OrigHighPc = 0;
317
318 /// Offset to apply to PC addresses inside a function.
319 int64_t PCOffset = 0;
320
321 /// Does the DIE have a low_pc attribute?
322 bool HasLowPc = false;
323
324 /// Does the DIE have a ranges attribute?
325 bool HasRanges = false;
326
327 /// Is this DIE only a declaration?
328 bool IsDeclaration = false;
329
330 AttributesInfo() = default;
331 };
332
333 /// Helper for cloneDIE.
334 unsigned cloneAttribute(DIE &Die, const DWARFDie &InputDIE,
335 const DebugMapObject &DMO, CompileUnit &U,
336 OffsetsStringPool &StringPool,
337 const DWARFFormValue &Val,
338 const AttributeSpec AttrSpec, unsigned AttrSize,
339 AttributesInfo &AttrInfo);
340
341 /// Clone a string attribute described by \p AttrSpec and add
342 /// it to \p Die.
343 /// \returns the size of the new attribute.
344 unsigned cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec,
345 const DWARFFormValue &Val, const DWARFUnit &U,
346 OffsetsStringPool &StringPool,
347 AttributesInfo &Info);
348
349 /// Clone an attribute referencing another DIE and add
350 /// it to \p Die.
351 /// \returns the size of the new attribute.
352 unsigned cloneDieReferenceAttribute(DIE &Die, const DWARFDie &InputDIE,
353 AttributeSpec AttrSpec,
354 unsigned AttrSize,
355 const DWARFFormValue &Val,
356 const DebugMapObject &DMO,
357 CompileUnit &Unit);
358
359 /// Clone an attribute referencing another DIE and add
360 /// it to \p Die.
361 /// \returns the size of the new attribute.
362 unsigned cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec,
363 const DWARFFormValue &Val, unsigned AttrSize);
364
365 /// Clone an attribute referencing another DIE and add
366 /// it to \p Die.
367 /// \returns the size of the new attribute.
368 unsigned cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
369 const DWARFFormValue &Val,
370 const CompileUnit &Unit,
371 AttributesInfo &Info);
372
373 /// Clone a scalar attribute and add it to \p Die.
374 /// \returns the size of the new attribute.
375 unsigned cloneScalarAttribute(DIE &Die, const DWARFDie &InputDIE,
376 const DebugMapObject &DMO, CompileUnit &U,
377 AttributeSpec AttrSpec,
378 const DWARFFormValue &Val, unsigned AttrSize,
379 AttributesInfo &Info);
380
381 /// Get the potential name and mangled name for the entity
382 /// described by \p Die and store them in \Info if they are not
383 /// already there.
384 /// \returns is a name was found.
385 bool getDIENames(const DWARFDie &Die, AttributesInfo &Info,
386 OffsetsStringPool &StringPool, bool StripTemplate = false);
387
388 /// Create a copy of abbreviation Abbrev.
389 void copyAbbrev(const DWARFAbbreviationDeclaration &Abbrev, bool hasODR);
390
391 uint32_t hashFullyQualifiedName(DWARFDie DIE, CompileUnit &U,
392 const DebugMapObject &DMO,
393 int RecurseDepth = 0);
394
395 /// Helper for cloneDIE.
396 void addObjCAccelerator(CompileUnit &Unit, const DIE *Die,
397 DwarfStringPoolEntryRef Name,
398 OffsetsStringPool &StringPool, bool SkipPubSection);
399 };
400
401 /// Assign an abbreviation number to \p Abbrev
402 void AssignAbbrev(DIEAbbrev &Abbrev);
403
404 /// Compute and emit debug_ranges section for \p Unit, and
405 /// patch the attributes referencing it.
406 void patchRangesForUnit(const CompileUnit &Unit, DWARFContext &Dwarf,
407 const DebugMapObject &DMO) const;
408
409 /// Generate and emit the DW_AT_ranges attribute for a compile_unit if it had
410 /// one.
411 void generateUnitRanges(CompileUnit &Unit) const;
412
413 /// Extract the line tables from the original dwarf, extract the relevant
414 /// parts according to the linked function ranges and emit the result in the
415 /// debug_line section.
416 void patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf,
417 RangesTy &Ranges, const DebugMapObject &DMO);
418
419 /// Emit the accelerator entries for \p Unit.
420 void emitAcceleratorEntriesForUnit(CompileUnit &Unit);
Jonas Devlieghere7c767bd2018-07-25 23:01:38 +0000421 void emitDwarfAcceleratorEntriesForUnit(CompileUnit &Unit);
422 void emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit);
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000423
424 /// Patch the frame info for an object file and emit it.
425 void patchFrameInfoForObject(const DebugMapObject &, RangesTy &Ranges,
426 DWARFContext &, unsigned AddressSize);
427
428 /// FoldingSet that uniques the abbreviations.
429 FoldingSet<DIEAbbrev> AbbreviationsSet;
430
431 /// Storage for the unique Abbreviations.
432 /// This is passed to AsmPrinter::emitDwarfAbbrevs(), thus it cannot be
433 /// changed to a vector of unique_ptrs.
434 std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
435
436 /// DIELoc objects that need to be destructed (but not freed!).
437 std::vector<DIELoc *> DIELocs;
438
439 /// DIEBlock objects that need to be destructed (but not freed!).
440 std::vector<DIEBlock *> DIEBlocks;
441
442 /// Allocator used for all the DIEValue objects.
443 BumpPtrAllocator DIEAlloc;
444 /// @}
445
446 /// \defgroup Helpers Various helper methods.
447 ///
448 /// @{
449 bool createStreamer(const Triple &TheTriple, raw_fd_ostream &OutFile);
450
451 /// Attempt to load a debug object from disk.
Jonas Devlieghere4d3e6c12018-06-29 16:50:41 +0000452 ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000453 const DebugMap &Map);
454 /// @}
455
456 raw_fd_ostream &OutFile;
Jonas Devlieghere9f33bbfe2018-06-29 16:51:52 +0000457 BinaryHolder &BinHolder;
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000458 LinkOptions Options;
459 std::unique_ptr<DwarfStreamer> Streamer;
460 uint64_t OutputDebugInfoSize;
Jonas Devlieghere7c767bd2018-07-25 23:01:38 +0000461
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000462 unsigned MaxDwarfVersion = 0;
Jonas Devlieghere7c767bd2018-07-25 23:01:38 +0000463 unsigned MinDwarfVersion = std::numeric_limits<unsigned>::max();
464
465 bool AtLeastOneAppleAccelTable = false;
466 bool AtLeastOneDwarfAccelTable = false;
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000467
468 /// The CIEs that have been emitted in the output section. The actual CIE
469 /// data serves a the key to this StringMap, this takes care of comparing the
470 /// semantics of CIEs defined in different object files.
471 StringMap<uint32_t> EmittedCIEs;
472
473 /// Offset of the last CIE that has been emitted in the output
474 /// debug_frame section.
475 uint32_t LastCIEOffset = 0;
476
477 /// Apple accelerator tables.
Jonas Devlieghere7c767bd2018-07-25 23:01:38 +0000478 AccelTable<DWARF5AccelTableStaticData> DebugNames;
Jonas Devlieghere928fea22018-06-27 16:13:40 +0000479 AccelTable<AppleAccelTableStaticOffsetData> AppleNames;
480 AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;
481 AccelTable<AppleAccelTableStaticOffsetData> AppleObjc;
482 AccelTable<AppleAccelTableStaticTypeData> AppleTypes;
483
484 /// Mapping the PCM filename to the DwoId.
485 StringMap<uint64_t> ClangModules;
486
487 bool ModuleCacheHintDisplayed = false;
488 bool ArchiveHintDisplayed = false;
489};
490
491} // end namespace dsymutil
492} // end namespace llvm
493
494#endif // LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H