LLVM 17.0.0git
DWARFLinker.cpp
Go to the documentation of this file.
1//=== DWARFLinker.cpp -----------------------------------------------------===//
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//===----------------------------------------------------------------------===//
8
10#include "llvm/ADT/ArrayRef.h"
11#include "llvm/ADT/BitVector.h"
12#include "llvm/ADT/STLExtras.h"
26#include "llvm/MC/MCDwarf.h"
28#include "llvm/Support/Error.h"
32#include "llvm/Support/LEB128.h"
33#include "llvm/Support/Path.h"
35#include <vector>
36
37namespace llvm {
38
39/// Hold the input and output of the debug info size in bytes.
43};
44
45/// Compute the total size of the debug info.
47 uint64_t Size = 0;
48 for (auto &Unit : Dwarf.compile_units()) {
49 Size += Unit->getLength();
50 }
51 return Size;
52}
53
54/// Similar to DWARFUnitSection::getUnitForOffset(), but returning our
55/// CompileUnit object instead.
57 auto CU = llvm::upper_bound(
58 Units, Offset, [](uint64_t LHS, const std::unique_ptr<CompileUnit> &RHS) {
59 return LHS < RHS->getOrigUnit().getNextUnitOffset();
60 });
61 return CU != Units.end() ? CU->get() : nullptr;
62}
63
64/// Resolve the DIE attribute reference that has been extracted in \p RefValue.
65/// The resulting DIE might be in another CompileUnit which is stored into \p
66/// ReferencedCU. \returns null if resolving fails for any reason.
67DWARFDie DWARFLinker::resolveDIEReference(const DWARFFile &File,
68 const UnitListTy &Units,
69 const DWARFFormValue &RefValue,
70 const DWARFDie &DIE,
71 CompileUnit *&RefCU) {
72 assert(RefValue.isFormClass(DWARFFormValue::FC_Reference));
73 uint64_t RefOffset = *RefValue.getAsReference();
74 if ((RefCU = getUnitForOffset(Units, RefOffset)))
75 if (const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) {
76 // In a file with broken references, an attribute might point to a NULL
77 // DIE.
78 if (!RefDie.isNULL())
79 return RefDie;
80 }
81
82 reportWarning("could not find referenced DIE", File, &DIE);
83 return DWARFDie();
84}
85
86/// \returns whether the passed \a Attr type might contain a DIE reference
87/// suitable for ODR uniquing.
88static bool isODRAttribute(uint16_t Attr) {
89 switch (Attr) {
90 default:
91 return false;
92 case dwarf::DW_AT_type:
93 case dwarf::DW_AT_containing_type:
94 case dwarf::DW_AT_specification:
95 case dwarf::DW_AT_abstract_origin:
96 case dwarf::DW_AT_import:
97 return true;
98 }
99 llvm_unreachable("Improper attribute.");
100}
101
102static bool isTypeTag(uint16_t Tag) {
103 switch (Tag) {
104 case dwarf::DW_TAG_array_type:
105 case dwarf::DW_TAG_class_type:
106 case dwarf::DW_TAG_enumeration_type:
107 case dwarf::DW_TAG_pointer_type:
108 case dwarf::DW_TAG_reference_type:
109 case dwarf::DW_TAG_string_type:
110 case dwarf::DW_TAG_structure_type:
111 case dwarf::DW_TAG_subroutine_type:
112 case dwarf::DW_TAG_typedef:
113 case dwarf::DW_TAG_union_type:
114 case dwarf::DW_TAG_ptr_to_member_type:
115 case dwarf::DW_TAG_set_type:
116 case dwarf::DW_TAG_subrange_type:
117 case dwarf::DW_TAG_base_type:
118 case dwarf::DW_TAG_const_type:
119 case dwarf::DW_TAG_constant:
120 case dwarf::DW_TAG_file_type:
121 case dwarf::DW_TAG_namelist:
122 case dwarf::DW_TAG_packed_type:
123 case dwarf::DW_TAG_volatile_type:
124 case dwarf::DW_TAG_restrict_type:
125 case dwarf::DW_TAG_atomic_type:
126 case dwarf::DW_TAG_interface_type:
127 case dwarf::DW_TAG_unspecified_type:
128 case dwarf::DW_TAG_shared_type:
129 case dwarf::DW_TAG_immutable_type:
130 return true;
131 default:
132 break;
133 }
134 return false;
135}
136
138
140
141static std::optional<StringRef> StripTemplateParameters(StringRef Name) {
142 // We are looking for template parameters to strip from Name. e.g.
143 //
144 // operator<<B>
145 //
146 // We look for > at the end but if it does not contain any < then we
147 // have something like operator>>. We check for the operator<=> case.
148 if (!Name.endswith(">") || Name.count("<") == 0 || Name.endswith("<=>"))
149 return {};
150
151 // How many < until we have the start of the template parameters.
152 size_t NumLeftAnglesToSkip = 1;
153
154 // If we have operator<=> then we need to skip its < as well.
155 NumLeftAnglesToSkip += Name.count("<=>");
156
157 size_t RightAngleCount = Name.count('>');
158 size_t LeftAngleCount = Name.count('<');
159
160 // If we have more < than > we have operator< or operator<<
161 // we to account for their < as well.
162 if (LeftAngleCount > RightAngleCount)
163 NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
164
165 size_t StartOfTemplate = 0;
166 while (NumLeftAnglesToSkip--)
167 StartOfTemplate = Name.find('<', StartOfTemplate) + 1;
168
169 return Name.substr(0, StartOfTemplate - 1);
170}
171
172bool DWARFLinker::DIECloner::getDIENames(const DWARFDie &Die,
173 AttributesInfo &Info,
174 OffsetsStringPool &StringPool,
175 bool StripTemplate) {
176 // This function will be called on DIEs having low_pcs and
177 // ranges. As getting the name might be more expansive, filter out
178 // blocks directly.
179 if (Die.getTag() == dwarf::DW_TAG_lexical_block)
180 return false;
181
182 if (!Info.MangledName)
183 if (const char *MangledName = Die.getLinkageName())
184 Info.MangledName = StringPool.getEntry(MangledName);
185
186 if (!Info.Name)
187 if (const char *Name = Die.getShortName())
188 Info.Name = StringPool.getEntry(Name);
189
190 if (!Info.MangledName)
191 Info.MangledName = Info.Name;
192
193 if (StripTemplate && Info.Name && Info.MangledName != Info.Name) {
194 StringRef Name = Info.Name.getString();
195 if (std::optional<StringRef> StrippedName = StripTemplateParameters(Name))
196 Info.NameWithoutTemplate = StringPool.getEntry(*StrippedName);
197 }
198
199 return Info.Name || Info.MangledName;
200}
201
202/// Resolve the relative path to a build artifact referenced by DWARF by
203/// applying DW_AT_comp_dir.
205 sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), ""));
206}
207
208/// Collect references to parseable Swift interfaces in imported
209/// DW_TAG_module blocks.
211 const DWARFDie &DIE, CompileUnit &CU,
212 swiftInterfacesMap *ParseableSwiftInterfaces,
213 std::function<void(const Twine &, const DWARFDie &)> ReportWarning) {
214 if (CU.getLanguage() != dwarf::DW_LANG_Swift)
215 return;
216
217 if (!ParseableSwiftInterfaces)
218 return;
219
220 StringRef Path = dwarf::toStringRef(DIE.find(dwarf::DW_AT_LLVM_include_path));
221 if (!Path.endswith(".swiftinterface"))
222 return;
223 // Don't track interfaces that are part of the SDK.
224 StringRef SysRoot = dwarf::toStringRef(DIE.find(dwarf::DW_AT_LLVM_sysroot));
225 if (SysRoot.empty())
226 SysRoot = CU.getSysRoot();
227 if (!SysRoot.empty() && Path.startswith(SysRoot))
228 return;
229 std::optional<const char *> Name =
230 dwarf::toString(DIE.find(dwarf::DW_AT_name));
231 if (!Name)
232 return;
233 auto &Entry = (*ParseableSwiftInterfaces)[*Name];
234 // The prepend path is applied later when copying.
235 DWARFDie CUDie = CU.getOrigUnit().getUnitDIE();
236 SmallString<128> ResolvedPath;
237 if (sys::path::is_relative(Path))
238 resolveRelativeObjectPath(ResolvedPath, CUDie);
239 sys::path::append(ResolvedPath, Path);
240 if (!Entry.empty() && Entry != ResolvedPath)
241 ReportWarning(Twine("Conflicting parseable interfaces for Swift Module ") +
242 *Name + ": " + Entry + " and " + Path,
243 DIE);
244 Entry = std::string(ResolvedPath.str());
245}
246
247/// The distinct types of work performed by the work loop in
248/// analyzeContextInfo.
249enum class ContextWorklistItemType : uint8_t {
253};
254
255/// This class represents an item in the work list. The type defines what kind
256/// of work needs to be performed when processing the current item. Everything
257/// but the Type and Die fields are optional based on the type.
260 unsigned ParentIdx;
261 union {
264 };
267
272
274 bool InImportedModule)
278};
279
280static bool updatePruning(const DWARFDie &Die, CompileUnit &CU,
281 uint64_t ModulesEndOffset) {
282 CompileUnit::DIEInfo &Info = CU.getInfo(Die);
283
284 // Prune this DIE if it is either a forward declaration inside a
285 // DW_TAG_module or a DW_TAG_module that contains nothing but
286 // forward declarations.
287 Info.Prune &= (Die.getTag() == dwarf::DW_TAG_module) ||
288 (isTypeTag(Die.getTag()) &&
289 dwarf::toUnsigned(Die.find(dwarf::DW_AT_declaration), 0));
290
291 // Only prune forward declarations inside a DW_TAG_module for which a
292 // definition exists elsewhere.
293 if (ModulesEndOffset == 0)
294 Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset();
295 else
296 Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset() > 0 &&
297 Info.Ctxt->getCanonicalDIEOffset() <= ModulesEndOffset;
298
299 return Info.Prune;
300}
301
302static void updateChildPruning(const DWARFDie &Die, CompileUnit &CU,
303 CompileUnit::DIEInfo &ChildInfo) {
304 CompileUnit::DIEInfo &Info = CU.getInfo(Die);
305 Info.Prune &= ChildInfo.Prune;
306}
307
308/// Recursive helper to build the global DeclContext information and
309/// gather the child->parent relationships in the original compile unit.
310///
311/// This function uses the same work list approach as lookForDIEsToKeep.
312///
313/// \return true when this DIE and all of its children are only
314/// forward declarations to types defined in external clang modules
315/// (i.e., forward declarations that are children of a DW_TAG_module).
317 const DWARFDie &DIE, unsigned ParentIdx, CompileUnit &CU,
318 DeclContext *CurrentDeclContext, DeclContextTree &Contexts,
319 uint64_t ModulesEndOffset, swiftInterfacesMap *ParseableSwiftInterfaces,
320 std::function<void(const Twine &, const DWARFDie &)> ReportWarning) {
321 // LIFO work list.
322 std::vector<ContextWorklistItem> Worklist;
323 Worklist.emplace_back(DIE, CurrentDeclContext, ParentIdx, false);
324
325 while (!Worklist.empty()) {
326 ContextWorklistItem Current = Worklist.back();
327 Worklist.pop_back();
328
329 switch (Current.Type) {
331 updatePruning(Current.Die, CU, ModulesEndOffset);
332 continue;
334 updateChildPruning(Current.Die, CU, *Current.OtherInfo);
335 continue;
337 break;
338 }
339
340 unsigned Idx = CU.getOrigUnit().getDIEIndex(Current.Die);
341 CompileUnit::DIEInfo &Info = CU.getInfo(Idx);
342
343 // Clang imposes an ODR on modules(!) regardless of the language:
344 // "The module-id should consist of only a single identifier,
345 // which provides the name of the module being defined. Each
346 // module shall have a single definition."
347 //
348 // This does not extend to the types inside the modules:
349 // "[I]n C, this implies that if two structs are defined in
350 // different submodules with the same name, those two types are
351 // distinct types (but may be compatible types if their
352 // definitions match)."
353 //
354 // We treat non-C++ modules like namespaces for this reason.
355 if (Current.Die.getTag() == dwarf::DW_TAG_module &&
356 Current.ParentIdx == 0 &&
357 dwarf::toString(Current.Die.find(dwarf::DW_AT_name), "") !=
358 CU.getClangModuleName()) {
359 Current.InImportedModule = true;
360 analyzeImportedModule(Current.Die, CU, ParseableSwiftInterfaces,
361 ReportWarning);
362 }
363
364 Info.ParentIdx = Current.ParentIdx;
365 Info.InModuleScope = CU.isClangModule() || Current.InImportedModule;
366 if (CU.hasODR() || Info.InModuleScope) {
367 if (Current.Context) {
368 auto PtrInvalidPair = Contexts.getChildDeclContext(
369 *Current.Context, Current.Die, CU, Info.InModuleScope);
370 Current.Context = PtrInvalidPair.getPointer();
371 Info.Ctxt =
372 PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();
373 if (Info.Ctxt)
374 Info.Ctxt->setDefinedInClangModule(Info.InModuleScope);
375 } else
376 Info.Ctxt = Current.Context = nullptr;
377 }
378
379 Info.Prune = Current.InImportedModule;
380 // Add children in reverse order to the worklist to effectively process
381 // them in order.
382 Worklist.emplace_back(Current.Die, ContextWorklistItemType::UpdatePruning);
383 for (auto Child : reverse(Current.Die.children())) {
384 CompileUnit::DIEInfo &ChildInfo = CU.getInfo(Child);
385 Worklist.emplace_back(
387 Worklist.emplace_back(Child, Current.Context, Idx,
388 Current.InImportedModule);
389 }
390 }
391}
392
394 switch (Tag) {
395 default:
396 return false;
397 case dwarf::DW_TAG_class_type:
398 case dwarf::DW_TAG_common_block:
399 case dwarf::DW_TAG_lexical_block:
400 case dwarf::DW_TAG_structure_type:
401 case dwarf::DW_TAG_subprogram:
402 case dwarf::DW_TAG_subroutine_type:
403 case dwarf::DW_TAG_union_type:
404 return true;
405 }
406 llvm_unreachable("Invalid Tag");
407}
408
409void DWARFLinker::cleanupAuxiliarryData(LinkContext &Context) {
410 Context.clear();
411
412 for (DIEBlock *I : DIEBlocks)
413 I->~DIEBlock();
414 for (DIELoc *I : DIELocs)
415 I->~DIELoc();
416
417 DIEBlocks.clear();
418 DIELocs.clear();
419 DIEAlloc.Reset();
420}
421
422/// Check if a variable describing DIE should be kept.
423/// \returns updated TraversalFlags.
424unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
425 const DWARFDie &DIE,
426 CompileUnit::DIEInfo &MyInfo,
427 unsigned Flags) {
428 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
429
430 // Global variables with constant value can always be kept.
431 if (!(Flags & TF_InFunctionScope) &&
432 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
433 MyInfo.InDebugMap = true;
434 return Flags | TF_Keep;
435 }
436
437 // See if there is a relocation to a valid debug map entry inside this
438 // variable's location. The order is important here. We want to always check
439 // if the variable has a valid relocation, so that the DIEInfo is filled.
440 // However, we don't want a static variable in a function to force us to keep
441 // the enclosing function, unless requested explicitly.
442 const bool HasLiveMemoryLocation = RelocMgr.isLiveVariable(DIE, MyInfo);
443 if (!HasLiveMemoryLocation || ((Flags & TF_InFunctionScope) &&
444 !LLVM_UNLIKELY(Options.KeepFunctionForStatic)))
445 return Flags;
446
447 if (Options.Verbose) {
448 outs() << "Keeping variable DIE:";
449 DIDumpOptions DumpOpts;
450 DumpOpts.ChildRecurseDepth = 0;
451 DumpOpts.Verbose = Options.Verbose;
452 DIE.dump(outs(), 8 /* Indent */, DumpOpts);
453 }
454
455 return Flags | TF_Keep;
456}
457
458/// Check if a function describing DIE should be kept.
459/// \returns updated TraversalFlags.
460unsigned DWARFLinker::shouldKeepSubprogramDIE(
461 AddressesMap &RelocMgr, RangesTy &Ranges, const DWARFDie &DIE,
462 const DWARFFile &File, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
463 unsigned Flags) {
464 Flags |= TF_InFunctionScope;
465
466 auto LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc));
467 if (!LowPc)
468 return Flags;
469
470 assert(LowPc && "low_pc attribute is not an address.");
471 if (!RelocMgr.isLiveSubprogram(DIE, MyInfo))
472 return Flags;
473
474 if (Options.Verbose) {
475 outs() << "Keeping subprogram DIE:";
476 DIDumpOptions DumpOpts;
477 DumpOpts.ChildRecurseDepth = 0;
478 DumpOpts.Verbose = Options.Verbose;
479 DIE.dump(outs(), 8 /* Indent */, DumpOpts);
480 }
481
482 if (DIE.getTag() == dwarf::DW_TAG_label) {
483 if (Unit.hasLabelAt(*LowPc))
484 return Flags;
485
486 DWARFUnit &OrigUnit = Unit.getOrigUnit();
487 // FIXME: dsymutil-classic compat. dsymutil-classic doesn't consider labels
488 // that don't fall into the CU's aranges. This is wrong IMO. Debug info
489 // generation bugs aside, this is really wrong in the case of labels, where
490 // a label marking the end of a function will have a PC == CU's high_pc.
491 if (dwarf::toAddress(OrigUnit.getUnitDIE().find(dwarf::DW_AT_high_pc))
492 .value_or(UINT64_MAX) <= LowPc)
493 return Flags;
494 Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust);
495 return Flags | TF_Keep;
496 }
497
498 Flags |= TF_Keep;
499
500 std::optional<uint64_t> HighPc = DIE.getHighPC(*LowPc);
501 if (!HighPc) {
502 reportWarning("Function without high_pc. Range will be discarded.\n", File,
503 &DIE);
504 return Flags;
505 }
506 if (*LowPc > *HighPc) {
507 reportWarning("low_pc greater than high_pc. Range will be discarded.\n",
508 File, &DIE);
509 return Flags;
510 }
511
512 // Replace the debug map range with a more accurate one.
513 Ranges.insert({*LowPc, *HighPc}, MyInfo.AddrAdjust);
514 Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust);
515 return Flags;
516}
517
518/// Check if a DIE should be kept.
519/// \returns updated TraversalFlags.
520unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr, RangesTy &Ranges,
521 const DWARFDie &DIE, const DWARFFile &File,
522 CompileUnit &Unit,
523 CompileUnit::DIEInfo &MyInfo,
524 unsigned Flags) {
525 switch (DIE.getTag()) {
526 case dwarf::DW_TAG_constant:
527 case dwarf::DW_TAG_variable:
528 return shouldKeepVariableDIE(RelocMgr, DIE, MyInfo, Flags);
529 case dwarf::DW_TAG_subprogram:
530 case dwarf::DW_TAG_label:
531 return shouldKeepSubprogramDIE(RelocMgr, Ranges, DIE, File, Unit, MyInfo,
532 Flags);
533 case dwarf::DW_TAG_base_type:
534 // DWARF Expressions may reference basic types, but scanning them
535 // is expensive. Basic types are tiny, so just keep all of them.
536 case dwarf::DW_TAG_imported_module:
537 case dwarf::DW_TAG_imported_declaration:
538 case dwarf::DW_TAG_imported_unit:
539 // We always want to keep these.
540 return Flags | TF_Keep;
541 default:
542 break;
543 }
544
545 return Flags;
546}
547
548/// Helper that updates the completeness of the current DIE based on the
549/// completeness of one of its children. It depends on the incompleteness of
550/// the children already being computed.
552 CompileUnit::DIEInfo &ChildInfo) {
553 switch (Die.getTag()) {
554 case dwarf::DW_TAG_structure_type:
555 case dwarf::DW_TAG_class_type:
556 case dwarf::DW_TAG_union_type:
557 break;
558 default:
559 return;
560 }
561
562 CompileUnit::DIEInfo &MyInfo = CU.getInfo(Die);
563
564 if (ChildInfo.Incomplete || ChildInfo.Prune)
565 MyInfo.Incomplete = true;
566}
567
568/// Helper that updates the completeness of the current DIE based on the
569/// completeness of the DIEs it references. It depends on the incompleteness of
570/// the referenced DIE already being computed.
572 CompileUnit::DIEInfo &RefInfo) {
573 switch (Die.getTag()) {
574 case dwarf::DW_TAG_typedef:
575 case dwarf::DW_TAG_member:
576 case dwarf::DW_TAG_reference_type:
577 case dwarf::DW_TAG_ptr_to_member_type:
578 case dwarf::DW_TAG_pointer_type:
579 break;
580 default:
581 return;
582 }
583
584 CompileUnit::DIEInfo &MyInfo = CU.getInfo(Die);
585
586 if (MyInfo.Incomplete)
587 return;
588
589 if (RefInfo.Incomplete)
590 MyInfo.Incomplete = true;
591}
592
593/// Look at the children of the given DIE and decide whether they should be
594/// kept.
595void DWARFLinker::lookForChildDIEsToKeep(
596 const DWARFDie &Die, CompileUnit &CU, unsigned Flags,
597 SmallVectorImpl<WorklistItem> &Worklist) {
598 // The TF_ParentWalk flag tells us that we are currently walking up the
599 // parent chain of a required DIE, and we don't want to mark all the children
600 // of the parents as kept (consider for example a DW_TAG_namespace node in
601 // the parent chain). There are however a set of DIE types for which we want
602 // to ignore that directive and still walk their children.
603 if (dieNeedsChildrenToBeMeaningful(Die.getTag()))
604 Flags &= ~DWARFLinker::TF_ParentWalk;
605
606 // We're finished if this DIE has no children or we're walking the parent
607 // chain.
608 if (!Die.hasChildren() || (Flags & DWARFLinker::TF_ParentWalk))
609 return;
610
611 // Add children in reverse order to the worklist to effectively process them
612 // in order.
613 for (auto Child : reverse(Die.children())) {
614 // Add a worklist item before every child to calculate incompleteness right
615 // after the current child is processed.
616 CompileUnit::DIEInfo &ChildInfo = CU.getInfo(Child);
617 Worklist.emplace_back(Die, CU, WorklistItemType::UpdateChildIncompleteness,
618 &ChildInfo);
619 Worklist.emplace_back(Child, CU, Flags);
620 }
621}
622
624 CompileUnit::DIEInfo &Info = CU.getInfo(Die);
625
626 if (!Info.Ctxt || (Die.getTag() == dwarf::DW_TAG_namespace))
627 return false;
628
629 if (!CU.hasODR() && !Info.InModuleScope)
630 return false;
631
632 return !Info.Incomplete && Info.Ctxt != CU.getInfo(Info.ParentIdx).Ctxt;
633}
634
635void DWARFLinker::markODRCanonicalDie(const DWARFDie &Die, CompileUnit &CU) {
636 CompileUnit::DIEInfo &Info = CU.getInfo(Die);
637
638 Info.ODRMarkingDone = true;
639 if (Info.Keep && isODRCanonicalCandidate(Die, CU) &&
640 !Info.Ctxt->hasCanonicalDIE())
641 Info.Ctxt->setHasCanonicalDIE();
642}
643
644/// Look at DIEs referenced by the given DIE and decide whether they should be
645/// kept. All DIEs referenced though attributes should be kept.
646void DWARFLinker::lookForRefDIEsToKeep(
647 const DWARFDie &Die, CompileUnit &CU, unsigned Flags,
648 const UnitListTy &Units, const DWARFFile &File,
649 SmallVectorImpl<WorklistItem> &Worklist) {
650 bool UseOdr = (Flags & DWARFLinker::TF_DependencyWalk)
651 ? (Flags & DWARFLinker::TF_ODR)
652 : CU.hasODR();
653 DWARFUnit &Unit = CU.getOrigUnit();
654 DWARFDataExtractor Data = Unit.getDebugInfoExtractor();
655 const auto *Abbrev = Die.getAbbreviationDeclarationPtr();
656 uint64_t Offset = Die.getOffset() + getULEB128Size(Abbrev->getCode());
657
658 SmallVector<std::pair<DWARFDie, CompileUnit &>, 4> ReferencedDIEs;
659 for (const auto &AttrSpec : Abbrev->attributes()) {
660 DWARFFormValue Val(AttrSpec.Form);
661 if (!Val.isFormClass(DWARFFormValue::FC_Reference) ||
662 AttrSpec.Attr == dwarf::DW_AT_sibling) {
663 DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
664 Unit.getFormParams());
665 continue;
666 }
667
668 Val.extractValue(Data, &Offset, Unit.getFormParams(), &Unit);
669 CompileUnit *ReferencedCU;
670 if (auto RefDie =
671 resolveDIEReference(File, Units, Val, Die, ReferencedCU)) {
672 CompileUnit::DIEInfo &Info = ReferencedCU->getInfo(RefDie);
673 // If the referenced DIE has a DeclContext that has already been
674 // emitted, then do not keep the one in this CU. We'll link to
675 // the canonical DIE in cloneDieReferenceAttribute.
676 //
677 // FIXME: compatibility with dsymutil-classic. UseODR shouldn't
678 // be necessary and could be advantageously replaced by
679 // ReferencedCU->hasODR() && CU.hasODR().
680 //
681 // FIXME: compatibility with dsymutil-classic. There is no
682 // reason not to unique ref_addr references.
683 if (AttrSpec.Form != dwarf::DW_FORM_ref_addr &&
684 isODRAttribute(AttrSpec.Attr) && Info.Ctxt &&
685 Info.Ctxt->hasCanonicalDIE())
686 continue;
687
688 // Keep a module forward declaration if there is no definition.
689 if (!(isODRAttribute(AttrSpec.Attr) && Info.Ctxt &&
690 Info.Ctxt->hasCanonicalDIE()))
691 Info.Prune = false;
692 ReferencedDIEs.emplace_back(RefDie, *ReferencedCU);
693 }
694 }
695
696 unsigned ODRFlag = UseOdr ? DWARFLinker::TF_ODR : 0;
697
698 // Add referenced DIEs in reverse order to the worklist to effectively
699 // process them in order.
700 for (auto &P : reverse(ReferencedDIEs)) {
701 // Add a worklist item before every child to calculate incompleteness right
702 // after the current child is processed.
703 CompileUnit::DIEInfo &Info = P.second.getInfo(P.first);
704 Worklist.emplace_back(Die, CU, WorklistItemType::UpdateRefIncompleteness,
705 &Info);
706 Worklist.emplace_back(P.first, P.second,
707 DWARFLinker::TF_Keep |
708 DWARFLinker::TF_DependencyWalk | ODRFlag);
709 }
710}
711
712/// Look at the parent of the given DIE and decide whether they should be kept.
713void DWARFLinker::lookForParentDIEsToKeep(
714 unsigned AncestorIdx, CompileUnit &CU, unsigned Flags,
715 SmallVectorImpl<WorklistItem> &Worklist) {
716 // Stop if we encounter an ancestor that's already marked as kept.
717 if (CU.getInfo(AncestorIdx).Keep)
718 return;
719
720 DWARFUnit &Unit = CU.getOrigUnit();
721 DWARFDie ParentDIE = Unit.getDIEAtIndex(AncestorIdx);
722 Worklist.emplace_back(CU.getInfo(AncestorIdx).ParentIdx, CU, Flags);
723 Worklist.emplace_back(ParentDIE, CU, Flags);
724}
725
726/// Recursively walk the \p DIE tree and look for DIEs to keep. Store that
727/// information in \p CU's DIEInfo.
728///
729/// This function is the entry point of the DIE selection algorithm. It is
730/// expected to walk the DIE tree in file order and (though the mediation of
731/// its helper) call hasValidRelocation() on each DIE that might be a 'root
732/// DIE' (See DwarfLinker class comment).
733///
734/// While walking the dependencies of root DIEs, this function is also called,
735/// but during these dependency walks the file order is not respected. The
736/// TF_DependencyWalk flag tells us which kind of traversal we are currently
737/// doing.
738///
739/// The recursive algorithm is implemented iteratively as a work list because
740/// very deep recursion could exhaust the stack for large projects. The work
741/// list acts as a scheduler for different types of work that need to be
742/// performed.
743///
744/// The recursive nature of the algorithm is simulated by running the "main"
745/// algorithm (LookForDIEsToKeep) followed by either looking at more DIEs
746/// (LookForChildDIEsToKeep, LookForRefDIEsToKeep, LookForParentDIEsToKeep) or
747/// fixing up a computed property (UpdateChildIncompleteness,
748/// UpdateRefIncompleteness).
749///
750/// The return value indicates whether the DIE is incomplete.
751void DWARFLinker::lookForDIEsToKeep(AddressesMap &AddressesMap,
752 RangesTy &Ranges, const UnitListTy &Units,
753 const DWARFDie &Die, const DWARFFile &File,
754 CompileUnit &Cu, unsigned Flags) {
755 // LIFO work list.
756 SmallVector<WorklistItem, 4> Worklist;
757 Worklist.emplace_back(Die, Cu, Flags);
758
759 while (!Worklist.empty()) {
760 WorklistItem Current = Worklist.pop_back_val();
761
762 // Look at the worklist type to decide what kind of work to perform.
763 switch (Current.Type) {
764 case WorklistItemType::UpdateChildIncompleteness:
765 updateChildIncompleteness(Current.Die, Current.CU, *Current.OtherInfo);
766 continue;
767 case WorklistItemType::UpdateRefIncompleteness:
768 updateRefIncompleteness(Current.Die, Current.CU, *Current.OtherInfo);
769 continue;
770 case WorklistItemType::LookForChildDIEsToKeep:
771 lookForChildDIEsToKeep(Current.Die, Current.CU, Current.Flags, Worklist);
772 continue;
773 case WorklistItemType::LookForRefDIEsToKeep:
774 lookForRefDIEsToKeep(Current.Die, Current.CU, Current.Flags, Units, File,
775 Worklist);
776 continue;
777 case WorklistItemType::LookForParentDIEsToKeep:
778 lookForParentDIEsToKeep(Current.AncestorIdx, Current.CU, Current.Flags,
779 Worklist);
780 continue;
781 case WorklistItemType::MarkODRCanonicalDie:
782 markODRCanonicalDie(Current.Die, Current.CU);
783 continue;
784 case WorklistItemType::LookForDIEsToKeep:
785 break;
786 }
787
788 unsigned Idx = Current.CU.getOrigUnit().getDIEIndex(Current.Die);
789 CompileUnit::DIEInfo &MyInfo = Current.CU.getInfo(Idx);
790
791 if (MyInfo.Prune) {
792 // We're walking the dependencies of a module forward declaration that was
793 // kept because there is no definition.
794 if (Current.Flags & TF_DependencyWalk)
795 MyInfo.Prune = false;
796 else
797 continue;
798 }
799
800 // If the Keep flag is set, we are marking a required DIE's dependencies.
801 // If our target is already marked as kept, we're all set.
802 bool AlreadyKept = MyInfo.Keep;
803 if ((Current.Flags & TF_DependencyWalk) && AlreadyKept)
804 continue;
805
806 // We must not call shouldKeepDIE while called from keepDIEAndDependencies,
807 // because it would screw up the relocation finding logic.
808 if (!(Current.Flags & TF_DependencyWalk))
809 Current.Flags = shouldKeepDIE(AddressesMap, Ranges, Current.Die, File,
810 Current.CU, MyInfo, Current.Flags);
811
812 // We need to mark context for the canonical die in the end of normal
813 // traversing(not TF_DependencyWalk) or after normal traversing if die
814 // was not marked as kept.
815 if (!(Current.Flags & TF_DependencyWalk) ||
816 (MyInfo.ODRMarkingDone && !MyInfo.Keep)) {
817 if (Current.CU.hasODR() || MyInfo.InModuleScope)
818 Worklist.emplace_back(Current.Die, Current.CU,
819 WorklistItemType::MarkODRCanonicalDie);
820 }
821
822 // Finish by looking for child DIEs. Because of the LIFO worklist we need
823 // to schedule that work before any subsequent items are added to the
824 // worklist.
825 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
826 WorklistItemType::LookForChildDIEsToKeep);
827
828 if (AlreadyKept || !(Current.Flags & TF_Keep))
829 continue;
830
831 // If it is a newly kept DIE mark it as well as all its dependencies as
832 // kept.
833 MyInfo.Keep = true;
834
835 // We're looking for incomplete types.
836 MyInfo.Incomplete =
837 Current.Die.getTag() != dwarf::DW_TAG_subprogram &&
838 Current.Die.getTag() != dwarf::DW_TAG_member &&
839 dwarf::toUnsigned(Current.Die.find(dwarf::DW_AT_declaration), 0);
840
841 // After looking at the parent chain, look for referenced DIEs. Because of
842 // the LIFO worklist we need to schedule that work before any subsequent
843 // items are added to the worklist.
844 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
845 WorklistItemType::LookForRefDIEsToKeep);
846
847 bool UseOdr = (Current.Flags & TF_DependencyWalk) ? (Current.Flags & TF_ODR)
848 : Current.CU.hasODR();
849 unsigned ODRFlag = UseOdr ? TF_ODR : 0;
850 unsigned ParFlags = TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag;
851
852 // Now schedule the parent walk.
853 Worklist.emplace_back(MyInfo.ParentIdx, Current.CU, ParFlags);
854 }
855}
856
857#ifndef NDEBUG
858/// A broken link in the keep chain. By recording both the parent and the child
859/// we can show only broken links for DIEs with multiple children.
864};
865
866/// Verify the keep chain by looking for DIEs that are kept but who's parent
867/// isn't.
869 std::vector<DWARFDie> Worklist;
870 Worklist.push_back(CU.getOrigUnit().getUnitDIE());
871
872 // List of broken links.
873 std::vector<BrokenLink> BrokenLinks;
874
875 while (!Worklist.empty()) {
876 const DWARFDie Current = Worklist.back();
877 Worklist.pop_back();
878
879 const bool CurrentDieIsKept = CU.getInfo(Current).Keep;
880
881 for (DWARFDie Child : reverse(Current.children())) {
882 Worklist.push_back(Child);
883
884 const bool ChildDieIsKept = CU.getInfo(Child).Keep;
885 if (!CurrentDieIsKept && ChildDieIsKept)
886 BrokenLinks.emplace_back(Current, Child);
887 }
888 }
889
890 if (!BrokenLinks.empty()) {
891 for (BrokenLink Link : BrokenLinks) {
893 "Found invalid link in keep chain between {0:x} and {1:x}\n",
894 Link.Parent.getOffset(), Link.Child.getOffset());
895
896 errs() << "Parent:";
897 Link.Parent.dump(errs(), 0, {});
898 CU.getInfo(Link.Parent).dump();
899
900 errs() << "Child:";
901 Link.Child.dump(errs(), 2, {});
902 CU.getInfo(Link.Child).dump();
903 }
904 report_fatal_error("invalid keep chain");
905 }
906}
907#endif
908
909/// Assign an abbreviation number to \p Abbrev.
910///
911/// Our DIEs get freed after every DebugMapObject has been processed,
912/// thus the FoldingSet we use to unique DIEAbbrevs cannot refer to
913/// the instances hold by the DIEs. When we encounter an abbreviation
914/// that we don't know, we create a permanent copy of it.
915void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) {
916 // Check the set for priors.
917 FoldingSetNodeID ID;
918 Abbrev.Profile(ID);
919 void *InsertToken;
920 DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken);
921
922 // If it's newly added.
923 if (InSet) {
924 // Assign existing abbreviation number.
925 Abbrev.setNumber(InSet->getNumber());
926 } else {
927 // Add to abbreviation list.
928 Abbreviations.push_back(
929 std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
930 for (const auto &Attr : Abbrev.getData())
931 Abbreviations.back()->AddAttribute(Attr);
932 AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
933 // Assign the unique abbreviation number.
934 Abbrev.setNumber(Abbreviations.size());
935 Abbreviations.back()->setNumber(Abbreviations.size());
936 }
937}
938
939unsigned DWARFLinker::DIECloner::cloneStringAttribute(
940 DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val,
941 const DWARFUnit &, OffsetsStringPool &StringPool, AttributesInfo &Info) {
942 std::optional<const char *> String = dwarf::toString(Val);
943 if (!String)
944 return 0;
945
946 // Switch everything to out of line strings.
947 auto StringEntry = StringPool.getEntry(*String);
948
949 // Update attributes info.
950 if (AttrSpec.Attr == dwarf::DW_AT_name)
951 Info.Name = StringEntry;
952 else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
953 AttrSpec.Attr == dwarf::DW_AT_linkage_name)
954 Info.MangledName = StringEntry;
955
956 Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_strp,
957 DIEInteger(StringEntry.getOffset()));
958
959 return 4;
960}
961
962unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute(
963 DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec,
964 unsigned AttrSize, const DWARFFormValue &Val, const DWARFFile &File,
965 CompileUnit &Unit) {
966 const DWARFUnit &U = Unit.getOrigUnit();
967 uint64_t Ref = *Val.getAsReference();
968
969 DIE *NewRefDie = nullptr;
970 CompileUnit *RefUnit = nullptr;
971
972 DWARFDie RefDie =
973 Linker.resolveDIEReference(File, CompileUnits, Val, InputDIE, RefUnit);
974
975 // If the referenced DIE is not found, drop the attribute.
976 if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling)
977 return 0;
978
979 CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(RefDie);
980
981 // If we already have emitted an equivalent DeclContext, just point
982 // at it.
983 if (isODRAttribute(AttrSpec.Attr) && RefInfo.Ctxt &&
984 RefInfo.Ctxt->getCanonicalDIEOffset()) {
985 assert(RefInfo.Ctxt->hasCanonicalDIE() &&
986 "Offset to canonical die is set, but context is not marked");
987 DIEInteger Attr(RefInfo.Ctxt->getCanonicalDIEOffset());
988 Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
989 dwarf::DW_FORM_ref_addr, Attr);
990 return U.getRefAddrByteSize();
991 }
992
993 if (!RefInfo.Clone) {
994 // We haven't cloned this DIE yet. Just create an empty one and
995 // store it. It'll get really cloned when we process it.
996 RefInfo.UnclonedReference = true;
997 RefInfo.Clone = DIE::get(DIEAlloc, dwarf::Tag(RefDie.getTag()));
998 }
999 NewRefDie = RefInfo.Clone;
1000
1001 if (AttrSpec.Form == dwarf::DW_FORM_ref_addr ||
1002 (Unit.hasODR() && isODRAttribute(AttrSpec.Attr))) {
1003 // We cannot currently rely on a DIEEntry to emit ref_addr
1004 // references, because the implementation calls back to DwarfDebug
1005 // to find the unit offset. (We don't have a DwarfDebug)
1006 // FIXME: we should be able to design DIEEntry reliance on
1007 // DwarfDebug away.
1008 uint64_t Attr;
1009 if (Ref < InputDIE.getOffset() && !RefInfo.UnclonedReference) {
1010 // We have already cloned that DIE.
1011 uint32_t NewRefOffset =
1012 RefUnit->getStartOffset() + NewRefDie->getOffset();
1013 Attr = NewRefOffset;
1014 Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
1015 dwarf::DW_FORM_ref_addr, DIEInteger(Attr));
1016 } else {
1017 // A forward reference. Note and fixup later.
1018 Attr = 0xBADDEF;
1019 Unit.noteForwardReference(
1020 NewRefDie, RefUnit, RefInfo.Ctxt,
1021 Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
1022 dwarf::DW_FORM_ref_addr, DIEInteger(Attr)));
1023 }
1024 return U.getRefAddrByteSize();
1025 }
1026
1027 Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
1028 dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie));
1029
1030 return AttrSize;
1031}
1032
1033void DWARFLinker::DIECloner::cloneExpression(
1034 DataExtractor &Data, DWARFExpression Expression, const DWARFFile &File,
1035 CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer) {
1036 using Encoding = DWARFExpression::Operation::Encoding;
1037
1038 uint64_t OpOffset = 0;
1039 for (auto &Op : Expression) {
1040 auto Description = Op.getDescription();
1041 // DW_OP_const_type is variable-length and has 3
1042 // operands. DWARFExpression thus far only supports 2.
1043 auto Op0 = Description.Op[0];
1044 auto Op1 = Description.Op[1];
1045 if ((Op0 == Encoding::BaseTypeRef && Op1 != Encoding::SizeNA) ||
1046 (Op1 == Encoding::BaseTypeRef && Op0 != Encoding::Size1))
1047 Linker.reportWarning("Unsupported DW_OP encoding.", File);
1048
1049 if ((Op0 == Encoding::BaseTypeRef && Op1 == Encoding::SizeNA) ||
1050 (Op1 == Encoding::BaseTypeRef && Op0 == Encoding::Size1)) {
1051 // This code assumes that the other non-typeref operand fits into 1 byte.
1052 assert(OpOffset < Op.getEndOffset());
1053 uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1;
1054 assert(ULEBsize <= 16);
1055
1056 // Copy over the operation.
1057 OutputBuffer.push_back(Op.getCode());
1058 uint64_t RefOffset;
1059 if (Op1 == Encoding::SizeNA) {
1060 RefOffset = Op.getRawOperand(0);
1061 } else {
1062 OutputBuffer.push_back(Op.getRawOperand(0));
1063 RefOffset = Op.getRawOperand(1);
1064 }
1065 uint32_t Offset = 0;
1066 // Look up the base type. For DW_OP_convert, the operand may be 0 to
1067 // instead indicate the generic type. The same holds for
1068 // DW_OP_reinterpret, which is currently not supported.
1069 if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) {
1070 RefOffset += Unit.getOrigUnit().getOffset();
1071 auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset);
1072 CompileUnit::DIEInfo &Info = Unit.getInfo(RefDie);
1073 if (DIE *Clone = Info.Clone)
1074 Offset = Clone->getOffset();
1075 else
1076 Linker.reportWarning(
1077 "base type ref doesn't point to DW_TAG_base_type.", File);
1078 }
1079 uint8_t ULEB[16];
1080 unsigned RealSize = encodeULEB128(Offset, ULEB, ULEBsize);
1081 if (RealSize > ULEBsize) {
1082 // Emit the generic type as a fallback.
1083 RealSize = encodeULEB128(0, ULEB, ULEBsize);
1084 Linker.reportWarning("base type ref doesn't fit.", File);
1085 }
1086 assert(RealSize == ULEBsize && "padding failed");
1087 ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
1088 OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
1089 } else {
1090 // Copy over everything else unmodified.
1091 StringRef Bytes = Data.getData().slice(OpOffset, Op.getEndOffset());
1092 OutputBuffer.append(Bytes.begin(), Bytes.end());
1093 }
1094 OpOffset = Op.getEndOffset();
1095 }
1096}
1097
1098unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
1099 DIE &Die, const DWARFFile &File, CompileUnit &Unit, AttributeSpec AttrSpec,
1100 const DWARFFormValue &Val, unsigned AttrSize, bool IsLittleEndian) {
1101 DIEValueList *Attr;
1102 DIEValue Value;
1103 DIELoc *Loc = nullptr;
1104 DIEBlock *Block = nullptr;
1105 if (AttrSpec.Form == dwarf::DW_FORM_exprloc) {
1106 Loc = new (DIEAlloc) DIELoc;
1107 Linker.DIELocs.push_back(Loc);
1108 } else {
1109 Block = new (DIEAlloc) DIEBlock;
1110 Linker.DIEBlocks.push_back(Block);
1111 }
1112 Attr = Loc ? static_cast<DIEValueList *>(Loc)
1113 : static_cast<DIEValueList *>(Block);
1114
1115 if (Loc)
1116 Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
1117 dwarf::Form(AttrSpec.Form), Loc);
1118 else
1119 Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
1120 dwarf::Form(AttrSpec.Form), Block);
1121
1122 // If the block is a DWARF Expression, clone it into the temporary
1123 // buffer using cloneExpression(), otherwise copy the data directly.
1124 SmallVector<uint8_t, 32> Buffer;
1125 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
1126 if (DWARFAttribute::mayHaveLocationExpr(AttrSpec.Attr) &&
1127 (Val.isFormClass(DWARFFormValue::FC_Block) ||
1128 Val.isFormClass(DWARFFormValue::FC_Exprloc))) {
1129 DWARFUnit &OrigUnit = Unit.getOrigUnit();
1130 DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()),
1131 IsLittleEndian, OrigUnit.getAddressByteSize());
1132 DWARFExpression Expr(Data, OrigUnit.getAddressByteSize(),
1133 OrigUnit.getFormParams().Format);
1134 cloneExpression(Data, Expr, File, Unit, Buffer);
1135 Bytes = Buffer;
1136 }
1137 for (auto Byte : Bytes)
1138 Attr->addValue(DIEAlloc, static_cast<dwarf::Attribute>(0),
1139 dwarf::DW_FORM_data1, DIEInteger(Byte));
1140
1141 // FIXME: If DIEBlock and DIELoc just reuses the Size field of
1142 // the DIE class, this "if" could be replaced by
1143 // Attr->setSize(Bytes.size()).
1144 if (Loc)
1145 Loc->setSize(Bytes.size());
1146 else
1147 Block->setSize(Bytes.size());
1148
1149 Die.addValue(DIEAlloc, Value);
1150 return AttrSize;
1151}
1152
1153unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
1154 DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1155 unsigned AttrSize, const DWARFFormValue &Val, const CompileUnit &Unit,
1156 AttributesInfo &Info) {
1157 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
1158 Info.HasLowPc = true;
1159
1160 if (LLVM_UNLIKELY(Linker.Options.Update)) {
1161 Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
1162 dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));
1163 return AttrSize;
1164 }
1165
1166 // Cloned Die may have address attributes relocated to a
1167 // totally unrelated value. This can happen:
1168 // - If high_pc is an address (Dwarf version == 2), then it might have been
1169 // relocated to a totally unrelated value (because the end address in the
1170 // object file might be start address of another function which got moved
1171 // independently by the linker).
1172 // - If address relocated in an inline_subprogram that happens at the
1173 // beginning of its inlining function.
1174 // To avoid above cases and to not apply relocation twice (in applyValidRelocs
1175 // and here), read address attribute from InputDIE and apply Info.PCOffset
1176 // here.
1177
1178 std::optional<DWARFFormValue> AddrAttribute = InputDIE.find(AttrSpec.Attr);
1179 if (!AddrAttribute)
1180 llvm_unreachable("Cann't find attribute.");
1181
1182 std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();
1183 if (!Addr) {
1184 Linker.reportWarning("Cann't read address attribute value.", ObjFile);
1185 Addr = 0;
1186 }
1187
1188 if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1189 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
1190 if (std::optional<uint64_t> LowPC = Unit.getLowPc())
1191 Addr = *LowPC;
1192 else
1193 return 0;
1194 } else if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1195 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
1196 if (uint64_t HighPc = Unit.getHighPc())
1197 Addr = HighPc;
1198 else
1199 return 0;
1200 } else {
1201 *Addr += Info.PCOffset;
1202 }
1203
1204 switch (AttrSpec.Form) {
1205 case dwarf::DW_FORM_addrx:
1206 case dwarf::DW_FORM_addrx1:
1207 case dwarf::DW_FORM_addrx2:
1208 case dwarf::DW_FORM_addrx3:
1209 case dwarf::DW_FORM_addrx4: {
1210 // DWARFLinker does not use addrx forms since it generates relocated
1211 // addresses. Replace DW_FORM_addrx* with DW_FORM_addr here.
1212 AttrSpec.Form = dwarf::DW_FORM_addr;
1213 break;
1214 }
1215 default:
1216 // Nothing to do.
1217 break;
1218 }
1219
1220 Die.addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr),
1221 AttrSpec.Form, DIEInteger(*Addr));
1222 return Unit.getOrigUnit().getAddressByteSize();
1223}
1224
1225unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
1226 DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File,
1227 CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val,
1228 unsigned AttrSize, AttributesInfo &Info) {
1230
1231 // Check for the offset to the macro table. If offset is incorrect then we
1232 // need to remove the attribute.
1233 if (AttrSpec.Attr == dwarf::DW_AT_macro_info) {
1234 if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
1235 const DWARFDebugMacro *Macro = File.Dwarf->getDebugMacinfo();
1236 if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))
1237 return 0;
1238 }
1239 }
1240
1241 if (AttrSpec.Attr == dwarf::DW_AT_macros) {
1242 if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
1243 const DWARFDebugMacro *Macro = File.Dwarf->getDebugMacro();
1244 if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))
1245 return 0;
1246 }
1247 }
1248
1249 if (LLVM_UNLIKELY(Linker.Options.Update)) {
1250 if (auto OptionalValue = Val.getAsUnsignedConstant())
1251 Value = *OptionalValue;
1252 else if (auto OptionalValue = Val.getAsSignedConstant())
1253 Value = *OptionalValue;
1254 else if (auto OptionalValue = Val.getAsSectionOffset())
1255 Value = *OptionalValue;
1256 else {
1257 Linker.reportWarning(
1258 "Unsupported scalar attribute form. Dropping attribute.", File,
1259 &InputDIE);
1260 return 0;
1261 }
1262 if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
1263 Info.IsDeclaration = true;
1264
1265 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
1266 Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
1267 dwarf::Form(AttrSpec.Form), DIELocList(Value));
1268 else
1269 Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
1270 dwarf::Form(AttrSpec.Form), DIEInteger(Value));
1271 return AttrSize;
1272 }
1273
1274 [[maybe_unused]] dwarf::Form OriginalForm = AttrSpec.Form;
1275 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
1276 // DWARFLinker does not generate .debug_addr table. Thus we need to change
1277 // all "addrx" related forms to "addr" version. Change DW_FORM_rnglistx
1278 // to DW_FORM_sec_offset here.
1279 std::optional<uint64_t> Index = Val.getAsSectionOffset();
1280 if (!Index) {
1281 Linker.reportWarning("Cannot read the attribute. Dropping.", File,
1282 &InputDIE);
1283 return 0;
1284 }
1285 std::optional<uint64_t> Offset =
1286 Unit.getOrigUnit().getRnglistOffset(*Index);
1287 if (!Offset) {
1288 Linker.reportWarning("Cannot read the attribute. Dropping.", File,
1289 &InputDIE);
1290 return 0;
1291 }
1292
1293 Value = *Offset;
1294 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1295 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1296 } else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
1297 // DWARFLinker does not generate .debug_addr table. Thus we need to change
1298 // all "addrx" related forms to "addr" version. Change DW_FORM_loclistx
1299 // to DW_FORM_sec_offset here.
1300 std::optional<uint64_t> Index = Val.getAsSectionOffset();
1301 if (!Index) {
1302 Linker.reportWarning("Cannot read the attribute. Dropping.", File,
1303 &InputDIE);
1304 return 0;
1305 }
1306 std::optional<uint64_t> Offset =
1307 Unit.getOrigUnit().getLoclistOffset(*Index);
1308 if (!Offset) {
1309 Linker.reportWarning("Cannot read the attribute. Dropping.", File,
1310 &InputDIE);
1311 return 0;
1312 }
1313
1314 Value = *Offset;
1315 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1316 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1317 } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
1318 Die.getTag() == dwarf::DW_TAG_compile_unit) {
1319 std::optional<uint64_t> LowPC = Unit.getLowPc();
1320 if (!LowPC)
1321 return 0;
1322 // Dwarf >= 4 high_pc is an size, not an address.
1323 Value = Unit.getHighPc() - *LowPC;
1324 } else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
1325 Value = *Val.getAsSectionOffset();
1326 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
1327 Value = *Val.getAsSignedConstant();
1328 else if (auto OptionalValue = Val.getAsUnsignedConstant())
1329 Value = *OptionalValue;
1330 else {
1331 Linker.reportWarning(
1332 "Unsupported scalar attribute form. Dropping attribute.", File,
1333 &InputDIE);
1334 return 0;
1335 }
1336
1337 PatchLocation Patch =
1338 Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
1339 dwarf::Form(AttrSpec.Form), DIEInteger(Value));
1340 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
1341 AttrSpec.Attr == dwarf::DW_AT_start_scope) {
1342 Unit.noteRangeAttribute(Die, Patch);
1343 Info.HasRanges = true;
1344 } else if (DWARFAttribute::mayHaveLocationList(AttrSpec.Attr) &&
1345 dwarf::doesFormBelongToClass(AttrSpec.Form,
1347 Unit.getOrigUnit().getVersion())) {
1348 Unit.noteLocationAttribute(Patch, Info.PCOffset);
1349 } else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
1350 Info.IsDeclaration = true;
1351
1352 // check that all dwarf::DW_FORM_rnglistx are handled previously.
1353 assert((Info.HasRanges || (OriginalForm != dwarf::DW_FORM_rnglistx)) &&
1354 "Unhandled DW_FORM_rnglistx attribute");
1355
1356 return AttrSize;
1357}
1358
1359/// Clone \p InputDIE's attribute described by \p AttrSpec with
1360/// value \p Val, and add it to \p Die.
1361/// \returns the size of the cloned attribute.
1362unsigned DWARFLinker::DIECloner::cloneAttribute(
1363 DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File,
1364 CompileUnit &Unit, OffsetsStringPool &StringPool, const DWARFFormValue &Val,
1365 const AttributeSpec AttrSpec, unsigned AttrSize, AttributesInfo &Info,
1366 bool IsLittleEndian) {
1367 const DWARFUnit &U = Unit.getOrigUnit();
1368
1369 switch (AttrSpec.Form) {
1370 case dwarf::DW_FORM_strp:
1371 case dwarf::DW_FORM_string:
1372 case dwarf::DW_FORM_strx:
1373 case dwarf::DW_FORM_strx1:
1374 case dwarf::DW_FORM_strx2:
1375 case dwarf::DW_FORM_strx3:
1376 case dwarf::DW_FORM_strx4:
1377 return cloneStringAttribute(Die, AttrSpec, Val, U, StringPool, Info);
1378 case dwarf::DW_FORM_ref_addr:
1379 case dwarf::DW_FORM_ref1:
1380 case dwarf::DW_FORM_ref2:
1381 case dwarf::DW_FORM_ref4:
1382 case dwarf::DW_FORM_ref8:
1383 return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,
1384 File, Unit);
1385 case dwarf::DW_FORM_block:
1386 case dwarf::DW_FORM_block1:
1387 case dwarf::DW_FORM_block2:
1388 case dwarf::DW_FORM_block4:
1389 case dwarf::DW_FORM_exprloc:
1390 return cloneBlockAttribute(Die, File, Unit, AttrSpec, Val, AttrSize,
1391 IsLittleEndian);
1392 case dwarf::DW_FORM_addr:
1393 case dwarf::DW_FORM_addrx:
1394 case dwarf::DW_FORM_addrx1:
1395 case dwarf::DW_FORM_addrx2:
1396 case dwarf::DW_FORM_addrx3:
1397 case dwarf::DW_FORM_addrx4:
1398 return cloneAddressAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, Unit,
1399 Info);
1400 case dwarf::DW_FORM_data1:
1401 case dwarf::DW_FORM_data2:
1402 case dwarf::DW_FORM_data4:
1403 case dwarf::DW_FORM_data8:
1404 case dwarf::DW_FORM_udata:
1405 case dwarf::DW_FORM_sdata:
1406 case dwarf::DW_FORM_sec_offset:
1407 case dwarf::DW_FORM_flag:
1408 case dwarf::DW_FORM_flag_present:
1409 case dwarf::DW_FORM_rnglistx:
1410 case dwarf::DW_FORM_loclistx:
1411 case dwarf::DW_FORM_implicit_const:
1412 return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1413 AttrSize, Info);
1414 default:
1415 Linker.reportWarning("Unsupported attribute form " +
1416 dwarf::FormEncodingString(AttrSpec.Form) +
1417 " in cloneAttribute. Dropping.",
1418 File, &InputDIE);
1419 }
1420
1421 return 0;
1422}
1423
1425 return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') &&
1426 (Name[1] == '[');
1427}
1428
1429void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
1430 const DIE *Die,
1431 DwarfStringPoolEntryRef Name,
1432 OffsetsStringPool &StringPool,
1433 bool SkipPubSection) {
1434 assert(isObjCSelector(Name.getString()) && "not an objc selector");
1435 // Objective C method or class function.
1436 // "- [Class(Category) selector :withArg ...]"
1437 StringRef ClassNameStart(Name.getString().drop_front(2));
1438 size_t FirstSpace = ClassNameStart.find(' ');
1439 if (FirstSpace == StringRef::npos)
1440 return;
1441
1442 StringRef SelectorStart(ClassNameStart.data() + FirstSpace + 1);
1443 if (!SelectorStart.size())
1444 return;
1445
1446 StringRef Selector(SelectorStart.data(), SelectorStart.size() - 1);
1447 Unit.addNameAccelerator(Die, StringPool.getEntry(Selector), SkipPubSection);
1448
1449 // Add an entry for the class name that points to this
1450 // method/class function.
1451 StringRef ClassName(ClassNameStart.data(), FirstSpace);
1452 Unit.addObjCAccelerator(Die, StringPool.getEntry(ClassName), SkipPubSection);
1453
1454 if (ClassName[ClassName.size() - 1] == ')') {
1455 size_t OpenParens = ClassName.find('(');
1456 if (OpenParens != StringRef::npos) {
1457 StringRef ClassNameNoCategory(ClassName.data(), OpenParens);
1458 Unit.addObjCAccelerator(Die, StringPool.getEntry(ClassNameNoCategory),
1459 SkipPubSection);
1460
1461 std::string MethodNameNoCategory(Name.getString().data(), OpenParens + 2);
1462 // FIXME: The missing space here may be a bug, but
1463 // dsymutil-classic also does it this way.
1464 MethodNameNoCategory.append(std::string(SelectorStart));
1465 Unit.addNameAccelerator(Die, StringPool.getEntry(MethodNameNoCategory),
1466 SkipPubSection);
1467 }
1468 }
1469}
1470
1472 bool Update, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
1473 uint16_t Tag, bool InDebugMap, bool SkipPC, bool InFunctionScope) {
1474 switch (AttrSpec.Attr) {
1475 default:
1476 return false;
1477 case dwarf::DW_AT_low_pc:
1478 case dwarf::DW_AT_high_pc:
1479 case dwarf::DW_AT_ranges:
1480 return !Update && SkipPC;
1481 case dwarf::DW_AT_addr_base:
1482 // In case !Update the .debug_addr table is not generated/preserved.
1483 return !Update;
1484 case dwarf::DW_AT_rnglists_base:
1485 // In case !Update the .debug_addr table is not generated/preserved.
1486 // Thus instead of DW_FORM_rnglistx the DW_FORM_sec_offset is used.
1487 // Since DW_AT_rnglists_base is used for only DW_FORM_rnglistx the
1488 // DW_AT_rnglists_base is removed.
1489 return !Update;
1490 case dwarf::DW_AT_str_offsets_base:
1491 // FIXME: Use the string offset table with Dwarf 5.
1492 return true;
1493 case dwarf::DW_AT_loclists_base:
1494 // In case !Update the .debug_addr table is not generated/preserved.
1495 // Thus instead of DW_FORM_loclistx the DW_FORM_sec_offset is used.
1496 // Since DW_AT_loclists_base is used for only DW_FORM_loclistx the
1497 // DW_AT_loclists_base is removed.
1498 return !Update;
1499 case dwarf::DW_AT_location:
1500 case dwarf::DW_AT_frame_base:
1501 // FIXME: for some reason dsymutil-classic keeps the location attributes
1502 // when they are of block type (i.e. not location lists). This is totally
1503 // wrong for globals where we will keep a wrong address. It is mostly
1504 // harmless for locals, but there is no point in keeping these anyway when
1505 // the function wasn't linked.
1506 return !Update &&
1507 (SkipPC || (!InFunctionScope && Tag == dwarf::DW_TAG_variable &&
1508 !InDebugMap)) &&
1510 }
1511}
1512
1513DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
1514 const DWARFFile &File, CompileUnit &Unit,
1515 OffsetsStringPool &StringPool,
1516 int64_t PCOffset, uint32_t OutOffset,
1517 unsigned Flags, bool IsLittleEndian,
1518 DIE *Die) {
1519 DWARFUnit &U = Unit.getOrigUnit();
1520 unsigned Idx = U.getDIEIndex(InputDIE);
1521 CompileUnit::DIEInfo &Info = Unit.getInfo(Idx);
1522
1523 // Should the DIE appear in the output?
1524 if (!Unit.getInfo(Idx).Keep)
1525 return nullptr;
1526
1527 uint64_t Offset = InputDIE.getOffset();
1528 assert(!(Die && Info.Clone) && "Can't supply a DIE and a cloned DIE");
1529 if (!Die) {
1530 // The DIE might have been already created by a forward reference
1531 // (see cloneDieReferenceAttribute()).
1532 if (!Info.Clone)
1533 Info.Clone = DIE::get(DIEAlloc, dwarf::Tag(InputDIE.getTag()));
1534 Die = Info.Clone;
1535 }
1536
1537 assert(Die->getTag() == InputDIE.getTag());
1538 Die->setOffset(OutOffset);
1539 if (isODRCanonicalCandidate(InputDIE, Unit) && Info.Ctxt &&
1540 (Info.Ctxt->getCanonicalDIEOffset() == 0)) {
1541 if (!Info.Ctxt->hasCanonicalDIE())
1542 Info.Ctxt->setHasCanonicalDIE();
1543 // We are about to emit a DIE that is the root of its own valid
1544 // DeclContext tree. Make the current offset the canonical offset
1545 // for this context.
1546 Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset());
1547 }
1548
1549 // Extract and clone every attribute.
1550 DWARFDataExtractor Data = U.getDebugInfoExtractor();
1551 // Point to the next DIE (generally there is always at least a NULL
1552 // entry after the current one). If this is a lone
1553 // DW_TAG_compile_unit without any children, point to the next unit.
1554 uint64_t NextOffset = (Idx + 1 < U.getNumDIEs())
1555 ? U.getDIEAtIndex(Idx + 1).getOffset()
1556 : U.getNextUnitOffset();
1557 AttributesInfo AttrInfo;
1558
1559 // We could copy the data only if we need to apply a relocation to it. After
1560 // testing, it seems there is no performance downside to doing the copy
1561 // unconditionally, and it makes the code simpler.
1562 SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset));
1563 Data =
1564 DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize());
1565
1566 // Modify the copy with relocated addresses.
1567 ObjFile.Addresses->applyValidRelocs(DIECopy, Offset, Data.isLittleEndian());
1568
1569 // Reset the Offset to 0 as we will be working on the local copy of
1570 // the data.
1571 Offset = 0;
1572
1573 const auto *Abbrev = InputDIE.getAbbreviationDeclarationPtr();
1574 Offset += getULEB128Size(Abbrev->getCode());
1575
1576 // We are entering a subprogram. Get and propagate the PCOffset.
1577 if (Die->getTag() == dwarf::DW_TAG_subprogram)
1578 PCOffset = Info.AddrAdjust;
1579 AttrInfo.PCOffset = PCOffset;
1580
1581 if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) {
1582 Flags |= TF_InFunctionScope;
1583 if (!Info.InDebugMap && LLVM_LIKELY(!Update))
1584 Flags |= TF_SkipPC;
1585 } else if (Abbrev->getTag() == dwarf::DW_TAG_variable) {
1586 // Function-local globals could be in the debug map even when the function
1587 // is not, e.g., inlined functions.
1588 if ((Flags & TF_InFunctionScope) && Info.InDebugMap)
1589 Flags &= ~TF_SkipPC;
1590 }
1591
1592 for (const auto &AttrSpec : Abbrev->attributes()) {
1593 if (shouldSkipAttribute(Update, AttrSpec, Die->getTag(), Info.InDebugMap,
1594 Flags & TF_SkipPC, Flags & TF_InFunctionScope)) {
1595 DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
1596 U.getFormParams());
1597 continue;
1598 }
1599
1600 DWARFFormValue Val = AttrSpec.getFormValue();
1601 uint64_t AttrSize = Offset;
1602 Val.extractValue(Data, &Offset, U.getFormParams(), &U);
1603 AttrSize = Offset - AttrSize;
1604
1605 OutOffset += cloneAttribute(*Die, InputDIE, File, Unit, StringPool, Val,
1606 AttrSpec, AttrSize, AttrInfo, IsLittleEndian);
1607 }
1608
1609 // Look for accelerator entries.
1610 uint16_t Tag = InputDIE.getTag();
1611 // FIXME: This is slightly wrong. An inline_subroutine without a
1612 // low_pc, but with AT_ranges might be interesting to get into the
1613 // accelerator tables too. For now stick with dsymutil's behavior.
1614 if ((Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) &&
1615 Tag != dwarf::DW_TAG_compile_unit &&
1616 getDIENames(InputDIE, AttrInfo, StringPool,
1617 Tag != dwarf::DW_TAG_inlined_subroutine)) {
1618 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
1619 Unit.addNameAccelerator(Die, AttrInfo.MangledName,
1620 Tag == dwarf::DW_TAG_inlined_subroutine);
1621 if (AttrInfo.Name) {
1622 if (AttrInfo.NameWithoutTemplate)
1623 Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate,
1624 /* SkipPubSection */ true);
1625 Unit.addNameAccelerator(Die, AttrInfo.Name,
1626 Tag == dwarf::DW_TAG_inlined_subroutine);
1627 }
1628 if (AttrInfo.Name && isObjCSelector(AttrInfo.Name.getString()))
1629 addObjCAccelerator(Unit, Die, AttrInfo.Name, StringPool,
1630 /* SkipPubSection =*/true);
1631
1632 } else if (Tag == dwarf::DW_TAG_namespace) {
1633 if (!AttrInfo.Name)
1634 AttrInfo.Name = StringPool.getEntry("(anonymous namespace)");
1635 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1636 } else if (Tag == dwarf::DW_TAG_imported_declaration && AttrInfo.Name) {
1637 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1638 } else if (isTypeTag(Tag) && !AttrInfo.IsDeclaration &&
1639 getDIENames(InputDIE, AttrInfo, StringPool) && AttrInfo.Name &&
1640 AttrInfo.Name.getString()[0]) {
1641 uint32_t Hash = hashFullyQualifiedName(InputDIE, Unit, File);
1642 uint64_t RuntimeLang =
1643 dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_runtime_class))
1644 .value_or(0);
1645 bool ObjCClassIsImplementation =
1646 (RuntimeLang == dwarf::DW_LANG_ObjC ||
1647 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
1648 dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_objc_complete_type))
1649 .value_or(0);
1650 Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation,
1651 Hash);
1652 }
1653
1654 // Determine whether there are any children that we want to keep.
1655 bool HasChildren = false;
1656 for (auto Child : InputDIE.children()) {
1657 unsigned Idx = U.getDIEIndex(Child);
1658 if (Unit.getInfo(Idx).Keep) {
1659 HasChildren = true;
1660 break;
1661 }
1662 }
1663
1664 DIEAbbrev NewAbbrev = Die->generateAbbrev();
1665 if (HasChildren)
1666 NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
1667 // Assign a permanent abbrev number
1668 Linker.assignAbbrev(NewAbbrev);
1669 Die->setAbbrevNumber(NewAbbrev.getNumber());
1670
1671 // Add the size of the abbreviation number to the output offset.
1672 OutOffset += getULEB128Size(Die->getAbbrevNumber());
1673
1674 if (!HasChildren) {
1675 // Update our size.
1676 Die->setSize(OutOffset - Die->getOffset());
1677 return Die;
1678 }
1679
1680 // Recursively clone children.
1681 for (auto Child : InputDIE.children()) {
1682 if (DIE *Clone = cloneDIE(Child, File, Unit, StringPool, PCOffset,
1683 OutOffset, Flags, IsLittleEndian)) {
1684 Die->addChild(Clone);
1685 OutOffset = Clone->getOffset() + Clone->getSize();
1686 }
1687 }
1688
1689 // Account for the end of children marker.
1690 OutOffset += sizeof(int8_t);
1691 // Update our size.
1692 Die->setSize(OutOffset - Die->getOffset());
1693 return Die;
1694}
1695
1696/// Patch the input object file relevant debug_ranges or debug_rnglists
1697/// entries and emit them in the output file. Update the relevant attributes
1698/// to point at the new entries.
1699void DWARFLinker::generateUnitRanges(CompileUnit &Unit,
1700 const DWARFFile &File) const {
1701 if (LLVM_UNLIKELY(Options.Update))
1702 return;
1703
1704 const auto &FunctionRanges = Unit.getFunctionRanges();
1705
1706 // Build set of linked address ranges for unit function ranges.
1707 AddressRanges LinkedFunctionRanges;
1708 for (const AddressRangeValuePair &Range : FunctionRanges)
1709 LinkedFunctionRanges.insert(
1710 {Range.Range.start() + Range.Value, Range.Range.end() + Range.Value});
1711
1712 // Emit LinkedFunctionRanges into .debug_aranges
1713 if (!LinkedFunctionRanges.empty())
1714 TheDwarfEmitter->emitDwarfDebugArangesTable(Unit, LinkedFunctionRanges);
1715
1716 RngListAttributesTy AllRngListAttributes = Unit.getRangesAttributes();
1717 std::optional<PatchLocation> UnitRngListAttribute =
1718 Unit.getUnitRangesAttribute();
1719
1720 if (!AllRngListAttributes.empty() || UnitRngListAttribute) {
1721 std::optional<AddressRangeValuePair> CachedRange;
1722 MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugRangeListHeader(Unit);
1723
1724 // Read original address ranges, apply relocation value, emit linked address
1725 // ranges.
1726 for (PatchLocation &AttributePatch : AllRngListAttributes) {
1727 // Get ranges from the source DWARF corresponding to the current
1728 // attribute.
1729 AddressRanges LinkedRanges;
1730 if (Expected<DWARFAddressRangesVector> OriginalRanges =
1731 Unit.getOrigUnit().findRnglistFromOffset(AttributePatch.get())) {
1732 // Apply relocation adjustment.
1733 for (const auto &Range : *OriginalRanges) {
1734 if (!CachedRange || !CachedRange->Range.contains(Range.LowPC))
1735 CachedRange = FunctionRanges.getRangeThatContains(Range.LowPC);
1736
1737 // All range entries should lie in the function range.
1738 if (!CachedRange) {
1739 reportWarning("inconsistent range data.", File);
1740 continue;
1741 }
1742
1743 // Store range for emiting.
1744 LinkedRanges.insert({Range.LowPC + CachedRange->Value,
1745 Range.HighPC + CachedRange->Value});
1746 }
1747 } else {
1748 llvm::consumeError(OriginalRanges.takeError());
1749 reportWarning("invalid range list ignored.", File);
1750 }
1751
1752 // Emit linked ranges.
1753 TheDwarfEmitter->emitDwarfDebugRangeListFragment(Unit, LinkedRanges,
1754 AttributePatch);
1755 }
1756
1757 // Emit ranges for Unit AT_ranges attribute.
1758 if (UnitRngListAttribute.has_value())
1759 TheDwarfEmitter->emitDwarfDebugRangeListFragment(
1760 Unit, LinkedFunctionRanges, *UnitRngListAttribute);
1761
1762 // Emit ranges footer.
1763 TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel);
1764 }
1765}
1766
1767void DWARFLinker::generateUnitLocations(
1768 CompileUnit &Unit, const DWARFFile &File,
1769 ExpressionHandlerRef ExprHandler) const {
1770 if (LLVM_UNLIKELY(Options.Update))
1771 return;
1772
1773 const LocListAttributesTy &AllLocListAttributes =
1774 Unit.getLocationAttributes();
1775
1776 if (AllLocListAttributes.empty())
1777 return;
1778
1779 // Emit locations list table header.
1780 MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugLocListHeader(Unit);
1781
1782 for (auto &CurLocAttr : AllLocListAttributes) {
1783 // Get location expressions vector corresponding to the current attribute
1784 // from the source DWARF.
1785 Expected<DWARFLocationExpressionsVector> OriginalLocations =
1786 Unit.getOrigUnit().findLoclistFromOffset((CurLocAttr.first).get());
1787
1788 if (!OriginalLocations) {
1789 llvm::consumeError(OriginalLocations.takeError());
1790 reportWarning("Invalid location attribute ignored.", File);
1791 continue;
1792 }
1793
1794 DWARFLocationExpressionsVector LinkedLocationExpressions;
1795 for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
1796
1797 DWARFLocationExpression LinkedExpression;
1798
1799 if (CurExpression.Range) {
1800 // Relocate address range.
1801 LinkedExpression.Range = {
1802 CurExpression.Range->LowPC + CurLocAttr.second,
1803 CurExpression.Range->HighPC + CurLocAttr.second};
1804 }
1805
1806 // Clone expression.
1807 LinkedExpression.Expr.reserve(CurExpression.Expr.size());
1808 ExprHandler(CurExpression.Expr, LinkedExpression.Expr);
1809
1810 LinkedLocationExpressions.push_back(LinkedExpression);
1811 }
1812
1813 // Emit locations list table fragment corresponding to the CurLocAttr.
1814 TheDwarfEmitter->emitDwarfDebugLocListFragment(
1815 Unit, LinkedLocationExpressions, CurLocAttr.first);
1816 }
1817
1818 // Emit locations list table footer.
1819 TheDwarfEmitter->emitDwarfDebugLocListFooter(Unit, EndLabel);
1820}
1821
1822/// Insert the new line info sequence \p Seq into the current
1823/// set of already linked line info \p Rows.
1824static void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
1825 std::vector<DWARFDebugLine::Row> &Rows) {
1826 if (Seq.empty())
1827 return;
1828
1829 if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {
1830 llvm::append_range(Rows, Seq);
1831 Seq.clear();
1832 return;
1833 }
1834
1835 object::SectionedAddress Front = Seq.front().Address;
1836 auto InsertPoint = partition_point(
1837 Rows, [=](const DWARFDebugLine::Row &O) { return O.Address < Front; });
1838
1839 // FIXME: this only removes the unneeded end_sequence if the
1840 // sequences have been inserted in order. Using a global sort like
1841 // described in patchLineTableForUnit() and delaying the end_sequene
1842 // elimination to emitLineTableForUnit() we can get rid of all of them.
1843 if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&
1844 InsertPoint->EndSequence) {
1845 *InsertPoint = Seq.front();
1846 Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
1847 } else {
1848 Rows.insert(InsertPoint, Seq.begin(), Seq.end());
1849 }
1850
1851 Seq.clear();
1852}
1853
1855 for (auto &V : Die.values())
1856 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
1857 V = DIEValue(V.getAttribute(), V.getForm(), Offset);
1858 return;
1859 }
1860
1861 llvm_unreachable("Didn't find DW_AT_stmt_list in cloned DIE!");
1862}
1863
1864/// Extract the line table for \p Unit from \p OrigDwarf, and
1865/// recreate a relocated version of these for the address ranges that
1866/// are present in the binary.
1867void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
1868 DWARFContext &OrigDwarf,
1869 const DWARFFile &File) {
1870 DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE();
1871 auto StmtList = dwarf::toSectionOffset(CUDie.find(dwarf::DW_AT_stmt_list));
1872 if (!StmtList)
1873 return;
1874
1875 // Update the cloned DW_AT_stmt_list with the correct debug_line offset.
1876 if (auto *OutputDIE = Unit.getOutputUnitDIE())
1877 patchStmtList(*OutputDIE,
1878 DIEInteger(TheDwarfEmitter->getLineSectionSize()));
1879
1880 RangesTy &Ranges = File.Addresses->getValidAddressRanges();
1881
1882 // Parse the original line info for the unit.
1883 DWARFDebugLine::LineTable LineTable;
1884 uint64_t StmtOffset = *StmtList;
1885 DWARFDataExtractor LineExtractor(
1886 OrigDwarf.getDWARFObj(), OrigDwarf.getDWARFObj().getLineSection(),
1887 OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize());
1888 if (needToTranslateStrings())
1889 return TheDwarfEmitter->translateLineTable(LineExtractor, StmtOffset);
1890
1891 if (Error Err =
1892 LineTable.parse(LineExtractor, &StmtOffset, OrigDwarf,
1893 &Unit.getOrigUnit(), OrigDwarf.getWarningHandler()))
1894 OrigDwarf.getWarningHandler()(std::move(Err));
1895
1896 // This vector is the output line table.
1897 std::vector<DWARFDebugLine::Row> NewRows;
1898 NewRows.reserve(LineTable.Rows.size());
1899
1900 // Current sequence of rows being extracted, before being inserted
1901 // in NewRows.
1902 std::vector<DWARFDebugLine::Row> Seq;
1903 const auto &FunctionRanges = Unit.getFunctionRanges();
1904 std::optional<AddressRangeValuePair> CurrRange;
1905
1906 // FIXME: This logic is meant to generate exactly the same output as
1907 // Darwin's classic dsymutil. There is a nicer way to implement this
1908 // by simply putting all the relocated line info in NewRows and simply
1909 // sorting NewRows before passing it to emitLineTableForUnit. This
1910 // should be correct as sequences for a function should stay
1911 // together in the sorted output. There are a few corner cases that
1912 // look suspicious though, and that required to implement the logic
1913 // this way. Revisit that once initial validation is finished.
1914
1915 // Iterate over the object file line info and extract the sequences
1916 // that correspond to linked functions.
1917 for (auto &Row : LineTable.Rows) {
1918 // Check whether we stepped out of the range. The range is
1919 // half-open, but consider accept the end address of the range if
1920 // it is marked as end_sequence in the input (because in that
1921 // case, the relocation offset is accurate and that entry won't
1922 // serve as the start of another function).
1923 if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address) ||
1924 (Row.Address.Address == CurrRange->Range.end() && !Row.EndSequence)) {
1925 // We just stepped out of a known range. Insert a end_sequence
1926 // corresponding to the end of the range.
1927 uint64_t StopAddress =
1928 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
1929 CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);
1930 if (!CurrRange) {
1931 if (StopAddress != -1ULL) {
1932 // Try harder by looking in the Address ranges map.
1933 // There are corner cases where this finds a
1934 // valid entry. It's unclear if this is right or wrong, but
1935 // for now do as dsymutil.
1936 // FIXME: Understand exactly what cases this addresses and
1937 // potentially remove it along with the Ranges map.
1938 if (std::optional<AddressRangeValuePair> Range =
1939 Ranges.getRangeThatContains(Row.Address.Address))
1940 StopAddress = Row.Address.Address + (*Range).Value;
1941 }
1942 }
1943 if (StopAddress != -1ULL && !Seq.empty()) {
1944 // Insert end sequence row with the computed end address, but
1945 // the same line as the previous one.
1946 auto NextLine = Seq.back();
1947 NextLine.Address.Address = StopAddress;
1948 NextLine.EndSequence = 1;
1949 NextLine.PrologueEnd = 0;
1950 NextLine.BasicBlock = 0;
1951 NextLine.EpilogueBegin = 0;
1952 Seq.push_back(NextLine);
1953 insertLineSequence(Seq, NewRows);
1954 }
1955
1956 if (!CurrRange)
1957 continue;
1958 }
1959
1960 // Ignore empty sequences.
1961 if (Row.EndSequence && Seq.empty())
1962 continue;
1963
1964 // Relocate row address and add it to the current sequence.
1965 Row.Address.Address += CurrRange->Value;
1966 Seq.emplace_back(Row);
1967
1968 if (Row.EndSequence)
1969 insertLineSequence(Seq, NewRows);
1970 }
1971
1972 // Finished extracting, now emit the line tables.
1973 // FIXME: LLVM hard-codes its prologue values. We just copy the
1974 // prologue over and that works because we act as both producer and
1975 // consumer. It would be nicer to have a real configurable line
1976 // table emitter.
1977 if (LineTable.Prologue.getVersion() < 2 ||
1978 LineTable.Prologue.getVersion() > 5 ||
1979 LineTable.Prologue.DefaultIsStmt != DWARF2_LINE_DEFAULT_IS_STMT ||
1980 LineTable.Prologue.OpcodeBase > 13)
1981 reportWarning("line table parameters mismatch. Cannot emit.", File);
1982 else {
1983 uint32_t PrologueEnd = *StmtList + 10 + LineTable.Prologue.PrologueLength;
1984 // DWARF v5 has an extra 2 bytes of information before the header_length
1985 // field.
1986 if (LineTable.Prologue.getVersion() == 5)
1987 PrologueEnd += 2;
1988 StringRef LineData = OrigDwarf.getDWARFObj().getLineSection().Data;
1989 MCDwarfLineTableParams Params;
1990 Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase;
1991 Params.DWARF2LineBase = LineTable.Prologue.LineBase;
1992 Params.DWARF2LineRange = LineTable.Prologue.LineRange;
1993 TheDwarfEmitter->emitLineTableForUnit(
1994 Params, LineData.slice(*StmtList + 4, PrologueEnd),
1995 LineTable.Prologue.MinInstLength, NewRows,
1996 Unit.getOrigUnit().getAddressByteSize());
1997 }
1998}
1999
2000void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) {
2001 DWARFUnit &OrigUnit = Unit.getOrigUnit();
2002 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();
2003
2004 if (std::optional<uint64_t> MacroAttr =
2005 dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macros))) {
2006 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2007 return;
2008 }
2009
2010 if (std::optional<uint64_t> MacroAttr =
2011 dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macro_info))) {
2012 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2013 return;
2014 }
2015}
2016
2017void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
2018 for (DwarfLinkerAccelTableKind AccelTableKind : Options.AccelTables) {
2019 switch (AccelTableKind) {
2021 // Add namespaces.
2022 for (const auto &Namespace : Unit.getNamespaces())
2023 AppleNamespaces.addName(Namespace.Name, Namespace.Die->getOffset() +
2024 Unit.getStartOffset());
2025 // Add names.
2026 for (const auto &Pubname : Unit.getPubnames())
2027 AppleNames.addName(Pubname.Name,
2028 Pubname.Die->getOffset() + Unit.getStartOffset());
2029 // Add types.
2030 for (const auto &Pubtype : Unit.getPubtypes())
2031 AppleTypes.addName(
2032 Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(),
2033 Pubtype.Die->getTag(),
2034 Pubtype.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation
2035 : 0,
2036 Pubtype.QualifiedNameHash);
2037 // Add ObjC names.
2038 for (const auto &ObjC : Unit.getObjC())
2039 AppleObjc.addName(ObjC.Name,
2040 ObjC.Die->getOffset() + Unit.getStartOffset());
2041 } break;
2043 TheDwarfEmitter->emitPubNamesForUnit(Unit);
2044 TheDwarfEmitter->emitPubTypesForUnit(Unit);
2045 } break;
2047 for (const auto &Namespace : Unit.getNamespaces())
2048 DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(),
2049 Namespace.Die->getTag(), Unit.getUniqueID());
2050 for (const auto &Pubname : Unit.getPubnames())
2051 DebugNames.addName(Pubname.Name, Pubname.Die->getOffset(),
2052 Pubname.Die->getTag(), Unit.getUniqueID());
2053 for (const auto &Pubtype : Unit.getPubtypes())
2054 DebugNames.addName(Pubtype.Name, Pubtype.Die->getOffset(),
2055 Pubtype.Die->getTag(), Unit.getUniqueID());
2056 } break;
2057 }
2058 }
2059}
2060
2061/// Read the frame info stored in the object, and emit the
2062/// patched frame descriptions for the resulting file.
2063///
2064/// This is actually pretty easy as the data of the CIEs and FDEs can
2065/// be considered as black boxes and moved as is. The only thing to do
2066/// is to patch the addresses in the headers.
2067void DWARFLinker::patchFrameInfoForObject(const DWARFFile &File,
2068 RangesTy &Ranges,
2069 DWARFContext &OrigDwarf,
2070 unsigned AddrSize) {
2071 StringRef FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
2072 if (FrameData.empty())
2073 return;
2074
2075 DataExtractor Data(FrameData, OrigDwarf.isLittleEndian(), 0);
2076 uint64_t InputOffset = 0;
2077
2078 // Store the data of the CIEs defined in this object, keyed by their
2079 // offsets.
2080 DenseMap<uint64_t, StringRef> LocalCIES;
2081
2082 while (Data.isValidOffset(InputOffset)) {
2083 uint64_t EntryOffset = InputOffset;
2084 uint32_t InitialLength = Data.getU32(&InputOffset);
2085 if (InitialLength == 0xFFFFFFFF)
2086 return reportWarning("Dwarf64 bits no supported", File);
2087
2088 uint32_t CIEId = Data.getU32(&InputOffset);
2089 if (CIEId == 0xFFFFFFFF) {
2090 // This is a CIE, store it.
2091 StringRef CIEData = FrameData.substr(EntryOffset, InitialLength + 4);
2092 LocalCIES[EntryOffset] = CIEData;
2093 // The -4 is to account for the CIEId we just read.
2094 InputOffset += InitialLength - 4;
2095 continue;
2096 }
2097
2098 uint64_t Loc = Data.getUnsigned(&InputOffset, AddrSize);
2099
2100 // Some compilers seem to emit frame info that doesn't start at
2101 // the function entry point, thus we can't just lookup the address
2102 // in the debug map. Use the AddressInfo's range map to see if the FDE
2103 // describes something that we can relocate.
2104 std::optional<AddressRangeValuePair> Range =
2105 Ranges.getRangeThatContains(Loc);
2106 if (!Range) {
2107 // The +4 is to account for the size of the InitialLength field itself.
2108 InputOffset = EntryOffset + InitialLength + 4;
2109 continue;
2110 }
2111
2112 // This is an FDE, and we have a mapping.
2113 // Have we already emitted a corresponding CIE?
2114 StringRef CIEData = LocalCIES[CIEId];
2115 if (CIEData.empty())
2116 return reportWarning("Inconsistent debug_frame content. Dropping.", File);
2117
2118 // Look if we already emitted a CIE that corresponds to the
2119 // referenced one (the CIE data is the key of that lookup).
2120 auto IteratorInserted = EmittedCIEs.insert(
2121 std::make_pair(CIEData, TheDwarfEmitter->getFrameSectionSize()));
2122 // If there is no CIE yet for this ID, emit it.
2123 if (IteratorInserted.second) {
2124 LastCIEOffset = TheDwarfEmitter->getFrameSectionSize();
2125 IteratorInserted.first->getValue() = LastCIEOffset;
2126 TheDwarfEmitter->emitCIE(CIEData);
2127 }
2128
2129 // Emit the FDE with updated address and CIE pointer.
2130 // (4 + AddrSize) is the size of the CIEId + initial_location
2131 // fields that will get reconstructed by emitFDE().
2132 unsigned FDERemainingBytes = InitialLength - (4 + AddrSize);
2133 TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), AddrSize,
2134 Loc + Range->Value,
2135 FrameData.substr(InputOffset, FDERemainingBytes));
2136 InputOffset += FDERemainingBytes;
2137 }
2138}
2139
2140uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
2141 CompileUnit &U,
2142 const DWARFFile &File,
2143 int ChildRecurseDepth) {
2144 const char *Name = nullptr;
2145 DWARFUnit *OrigUnit = &U.getOrigUnit();
2146 CompileUnit *CU = &U;
2147 std::optional<DWARFFormValue> Ref;
2148
2149 while (true) {
2150 if (const char *CurrentName = DIE.getName(DINameKind::ShortName))
2151 Name = CurrentName;
2152
2153 if (!(Ref = DIE.find(dwarf::DW_AT_specification)) &&
2154 !(Ref = DIE.find(dwarf::DW_AT_abstract_origin)))
2155 break;
2156
2157 if (!Ref->isFormClass(DWARFFormValue::FC_Reference))
2158 break;
2159
2160 CompileUnit *RefCU;
2161 if (auto RefDIE =
2162 Linker.resolveDIEReference(File, CompileUnits, *Ref, DIE, RefCU)) {
2163 CU = RefCU;
2164 OrigUnit = &RefCU->getOrigUnit();
2165 DIE = RefDIE;
2166 }
2167 }
2168
2169 unsigned Idx = OrigUnit->getDIEIndex(DIE);
2170 if (!Name && DIE.getTag() == dwarf::DW_TAG_namespace)
2171 Name = "(anonymous namespace)";
2172
2173 if (CU->getInfo(Idx).ParentIdx == 0 ||
2174 // FIXME: dsymutil-classic compatibility. Ignore modules.
2175 CU->getOrigUnit().getDIEAtIndex(CU->getInfo(Idx).ParentIdx).getTag() ==
2176 dwarf::DW_TAG_module)
2177 return djbHash(Name ? Name : "", djbHash(ChildRecurseDepth ? "" : "::"));
2178
2179 DWARFDie Die = OrigUnit->getDIEAtIndex(CU->getInfo(Idx).ParentIdx);
2180 return djbHash(
2181 (Name ? Name : ""),
2182 djbHash((Name ? "::" : ""),
2183 hashFullyQualifiedName(Die, *CU, File, ++ChildRecurseDepth)));
2184}
2185
2186static uint64_t getDwoId(const DWARFDie &CUDie) {
2187 auto DwoId = dwarf::toUnsigned(
2188 CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
2189 if (DwoId)
2190 return *DwoId;
2191 return 0;
2192}
2193
2194static std::string remapPath(StringRef Path,
2195 const objectPrefixMap &ObjectPrefixMap) {
2196 if (ObjectPrefixMap.empty())
2197 return Path.str();
2198
2199 SmallString<256> p = Path;
2200 for (const auto &Entry : ObjectPrefixMap)
2201 if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second))
2202 break;
2203 return p.str().str();
2204}
2205
2206static std::string getPCMFile(const DWARFDie &CUDie,
2207 objectPrefixMap *ObjectPrefixMap) {
2208 std::string PCMFile = dwarf::toString(
2209 CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
2210
2211 if (PCMFile.empty())
2212 return PCMFile;
2213
2214 if (ObjectPrefixMap)
2215 PCMFile = remapPath(PCMFile, *ObjectPrefixMap);
2216
2217 return PCMFile;
2218}
2219
2220std::pair<bool, bool> DWARFLinker::isClangModuleRef(const DWARFDie &CUDie,
2221 std::string &PCMFile,
2222 LinkContext &Context,
2223 unsigned Indent,
2224 bool Quiet) {
2225 if (PCMFile.empty())
2226 return std::make_pair(false, false);
2227
2228 // Clang module DWARF skeleton CUs abuse this for the path to the module.
2229 uint64_t DwoId = getDwoId(CUDie);
2230
2231 std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
2232 if (Name.empty()) {
2233 if (!Quiet)
2234 reportWarning("Anonymous module skeleton CU for " + PCMFile,
2235 Context.File);
2236 return std::make_pair(true, true);
2237 }
2238
2239 if (!Quiet && Options.Verbose) {
2240 outs().indent(Indent);
2241 outs() << "Found clang module reference " << PCMFile;
2242 }
2243
2244 auto Cached = ClangModules.find(PCMFile);
2245 if (Cached != ClangModules.end()) {
2246 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
2247 // fixed in clang, only warn about DWO_id mismatches in verbose mode.
2248 // ASTFileSignatures will change randomly when a module is rebuilt.
2249 if (!Quiet && Options.Verbose && (Cached->second != DwoId))
2250 reportWarning(Twine("hash mismatch: this object file was built against a "
2251 "different version of the module ") +
2252 PCMFile,
2253 Context.File);
2254 if (!Quiet && Options.Verbose)
2255 outs() << " [cached].\n";
2256 return std::make_pair(true, true);
2257 }
2258
2259 return std::make_pair(true, false);
2260}
2261
2262bool DWARFLinker::registerModuleReference(const DWARFDie &CUDie,
2263 LinkContext &Context,
2264 objFileLoader Loader,
2265 CompileUnitHandler OnCUDieLoaded,
2266 unsigned Indent) {
2267 std::string PCMFile = getPCMFile(CUDie, Options.ObjectPrefixMap);
2268 std::pair<bool, bool> IsClangModuleRef =
2269 isClangModuleRef(CUDie, PCMFile, Context, Indent, false);
2270
2271 if (!IsClangModuleRef.first)
2272 return false;
2273
2274 if (IsClangModuleRef.second)
2275 return true;
2276
2277 if (Options.Verbose)
2278 outs() << " ...\n";
2279
2280 // Cyclic dependencies are disallowed by Clang, but we still
2281 // shouldn't run into an infinite loop, so mark it as processed now.
2282 ClangModules.insert({PCMFile, getDwoId(CUDie)});
2283
2284 if (Error E = loadClangModule(Loader, CUDie, PCMFile, Context, OnCUDieLoaded,
2285 Indent + 2)) {
2286 consumeError(std::move(E));
2287 return false;
2288 }
2289 return true;
2290}
2291
2292Error DWARFLinker::loadClangModule(objFileLoader Loader, const DWARFDie &CUDie,
2293 const std::string &PCMFile,
2294 LinkContext &Context,
2295 CompileUnitHandler OnCUDieLoaded,
2296 unsigned Indent) {
2297
2298 uint64_t DwoId = getDwoId(CUDie);
2299 std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
2300
2301 /// Using a SmallString<0> because loadClangModule() is recursive.
2302 SmallString<0> Path(Options.PrependPath);
2303 if (sys::path::is_relative(PCMFile))
2304 resolveRelativeObjectPath(Path, CUDie);
2305 sys::path::append(Path, PCMFile);
2306 // Don't use the cached binary holder because we have no thread-safety
2307 // guarantee and the lifetime is limited.
2308
2309 if (Loader == nullptr) {
2310 reportError("Could not load clang module: loader is not specified.\n",
2311 Context.File);
2312 return Error::success();
2313 }
2314
2315 auto ErrOrObj = Loader(Context.File.FileName, Path);
2316 if (!ErrOrObj)
2317 return Error::success();
2318
2319 std::unique_ptr<CompileUnit> Unit;
2320 for (const auto &CU : ErrOrObj->Dwarf->compile_units()) {
2321 OnCUDieLoaded(*CU);
2322 // Recursively get all modules imported by this one.
2323 auto ChildCUDie = CU->getUnitDIE();
2324 if (!ChildCUDie)
2325 continue;
2326 if (!registerModuleReference(ChildCUDie, Context, Loader, OnCUDieLoaded,
2327 Indent)) {
2328 if (Unit) {
2329 std::string Err =
2330 (PCMFile +
2331 ": Clang modules are expected to have exactly 1 compile unit.\n");
2332 reportError(Err, Context.File);
2333 return make_error<StringError>(Err, inconvertibleErrorCode());
2334 }
2335 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
2336 // fixed in clang, only warn about DWO_id mismatches in verbose mode.
2337 // ASTFileSignatures will change randomly when a module is rebuilt.
2338 uint64_t PCMDwoId = getDwoId(ChildCUDie);
2339 if (PCMDwoId != DwoId) {
2340 if (Options.Verbose)
2341 reportWarning(
2342 Twine("hash mismatch: this object file was built against a "
2343 "different version of the module ") +
2344 PCMFile,
2345 Context.File);
2346 // Update the cache entry with the DwoId of the module loaded from disk.
2347 ClangModules[PCMFile] = PCMDwoId;
2348 }
2349
2350 // Add this module.
2351 Unit = std::make_unique<CompileUnit>(*CU, UniqueUnitID++, !Options.NoODR,
2352 ModuleName);
2353 }
2354 }
2355
2356 if (Unit)
2357 Context.ModuleUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
2358
2359 return Error::success();
2360}
2361
2362uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
2363 DWARFContext &DwarfContext, const DWARFFile &File,
2364 OffsetsStringPool &StringPool, bool IsLittleEndian) {
2365 uint64_t OutputDebugInfoSize =
2366 Linker.Options.NoOutput ? 0 : Emitter->getDebugInfoSectionSize();
2367 const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
2368
2369 for (auto &CurrentUnit : CompileUnits) {
2370 const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2371 const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;
2372 auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
2373 CurrentUnit->setStartOffset(OutputDebugInfoSize);
2374 if (!InputDIE) {
2375 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2376 continue;
2377 }
2378 if (CurrentUnit->getInfo(0).Keep) {
2379 // Clone the InputDIE into your Unit DIE in our compile unit since it
2380 // already has a DIE inside of it.
2381 CurrentUnit->createOutputDIE();
2382 rememberUnitForMacroOffset(*CurrentUnit);
2383 cloneDIE(InputDIE, File, *CurrentUnit, StringPool, 0 /* PC offset */,
2384 UnitHeaderSize, 0, IsLittleEndian,
2385 CurrentUnit->getOutputUnitDIE());
2386 }
2387
2388 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2389
2390 if (!Linker.Options.NoOutput) {
2391 assert(Emitter);
2392
2393 if (LLVM_LIKELY(!Linker.Options.Update) ||
2394 Linker.needToTranslateStrings())
2395 Linker.patchLineTableForUnit(*CurrentUnit, DwarfContext, File);
2396
2397 Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
2398
2399 if (LLVM_UNLIKELY(Linker.Options.Update))
2400 continue;
2401
2402 Linker.generateUnitRanges(*CurrentUnit, File);
2403
2404 auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
2405 SmallVectorImpl<uint8_t> &OutBytes) {
2406 DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
2407 DataExtractor Data(SrcBytes, IsLittleEndian,
2408 OrigUnit.getAddressByteSize());
2409 cloneExpression(Data,
2410 DWARFExpression(Data, OrigUnit.getAddressByteSize(),
2411 OrigUnit.getFormParams().Format),
2412 File, *CurrentUnit, OutBytes);
2413 };
2414 Linker.generateUnitLocations(*CurrentUnit, File, ProcessExpr);
2415 }
2416 }
2417
2418 if (!Linker.Options.NoOutput) {
2419 assert(Emitter);
2420 // Emit macro tables.
2421 Emitter->emitMacroTables(File.Dwarf, UnitMacroMap, StringPool);
2422
2423 // Emit all the compile unit's debug information.
2424 for (auto &CurrentUnit : CompileUnits) {
2425 CurrentUnit->fixupForwardReferences();
2426
2427 if (!CurrentUnit->getOutputUnitDIE())
2428 continue;
2429
2430 unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2431
2432 assert(Emitter->getDebugInfoSectionSize() ==
2433 CurrentUnit->getStartOffset());
2434 Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
2435 Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());
2436 assert(Emitter->getDebugInfoSectionSize() ==
2437 CurrentUnit->computeNextUnitOffset(DwarfVersion));
2438 }
2439 }
2440
2441 return OutputDebugInfoSize - StartOutputDebugInfoSize;
2442}
2443
2444bool DWARFLinker::emitPaperTrailWarnings(const DWARFFile &File,
2445 OffsetsStringPool &StringPool) {
2446
2447 if (File.Warnings.empty())
2448 return false;
2449
2450 DIE *CUDie = DIE::get(DIEAlloc, dwarf::DW_TAG_compile_unit);
2451 CUDie->setOffset(11);
2452 StringRef Producer;
2453 StringRef WarningHeader;
2454
2455 switch (DwarfLinkerClientID) {
2457 Producer = StringPool.internString("dsymutil");
2458 WarningHeader = "dsymutil_warning";
2459 break;
2460
2461 default:
2462 Producer = StringPool.internString("dwarfopt");
2463 WarningHeader = "dwarfopt_warning";
2464 break;
2465 }
2466
2467 StringRef FileName = StringPool.internString(File.FileName);
2468 CUDie->addValue(DIEAlloc, dwarf::DW_AT_producer, dwarf::DW_FORM_strp,
2469 DIEInteger(StringPool.getStringOffset(Producer)));
2470 DIEBlock *String = new (DIEAlloc) DIEBlock();
2471 DIEBlocks.push_back(String);
2472 for (auto &C : FileName)
2473 String->addValue(DIEAlloc, dwarf::Attribute(0), dwarf::DW_FORM_data1,
2474 DIEInteger(C));
2475 String->addValue(DIEAlloc, dwarf::Attribute(0), dwarf::DW_FORM_data1,
2476 DIEInteger(0));
2477
2478 CUDie->addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_string, String);
2479 for (const auto &Warning : File.Warnings) {
2480 DIE &ConstDie = CUDie->addChild(DIE::get(DIEAlloc, dwarf::DW_TAG_constant));
2481 ConstDie.addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp,
2482 DIEInteger(StringPool.getStringOffset(WarningHeader)));
2483 ConstDie.addValue(DIEAlloc, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag,
2484 DIEInteger(1));
2485 ConstDie.addValue(DIEAlloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_strp,
2486 DIEInteger(StringPool.getStringOffset(Warning)));
2487 }
2488 unsigned Size = 4 /* FORM_strp */ + FileName.size() + 1 +
2489 File.Warnings.size() * (4 + 1 + 4) + 1 /* End of children */;
2490 DIEAbbrev Abbrev = CUDie->generateAbbrev();
2491 assignAbbrev(Abbrev);
2492 CUDie->setAbbrevNumber(Abbrev.getNumber());
2493 Size += getULEB128Size(Abbrev.getNumber());
2494 // Abbreviation ordering needed for classic compatibility.
2495 for (auto &Child : CUDie->children()) {
2496 Abbrev = Child.generateAbbrev();
2497 assignAbbrev(Abbrev);
2498 Child.setAbbrevNumber(Abbrev.getNumber());
2499 Size += getULEB128Size(Abbrev.getNumber());
2500 }
2501 CUDie->setSize(Size);
2502 TheDwarfEmitter->emitPaperTrailWarningsDie(*CUDie);
2503
2504 return true;
2505}
2506
2507void DWARFLinker::copyInvariantDebugSection(DWARFContext &Dwarf) {
2508 if (!needToTranslateStrings())
2509 TheDwarfEmitter->emitSectionContents(
2510 Dwarf.getDWARFObj().getLineSection().Data, "debug_line");
2511 TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getLocSection().Data,
2512 "debug_loc");
2513 TheDwarfEmitter->emitSectionContents(
2514 Dwarf.getDWARFObj().getRangesSection().Data, "debug_ranges");
2515 TheDwarfEmitter->emitSectionContents(
2516 Dwarf.getDWARFObj().getFrameSection().Data, "debug_frame");
2517 TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getArangesSection(),
2518 "debug_aranges");
2519 TheDwarfEmitter->emitSectionContents(
2520 Dwarf.getDWARFObj().getAddrSection().Data, "debug_addr");
2521 TheDwarfEmitter->emitSectionContents(
2522 Dwarf.getDWARFObj().getRnglistsSection().Data, "debug_rnglists");
2523 TheDwarfEmitter->emitSectionContents(
2524 Dwarf.getDWARFObj().getLoclistsSection().Data, "debug_loclists");
2525}
2526
2528 CompileUnitHandler OnCUDieLoaded) {
2529 ObjectContexts.emplace_back(LinkContext(File));
2530
2531 if (ObjectContexts.back().File.Dwarf) {
2532 for (const std::unique_ptr<DWARFUnit> &CU :
2533 ObjectContexts.back().File.Dwarf->compile_units()) {
2534 DWARFDie CUDie = CU->getUnitDIE();
2535
2536 if (!CUDie)
2537 continue;
2538
2539 OnCUDieLoaded(*CU);
2540
2541 if (!LLVM_UNLIKELY(Options.Update))
2542 registerModuleReference(CUDie, ObjectContexts.back(), Loader,
2543 OnCUDieLoaded);
2544 }
2545 }
2546}
2547
2549 assert(Options.NoOutput || TheDwarfEmitter);
2550 assert((Options.TargetDWARFVersion != 0) &&
2551 "TargetDWARFVersion should be set");
2552
2553 // First populate the data structure we need for each iteration of the
2554 // parallel loop.
2555 unsigned NumObjects = ObjectContexts.size();
2556
2557 // This Dwarf string pool which is used for emission. It must be used
2558 // serially as the order of calling getStringOffset matters for
2559 // reproducibility.
2560 OffsetsStringPool OffsetsStringPool(StringsTranslator, true);
2561
2562 // ODR Contexts for the optimize.
2563 DeclContextTree ODRContexts;
2564
2565 for (LinkContext &OptContext : ObjectContexts) {
2566 if (Options.Verbose) {
2567 if (DwarfLinkerClientID == DwarfLinkerClient::Dsymutil)
2568 outs() << "DEBUG MAP OBJECT: " << OptContext.File.FileName << "\n";
2569 else
2570 outs() << "OBJECT FILE: " << OptContext.File.FileName << "\n";
2571 }
2572
2573 if (emitPaperTrailWarnings(OptContext.File, OffsetsStringPool))
2574 continue;
2575
2576 if (!OptContext.File.Dwarf)
2577 continue;
2578
2579 if (Options.VerifyInputDWARF)
2580 verify(OptContext.File);
2581
2582 // Look for relocations that correspond to address map entries.
2583
2584 // there was findvalidrelocations previously ... probably we need to gather
2585 // info here
2586 if (LLVM_LIKELY(!Options.Update) &&
2587 !OptContext.File.Addresses->hasValidRelocs()) {
2588 if (Options.Verbose)
2589 outs() << "No valid relocations found. Skipping.\n";
2590
2591 // Set "Skip" flag as a signal to other loops that we should not
2592 // process this iteration.
2593 OptContext.Skip = true;
2594 continue;
2595 }
2596
2597 // Setup access to the debug info.
2598 if (!OptContext.File.Dwarf)
2599 continue;
2600
2601 // Check whether type units are presented.
2602 if (!OptContext.File.Dwarf->types_section_units().empty()) {
2603 reportWarning("type units are not currently supported: file will "
2604 "be skipped",
2605 OptContext.File);
2606 OptContext.Skip = true;
2607 continue;
2608 }
2609
2610 // In a first phase, just read in the debug info and load all clang modules.
2611 OptContext.CompileUnits.reserve(
2612 OptContext.File.Dwarf->getNumCompileUnits());
2613
2614 for (const auto &CU : OptContext.File.Dwarf->compile_units()) {
2615 auto CUDie = CU->getUnitDIE(false);
2616 if (Options.Verbose) {
2617 outs() << "Input compilation unit:";
2618 DIDumpOptions DumpOpts;
2619 DumpOpts.ChildRecurseDepth = 0;
2620 DumpOpts.Verbose = Options.Verbose;
2621 CUDie.dump(outs(), 0, DumpOpts);
2622 }
2623 }
2624
2625 for (auto &CU : OptContext.ModuleUnits) {
2626 if (Error Err =
2627 cloneModuleUnit(OptContext, CU, ODRContexts, OffsetsStringPool))
2628 reportWarning(toString(std::move(Err)), CU.File);
2629 }
2630 }
2631
2632 // At this point we know how much data we have emitted. We use this value to
2633 // compare canonical DIE offsets in analyzeContextInfo to see if a definition
2634 // is already emitted, without being affected by canonical die offsets set
2635 // later. This prevents undeterminism when analyze and clone execute
2636 // concurrently, as clone set the canonical DIE offset and analyze reads it.
2637 const uint64_t ModulesEndOffset =
2638 Options.NoOutput ? 0 : TheDwarfEmitter->getDebugInfoSectionSize();
2639
2640 // These variables manage the list of processed object files.
2641 // The mutex and condition variable are to ensure that this is thread safe.
2642 std::mutex ProcessedFilesMutex;
2643 std::condition_variable ProcessedFilesConditionVariable;
2644 BitVector ProcessedFiles(NumObjects, false);
2645
2646 // Analyzing the context info is particularly expensive so it is executed in
2647 // parallel with emitting the previous compile unit.
2648 auto AnalyzeLambda = [&](size_t I) {
2649 auto &Context = ObjectContexts[I];
2650
2651 if (Context.Skip || !Context.File.Dwarf)
2652 return;
2653
2654 for (const auto &CU : Context.File.Dwarf->compile_units()) {
2655 // The !isClangModuleRef condition effectively skips over fully resolved
2656 // skeleton units.
2657 auto CUDie = CU->getUnitDIE();
2658 std::string PCMFile = getPCMFile(CUDie, Options.ObjectPrefixMap);
2659
2660 if (!CUDie || LLVM_UNLIKELY(Options.Update) ||
2661 !isClangModuleRef(CUDie, PCMFile, Context, 0, true).first) {
2662 Context.CompileUnits.push_back(std::make_unique<CompileUnit>(
2663 *CU, UniqueUnitID++, !Options.NoODR && !Options.Update, ""));
2664 }
2665 }
2666
2667 // Now build the DIE parent links that we will use during the next phase.
2668 for (auto &CurrentUnit : Context.CompileUnits) {
2669 auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE();
2670 if (!CUDie)
2671 continue;
2672 analyzeContextInfo(CurrentUnit->getOrigUnit().getUnitDIE(), 0,
2673 *CurrentUnit, &ODRContexts.getRoot(), ODRContexts,
2674 ModulesEndOffset, Options.ParseableSwiftInterfaces,
2675 [&](const Twine &Warning, const DWARFDie &DIE) {
2676 reportWarning(Warning, Context.File, &DIE);
2677 });
2678 }
2679 };
2680
2681 // For each object file map how many bytes were emitted.
2682 StringMap<DebugInfoSize> SizeByObject;
2683
2684 // And then the remaining work in serial again.
2685 // Note, although this loop runs in serial, it can run in parallel with
2686 // the analyzeContextInfo loop so long as we process files with indices >=
2687 // than those processed by analyzeContextInfo.
2688 auto CloneLambda = [&](size_t I) {
2689 auto &OptContext = ObjectContexts[I];
2690 if (OptContext.Skip || !OptContext.File.Dwarf)
2691 return;
2692
2693 // Then mark all the DIEs that need to be present in the generated output
2694 // and collect some information about them.
2695 // Note that this loop can not be merged with the previous one because
2696 // cross-cu references require the ParentIdx to be setup for every CU in
2697 // the object file before calling this.
2698 if (LLVM_UNLIKELY(Options.Update)) {
2699 for (auto &CurrentUnit : OptContext.CompileUnits)
2700 CurrentUnit->markEverythingAsKept();
2701 copyInvariantDebugSection(*OptContext.File.Dwarf);
2702 } else {
2703 for (auto &CurrentUnit : OptContext.CompileUnits) {
2704 lookForDIEsToKeep(*OptContext.File.Addresses,
2705 OptContext.File.Addresses->getValidAddressRanges(),
2706 OptContext.CompileUnits,
2707 CurrentUnit->getOrigUnit().getUnitDIE(),
2708 OptContext.File, *CurrentUnit, 0);
2709#ifndef NDEBUG
2710 verifyKeepChain(*CurrentUnit);
2711#endif
2712 }
2713 }
2714
2715 // The calls to applyValidRelocs inside cloneDIE will walk the reloc
2716 // array again (in the same way findValidRelocsInDebugInfo() did). We
2717 // need to reset the NextValidReloc index to the beginning.
2718 if (OptContext.File.Addresses->hasValidRelocs() ||
2719 LLVM_UNLIKELY(Options.Update)) {
2720 SizeByObject[OptContext.File.FileName].Input =
2721 getDebugInfoSize(*OptContext.File.Dwarf);
2722 SizeByObject[OptContext.File.FileName].Output =
2723 DIECloner(*this, TheDwarfEmitter, OptContext.File, DIEAlloc,
2724 OptContext.CompileUnits, Options.Update)
2725 .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
2727 OptContext.File.Dwarf->isLittleEndian());
2728 }
2729 if (!Options.NoOutput && !OptContext.CompileUnits.empty() &&
2730 LLVM_LIKELY(!Options.Update))
2731 patchFrameInfoForObject(
2732 OptContext.File, OptContext.File.Addresses->getValidAddressRanges(),
2733 *OptContext.File.Dwarf,
2734 OptContext.CompileUnits[0]->getOrigUnit().getAddressByteSize());
2735
2736 // Clean-up before starting working on the next object.
2737 cleanupAuxiliarryData(OptContext);
2738 };
2739
2740 auto EmitLambda = [&]() {
2741 // Emit everything that's global.
2742 if (!Options.NoOutput) {
2743 TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
2744 TheDwarfEmitter->emitStrings(OffsetsStringPool);
2745 for (DwarfLinkerAccelTableKind TableKind : Options.AccelTables) {
2746 switch (TableKind) {
2748 TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces);
2749 TheDwarfEmitter->emitAppleNames(AppleNames);
2750 TheDwarfEmitter->emitAppleTypes(AppleTypes);
2751 TheDwarfEmitter->emitAppleObjc(AppleObjc);
2752 break;
2754 // Already emitted by emitAcceleratorEntriesForUnit.
2755 // Already emitted by emitAcceleratorEntriesForUnit.
2756 break;
2758 TheDwarfEmitter->emitDebugNames(DebugNames);
2759 break;
2760 }
2761 }
2762 }
2763 };
2764
2765 auto AnalyzeAll = [&]() {
2766 for (unsigned I = 0, E = NumObjects; I != E; ++I) {
2767 AnalyzeLambda(I);
2768
2769 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
2770 ProcessedFiles.set(I);
2771 ProcessedFilesConditionVariable.notify_one();
2772 }
2773 };
2774
2775 auto CloneAll = [&]() {
2776 for (unsigned I = 0, E = NumObjects; I != E; ++I) {
2777 {
2778 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
2779 if (!ProcessedFiles[I]) {
2780 ProcessedFilesConditionVariable.wait(
2781 LockGuard, [&]() { return ProcessedFiles[I]; });
2782 }
2783 }
2784
2785 CloneLambda(I);
2786 }
2787 EmitLambda();
2788 };
2789
2790 // To limit memory usage in the single threaded case, analyze and clone are
2791 // run sequentially so the OptContext is freed after processing each object
2792 // in endDebugObject.
2793 if (Options.Threads == 1) {
2794 for (unsigned I = 0, E = NumObjects; I != E; ++I) {
2795 AnalyzeLambda(I);
2796 CloneLambda(I);
2797 }
2798 EmitLambda();
2799 } else {
2801 Pool.async(AnalyzeAll);
2802 Pool.async(CloneAll);
2803 Pool.wait();
2804 }
2805
2806 if (Options.Statistics) {
2807 // Create a vector sorted in descending order by output size.
2808 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
2809 for (auto &E : SizeByObject)
2810 Sorted.emplace_back(E.first(), E.second);
2811 llvm::sort(Sorted, [](auto &LHS, auto &RHS) {
2812 return LHS.second.Output > RHS.second.Output;
2813 });
2814
2815 auto ComputePercentange = [](int64_t Input, int64_t Output) -> float {
2816 const float Difference = Output - Input;
2817 const float Sum = Input + Output;
2818 if (Sum == 0)
2819 return 0;
2820 return (Difference / (Sum / 2));
2821 };
2822
2823 int64_t InputTotal = 0;
2824 int64_t OutputTotal = 0;
2825 const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n";
2826
2827 // Print header.
2828 outs() << ".debug_info section size (in bytes)\n";
2829 outs() << "----------------------------------------------------------------"
2830 "---------------\n";
2831 outs() << "Filename Object "
2832 " dSYM Change\n";
2833 outs() << "----------------------------------------------------------------"
2834 "---------------\n";
2835
2836 // Print body.
2837 for (auto &E : Sorted) {
2838 InputTotal += E.second.Input;
2839 OutputTotal += E.second.Output;
2840 llvm::outs() << formatv(
2841 FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input,
2842 E.second.Output, ComputePercentange(E.second.Input, E.second.Output));
2843 }
2844 // Print total and footer.
2845 outs() << "----------------------------------------------------------------"
2846 "---------------\n";
2847 llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal,
2848 ComputePercentange(InputTotal, OutputTotal));
2849 outs() << "----------------------------------------------------------------"
2850 "---------------\n\n";
2851 }
2852
2853 return Error::success();
2854}
2855
2856Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
2857 DeclContextTree &ODRContexts,
2859 unsigned Indent) {
2860 assert(Unit.Unit.get() != nullptr);
2861
2862 if (!Unit.Unit->getOrigUnit().getUnitDIE().hasChildren())
2863 return Error::success();
2864
2865 if (Options.Verbose) {
2866 outs().indent(Indent);
2867 outs() << "cloning .debug_info from " << Unit.File.FileName << "\n";
2868 }
2869
2870 // Analyze context for the module.
2871 analyzeContextInfo(Unit.Unit->getOrigUnit().getUnitDIE(), 0, *(Unit.Unit),
2872 &ODRContexts.getRoot(), ODRContexts, 0,
2873 Options.ParseableSwiftInterfaces,
2874 [&](const Twine &Warning, const DWARFDie &DIE) {
2875 reportWarning(Warning, Context.File, &DIE);
2876 });
2877 // Keep everything.
2878 Unit.Unit->markEverythingAsKept();
2879
2880 // Clone unit.
2881 UnitListTy CompileUnits;
2882 CompileUnits.emplace_back(std::move(Unit.Unit));
2883 assert(TheDwarfEmitter);
2884 DIECloner(*this, TheDwarfEmitter, Unit.File, DIEAlloc, CompileUnits,
2885 Options.Update)
2886 .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File, OffsetsStringPool,
2887 Unit.File.Dwarf->isLittleEndian());
2888 return Error::success();
2889}
2890
2891bool DWARFLinker::verify(const DWARFFile &File) {
2892 assert(File.Dwarf);
2893
2894 DIDumpOptions DumpOpts;
2895 if (!File.Dwarf->verify(llvm::outs(), DumpOpts.noImplicitRecursion())) {
2896 reportWarning("input verification failed", File);
2897 return false;
2898 }
2899 return true;
2900}
2901
2902} // namespace llvm
This file implements the BitVector class.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
#define LLVM_UNLIKELY(EXPR)
Definition: Compiler.h:210
#define LLVM_LIKELY(EXPR)
Definition: Compiler.h:209
dxil DXContainer Global Emitter
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
uint64_t Addr
std::string Name
uint64_t Size
Provides ErrorOr<T> smart pointer.
#define DWARF2_LINE_DEFAULT_IS_STMT
Definition: MCDwarf.h:111
#define I(x, y, z)
Definition: MD5.cpp:58
LLVMContext & Context
#define P(N)
ppc ctr loops verify
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
@ Flags
Definition: TextStubV5.cpp:93
Value * RHS
Value * LHS
virtual ~AddressesMap()
BitVector & set()
Definition: BitVector.h:351
void Reset()
Deallocate all but the current slab and reset the current pointer to the beginning of it,...
Definition: Allocator.h:123
Stores all information relating to a compile unit, be it in its original instance in the object file ...
An integer value DIE.
Definition: DIE.h:168
value_range values()
Definition: DIE.h:732
A structured debug information entry.
Definition: DIE.h:744
static DIE * get(BumpPtrAllocator &Alloc, dwarf::Tag Tag)
Definition: DIE.h:774
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
Definition: DWARFContext.h:46
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition: DWARFDie.h:42
iterator_range< iterator > children() const
Definition: DWARFDie.h:395
std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition: DWARFDie.cpp:247
dwarf::Tag getTag() const
Definition: DWARFDie.h:71
Encoding
Size and signedness of expression operations' operands.
This class represents DWARF information for source file and its address map.
Definition: DWARFLinker.h:224
bool isFormClass(FormClass FC) const
bool skipValue(DataExtractor DebugInfoData, uint64_t *OffsetPtr, const dwarf::FormParams Params) const
Skip a form's value in DebugInfoData at the offset specified by OffsetPtr.
Error link()
Link debug info for added objFiles.
void addObjectFile(DWARFFile &File, objFileLoader Loader=nullptr, CompileUnitHandler OnCUDieLoaded=[](const DWARFUnit &) {})
Add object file to be linked.
This class gives a tree-like API to the DenseMap that stores the DeclContext objects.
PointerIntPair< DeclContext *, 1 > getChildDeclContext(DeclContext &Context, const DWARFDie &DIE, CompileUnit &Unit, bool InClangModule)
Get the child of Context described by DIE in Unit.
A DeclContext is a named program scope that is used for ODR uniquing of types.
virtual void emitPaperTrailWarningsDie(DIE &Die)=0
Emit DIE containing warnings.
virtual void emitCIE(StringRef CIEBytes)=0
Emit a CIE.
virtual void emitPubNamesForUnit(const CompileUnit &Unit)=0
Emit the .debug_pubnames contribution for Unit.
virtual void emitDwarfDebugArangesTable(const CompileUnit &Unit, const AddressRanges &LinkedRanges)=0
Emit .debug_aranges entries for Unit.
virtual uint64_t getLineSectionSize() const =0
Returns size of generated .debug_line section.
virtual MCSymbol * emitDwarfDebugRangeListHeader(const CompileUnit &Unit)=0
Emit debug ranges (.debug_ranges, .debug_rnglists) header.
virtual void emitAppleNames(AccelTable< AppleAccelTableStaticOffsetData > &Table)=0
Emit Apple names accelerator table.
virtual void emitDebugNames(AccelTable< DWARF5AccelTableStaticData > &Table)=0
Emit DWARF debug names.
virtual void translateLineTable(DataExtractor LineData, uint64_t Offset)=0
Copy the .debug_line over to the updated binary while unobfuscating the file names and directories.
virtual void emitStrings(const NonRelocatableStringpool &Pool)=0
Emit the string table described by Pool.
virtual void emitPubTypesForUnit(const CompileUnit &Unit)=0
Emit the .debug_pubtypes contribution for Unit.
virtual MCSymbol * emitDwarfDebugLocListHeader(const CompileUnit &Unit)=0
Emit debug locations (.debug_loc, .debug_loclists) header.
virtual void emitAppleNamespaces(AccelTable< AppleAccelTableStaticOffsetData > &Table)=0
Emit Apple namespaces accelerator table.
virtual void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint64_t Address, StringRef Bytes)=0
Emit an FDE with data Bytes.
virtual void emitLineTableForUnit(MCDwarfLineTableParams Params, StringRef PrologueBytes, unsigned MinInstLength, std::vector< DWARFDebugLine::Row > &Rows, unsigned AdddressSize)=0
Emit the line table described in Rows into the .debug_line section.
virtual uint64_t getDebugInfoSectionSize() const =0
Returns size of generated .debug_info section.
virtual ~DwarfEmitter()
virtual void emitDwarfDebugLocListFragment(const CompileUnit &Unit, const DWARFLocationExpressionsVector &LinkedLocationExpression, PatchLocation Patch)=0
Emit debug locations (.debug_loc, .debug_loclists) fragment.
virtual void emitAbbrevs(const std::vector< std::unique_ptr< DIEAbbrev > > &Abbrevs, unsigned DwarfVersion)=0
Emit the abbreviation table Abbrevs to the .debug_abbrev section.
virtual void emitAppleTypes(AccelTable< AppleAccelTableStaticTypeData > &Table)=0
Emit Apple type accelerator table.
virtual void emitDwarfDebugLocListFooter(const CompileUnit &Unit, MCSymbol *EndLabel)=0
Emit debug locations (.debug_loc, .debug_loclists) footer.
virtual void emitDwarfDebugRangeListFooter(const CompileUnit &Unit, MCSymbol *EndLabel)=0
Emit debug ranges (.debug_ranges, .debug_rnglists) footer.
virtual void emitSectionContents(StringRef SecData, StringRef SecName)=0
Emit section named SecName with data SecData.
virtual void emitDwarfDebugRangeListFragment(const CompileUnit &Unit, const AddressRanges &LinkedRanges, PatchLocation Patch)=0
Emit debug ranges (.debug_ranges, .debug_rnglists) fragment.
virtual uint64_t getFrameSectionSize() const =0
Returns size of generated .debug_frame section.
virtual void emitAppleObjc(AccelTable< AppleAccelTableStaticOffsetData > &Table)=0
Emit Apple Objective-C accelerator table.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:261
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:111
iterator end()
Definition: StringMap.h:204
iterator find(StringRef Key)
Definition: StringMap.h:217
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition: StringMap.h:286
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
StringRef take_back(size_t N=1) const
Return a StringRef equal to 'this' but with only the last N elements remaining.
Definition: StringRef.h:576
static constexpr size_t npos
Definition: StringRef.h:52
Helper for making strong types.
A ThreadPool for asynchronous parallel execution on a defined number of threads.
Definition: ThreadPool.h:52
void wait()
Blocking wait for all the threads to complete and the queue to be empty.
Definition: ThreadPool.cpp:202
auto async(Function &&F, Args &&...ArgList)
Asynchronous submission of a task to the pool.
Definition: ThreadPool.h:66
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
static raw_ostream & error()
Convenience method for printing "error: " to stderr.
Definition: WithColor.cpp:83
An efficient, type-erasing, non-owning reference to a callable.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
StringRef FormEncodingString(unsigned Encoding)
Definition: Dwarf.cpp:105
#define UINT64_MAX
Definition: DataTypes.h:77
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
std::optional< uint64_t > toAddress(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an address.
Attribute
Attributes.
Definition: Dwarf.h:123
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
bool doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC, uint16_t DwarfVersion)
Check whether specified Form belongs to the FC class.
std::optional< uint64_t > toSectionOffset(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an section offset.
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
@ DW_CHILDREN_yes
Definition: Dwarf.h:513
@ DW_FLAG_type_implementation
Definition: Dwarf.h:600
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
Definition: Path.cpp:699
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:577
bool replace_path_prefix(SmallVectorImpl< char > &Path, StringRef OldPrefix, StringRef NewPrefix, Style style=Style::native)
Replace matching path prefix with another path.
Definition: Path.cpp:518
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:456
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
ThreadPoolStrategy hardware_concurrency(unsigned ThreadCount=0)
Returns a default thread strategy where all available hardware resources are to be used,...
Definition: Threading.h:185
static void verifyKeepChain(CompileUnit &CU)
Verify the keep chain by looking for DIEs that are kept but who's parent isn't.
@ Offset
Definition: DWP.cpp:406
static std::string getPCMFile(const DWARFDie &CUDie, objectPrefixMap *ObjectPrefixMap)
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
static void updateRefIncompleteness(const DWARFDie &Die, CompileUnit &CU, CompileUnit::DIEInfo &RefInfo)
Helper that updates the completeness of the current DIE based on the completeness of the DIEs it refe...
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:79
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
Definition: STLExtras.h:2076
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Definition: STLExtras.h:2129
std::vector< std::unique_ptr< CompileUnit > > UnitListTy
Definition: DWARFLinker.h:220
SmallVector< PatchLocation > RngListAttributesTy
function_ref< void(const DWARFUnit &Unit)> CompileUnitHandler
Definition: DWARFLinker.h:253
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:2051
static CompileUnit * getUnitForOffset(const UnitListTy &Units, uint64_t Offset)
Similar to DWARFUnitSection::getUnitForOffset(), but returning our CompileUnit object instead.
Definition: DWARFLinker.cpp:56
static void resolveRelativeObjectPath(SmallVectorImpl< char > &Buf, DWARFDie CU)
Resolve the relative path to a build artifact referenced by DWARF by applying DW_AT_comp_dir.
SmallVector< std::pair< PatchLocation, int64_t > > LocListAttributesTy
static void insertLineSequence(std::vector< DWARFDebugLine::Row > &Seq, std::vector< DWARFDebugLine::Row > &Rows)
Insert the new line info sequence Seq into the current set of already linked line info Rows.
static void analyzeContextInfo(const DWARFDie &DIE, unsigned ParentIdx, CompileUnit &CU, DeclContext *CurrentDeclContext, DeclContextTree &Contexts, uint64_t ModulesEndOffset, swiftInterfacesMap *ParseableSwiftInterfaces, std::function< void(const Twine &, const DWARFDie &)> ReportWarning)
Recursive helper to build the global DeclContext information and gather the child->parent relationshi...
std::vector< DWARFLocationExpression > DWARFLocationExpressionsVector
Represents a set of absolute location expressions.
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:511
std::function< ErrorOr< DWARFFile & >(StringRef ContainerName, StringRef Path)> objFileLoader
Definition: DWARFLinker.h:249
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1744
static uint64_t getDebugInfoSize(DWARFContext &Dwarf)
Compute the total size of the debug info.
Definition: DWARFLinker.cpp:46
static bool isTypeTag(uint16_t Tag)
AccelTableKind
The kind of accelerator tables we should emit.
Definition: DwarfDebug.h:288
@ Dwarf
DWARF v5 .debug_names.
StrongType< NonRelocatableStringpool, OffsetsTag > OffsetsStringPool
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
static uint64_t getDwoId(const DWARFDie &CUDie)
std::map< std::string, std::string > swiftInterfacesMap
Definition: DWARFLinker.h:250
static bool updatePruning(const DWARFDie &Die, CompileUnit &CU, uint64_t ModulesEndOffset)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
static std::string remapPath(StringRef Path, const objectPrefixMap &ObjectPrefixMap)
@ Ref
The access may reference the value stored in memory.
static std::optional< StringRef > StripTemplateParameters(StringRef Name)
unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
Definition: LEB128.cpp:19
DwarfLinkerAccelTableKind
The kind of accelerator tables we should emit.
Definition: DWARFLinker.h:34
@ Apple
.apple_names, .apple_namespaces, .apple_types, .apple_objc.
@ Pub
.debug_pubnames, .debug_pubtypes
static bool shouldSkipAttribute(bool Update, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, uint16_t Tag, bool InDebugMap, bool SkipPC, bool InFunctionScope)
static void updateChildIncompleteness(const DWARFDie &Die, CompileUnit &CU, CompileUnit::DIEInfo &ChildInfo)
Helper that updates the completeness of the current DIE based on the completeness of one of its child...
static void updateChildPruning(const DWARFDie &Die, CompileUnit &CU, CompileUnit::DIEInfo &ChildInfo)
std::map< std::string, std::string > objectPrefixMap
Definition: DWARFLinker.h:251
uint32_t djbHash(StringRef Buffer, uint32_t H=5381)
The Bernstein hash function used by the DWARF accelerator tables.
Definition: DJB.h:21
static void analyzeImportedModule(const DWARFDie &DIE, CompileUnit &CU, swiftInterfacesMap *ParseableSwiftInterfaces, std::function< void(const Twine &, const DWARFDie &)> ReportWarning)
Collect references to parseable Swift interfaces in imported DW_TAG_module blocks.
static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag)
static bool isODRCanonicalCandidate(const DWARFDie &Die, CompileUnit &CU)
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
Definition: LEB128.h:80
static bool isObjCSelector(StringRef Name)
ContextWorklistItemType
The distinct types of work performed by the work loop in analyzeContextInfo.
AddressRangesMap RangesTy
Mapped value in the address map is the offset to apply to the linked address.
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1043
static bool isODRAttribute(uint16_t Attr)
Definition: DWARFLinker.cpp:88
static void patchStmtList(DIE &Die, DIEInteger Offset)
Information gathered about a DIE in the object file.
bool Prune
Is this a pure forward declaration we can strip?
bool Incomplete
Does DIE transitively refer an incomplete decl?
This class represents an item in the work list.
CompileUnit::DIEInfo * OtherInfo
ContextWorklistItem(DWARFDie Die, DeclContext *Context, unsigned ParentIdx, bool InImportedModule)
ContextWorklistItemType Type
ContextWorklistItem(DWARFDie Die, ContextWorklistItemType T, CompileUnit::DIEInfo *OtherInfo=nullptr)
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:189
unsigned ChildRecurseDepth
Definition: DIContext.h:191
static bool mayHaveLocationList(dwarf::Attribute Attr)
Identify DWARF attributes that may contain a pointer to a location list.
Definition: DWARFDie.cpp:704
static bool mayHaveLocationExpr(dwarf::Attribute Attr)
Identifies DWARF attributes that may contain a reference to a DWARF expression.
Definition: DWARFDie.cpp:721
Standard .debug_line state machine structure.
Hold the input and output of the debug info size in bytes.
Definition: DWARFLinker.cpp:40