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