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