Clang] Fix expansion of response files in -Wp after integrated-cc1 change
[llvm-project.git] / llvm / tools / dsymutil / DwarfLinkerForBinary.h
blob018729a7c4230a84ae430fa006506fd13d4fc07f
1 //===- tools/dsymutil/DwarfLinkerForBinary.h --------------------*- 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 "DebugMap.h"
14 #include "DwarfStreamer.h"
15 #include "LinkUtils.h"
16 #include "llvm/DWARFLinker/DWARFLinker.h"
17 #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
18 #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
19 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
21 namespace llvm {
22 namespace dsymutil {
24 using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
26 /// The core of the Dwarf linking logic.
27 ///
28 /// The link of the dwarf information from the object files will be
29 /// driven by the selection of 'root DIEs', which are DIEs that
30 /// describe variables or functions that are present in the linked
31 /// binary (and thus have entries in the debug map). All the debug
32 /// information that will be linked (the DIEs, but also the line
33 /// tables, ranges, ...) is derived from that set of root DIEs.
34 ///
35 /// The root DIEs are identified because they contain relocations that
36 /// correspond to a debug map entry at specific places (the low_pc for
37 /// a function, the location for a variable). These relocations are
38 /// called ValidRelocs in the DwarfLinker and are gathered as a very
39 /// first step when we start processing a DebugMapObject.
40 class DwarfLinkerForBinary {
41 public:
42 DwarfLinkerForBinary(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
43 LinkOptions Options)
44 : OutFile(OutFile), BinHolder(BinHolder), Options(std::move(Options)) {}
46 /// Link the contents of the DebugMap.
47 bool link(const DebugMap &);
49 void reportWarning(const Twine &Warning, const DebugMapObject &DMO,
50 const DWARFDie *DIE = nullptr) const;
52 /// Flags passed to DwarfLinker::lookForDIEsToKeep
53 enum TraversalFlags {
54 TF_Keep = 1 << 0, ///< Mark the traversed DIEs as kept.
55 TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope.
56 TF_DependencyWalk = 1 << 2, ///< Walking the dependencies of a kept DIE.
57 TF_ParentWalk = 1 << 3, ///< Walking up the parents of a kept DIE.
58 TF_ODR = 1 << 4, ///< Use the ODR while keeping dependents.
59 TF_SkipPC = 1 << 5, ///< Skip all location attributes.
62 private:
63 /// Remembers the oldest and newest DWARF version we've seen in a unit.
64 void updateDwarfVersion(unsigned Version) {
65 MaxDwarfVersion = std::max(MaxDwarfVersion, Version);
66 MinDwarfVersion = std::min(MinDwarfVersion, Version);
69 /// Remembers the kinds of accelerator tables we've seen in a unit.
70 void updateAccelKind(DWARFContext &Dwarf);
72 /// Emit warnings as Dwarf compile units to leave a trail after linking.
73 bool emitPaperTrailWarnings(const DebugMapObject &DMO, const DebugMap &Map,
74 OffsetsStringPool &StringPool);
76 /// Keeps track of relocations.
77 class RelocationManager : public AddressesMap {
78 struct ValidReloc {
79 uint64_t Offset;
80 uint32_t Size;
81 uint64_t Addend;
82 const DebugMapObject::DebugMapEntry *Mapping;
84 ValidReloc(uint64_t Offset, uint32_t Size, uint64_t Addend,
85 const DebugMapObject::DebugMapEntry *Mapping)
86 : Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {}
88 bool operator<(const ValidReloc &RHS) const {
89 return Offset < RHS.Offset;
93 const DwarfLinkerForBinary &Linker;
95 /// The valid relocations for the current DebugMapObject.
96 /// This vector is sorted by relocation offset.
97 std::vector<ValidReloc> ValidRelocs;
99 /// Index into ValidRelocs of the next relocation to consider. As we walk
100 /// the DIEs in acsending file offset and as ValidRelocs is sorted by file
101 /// offset, keeping this index up to date is all we have to do to have a
102 /// cheap lookup during the root DIE selection and during DIE cloning.
103 unsigned NextValidReloc = 0;
105 RangesTy AddressRanges;
107 public:
108 RelocationManager(DwarfLinkerForBinary &Linker,
109 const object::ObjectFile &Obj, const DebugMapObject &DMO)
110 : Linker(Linker) {
111 findValidRelocsInDebugInfo(Obj, DMO);
113 // Iterate over the debug map entries and put all the ones that are
114 // functions (because they have a size) into the Ranges map. This map is
115 // very similar to the FunctionRanges that are stored in each unit, with 2
116 // notable differences:
118 // 1. Obviously this one is global, while the other ones are per-unit.
120 // 2. This one contains not only the functions described in the DIE
121 // tree, but also the ones that are only in the debug map.
123 // The latter information is required to reproduce dsymutil's logic while
124 // linking line tables. The cases where this information matters look like
125 // bugs that need to be investigated, but for now we need to reproduce
126 // dsymutil's behavior.
127 // FIXME: Once we understood exactly if that information is needed,
128 // maybe totally remove this (or try to use it to do a real
129 // -gline-tables-only on Darwin.
130 for (const auto &Entry : DMO.symbols()) {
131 const auto &Mapping = Entry.getValue();
132 if (Mapping.Size && Mapping.ObjectAddress)
133 AddressRanges[*Mapping.ObjectAddress] = ObjFileAddressRange(
134 *Mapping.ObjectAddress + Mapping.Size,
135 int64_t(Mapping.BinaryAddress) - *Mapping.ObjectAddress);
138 virtual ~RelocationManager() override { clear(); }
140 virtual bool areRelocationsResolved() const override { return true; }
142 bool hasValidRelocs(bool ResetRelocsPtr = true) override {
143 if (ResetRelocsPtr)
144 NextValidReloc = 0;
145 return !ValidRelocs.empty();
148 /// \defgroup FindValidRelocations Translate debug map into a list
149 /// of relevant relocations
151 /// @{
152 bool findValidRelocsInDebugInfo(const object::ObjectFile &Obj,
153 const DebugMapObject &DMO);
155 bool findValidRelocs(const object::SectionRef &Section,
156 const object::ObjectFile &Obj,
157 const DebugMapObject &DMO);
159 void findValidRelocsMachO(const object::SectionRef &Section,
160 const object::MachOObjectFile &Obj,
161 const DebugMapObject &DMO);
162 /// @}
164 bool hasValidRelocationAt(uint64_t StartOffset, uint64_t EndOffset,
165 CompileUnit::DIEInfo &Info) override;
167 bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
168 bool IsLittleEndian) override;
170 RangesTy &getValidAddressRanges() override { return AddressRanges; }
172 void clear() override {
173 AddressRanges.clear();
174 ValidRelocs.clear();
175 NextValidReloc = 0;
179 /// Keeps track of data associated with one object during linking.
180 struct LinkContext {
181 DwarfLinkerForBinary &Linker;
182 DebugMapObject &DMO;
183 const object::ObjectFile *ObjectFile = nullptr;
184 std::unique_ptr<RelocationManager> RelocMgr;
185 std::unique_ptr<DWARFContext> DwarfContext;
186 RangesTy Ranges;
187 UnitListTy CompileUnits;
189 LinkContext(const DebugMap &Map, DwarfLinkerForBinary &Linker,
190 DebugMapObject &DMO)
191 : Linker(Linker), DMO(DMO) {
192 // Swift ASTs are not object files.
193 if (DMO.getType() == MachO::N_AST) {
194 ObjectFile = nullptr;
195 return;
197 if (auto ErrOrObj = Linker.loadObject(DMO, Map)) {
198 ObjectFile = &*ErrOrObj;
199 DwarfContext = DWARFContext::create(*ObjectFile);
200 RelocMgr.reset(new RelocationManager(Linker, *ObjectFile, DMO));
204 /// Clear part of the context that's no longer needed when we're done with
205 /// the debug object.
206 void Clear() {
207 DwarfContext.reset(nullptr);
208 CompileUnits.clear();
209 Ranges.clear();
210 RelocMgr->clear();
214 /// Called at the start of a debug object link.
215 void startDebugObject(LinkContext &Context);
217 /// Called at the end of a debug object link.
218 void endDebugObject(LinkContext &Context);
220 /// \defgroup FindRootDIEs Find DIEs corresponding to debug map entries.
222 /// @{
223 /// Recursively walk the \p DIE tree and look for DIEs to
224 /// keep. Store that information in \p CU's DIEInfo.
226 /// The return value indicates whether the DIE is incomplete.
227 void lookForDIEsToKeep(RelocationManager &RelocMgr, RangesTy &Ranges,
228 const UnitListTy &Units, const DWARFDie &DIE,
229 const DebugMapObject &DMO, CompileUnit &CU,
230 unsigned Flags);
232 /// If this compile unit is really a skeleton CU that points to a
233 /// clang module, register it in ClangModules and return true.
235 /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
236 /// pointing to the module, and a DW_AT_gnu_dwo_id with the module
237 /// hash.
238 bool registerModuleReference(DWARFDie CUDie, const DWARFUnit &Unit,
239 DebugMap &ModuleMap, const DebugMapObject &DMO,
240 RangesTy &Ranges,
241 OffsetsStringPool &OffsetsStringPool,
242 UniquingStringPool &UniquingStringPoolStringPool,
243 DeclContextTree &ODRContexts,
244 uint64_t ModulesEndOffset, unsigned &UnitID,
245 bool IsLittleEndian, unsigned Indent = 0,
246 bool Quiet = false);
248 /// Recursively add the debug info in this clang module .pcm
249 /// file (and all the modules imported by it in a bottom-up fashion)
250 /// to Units.
251 Error loadClangModule(DWARFDie CUDie, StringRef FilePath,
252 StringRef ModuleName, uint64_t DwoId,
253 DebugMap &ModuleMap, const DebugMapObject &DMO,
254 RangesTy &Ranges, OffsetsStringPool &OffsetsStringPool,
255 UniquingStringPool &UniquingStringPool,
256 DeclContextTree &ODRContexts, uint64_t ModulesEndOffset,
257 unsigned &UnitID, bool IsLittleEndian,
258 unsigned Indent = 0, bool Quiet = false);
260 /// Mark the passed DIE as well as all the ones it depends on as kept.
261 void keepDIEAndDependencies(RelocationManager &RelocMgr, RangesTy &Ranges,
262 const UnitListTy &Units, const DWARFDie &DIE,
263 CompileUnit::DIEInfo &MyInfo,
264 const DebugMapObject &DMO, CompileUnit &CU,
265 bool UseODR);
267 unsigned shouldKeepDIE(RelocationManager &RelocMgr, RangesTy &Ranges,
268 const DWARFDie &DIE, const DebugMapObject &DMO,
269 CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
270 unsigned Flags);
272 /// Check if a variable describing DIE should be kept.
273 /// \returns updated TraversalFlags.
274 unsigned shouldKeepVariableDIE(RelocationManager &RelocMgr,
275 const DWARFDie &DIE, CompileUnit &Unit,
276 CompileUnit::DIEInfo &MyInfo, unsigned Flags);
278 unsigned shouldKeepSubprogramDIE(RelocationManager &RelocMgr,
279 RangesTy &Ranges, const DWARFDie &DIE,
280 const DebugMapObject &DMO, CompileUnit &Unit,
281 CompileUnit::DIEInfo &MyInfo,
282 unsigned Flags);
284 bool hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
285 CompileUnit::DIEInfo &Info);
286 /// @}
288 /// \defgroup Linking Methods used to link the debug information
290 /// @{
292 class DIECloner {
293 DwarfLinkerForBinary &Linker;
294 RelocationManager &RelocMgr;
296 /// Allocator used for all the DIEValue objects.
297 BumpPtrAllocator &DIEAlloc;
299 std::vector<std::unique_ptr<CompileUnit>> &CompileUnits;
300 LinkOptions Options;
302 public:
303 DIECloner(DwarfLinkerForBinary &Linker, RelocationManager &RelocMgr,
304 BumpPtrAllocator &DIEAlloc,
305 std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
306 LinkOptions &Options)
307 : Linker(Linker), RelocMgr(RelocMgr), DIEAlloc(DIEAlloc),
308 CompileUnits(CompileUnits), Options(Options) {}
310 /// Recursively clone \p InputDIE into an tree of DIE objects
311 /// where useless (as decided by lookForDIEsToKeep()) bits have been
312 /// stripped out and addresses have been rewritten according to the
313 /// debug map.
315 /// \param OutOffset is the offset the cloned DIE in the output
316 /// compile unit.
317 /// \param PCOffset (while cloning a function scope) is the offset
318 /// applied to the entry point of the function to get the linked address.
319 /// \param Die the output DIE to use, pass NULL to create one.
320 /// \returns the root of the cloned tree or null if nothing was selected.
321 DIE *cloneDIE(const DWARFDie &InputDIE, const DebugMapObject &DMO,
322 CompileUnit &U, OffsetsStringPool &StringPool,
323 int64_t PCOffset, uint32_t OutOffset, unsigned Flags,
324 bool IsLittleEndian, DIE *Die = nullptr);
326 /// Construct the output DIE tree by cloning the DIEs we
327 /// chose to keep above. If there are no valid relocs, then there's
328 /// nothing to clone/emit.
329 void cloneAllCompileUnits(DWARFContext &DwarfContext,
330 const DebugMapObject &DMO, RangesTy &Ranges,
331 OffsetsStringPool &StringPool,
332 bool IsLittleEndian);
334 private:
335 using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec;
337 /// Information gathered and exchanged between the various
338 /// clone*Attributes helpers about the attributes of a particular DIE.
339 struct AttributesInfo {
340 /// Names.
341 DwarfStringPoolEntryRef Name, MangledName, NameWithoutTemplate;
343 /// Offsets in the string pool.
344 uint32_t NameOffset = 0;
345 uint32_t MangledNameOffset = 0;
347 /// Value of AT_low_pc in the input DIE
348 uint64_t OrigLowPc = std::numeric_limits<uint64_t>::max();
350 /// Value of AT_high_pc in the input DIE
351 uint64_t OrigHighPc = 0;
353 /// Offset to apply to PC addresses inside a function.
354 int64_t PCOffset = 0;
356 /// Does the DIE have a low_pc attribute?
357 bool HasLowPc = false;
359 /// Does the DIE have a ranges attribute?
360 bool HasRanges = false;
362 /// Is this DIE only a declaration?
363 bool IsDeclaration = false;
365 AttributesInfo() = default;
368 /// Helper for cloneDIE.
369 unsigned cloneAttribute(DIE &Die, const DWARFDie &InputDIE,
370 const DebugMapObject &DMO, CompileUnit &U,
371 OffsetsStringPool &StringPool,
372 const DWARFFormValue &Val,
373 const AttributeSpec AttrSpec, unsigned AttrSize,
374 AttributesInfo &AttrInfo, bool IsLittleEndian);
376 /// Clone a string attribute described by \p AttrSpec and add
377 /// it to \p Die.
378 /// \returns the size of the new attribute.
379 unsigned cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec,
380 const DWARFFormValue &Val, const DWARFUnit &U,
381 OffsetsStringPool &StringPool,
382 AttributesInfo &Info);
384 /// Clone an attribute referencing another DIE and add
385 /// it to \p Die.
386 /// \returns the size of the new attribute.
387 unsigned cloneDieReferenceAttribute(DIE &Die, const DWARFDie &InputDIE,
388 AttributeSpec AttrSpec,
389 unsigned AttrSize,
390 const DWARFFormValue &Val,
391 const DebugMapObject &DMO,
392 CompileUnit &Unit);
394 /// Clone a DWARF expression that may be referencing another DIE.
395 void cloneExpression(DataExtractor &Data, DWARFExpression Expression,
396 const DebugMapObject &DMO, CompileUnit &Unit,
397 SmallVectorImpl<uint8_t> &OutputBuffer);
399 /// Clone an attribute referencing another DIE and add
400 /// it to \p Die.
401 /// \returns the size of the new attribute.
402 unsigned cloneBlockAttribute(DIE &Die, const DebugMapObject &DMO,
403 CompileUnit &Unit, AttributeSpec AttrSpec,
404 const DWARFFormValue &Val, unsigned AttrSize,
405 bool IsLittleEndian);
407 /// Clone an attribute referencing another DIE and add
408 /// it to \p Die.
409 /// \returns the size of the new attribute.
410 unsigned cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
411 const DWARFFormValue &Val,
412 const CompileUnit &Unit,
413 AttributesInfo &Info);
415 /// Clone a scalar attribute and add it to \p Die.
416 /// \returns the size of the new attribute.
417 unsigned cloneScalarAttribute(DIE &Die, const DWARFDie &InputDIE,
418 const DebugMapObject &DMO, CompileUnit &U,
419 AttributeSpec AttrSpec,
420 const DWARFFormValue &Val, unsigned AttrSize,
421 AttributesInfo &Info);
423 /// Get the potential name and mangled name for the entity
424 /// described by \p Die and store them in \Info if they are not
425 /// already there.
426 /// \returns is a name was found.
427 bool getDIENames(const DWARFDie &Die, AttributesInfo &Info,
428 OffsetsStringPool &StringPool, bool StripTemplate = false);
430 /// Create a copy of abbreviation Abbrev.
431 void copyAbbrev(const DWARFAbbreviationDeclaration &Abbrev, bool hasODR);
433 uint32_t hashFullyQualifiedName(DWARFDie DIE, CompileUnit &U,
434 const DebugMapObject &DMO,
435 int RecurseDepth = 0);
437 /// Helper for cloneDIE.
438 void addObjCAccelerator(CompileUnit &Unit, const DIE *Die,
439 DwarfStringPoolEntryRef Name,
440 OffsetsStringPool &StringPool, bool SkipPubSection);
443 /// Assign an abbreviation number to \p Abbrev
444 void assignAbbrev(DIEAbbrev &Abbrev);
446 /// Compute and emit debug_ranges section for \p Unit, and
447 /// patch the attributes referencing it.
448 void patchRangesForUnit(const CompileUnit &Unit, DWARFContext &Dwarf,
449 const DebugMapObject &DMO) const;
451 /// Generate and emit the DW_AT_ranges attribute for a compile_unit if it had
452 /// one.
453 void generateUnitRanges(CompileUnit &Unit) const;
455 /// Extract the line tables from the original dwarf, extract the relevant
456 /// parts according to the linked function ranges and emit the result in the
457 /// debug_line section.
458 void patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf,
459 RangesTy &Ranges, const DebugMapObject &DMO);
461 /// Emit the accelerator entries for \p Unit.
462 void emitAcceleratorEntriesForUnit(CompileUnit &Unit);
463 void emitDwarfAcceleratorEntriesForUnit(CompileUnit &Unit);
464 void emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit);
466 /// Patch the frame info for an object file and emit it.
467 void patchFrameInfoForObject(const DebugMapObject &, RangesTy &Ranges,
468 DWARFContext &, unsigned AddressSize);
470 /// FoldingSet that uniques the abbreviations.
471 FoldingSet<DIEAbbrev> AbbreviationsSet;
473 /// Storage for the unique Abbreviations.
474 /// This is passed to AsmPrinter::emitDwarfAbbrevs(), thus it cannot be
475 /// changed to a vector of unique_ptrs.
476 std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
478 /// DIELoc objects that need to be destructed (but not freed!).
479 std::vector<DIELoc *> DIELocs;
481 /// DIEBlock objects that need to be destructed (but not freed!).
482 std::vector<DIEBlock *> DIEBlocks;
484 /// Allocator used for all the DIEValue objects.
485 BumpPtrAllocator DIEAlloc;
486 /// @}
488 /// \defgroup Helpers Various helper methods.
490 /// @{
491 bool createStreamer(const Triple &TheTriple, raw_fd_ostream &OutFile);
493 /// Attempt to load a debug object from disk.
494 ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,
495 const DebugMap &Map);
496 /// @}
498 raw_fd_ostream &OutFile;
499 BinaryHolder &BinHolder;
500 LinkOptions Options;
501 std::unique_ptr<DwarfStreamer> Streamer;
503 unsigned MaxDwarfVersion = 0;
504 unsigned MinDwarfVersion = std::numeric_limits<unsigned>::max();
506 bool AtLeastOneAppleAccelTable = false;
507 bool AtLeastOneDwarfAccelTable = false;
509 /// The CIEs that have been emitted in the output section. The actual CIE
510 /// data serves a the key to this StringMap, this takes care of comparing the
511 /// semantics of CIEs defined in different object files.
512 StringMap<uint32_t> EmittedCIEs;
514 /// Offset of the last CIE that has been emitted in the output
515 /// debug_frame section.
516 uint32_t LastCIEOffset = 0;
518 /// Apple accelerator tables.
519 AccelTable<DWARF5AccelTableStaticData> DebugNames;
520 AccelTable<AppleAccelTableStaticOffsetData> AppleNames;
521 AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;
522 AccelTable<AppleAccelTableStaticOffsetData> AppleObjc;
523 AccelTable<AppleAccelTableStaticTypeData> AppleTypes;
525 /// Mapping the PCM filename to the DwoId.
526 StringMap<uint64_t> ClangModules;
528 /// A list of all .swiftinterface files referenced by the debug
529 /// info, mapping Module name to path on disk. The entries need to
530 /// be uniqued and sorted and there are only few entries expected
531 /// per compile unit, which is why this is a std::map.
532 std::map<std::string, std::string> ParseableSwiftInterfaces;
534 bool ModuleCacheHintDisplayed = false;
535 bool ArchiveHintDisplayed = false;
538 } // end namespace dsymutil
539 } // end namespace llvm
541 #endif // LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H