LLVM 20.0.0git
DWARFLinkerCompileUnit.cpp
Go to the documentation of this file.
1//=== DWARFLinkerCompileUnit.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
11#include "DIEAttributeCloner.h"
12#include "DIEGenerator.h"
13#include "DependencyTracker.h"
18#include "llvm/Support/DJB.h"
21#include "llvm/Support/Path.h"
22#include <utility>
23
24using namespace llvm;
25using namespace dwarf_linker;
26using namespace dwarf_linker::parallel;
27
29 StringRef ClangModuleName, DWARFFile &File,
30 OffsetToUnitTy UnitFromOffset,
31 dwarf::FormParams Format, llvm::endianness Endianess)
32 : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),
33 getUnitFromOffset(UnitFromOffset), Stage(Stage::CreatedNotLoaded),
34 AcceleratorRecords(&GlobalData.getAllocator()) {
35 UnitName = File.FileName;
36 setOutputFormat(Format, Endianess);
38}
39
41 unsigned ID, StringRef ClangModuleName,
42 DWARFFile &File, OffsetToUnitTy UnitFromOffset,
44 : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),
45 OrigUnit(&OrigUnit), getUnitFromOffset(UnitFromOffset),
46 Stage(Stage::CreatedNotLoaded),
47 AcceleratorRecords(&GlobalData.getAllocator()) {
48 setOutputFormat(Format, Endianess);
50
51 DWARFDie CUDie = OrigUnit.getUnitDIE();
52 if (!CUDie)
53 return;
54
55 if (std::optional<DWARFFormValue> Val = CUDie.find(dwarf::DW_AT_language)) {
56 uint16_t LangVal = dwarf::toUnsigned(Val, 0);
57 if (isODRLanguage(LangVal))
58 Language = LangVal;
59 }
60
61 if (!GlobalData.getOptions().NoODR && Language.has_value())
62 NoODR = false;
63
64 if (const char *CUName = CUDie.getName(DINameKind::ShortName))
65 UnitName = CUName;
66 else
67 UnitName = File.FileName;
68 SysRoot = dwarf::toStringRef(CUDie.find(dwarf::DW_AT_LLVM_sysroot)).str();
69}
70
72 LineTablePtr = File.Dwarf->getLineTableForUnit(&getOrigUnit());
73}
74
76 // Nothing to reset if stage is less than "Loaded".
77 if (getStage() < Stage::Loaded)
78 return;
79
80 // Note: We need to do erasing for "Loaded" stage because
81 // if live analysys failed then we will have "Loaded" stage
82 // with marking from "LivenessAnalysisDone" stage partially
83 // done. That marking should be cleared.
84
85 for (DIEInfo &Info : DieInfoArray)
86 Info.unsetFlagsWhichSetDuringLiveAnalysis();
87
88 LowPc = std::nullopt;
89 HighPc = 0;
90 Labels.clear();
91 Ranges.clear();
92 Dependencies.reset(nullptr);
93
94 if (getStage() < Stage::Cloned) {
96 return;
97 }
98
99 AcceleratorRecords.erase();
100 AbbreviationsSet.clear();
101 Abbreviations.clear();
102 OutUnitDIE = nullptr;
103 DebugAddrIndexMap.clear();
104
105 for (uint64_t &Offset : OutDieOffsetArray)
106 Offset = 0;
107 for (TypeEntry *&Name : TypeEntries)
108 Name = nullptr;
110
112}
113
115 DWARFDie InputUnitDIE = getUnitDIE(false);
116 if (!InputUnitDIE)
117 return false;
118
119 // load input dies, resize Info structures array.
120 DieInfoArray.resize(getOrigUnit().getNumDIEs());
121 OutDieOffsetArray.resize(getOrigUnit().getNumDIEs(), 0);
122 if (!NoODR)
123 TypeEntries.resize(getOrigUnit().getNumDIEs());
124 return true;
125}
126
127void CompileUnit::analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
128 bool IsODRUnavailableFunctionScope) {
129 CompileUnit::DIEInfo &DieInfo = getDIEInfo(DieEntry);
130
131 for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry);
132 CurChild && CurChild->getAbbreviationDeclarationPtr();
133 CurChild = getSiblingEntry(CurChild)) {
134 CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild);
135 bool ChildIsODRUnavailableFunctionScope = IsODRUnavailableFunctionScope;
136
137 if (DieInfo.getIsInMouduleScope())
138 ChildInfo.setIsInMouduleScope();
139
140 if (DieInfo.getIsInFunctionScope())
141 ChildInfo.setIsInFunctionScope();
142
143 if (DieInfo.getIsInAnonNamespaceScope())
144 ChildInfo.setIsInAnonNamespaceScope();
145
146 switch (CurChild->getTag()) {
147 case dwarf::DW_TAG_module:
148 ChildInfo.setIsInMouduleScope();
149 if (DieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
150 dwarf::toString(find(CurChild, dwarf::DW_AT_name), "") !=
152 analyzeImportedModule(CurChild);
153 break;
154 case dwarf::DW_TAG_subprogram:
155 ChildInfo.setIsInFunctionScope();
156 if (!ChildIsODRUnavailableFunctionScope &&
157 !ChildInfo.getIsInMouduleScope()) {
158 if (find(CurChild,
159 {dwarf::DW_AT_abstract_origin, dwarf::DW_AT_specification}))
160 ChildIsODRUnavailableFunctionScope = true;
161 }
162 break;
163 case dwarf::DW_TAG_namespace: {
164 UnitEntryPairTy NamespaceEntry = {this, CurChild};
165
166 if (find(CurChild, dwarf::DW_AT_extension))
167 NamespaceEntry = NamespaceEntry.getNamespaceOrigin();
168
169 if (!NamespaceEntry.CU->find(NamespaceEntry.DieEntry, dwarf::DW_AT_name))
170 ChildInfo.setIsInAnonNamespaceScope();
171 } break;
172 default:
173 break;
174 }
175
176 if (!isClangModule() && !getGlobalData().getOptions().UpdateIndexTablesOnly)
177 ChildInfo.setTrackLiveness();
178
179 if ((!ChildInfo.getIsInAnonNamespaceScope() &&
180 !ChildIsODRUnavailableFunctionScope && !NoODR))
181 ChildInfo.setODRAvailable();
182
183 if (CurChild->hasChildren())
184 analyzeDWARFStructureRec(CurChild, ChildIsODRUnavailableFunctionScope);
185 }
186}
187
189 StringPool &GlobalStrings) {
190 if (LineTablePtr) {
191 if (LineTablePtr->hasFileAtIndex(FileIdx)) {
192 // Cache the resolved paths based on the index in the line table,
193 // because calling realpath is expensive.
194 ResolvedPathsMap::const_iterator It = ResolvedFullPaths.find(FileIdx);
195 if (It == ResolvedFullPaths.end()) {
196 std::string OrigFileName;
197 bool FoundFileName = LineTablePtr->getFileNameByIndex(
198 FileIdx, getOrigUnit().getCompilationDir(),
199 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
200 OrigFileName);
201 (void)FoundFileName;
202 assert(FoundFileName && "Must get file name from line table");
203
204 // Second level of caching, this time based on the file's parent
205 // path.
206 StringRef FileName = sys::path::filename(OrigFileName);
207 StringRef ParentPath = sys::path::parent_path(OrigFileName);
208
209 // If the ParentPath has not yet been resolved, resolve and cache it for
210 // future look-ups.
212 ResolvedParentPaths.find(ParentPath);
213 if (ParentIt == ResolvedParentPaths.end()) {
214 SmallString<256> RealPath;
215 sys::fs::real_path(ParentPath, RealPath);
216 ParentIt =
217 ResolvedParentPaths
218 .insert({ParentPath, GlobalStrings.insert(RealPath).first})
219 .first;
220 }
221
222 // Join the file name again with the resolved path.
223 SmallString<256> ResolvedPath(ParentIt->second->first());
224 sys::path::append(ResolvedPath, FileName);
225
226 It = ResolvedFullPaths
227 .insert(std::make_pair(
228 FileIdx, GlobalStrings.insert(ResolvedPath).first))
229 .first;
230 }
231
232 return It->second;
233 }
234 }
235
236 return nullptr;
237}
238
240 AbbreviationsSet.clear();
241 ResolvedFullPaths.shrink_and_clear();
242 ResolvedParentPaths.clear();
244 DieInfoArray = SmallVector<DIEInfo>();
245 OutDieOffsetArray = SmallVector<uint64_t>();
246 TypeEntries = SmallVector<TypeEntry *>();
247 Dependencies.reset(nullptr);
248 getOrigUnit().clear();
249}
250
251/// Collect references to parseable Swift interfaces in imported
252/// DW_TAG_module blocks.
254 if (!Language || Language != dwarf::DW_LANG_Swift)
255 return;
256
258 return;
259
260 StringRef Path =
261 dwarf::toStringRef(find(DieEntry, dwarf::DW_AT_LLVM_include_path));
262 if (!Path.ends_with(".swiftinterface"))
263 return;
264 // Don't track interfaces that are part of the SDK.
266 dwarf::toStringRef(find(DieEntry, dwarf::DW_AT_LLVM_sysroot));
267 if (SysRoot.empty())
269 if (!SysRoot.empty() && Path.starts_with(SysRoot))
270 return;
271 // Don't track interfaces that are part of the toolchain.
272 // For example: Swift, _Concurrency, ...
273 StringRef DeveloperDir = guessDeveloperDir(SysRoot);
274 if (!DeveloperDir.empty() && Path.starts_with(DeveloperDir))
275 return;
276 if (isInToolchainDir(Path))
277 return;
278 if (std::optional<DWARFFormValue> Val = find(DieEntry, dwarf::DW_AT_name)) {
279 Expected<const char *> Name = Val->getAsCString();
280 if (!Name) {
281 warn(Name.takeError());
282 return;
283 }
284
286 // The prepend path is applied later when copying.
287 SmallString<128> ResolvedPath;
288 if (sys::path::is_relative(Path))
290 ResolvedPath,
291 dwarf::toString(getUnitDIE().find(dwarf::DW_AT_comp_dir), ""));
292 sys::path::append(ResolvedPath, Path);
293 if (!Entry.empty() && Entry != ResolvedPath) {
294 DWARFDie Die = getDIE(DieEntry);
295 warn(Twine("conflicting parseable interfaces for Swift Module ") + *Name +
296 ": " + Entry + " and " + Path + ".",
297 &Die);
298 }
299 Entry = std::string(ResolvedPath);
300 }
301}
302
304 if (!getUnitDIE().isValid())
305 return Error::success();
306
307 SyntheticTypeNameBuilder NameBuilder(TypePoolRef);
308 return assignTypeNamesRec(getDebugInfoEntry(0), NameBuilder);
309}
310
311Error CompileUnit::assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry,
312 SyntheticTypeNameBuilder &NameBuilder) {
313 OrderedChildrenIndexAssigner ChildrenIndexAssigner(*this, DieEntry);
314 for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry);
315 CurChild && CurChild->getAbbreviationDeclarationPtr();
316 CurChild = getSiblingEntry(CurChild)) {
317 CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild);
318 if (!ChildInfo.needToPlaceInTypeTable())
319 continue;
320
321 assert(ChildInfo.getODRAvailable());
322 if (Error Err = NameBuilder.assignName(
323 {this, CurChild},
324 ChildrenIndexAssigner.getChildIndex(*this, CurChild)))
325 return Err;
326
327 if (Error Err = assignTypeNamesRec(CurChild, NameBuilder))
328 return Err;
329 }
330
331 return Error::success();
332}
333
335 if (std::optional<SectionDescriptor *> DebugInfoSection =
337
338 (*DebugInfoSection)
339 ->ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {
340 /// Replace stored DIE indexes with DIE output offsets.
342 Patch.RefCU.getPointer()->getDieOutOffset(
344 });
345
346 (*DebugInfoSection)
347 ->ListDebugULEB128DieRefPatch.forEach(
348 [&](DebugULEB128DieRefPatch &Patch) {
349 /// Replace stored DIE indexes with DIE output offsets.
351 Patch.RefCU.getPointer()->getDieOutOffset(
353 });
354 }
355
356 if (std::optional<SectionDescriptor *> DebugLocSection =
358 (*DebugLocSection)
359 ->ListDebugULEB128DieRefPatch.forEach(
360 [](DebugULEB128DieRefPatch &Patch) {
361 /// Replace stored DIE indexes with DIE output offsets.
363 Patch.RefCU.getPointer()->getDieOutOffset(
365 });
366 }
367
368 if (std::optional<SectionDescriptor *> DebugLocListsSection =
370 (*DebugLocListsSection)
371 ->ListDebugULEB128DieRefPatch.forEach(
372 [](DebugULEB128DieRefPatch &Patch) {
373 /// Replace stored DIE indexes with DIE output offsets.
375 Patch.RefCU.getPointer()->getDieOutOffset(
377 });
378 }
379}
380
381std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference(
382 const DWARFFormValue &RefValue,
383 ResolveInterCUReferencesMode CanResolveInterCUReferences) {
384 CompileUnit *RefCU;
385 uint64_t RefDIEOffset;
386 if (std::optional<uint64_t> Offset = RefValue.getAsRelativeReference()) {
387 RefCU = this;
388 RefDIEOffset = RefValue.getUnit()->getOffset() + *Offset;
389 } else if (Offset = RefValue.getAsDebugInfoReference(); Offset) {
390 RefCU = getUnitFromOffset(*Offset);
391 RefDIEOffset = *Offset;
392 } else {
393 return std::nullopt;
394 }
395
396 if (RefCU == this) {
397 // Referenced DIE is in current compile unit.
398 if (std::optional<uint32_t> RefDieIdx = getDIEIndexForOffset(RefDIEOffset))
399 return UnitEntryPairTy{this, getDebugInfoEntry(*RefDieIdx)};
400 } else if (RefCU && CanResolveInterCUReferences) {
401 // Referenced DIE is in other compile unit.
402
403 // Check whether DIEs are loaded for that compile unit.
404 enum Stage ReferredCUStage = RefCU->getStage();
405 if (ReferredCUStage < Stage::Loaded || ReferredCUStage > Stage::Cloned)
406 return UnitEntryPairTy{RefCU, nullptr};
407
408 if (std::optional<uint32_t> RefDieIdx =
409 RefCU->getDIEIndexForOffset(RefDIEOffset))
410 return UnitEntryPairTy{RefCU, RefCU->getDebugInfoEntry(*RefDieIdx)};
411 } else {
412 return UnitEntryPairTy{RefCU, nullptr};
413 }
414 return std::nullopt;
415}
416
417std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference(
418 const DWARFDebugInfoEntry *DieEntry, dwarf::Attribute Attr,
419 ResolveInterCUReferencesMode CanResolveInterCUReferences) {
420 if (std::optional<DWARFFormValue> AttrVal = find(DieEntry, Attr))
421 return resolveDIEReference(*AttrVal, CanResolveInterCUReferences);
422
423 return std::nullopt;
424}
425
426void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
427 int64_t PcOffset) {
428 std::lock_guard<std::mutex> Guard(RangesMutex);
429
430 Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
431 if (LowPc)
432 LowPc = std::min(*LowPc, FuncLowPc + PcOffset);
433 else
434 LowPc = FuncLowPc + PcOffset;
435 this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
436}
437
438void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
439 std::lock_guard<std::mutex> Guard(LabelsMutex);
440 Labels.insert({LabelLowPc, PcOffset});
441}
442
444 if (getGlobalData().getOptions().UpdateIndexTablesOnly)
445 return Error::success();
446
447 if (getOrigUnit().getVersion() < 5) {
448 emitLocations(DebugSectionKind::DebugLoc);
449 return Error::success();
450 }
451
452 emitLocations(DebugSectionKind::DebugLocLists);
453 return Error::success();
454}
455
456void CompileUnit::emitLocations(DebugSectionKind LocationSectionKind) {
457 SectionDescriptor &DebugInfoSection =
459
460 if (!DebugInfoSection.ListDebugLocPatch.empty()) {
461 SectionDescriptor &OutLocationSection =
462 getOrCreateSectionDescriptor(LocationSectionKind);
463 DWARFUnit &OrigUnit = getOrigUnit();
464
465 uint64_t OffsetAfterUnitLength = emitLocListHeader(OutLocationSection);
466
467 DebugInfoSection.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {
468 // Get location expressions vector corresponding to the current
469 // attribute from the source DWARF.
470 uint64_t InputDebugLocSectionOffset = DebugInfoSection.getIntVal(
471 Patch.PatchOffset,
472 DebugInfoSection.getFormParams().getDwarfOffsetByteSize());
474 OrigUnit.findLoclistFromOffset(InputDebugLocSectionOffset);
475
476 if (!OriginalLocations) {
477 warn(OriginalLocations.takeError());
478 return;
479 }
480
481 LinkedLocationExpressionsVector LinkedLocationExpressions;
482 for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
483 LinkedLocationExpressionsWithOffsetPatches LinkedExpression;
484
485 if (CurExpression.Range) {
486 // Relocate address range.
487 LinkedExpression.Expression.Range = {
488 CurExpression.Range->LowPC + Patch.AddrAdjustmentValue,
489 CurExpression.Range->HighPC + Patch.AddrAdjustmentValue};
490 }
491
492 DataExtractor Data(CurExpression.Expr, OrigUnit.isLittleEndian(),
493 OrigUnit.getAddressByteSize());
494
495 DWARFExpression InputExpression(Data, OrigUnit.getAddressByteSize(),
496 OrigUnit.getFormParams().Format);
497 cloneDieAttrExpression(InputExpression,
498 LinkedExpression.Expression.Expr,
499 OutLocationSection, Patch.AddrAdjustmentValue,
500 LinkedExpression.Patches);
501
502 LinkedLocationExpressions.push_back({LinkedExpression});
503 }
504
505 // Emit locations list table fragment corresponding to the CurLocAttr.
506 DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,
507 OutLocationSection.OS.tell());
508 emitLocListFragment(LinkedLocationExpressions, OutLocationSection);
509 });
510
511 if (OffsetAfterUnitLength > 0) {
512 assert(OffsetAfterUnitLength -
513 OutLocationSection.getFormParams().getDwarfOffsetByteSize() <
514 OffsetAfterUnitLength);
515 OutLocationSection.apply(
516 OffsetAfterUnitLength -
517 OutLocationSection.getFormParams().getDwarfOffsetByteSize(),
518 dwarf::DW_FORM_sec_offset,
519 OutLocationSection.OS.tell() - OffsetAfterUnitLength);
520 }
521 }
522}
523
524/// Emit debug locations(.debug_loc, .debug_loclists) header.
525uint64_t CompileUnit::emitLocListHeader(SectionDescriptor &OutLocationSection) {
526 if (getOrigUnit().getVersion() < 5)
527 return 0;
528
529 // unit_length.
530 OutLocationSection.emitUnitLength(0xBADDEF);
531 uint64_t OffsetAfterUnitLength = OutLocationSection.OS.tell();
532
533 // Version.
534 OutLocationSection.emitIntVal(5, 2);
535
536 // Address size.
537 OutLocationSection.emitIntVal(OutLocationSection.getFormParams().AddrSize, 1);
538
539 // Seg_size
540 OutLocationSection.emitIntVal(0, 1);
541
542 // Offset entry count
543 OutLocationSection.emitIntVal(0, 4);
544
545 return OffsetAfterUnitLength;
546}
547
548/// Emit debug locations(.debug_loc, .debug_loclists) fragment.
549uint64_t CompileUnit::emitLocListFragment(
550 const LinkedLocationExpressionsVector &LinkedLocationExpression,
551 SectionDescriptor &OutLocationSection) {
552 uint64_t OffsetBeforeLocationExpression = 0;
553
554 if (getOrigUnit().getVersion() < 5) {
555 uint64_t BaseAddress = 0;
556 if (std::optional<uint64_t> LowPC = getLowPc())
557 BaseAddress = *LowPC;
558
559 for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :
560 LinkedLocationExpression) {
561 if (LocExpression.Expression.Range) {
562 OutLocationSection.emitIntVal(
563 LocExpression.Expression.Range->LowPC - BaseAddress,
564 OutLocationSection.getFormParams().AddrSize);
565 OutLocationSection.emitIntVal(
566 LocExpression.Expression.Range->HighPC - BaseAddress,
567 OutLocationSection.getFormParams().AddrSize);
568 }
569
570 OutLocationSection.emitIntVal(LocExpression.Expression.Expr.size(), 2);
571 OffsetBeforeLocationExpression = OutLocationSection.OS.tell();
572 for (uint64_t *OffsetPtr : LocExpression.Patches)
573 *OffsetPtr += OffsetBeforeLocationExpression;
574
575 OutLocationSection.OS
576 << StringRef((const char *)LocExpression.Expression.Expr.data(),
577 LocExpression.Expression.Expr.size());
578 }
579
580 // Emit the terminator entry.
581 OutLocationSection.emitIntVal(0,
582 OutLocationSection.getFormParams().AddrSize);
583 OutLocationSection.emitIntVal(0,
584 OutLocationSection.getFormParams().AddrSize);
585 return OffsetBeforeLocationExpression;
586 }
587
588 std::optional<uint64_t> BaseAddress;
589 for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :
590 LinkedLocationExpression) {
591 if (LocExpression.Expression.Range) {
592 // Check whether base address is set. If it is not set yet
593 // then set current base address and emit base address selection entry.
594 if (!BaseAddress) {
595 BaseAddress = LocExpression.Expression.Range->LowPC;
596
597 // Emit base address.
598 OutLocationSection.emitIntVal(dwarf::DW_LLE_base_addressx, 1);
599 encodeULEB128(DebugAddrIndexMap.getValueIndex(*BaseAddress),
600 OutLocationSection.OS);
601 }
602
603 // Emit type of entry.
604 OutLocationSection.emitIntVal(dwarf::DW_LLE_offset_pair, 1);
605
606 // Emit start offset relative to base address.
607 encodeULEB128(LocExpression.Expression.Range->LowPC - *BaseAddress,
608 OutLocationSection.OS);
609
610 // Emit end offset relative to base address.
611 encodeULEB128(LocExpression.Expression.Range->HighPC - *BaseAddress,
612 OutLocationSection.OS);
613 } else
614 // Emit type of entry.
615 OutLocationSection.emitIntVal(dwarf::DW_LLE_default_location, 1);
616
617 encodeULEB128(LocExpression.Expression.Expr.size(), OutLocationSection.OS);
618 OffsetBeforeLocationExpression = OutLocationSection.OS.tell();
619 for (uint64_t *OffsetPtr : LocExpression.Patches)
620 *OffsetPtr += OffsetBeforeLocationExpression;
621
622 OutLocationSection.OS << StringRef(
623 (const char *)LocExpression.Expression.Expr.data(),
624 LocExpression.Expression.Expr.size());
625 }
626
627 // Emit the terminator entry.
628 OutLocationSection.emitIntVal(dwarf::DW_LLE_end_of_list, 1);
629 return OffsetBeforeLocationExpression;
630}
631
632Error CompileUnit::emitDebugAddrSection() {
634 return Error::success();
635
636 if (getVersion() < 5)
637 return Error::success();
638
639 if (DebugAddrIndexMap.empty())
640 return Error::success();
641
642 SectionDescriptor &OutAddrSection =
644
645 // Emit section header.
646
647 // Emit length.
648 OutAddrSection.emitUnitLength(0xBADDEF);
649 uint64_t OffsetAfterSectionLength = OutAddrSection.OS.tell();
650
651 // Emit version.
652 OutAddrSection.emitIntVal(5, 2);
653
654 // Emit address size.
655 OutAddrSection.emitIntVal(getFormParams().AddrSize, 1);
656
657 // Emit segment size.
658 OutAddrSection.emitIntVal(0, 1);
659
660 // Emit addresses.
661 for (uint64_t AddrValue : DebugAddrIndexMap.getValues())
662 OutAddrSection.emitIntVal(AddrValue, getFormParams().AddrSize);
663
664 // Patch section length.
665 OutAddrSection.apply(
666 OffsetAfterSectionLength -
667 OutAddrSection.getFormParams().getDwarfOffsetByteSize(),
668 dwarf::DW_FORM_sec_offset,
669 OutAddrSection.OS.tell() - OffsetAfterSectionLength);
670
671 return Error::success();
672}
673
675 if (getGlobalData().getOptions().UpdateIndexTablesOnly)
676 return Error::success();
677
678 // Build set of linked address ranges for unit function ranges.
679 AddressRanges LinkedFunctionRanges;
681 LinkedFunctionRanges.insert(
682 {Range.Range.start() + Range.Value, Range.Range.end() + Range.Value});
683
684 emitAranges(LinkedFunctionRanges);
685
686 if (getOrigUnit().getVersion() < 5) {
687 cloneAndEmitRangeList(DebugSectionKind::DebugRange, LinkedFunctionRanges);
688 return Error::success();
689 }
690
691 cloneAndEmitRangeList(DebugSectionKind::DebugRngLists, LinkedFunctionRanges);
692 return Error::success();
693}
694
695void CompileUnit::cloneAndEmitRangeList(DebugSectionKind RngSectionKind,
696 AddressRanges &LinkedFunctionRanges) {
697 SectionDescriptor &DebugInfoSection =
699 SectionDescriptor &OutRangeSection =
700 getOrCreateSectionDescriptor(RngSectionKind);
701
702 if (!DebugInfoSection.ListDebugRangePatch.empty()) {
703 std::optional<AddressRangeValuePair> CachedRange;
704 uint64_t OffsetAfterUnitLength = emitRangeListHeader(OutRangeSection);
705
706 DebugRangePatch *CompileUnitRangePtr = nullptr;
707 DebugInfoSection.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {
708 if (Patch.IsCompileUnitRanges) {
709 CompileUnitRangePtr = &Patch;
710 } else {
711 // Get ranges from the source DWARF corresponding to the current
712 // attribute.
713 AddressRanges LinkedRanges;
714 uint64_t InputDebugRangesSectionOffset = DebugInfoSection.getIntVal(
715 Patch.PatchOffset,
716 DebugInfoSection.getFormParams().getDwarfOffsetByteSize());
717 if (Expected<DWARFAddressRangesVector> InputRanges =
718 getOrigUnit().findRnglistFromOffset(
719 InputDebugRangesSectionOffset)) {
720 // Apply relocation adjustment.
721 for (const auto &Range : *InputRanges) {
722 if (!CachedRange || !CachedRange->Range.contains(Range.LowPC))
723 CachedRange =
724 getFunctionRanges().getRangeThatContains(Range.LowPC);
725
726 // All range entries should lie in the function range.
727 if (!CachedRange) {
728 warn("inconsistent range data.");
729 continue;
730 }
731
732 // Store range for emiting.
733 LinkedRanges.insert({Range.LowPC + CachedRange->Value,
734 Range.HighPC + CachedRange->Value});
735 }
736 } else {
737 llvm::consumeError(InputRanges.takeError());
738 warn("invalid range list ignored.");
739 }
740
741 // Emit linked ranges.
742 DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,
743 OutRangeSection.OS.tell());
744 emitRangeListFragment(LinkedRanges, OutRangeSection);
745 }
746 });
747
748 if (CompileUnitRangePtr != nullptr) {
749 // Emit compile unit ranges last to be binary compatible with classic
750 // dsymutil.
751 DebugInfoSection.apply(CompileUnitRangePtr->PatchOffset,
752 dwarf::DW_FORM_sec_offset,
753 OutRangeSection.OS.tell());
754 emitRangeListFragment(LinkedFunctionRanges, OutRangeSection);
755 }
756
757 if (OffsetAfterUnitLength > 0) {
758 assert(OffsetAfterUnitLength -
759 OutRangeSection.getFormParams().getDwarfOffsetByteSize() <
760 OffsetAfterUnitLength);
761 OutRangeSection.apply(
762 OffsetAfterUnitLength -
763 OutRangeSection.getFormParams().getDwarfOffsetByteSize(),
764 dwarf::DW_FORM_sec_offset,
765 OutRangeSection.OS.tell() - OffsetAfterUnitLength);
766 }
767 }
768}
769
770uint64_t CompileUnit::emitRangeListHeader(SectionDescriptor &OutRangeSection) {
771 if (OutRangeSection.getFormParams().Version < 5)
772 return 0;
773
774 // unit_length.
775 OutRangeSection.emitUnitLength(0xBADDEF);
776 uint64_t OffsetAfterUnitLength = OutRangeSection.OS.tell();
777
778 // Version.
779 OutRangeSection.emitIntVal(5, 2);
780
781 // Address size.
782 OutRangeSection.emitIntVal(OutRangeSection.getFormParams().AddrSize, 1);
783
784 // Seg_size
785 OutRangeSection.emitIntVal(0, 1);
786
787 // Offset entry count
788 OutRangeSection.emitIntVal(0, 4);
789
790 return OffsetAfterUnitLength;
791}
792
793void CompileUnit::emitRangeListFragment(const AddressRanges &LinkedRanges,
794 SectionDescriptor &OutRangeSection) {
795 if (OutRangeSection.getFormParams().Version < 5) {
796 // Emit ranges.
797 uint64_t BaseAddress = 0;
798 if (std::optional<uint64_t> LowPC = getLowPc())
799 BaseAddress = *LowPC;
800
801 for (const AddressRange &Range : LinkedRanges) {
802 OutRangeSection.emitIntVal(Range.start() - BaseAddress,
803 OutRangeSection.getFormParams().AddrSize);
804 OutRangeSection.emitIntVal(Range.end() - BaseAddress,
805 OutRangeSection.getFormParams().AddrSize);
806 }
807
808 // Add the terminator entry.
809 OutRangeSection.emitIntVal(0, OutRangeSection.getFormParams().AddrSize);
810 OutRangeSection.emitIntVal(0, OutRangeSection.getFormParams().AddrSize);
811 return;
812 }
813
814 std::optional<uint64_t> BaseAddress;
815 for (const AddressRange &Range : LinkedRanges) {
816 if (!BaseAddress) {
817 BaseAddress = Range.start();
818
819 // Emit base address.
820 OutRangeSection.emitIntVal(dwarf::DW_RLE_base_addressx, 1);
821 encodeULEB128(getDebugAddrIndex(*BaseAddress), OutRangeSection.OS);
822 }
823
824 // Emit type of entry.
825 OutRangeSection.emitIntVal(dwarf::DW_RLE_offset_pair, 1);
826
827 // Emit start offset relative to base address.
828 encodeULEB128(Range.start() - *BaseAddress, OutRangeSection.OS);
829
830 // Emit end offset relative to base address.
831 encodeULEB128(Range.end() - *BaseAddress, OutRangeSection.OS);
832 }
833
834 // Emit the terminator entry.
835 OutRangeSection.emitIntVal(dwarf::DW_RLE_end_of_list, 1);
836}
837
838void CompileUnit::emitAranges(AddressRanges &LinkedFunctionRanges) {
839 if (LinkedFunctionRanges.empty())
840 return;
841
842 SectionDescriptor &DebugInfoSection =
844 SectionDescriptor &OutArangesSection =
846
847 // Emit Header.
848 unsigned HeaderSize =
849 sizeof(int32_t) + // Size of contents (w/o this field
850 sizeof(int16_t) + // DWARF ARange version number
851 sizeof(int32_t) + // Offset of CU in the .debug_info section
852 sizeof(int8_t) + // Pointer Size (in bytes)
853 sizeof(int8_t); // Segment Size (in bytes)
854
855 unsigned TupleSize = OutArangesSection.getFormParams().AddrSize * 2;
856 unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));
857
858 OutArangesSection.emitOffset(0xBADDEF); // Aranges length
859 uint64_t OffsetAfterArangesLengthField = OutArangesSection.OS.tell();
860
861 OutArangesSection.emitIntVal(dwarf::DW_ARANGES_VERSION, 2); // Version number
862 OutArangesSection.notePatch(
863 DebugOffsetPatch{OutArangesSection.OS.tell(), &DebugInfoSection});
864 OutArangesSection.emitOffset(0xBADDEF); // Corresponding unit's offset
865 OutArangesSection.emitIntVal(OutArangesSection.getFormParams().AddrSize,
866 1); // Address size
867 OutArangesSection.emitIntVal(0, 1); // Segment size
868
869 for (size_t Idx = 0; Idx < Padding; Idx++)
870 OutArangesSection.emitIntVal(0, 1); // Padding
871
872 // Emit linked ranges.
873 for (const AddressRange &Range : LinkedFunctionRanges) {
874 OutArangesSection.emitIntVal(Range.start(),
875 OutArangesSection.getFormParams().AddrSize);
876 OutArangesSection.emitIntVal(Range.end() - Range.start(),
877 OutArangesSection.getFormParams().AddrSize);
878 }
879
880 // Emit terminator.
881 OutArangesSection.emitIntVal(0, OutArangesSection.getFormParams().AddrSize);
882 OutArangesSection.emitIntVal(0, OutArangesSection.getFormParams().AddrSize);
883
884 uint64_t OffsetAfterArangesEnd = OutArangesSection.OS.tell();
885
886 // Update Aranges lentgh.
887 OutArangesSection.apply(
888 OffsetAfterArangesLengthField -
889 OutArangesSection.getFormParams().getDwarfOffsetByteSize(),
890 dwarf::DW_FORM_sec_offset,
891 OffsetAfterArangesEnd - OffsetAfterArangesLengthField);
892}
893
895 if (getOutUnitDIE() == nullptr)
896 return Error::success();
897
898 DWARFUnit &OrigUnit = getOrigUnit();
899 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();
900
901 // Check for .debug_macro table.
902 if (std::optional<uint64_t> MacroAttr =
903 dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macros))) {
904 if (const DWARFDebugMacro *Table =
905 getContaingFile().Dwarf->getDebugMacro()) {
906 emitMacroTableImpl(Table, *MacroAttr, true);
907 }
908 }
909
910 // Check for .debug_macinfo table.
911 if (std::optional<uint64_t> MacroAttr =
912 dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macro_info))) {
913 if (const DWARFDebugMacro *Table =
914 getContaingFile().Dwarf->getDebugMacinfo()) {
915 emitMacroTableImpl(Table, *MacroAttr, false);
916 }
917 }
918
919 return Error::success();
920}
921
922void CompileUnit::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
923 uint64_t OffsetToMacroTable,
924 bool hasDWARFv5Header) {
925 SectionDescriptor &OutSection =
926 hasDWARFv5Header
929
930 bool DefAttributeIsReported = false;
931 bool UndefAttributeIsReported = false;
932 bool ImportAttributeIsReported = false;
933
934 for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {
935 if (OffsetToMacroTable == List.Offset) {
936 // Write DWARFv5 header.
937 if (hasDWARFv5Header) {
938 // Write header version.
939 OutSection.emitIntVal(List.Header.Version, sizeof(List.Header.Version));
940
941 uint8_t Flags = List.Header.Flags;
942
943 // Check for OPCODE_OPERANDS_TABLE.
944 if (Flags &
945 DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {
946 Flags &=
947 ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;
948 warn("opcode_operands_table is not supported yet.");
949 }
950
951 // Check for DEBUG_LINE_OFFSET.
952 std::optional<uint64_t> StmtListOffset;
953 if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {
954 // Get offset to the line table from the cloned compile unit.
955 for (auto &V : getOutUnitDIE()->values()) {
956 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
957 StmtListOffset = V.getDIEInteger().getValue();
958 break;
959 }
960 }
961
962 if (!StmtListOffset) {
963 Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;
964 warn("couldn`t find line table for macro table.");
965 }
966 }
967
968 // Write flags.
969 OutSection.emitIntVal(Flags, sizeof(Flags));
970
971 // Write offset to line table.
972 if (StmtListOffset) {
973 OutSection.notePatch(DebugOffsetPatch{
974 OutSection.OS.tell(),
976 // TODO: check that List.Header.getOffsetByteSize() and
977 // DebugOffsetPatch agree on size.
978 OutSection.emitIntVal(0xBADDEF, List.Header.getOffsetByteSize());
979 }
980 }
981
982 // Write macro entries.
983 for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {
984 if (MacroEntry.Type == 0) {
985 encodeULEB128(MacroEntry.Type, OutSection.OS);
986 continue;
987 }
988
989 uint8_t MacroType = MacroEntry.Type;
990 switch (MacroType) {
991 default: {
992 bool HasVendorSpecificExtension =
993 (!hasDWARFv5Header &&
994 MacroType == dwarf::DW_MACINFO_vendor_ext) ||
995 (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user &&
996 MacroType <= dwarf::DW_MACRO_hi_user));
997
998 if (HasVendorSpecificExtension) {
999 // Write macinfo type.
1000 OutSection.emitIntVal(MacroType, 1);
1001
1002 // Write vendor extension constant.
1003 encodeULEB128(MacroEntry.ExtConstant, OutSection.OS);
1004
1005 // Write vendor extension string.
1006 OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.ExtStr);
1007 } else
1008 warn("unknown macro type. skip.");
1009 } break;
1010 // debug_macro and debug_macinfo share some common encodings.
1011 // DW_MACRO_define == DW_MACINFO_define
1012 // DW_MACRO_undef == DW_MACINFO_undef
1013 // DW_MACRO_start_file == DW_MACINFO_start_file
1014 // DW_MACRO_end_file == DW_MACINFO_end_file
1015 // For readibility/uniformity we are using DW_MACRO_*.
1016 case dwarf::DW_MACRO_define:
1017 case dwarf::DW_MACRO_undef: {
1018 // Write macinfo type.
1019 OutSection.emitIntVal(MacroType, 1);
1020
1021 // Write source line.
1022 encodeULEB128(MacroEntry.Line, OutSection.OS);
1023
1024 // Write macro string.
1025 OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.MacroStr);
1026 } break;
1027 case dwarf::DW_MACRO_define_strp:
1028 case dwarf::DW_MACRO_undef_strp:
1029 case dwarf::DW_MACRO_define_strx:
1030 case dwarf::DW_MACRO_undef_strx: {
1031 // DW_MACRO_*_strx forms are not supported currently.
1032 // Convert to *_strp.
1033 switch (MacroType) {
1034 case dwarf::DW_MACRO_define_strx: {
1035 MacroType = dwarf::DW_MACRO_define_strp;
1036 if (!DefAttributeIsReported) {
1037 warn("DW_MACRO_define_strx unsupported yet. Convert to "
1038 "DW_MACRO_define_strp.");
1039 DefAttributeIsReported = true;
1040 }
1041 } break;
1042 case dwarf::DW_MACRO_undef_strx: {
1043 MacroType = dwarf::DW_MACRO_undef_strp;
1044 if (!UndefAttributeIsReported) {
1045 warn("DW_MACRO_undef_strx unsupported yet. Convert to "
1046 "DW_MACRO_undef_strp.");
1047 UndefAttributeIsReported = true;
1048 }
1049 } break;
1050 default:
1051 // Nothing to do.
1052 break;
1053 }
1054
1055 // Write macinfo type.
1056 OutSection.emitIntVal(MacroType, 1);
1057
1058 // Write source line.
1059 encodeULEB128(MacroEntry.Line, OutSection.OS);
1060
1061 // Write macro string.
1062 OutSection.emitString(dwarf::DW_FORM_strp, MacroEntry.MacroStr);
1063 break;
1064 }
1065 case dwarf::DW_MACRO_start_file: {
1066 // Write macinfo type.
1067 OutSection.emitIntVal(MacroType, 1);
1068 // Write source line.
1069 encodeULEB128(MacroEntry.Line, OutSection.OS);
1070 // Write source file id.
1071 encodeULEB128(MacroEntry.File, OutSection.OS);
1072 } break;
1073 case dwarf::DW_MACRO_end_file: {
1074 // Write macinfo type.
1075 OutSection.emitIntVal(MacroType, 1);
1076 } break;
1077 case dwarf::DW_MACRO_import:
1078 case dwarf::DW_MACRO_import_sup: {
1079 if (!ImportAttributeIsReported) {
1080 warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported "
1081 "yet. remove.");
1082 ImportAttributeIsReported = true;
1083 }
1084 } break;
1085 }
1086 }
1087
1088 return;
1089 }
1090 }
1091}
1092
1094 const DWARFExpression &InputExpression,
1095 SmallVectorImpl<uint8_t> &OutputExpression, SectionDescriptor &Section,
1096 std::optional<int64_t> VarAddressAdjustment,
1097 OffsetsPtrVector &PatchesOffsets) {
1098 using Encoding = DWARFExpression::Operation::Encoding;
1099
1100 DWARFUnit &OrigUnit = getOrigUnit();
1101 uint8_t OrigAddressByteSize = OrigUnit.getAddressByteSize();
1102
1103 uint64_t OpOffset = 0;
1104 for (auto &Op : InputExpression) {
1105 auto Desc = Op.getDescription();
1106 // DW_OP_const_type is variable-length and has 3
1107 // operands. Thus far we only support 2.
1108 if ((Desc.Op.size() == 2 && Desc.Op[0] == Encoding::BaseTypeRef) ||
1109 (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&
1110 Desc.Op[0] != Encoding::Size1))
1111 warn("unsupported DW_OP encoding.");
1112
1113 if ((Desc.Op.size() == 1 && Desc.Op[0] == Encoding::BaseTypeRef) ||
1114 (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&
1115 Desc.Op[0] == Encoding::Size1)) {
1116 // This code assumes that the other non-typeref operand fits into 1 byte.
1117 assert(OpOffset < Op.getEndOffset());
1118 uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1;
1119 assert(ULEBsize <= 16);
1120
1121 // Copy over the operation.
1122 assert(!Op.getSubCode() && "SubOps not yet supported");
1123 OutputExpression.push_back(Op.getCode());
1124 uint64_t RefOffset;
1125 if (Desc.Op.size() == 1) {
1126 RefOffset = Op.getRawOperand(0);
1127 } else {
1128 OutputExpression.push_back(Op.getRawOperand(0));
1129 RefOffset = Op.getRawOperand(1);
1130 }
1131 uint8_t ULEB[16];
1132 uint32_t Offset = 0;
1133 unsigned RealSize = 0;
1134 // Look up the base type. For DW_OP_convert, the operand may be 0 to
1135 // instead indicate the generic type. The same holds for
1136 // DW_OP_reinterpret, which is currently not supported.
1137 if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) {
1138 RefOffset += OrigUnit.getOffset();
1139 uint32_t RefDieIdx = 0;
1140 if (std::optional<uint32_t> Idx =
1141 OrigUnit.getDIEIndexForOffset(RefOffset))
1142 RefDieIdx = *Idx;
1143
1144 // Use fixed size for ULEB128 data, since we need to update that size
1145 // later with the proper offsets. Use 5 for DWARF32, 9 for DWARF64.
1146 ULEBsize = getFormParams().getDwarfOffsetByteSize() + 1;
1147
1148 RealSize = encodeULEB128(0xBADDEF, ULEB, ULEBsize);
1149
1150 Section.notePatchWithOffsetUpdate(
1151 DebugULEB128DieRefPatch(OutputExpression.size(), this, this,
1152 RefDieIdx),
1153 PatchesOffsets);
1154 } else
1155 RealSize = encodeULEB128(Offset, ULEB, ULEBsize);
1156
1157 if (RealSize > ULEBsize) {
1158 // Emit the generic type as a fallback.
1159 RealSize = encodeULEB128(0, ULEB, ULEBsize);
1160 warn("base type ref doesn't fit.");
1161 }
1162 assert(RealSize == ULEBsize && "padding failed");
1163 ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
1164 OutputExpression.append(ULEBbytes.begin(), ULEBbytes.end());
1165 } else if (!getGlobalData().getOptions().UpdateIndexTablesOnly &&
1166 Op.getCode() == dwarf::DW_OP_addrx) {
1167 if (std::optional<object::SectionedAddress> SA =
1169 // DWARFLinker does not use addrx forms since it generates relocated
1170 // addresses. Replace DW_OP_addrx with DW_OP_addr here.
1171 // Argument of DW_OP_addrx should be relocated here as it is not
1172 // processed by applyValidRelocs.
1173 OutputExpression.push_back(dwarf::DW_OP_addr);
1174 uint64_t LinkedAddress = SA->Address + VarAddressAdjustment.value_or(0);
1176 sys::swapByteOrder(LinkedAddress);
1177 ArrayRef<uint8_t> AddressBytes(
1178 reinterpret_cast<const uint8_t *>(&LinkedAddress),
1179 OrigAddressByteSize);
1180 OutputExpression.append(AddressBytes.begin(), AddressBytes.end());
1181 } else
1182 warn("cann't read DW_OP_addrx operand.");
1183 } else if (!getGlobalData().getOptions().UpdateIndexTablesOnly &&
1184 Op.getCode() == dwarf::DW_OP_constx) {
1185 if (std::optional<object::SectionedAddress> SA =
1187 // DWARFLinker does not use constx forms since it generates relocated
1188 // addresses. Replace DW_OP_constx with DW_OP_const[*]u here.
1189 // Argument of DW_OP_constx should be relocated here as it is not
1190 // processed by applyValidRelocs.
1191 std::optional<uint8_t> OutOperandKind;
1192 switch (OrigAddressByteSize) {
1193 case 2:
1194 OutOperandKind = dwarf::DW_OP_const2u;
1195 break;
1196 case 4:
1197 OutOperandKind = dwarf::DW_OP_const4u;
1198 break;
1199 case 8:
1200 OutOperandKind = dwarf::DW_OP_const8u;
1201 break;
1202 default:
1203 warn(
1204 formatv(("unsupported address size: {0}."), OrigAddressByteSize));
1205 break;
1206 }
1207
1208 if (OutOperandKind) {
1209 OutputExpression.push_back(*OutOperandKind);
1210 uint64_t LinkedAddress =
1211 SA->Address + VarAddressAdjustment.value_or(0);
1213 sys::swapByteOrder(LinkedAddress);
1214 ArrayRef<uint8_t> AddressBytes(
1215 reinterpret_cast<const uint8_t *>(&LinkedAddress),
1216 OrigAddressByteSize);
1217 OutputExpression.append(AddressBytes.begin(), AddressBytes.end());
1218 }
1219 } else
1220 warn("cann't read DW_OP_constx operand.");
1221 } else {
1222 // Copy over everything else unmodified.
1223 StringRef Bytes =
1224 InputExpression.getData().slice(OpOffset, Op.getEndOffset());
1225 OutputExpression.append(Bytes.begin(), Bytes.end());
1226 }
1227 OpOffset = Op.getEndOffset();
1228 }
1229}
1230
1232 std::optional<std::reference_wrapper<const Triple>> TargetTriple,
1233 TypeUnit *ArtificialTypeUnit) {
1235
1236 DWARFDie OrigUnitDIE = getOrigUnit().getUnitDIE();
1237 if (!OrigUnitDIE.isValid())
1238 return Error::success();
1239
1240 TypeEntry *RootEntry = nullptr;
1241 if (ArtificialTypeUnit)
1242 RootEntry = ArtificialTypeUnit->getTypePool().getRoot();
1243
1244 // Clone input DIE entry recursively.
1245 std::pair<DIE *, TypeEntry *> OutCUDie = cloneDIE(
1246 OrigUnitDIE.getDebugInfoEntry(), RootEntry, getDebugInfoHeaderSize(),
1247 std::nullopt, std::nullopt, Allocator, ArtificialTypeUnit);
1248 setOutUnitDIE(OutCUDie.first);
1249
1250 if (!TargetTriple.has_value() || (OutCUDie.first == nullptr))
1251 return Error::success();
1252
1253 if (Error Err = cloneAndEmitLineTable((*TargetTriple).get()))
1254 return Err;
1255
1256 if (Error Err = cloneAndEmitDebugMacro())
1257 return Err;
1258
1260 if (Error Err = emitDebugInfo((*TargetTriple).get()))
1261 return Err;
1262
1263 // ASSUMPTION: .debug_info section should already be emitted at this point.
1264 // cloneAndEmitRanges & cloneAndEmitDebugLocations use .debug_info section
1265 // data.
1266
1267 if (Error Err = cloneAndEmitRanges())
1268 return Err;
1269
1271 return Err;
1272
1273 if (Error Err = emitDebugAddrSection())
1274 return Err;
1275
1276 // Generate Pub accelerator tables.
1280
1282 return Err;
1283
1284 return emitAbbreviations();
1285}
1286
1287std::pair<DIE *, TypeEntry *> CompileUnit::cloneDIE(
1288 const DWARFDebugInfoEntry *InputDieEntry, TypeEntry *ClonedParentTypeDIE,
1289 uint64_t OutOffset, std::optional<int64_t> FuncAddressAdjustment,
1290 std::optional<int64_t> VarAddressAdjustment, BumpPtrAllocator &Allocator,
1291 TypeUnit *ArtificialTypeUnit) {
1292 uint32_t InputDieIdx = getDIEIndex(InputDieEntry);
1293 CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx);
1294
1295 bool NeedToClonePlainDIE = Info.needToKeepInPlainDwarf();
1296 bool NeedToCloneTypeDIE =
1297 (InputDieEntry->getTag() != dwarf::DW_TAG_compile_unit) &&
1298 Info.needToPlaceInTypeTable();
1299 std::pair<DIE *, TypeEntry *> ClonedDIE;
1300
1301 DIEGenerator PlainDIEGenerator(Allocator, *this);
1302
1303 if (NeedToClonePlainDIE)
1304 // Create a cloned DIE which would be placed into the cloned version
1305 // of input compile unit.
1306 ClonedDIE.first = createPlainDIEandCloneAttributes(
1307 InputDieEntry, PlainDIEGenerator, OutOffset, FuncAddressAdjustment,
1308 VarAddressAdjustment);
1309 if (NeedToCloneTypeDIE) {
1310 // Create a cloned DIE which would be placed into the artificial type
1311 // unit.
1312 assert(ArtificialTypeUnit != nullptr);
1313 DIEGenerator TypeDIEGenerator(
1314 ArtificialTypeUnit->getTypePool().getThreadLocalAllocator(), *this);
1315
1316 ClonedDIE.second = createTypeDIEandCloneAttributes(
1317 InputDieEntry, TypeDIEGenerator, ClonedParentTypeDIE,
1318 ArtificialTypeUnit);
1319 }
1320 TypeEntry *TypeParentForChild =
1321 ClonedDIE.second ? ClonedDIE.second : ClonedParentTypeDIE;
1322
1323 bool HasPlainChildrenToClone =
1324 (ClonedDIE.first && Info.getKeepPlainChildren());
1325
1326 bool HasTypeChildrenToClone =
1327 ((ClonedDIE.second ||
1328 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) &&
1329 Info.getKeepTypeChildren());
1330
1331 // Recursively clone children.
1332 if (HasPlainChildrenToClone || HasTypeChildrenToClone) {
1333 for (const DWARFDebugInfoEntry *CurChild =
1334 getFirstChildEntry(InputDieEntry);
1335 CurChild && CurChild->getAbbreviationDeclarationPtr();
1336 CurChild = getSiblingEntry(CurChild)) {
1337 std::pair<DIE *, TypeEntry *> ClonedChild = cloneDIE(
1338 CurChild, TypeParentForChild, OutOffset, FuncAddressAdjustment,
1339 VarAddressAdjustment, Allocator, ArtificialTypeUnit);
1340
1341 if (ClonedChild.first) {
1342 OutOffset =
1343 ClonedChild.first->getOffset() + ClonedChild.first->getSize();
1344 PlainDIEGenerator.addChild(ClonedChild.first);
1345 }
1346 }
1347 assert(ClonedDIE.first == nullptr ||
1348 HasPlainChildrenToClone == ClonedDIE.first->hasChildren());
1349
1350 // Account for the end of children marker.
1351 if (HasPlainChildrenToClone)
1352 OutOffset += sizeof(int8_t);
1353 }
1354
1355 // Update our size.
1356 if (ClonedDIE.first != nullptr)
1357 ClonedDIE.first->setSize(OutOffset - ClonedDIE.first->getOffset());
1358
1359 return ClonedDIE;
1360}
1361
1362DIE *CompileUnit::createPlainDIEandCloneAttributes(
1363 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator,
1364 uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
1365 std::optional<int64_t> &VarAddressAdjustment) {
1366 uint32_t InputDieIdx = getDIEIndex(InputDieEntry);
1367 CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx);
1368 DIE *ClonedDIE = nullptr;
1369 bool HasLocationExpressionAddress = false;
1370 if (InputDieEntry->getTag() == dwarf::DW_TAG_subprogram) {
1371 // Get relocation adjustment value for the current function.
1372 FuncAddressAdjustment =
1373 getContaingFile().Addresses->getSubprogramRelocAdjustment(
1374 getDIE(InputDieEntry), false);
1375 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_label) {
1376 // Get relocation adjustment value for the current label.
1377 std::optional<uint64_t> lowPC =
1378 dwarf::toAddress(find(InputDieEntry, dwarf::DW_AT_low_pc));
1379 if (lowPC) {
1380 LabelMapTy::iterator It = Labels.find(*lowPC);
1381 if (It != Labels.end())
1382 FuncAddressAdjustment = It->second;
1383 }
1384 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_variable) {
1385 // Get relocation adjustment value for the current variable.
1386 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
1387 getContaingFile().Addresses->getVariableRelocAdjustment(
1388 getDIE(InputDieEntry), false);
1389
1390 HasLocationExpressionAddress = LocExprAddrAndRelocAdjustment.first;
1391 if (LocExprAddrAndRelocAdjustment.first &&
1392 LocExprAddrAndRelocAdjustment.second)
1393 VarAddressAdjustment = *LocExprAddrAndRelocAdjustment.second;
1394 }
1395
1396 ClonedDIE = PlainDIEGenerator.createDIE(InputDieEntry->getTag(), OutOffset);
1397
1398 // Offset to the DIE would be used after output DIE tree is deleted.
1399 // Thus we need to remember DIE offset separately.
1400 rememberDieOutOffset(InputDieIdx, OutOffset);
1401
1402 // Clone Attributes.
1403 DIEAttributeCloner AttributesCloner(ClonedDIE, *this, this, InputDieEntry,
1404 PlainDIEGenerator, FuncAddressAdjustment,
1405 VarAddressAdjustment,
1406 HasLocationExpressionAddress);
1407 AttributesCloner.clone();
1408
1409 // Remember accelerator info.
1410 AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this, this);
1411 AccelRecordsSaver.save(InputDieEntry, ClonedDIE, AttributesCloner.AttrInfo,
1412 nullptr);
1413
1414 OutOffset =
1415 AttributesCloner.finalizeAbbreviations(Info.getKeepPlainChildren());
1416
1417 return ClonedDIE;
1418}
1419
1420/// Allocates output DIE for the specified \p TypeDescriptor.
1421DIE *CompileUnit::allocateTypeDie(TypeEntryBody *TypeDescriptor,
1422 DIEGenerator &TypeDIEGenerator,
1423 dwarf::Tag DieTag, bool IsDeclaration,
1424 bool IsParentDeclaration) {
1425 DIE *DefinitionDie = TypeDescriptor->Die;
1426 // Do not allocate any new DIE if definition DIE is already met.
1427 if (DefinitionDie)
1428 return nullptr;
1429
1430 DIE *DeclarationDie = TypeDescriptor->DeclarationDie;
1431 bool OldParentIsDeclaration = TypeDescriptor->ParentIsDeclaration;
1432
1433 if (IsDeclaration && !DeclarationDie) {
1434 // Alocate declaration DIE.
1435 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
1436 if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,
1437 NewDie))
1438 return NewDie;
1439 } else if (IsDeclaration && !IsParentDeclaration && OldParentIsDeclaration) {
1440 // Overwrite existing declaration DIE if it's parent is also an declaration
1441 // while parent of current declaration DIE is a definition.
1442 if (TypeDescriptor->ParentIsDeclaration.compare_exchange_weak(
1443 OldParentIsDeclaration, false)) {
1444 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
1445 TypeDescriptor->DeclarationDie = NewDie;
1446 return NewDie;
1447 }
1448 } else if (!IsDeclaration && IsParentDeclaration && !DeclarationDie) {
1449 // Alocate declaration DIE since parent of current DIE is marked as
1450 // declaration.
1451 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
1452 if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,
1453 NewDie))
1454 return NewDie;
1455 } else if (!IsDeclaration && !IsParentDeclaration) {
1456 // Allocate definition DIE.
1457 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
1458 if (TypeDescriptor->Die.compare_exchange_weak(DefinitionDie, NewDie)) {
1459 TypeDescriptor->ParentIsDeclaration = false;
1460 return NewDie;
1461 }
1462 }
1463
1464 return nullptr;
1465}
1466
1467TypeEntry *CompileUnit::createTypeDIEandCloneAttributes(
1468 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,
1469 TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit) {
1470 assert(ArtificialTypeUnit != nullptr);
1471 uint32_t InputDieIdx = getDIEIndex(InputDieEntry);
1472
1473 TypeEntry *Entry = getDieTypeEntry(InputDieIdx);
1474 assert(Entry != nullptr);
1475 assert(ClonedParentTypeDIE != nullptr);
1476 TypeEntryBody *EntryBody =
1477 ArtificialTypeUnit->getTypePool().getOrCreateTypeEntryBody(
1478 Entry, ClonedParentTypeDIE);
1479 assert(EntryBody);
1480
1481 bool IsDeclaration =
1482 dwarf::toUnsigned(find(InputDieEntry, dwarf::DW_AT_declaration), 0);
1483
1484 bool ParentIsDeclaration = false;
1485 if (std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx())
1486 ParentIsDeclaration =
1487 dwarf::toUnsigned(find(*ParentIdx, dwarf::DW_AT_declaration), 0);
1488
1489 DIE *OutDIE =
1490 allocateTypeDie(EntryBody, TypeDIEGenerator, InputDieEntry->getTag(),
1491 IsDeclaration, ParentIsDeclaration);
1492
1493 if (OutDIE != nullptr) {
1494 assert(ArtificialTypeUnit != nullptr);
1496
1497 DIEAttributeCloner AttributesCloner(OutDIE, *this, ArtificialTypeUnit,
1498 InputDieEntry, TypeDIEGenerator,
1499 std::nullopt, std::nullopt, false);
1500 AttributesCloner.clone();
1501
1502 // Remember accelerator info.
1503 AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this,
1504 ArtificialTypeUnit);
1505 AccelRecordsSaver.save(InputDieEntry, OutDIE, AttributesCloner.AttrInfo,
1506 Entry);
1507
1508 // if AttributesCloner.getOutOffset() == 0 then we need to add
1509 // 1 to avoid assertion for zero size. We will subtract it back later.
1510 OutDIE->setSize(AttributesCloner.getOutOffset() + 1);
1511 }
1512
1513 return Entry;
1514}
1515
1517 const DWARFDebugLine::LineTable *InputLineTable =
1518 getContaingFile().Dwarf->getLineTableForUnit(&getOrigUnit());
1519 if (InputLineTable == nullptr) {
1520 if (getOrigUnit().getUnitDIE().find(dwarf::DW_AT_stmt_list))
1521 warn("cann't load line table.");
1522 return Error::success();
1523 }
1524
1525 DWARFDebugLine::LineTable OutLineTable;
1526
1527 // Set Line Table header.
1528 OutLineTable.Prologue = InputLineTable->Prologue;
1530
1531 // Set Line Table Rows.
1532 if (getGlobalData().getOptions().UpdateIndexTablesOnly) {
1533 OutLineTable.Rows = InputLineTable->Rows;
1534 // If all the line table contains is a DW_LNE_end_sequence, clear the line
1535 // table rows, it will be inserted again in the DWARFStreamer.
1536 if (OutLineTable.Rows.size() == 1 && OutLineTable.Rows[0].EndSequence)
1537 OutLineTable.Rows.clear();
1538
1539 OutLineTable.Sequences = InputLineTable->Sequences;
1540 } else {
1541 // This vector is the output line table.
1542 std::vector<DWARFDebugLine::Row> NewRows;
1543 NewRows.reserve(InputLineTable->Rows.size());
1544
1545 // Current sequence of rows being extracted, before being inserted
1546 // in NewRows.
1547 std::vector<DWARFDebugLine::Row> Seq;
1548
1549 const auto &FunctionRanges = getFunctionRanges();
1550 std::optional<AddressRangeValuePair> CurrRange;
1551
1552 // FIXME: This logic is meant to generate exactly the same output as
1553 // Darwin's classic dsymutil. There is a nicer way to implement this
1554 // by simply putting all the relocated line info in NewRows and simply
1555 // sorting NewRows before passing it to emitLineTableForUnit. This
1556 // should be correct as sequences for a function should stay
1557 // together in the sorted output. There are a few corner cases that
1558 // look suspicious though, and that required to implement the logic
1559 // this way. Revisit that once initial validation is finished.
1560
1561 // Iterate over the object file line info and extract the sequences
1562 // that correspond to linked functions.
1563 for (DWARFDebugLine::Row Row : InputLineTable->Rows) {
1564 // Check whether we stepped out of the range. The range is
1565 // half-open, but consider accept the end address of the range if
1566 // it is marked as end_sequence in the input (because in that
1567 // case, the relocation offset is accurate and that entry won't
1568 // serve as the start of another function).
1569 if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address)) {
1570 // We just stepped out of a known range. Insert a end_sequence
1571 // corresponding to the end of the range.
1572 uint64_t StopAddress =
1573 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
1574 CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);
1575 if (StopAddress != -1ULL && !Seq.empty()) {
1576 // Insert end sequence row with the computed end address, but
1577 // the same line as the previous one.
1578 auto NextLine = Seq.back();
1579 NextLine.Address.Address = StopAddress;
1580 NextLine.EndSequence = 1;
1581 NextLine.PrologueEnd = 0;
1582 NextLine.BasicBlock = 0;
1583 NextLine.EpilogueBegin = 0;
1584 Seq.push_back(NextLine);
1585 insertLineSequence(Seq, NewRows);
1586 }
1587
1588 if (!CurrRange)
1589 continue;
1590 }
1591
1592 // Ignore empty sequences.
1593 if (Row.EndSequence && Seq.empty())
1594 continue;
1595
1596 // Relocate row address and add it to the current sequence.
1597 Row.Address.Address += CurrRange->Value;
1598 Seq.emplace_back(Row);
1599
1600 if (Row.EndSequence)
1601 insertLineSequence(Seq, NewRows);
1602 }
1603
1604 OutLineTable.Rows = std::move(NewRows);
1605 }
1606
1607 return emitDebugLine(TargetTriple, OutLineTable);
1608}
1609
1610void CompileUnit::insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
1611 std::vector<DWARFDebugLine::Row> &Rows) {
1612 if (Seq.empty())
1613 return;
1614
1615 if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {
1616 llvm::append_range(Rows, Seq);
1617 Seq.clear();
1618 return;
1619 }
1620
1621 object::SectionedAddress Front = Seq.front().Address;
1622 auto InsertPoint = partition_point(
1623 Rows, [=](const DWARFDebugLine::Row &O) { return O.Address < Front; });
1624
1625 // FIXME: this only removes the unneeded end_sequence if the
1626 // sequences have been inserted in order. Using a global sort like
1627 // described in cloneAndEmitLineTable() and delaying the end_sequene
1628 // elimination to DebugLineEmitter::emit() we can get rid of all of them.
1629 if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&
1630 InsertPoint->EndSequence) {
1631 *InsertPoint = Seq.front();
1632 Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
1633 } else {
1634 Rows.insert(InsertPoint, Seq.begin(), Seq.end());
1635 }
1636
1637 Seq.clear();
1638}
1639
1640#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1642 llvm::errs() << "{";
1643 llvm::errs() << " Placement: ";
1644 switch (getPlacement()) {
1645 case NotSet:
1646 llvm::errs() << "NotSet";
1647 break;
1648 case TypeTable:
1649 llvm::errs() << "TypeTable";
1650 break;
1651 case PlainDwarf:
1652 llvm::errs() << "PlainDwarf";
1653 break;
1654 case Both:
1655 llvm::errs() << "Both";
1656 break;
1657 }
1658
1659 llvm::errs() << " Keep: " << getKeep();
1660 llvm::errs() << " KeepPlainChildren: " << getKeepPlainChildren();
1661 llvm::errs() << " KeepTypeChildren: " << getKeepTypeChildren();
1662 llvm::errs() << " IsInMouduleScope: " << getIsInMouduleScope();
1663 llvm::errs() << " IsInFunctionScope: " << getIsInFunctionScope();
1664 llvm::errs() << " IsInAnonNamespaceScope: " << getIsInAnonNamespaceScope();
1665 llvm::errs() << " ODRAvailable: " << getODRAvailable();
1666 llvm::errs() << " TrackLiveness: " << getTrackLiveness();
1667 llvm::errs() << "}\n";
1668}
1669#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1670
1671std::optional<std::pair<StringRef, StringRef>>
1673 const DWARFFormValue &FileIdxValue) {
1674 uint64_t FileIdx;
1675 if (std::optional<uint64_t> Val = FileIdxValue.getAsUnsignedConstant())
1676 FileIdx = *Val;
1677 else if (std::optional<int64_t> Val = FileIdxValue.getAsSignedConstant())
1678 FileIdx = *Val;
1679 else if (std::optional<uint64_t> Val = FileIdxValue.getAsSectionOffset())
1680 FileIdx = *Val;
1681 else
1682 return std::nullopt;
1683
1684 return getDirAndFilenameFromLineTable(FileIdx);
1685}
1686
1687std::optional<std::pair<StringRef, StringRef>>
1689 FileNamesCache::iterator FileData = FileNames.find(FileIdx);
1690 if (FileData != FileNames.end())
1691 return std::make_pair(StringRef(FileData->second.first),
1692 StringRef(FileData->second.second));
1693
1694 if (const DWARFDebugLine::LineTable *LineTable =
1695 getOrigUnit().getContext().getLineTableForUnit(&getOrigUnit())) {
1696 if (LineTable->hasFileAtIndex(FileIdx)) {
1697
1699 LineTable->Prologue.getFileNameEntry(FileIdx);
1700
1701 Expected<const char *> Name = Entry.Name.getAsCString();
1702 if (!Name) {
1703 warn(Name.takeError());
1704 return std::nullopt;
1705 }
1706
1707 std::string FileName = *Name;
1708 if (isPathAbsoluteOnWindowsOrPosix(FileName)) {
1709 FileNamesCache::iterator FileData =
1710 FileNames
1711 .insert(std::make_pair(
1712 FileIdx,
1713 std::make_pair(std::string(""), std::move(FileName))))
1714 .first;
1715 return std::make_pair(StringRef(FileData->second.first),
1716 StringRef(FileData->second.second));
1717 }
1718
1719 SmallString<256> FilePath;
1720 StringRef IncludeDir;
1721 // Be defensive about the contents of Entry.
1722 if (getVersion() >= 5) {
1723 // DirIdx 0 is the compilation directory, so don't include it for
1724 // relative names.
1725 if ((Entry.DirIdx != 0) &&
1726 Entry.DirIdx < LineTable->Prologue.IncludeDirectories.size()) {
1727 Expected<const char *> DirName =
1728 LineTable->Prologue.IncludeDirectories[Entry.DirIdx]
1729 .getAsCString();
1730 if (DirName)
1731 IncludeDir = *DirName;
1732 else {
1733 warn(DirName.takeError());
1734 return std::nullopt;
1735 }
1736 }
1737 } else {
1738 if (0 < Entry.DirIdx &&
1739 Entry.DirIdx <= LineTable->Prologue.IncludeDirectories.size()) {
1740 Expected<const char *> DirName =
1741 LineTable->Prologue.IncludeDirectories[Entry.DirIdx - 1]
1742 .getAsCString();
1743 if (DirName)
1744 IncludeDir = *DirName;
1745 else {
1746 warn(DirName.takeError());
1747 return std::nullopt;
1748 }
1749 }
1750 }
1751
1753
1754 if (!CompDir.empty() && !isPathAbsoluteOnWindowsOrPosix(IncludeDir)) {
1755 sys::path::append(FilePath, sys::path::Style::native, CompDir);
1756 }
1757
1758 sys::path::append(FilePath, sys::path::Style::native, IncludeDir);
1759
1760 FileNamesCache::iterator FileData =
1761 FileNames
1762 .insert(
1763 std::make_pair(FileIdx, std::make_pair(std::string(FilePath),
1764 std::move(FileName))))
1765 .first;
1766 return std::make_pair(StringRef(FileData->second.first),
1767 StringRef(FileData->second.second));
1768 }
1769 }
1770
1771 return std::nullopt;
1772}
1773
1774#define MAX_REFERENCIES_DEPTH 1000
1776 UnitEntryPairTy CUDiePair(*this);
1777 std::optional<UnitEntryPairTy> RefDiePair;
1778 int refDepth = 0;
1779 do {
1780 RefDiePair = CUDiePair.CU->resolveDIEReference(
1781 CUDiePair.DieEntry, dwarf::DW_AT_extension,
1783 if (!RefDiePair || !RefDiePair->DieEntry)
1784 return CUDiePair;
1785
1786 CUDiePair = *RefDiePair;
1787 } while (refDepth++ < MAX_REFERENCIES_DEPTH);
1788
1789 return CUDiePair;
1790}
1791
1792std::optional<UnitEntryPairTy> UnitEntryPairTy::getParent() {
1793 if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx())
1794 return UnitEntryPairTy{CU, CU->getDebugInfoEntry(*ParentIdx)};
1795
1796 return std::nullopt;
1797}
1798
1800 : Ptr(U) {
1801 assert(U != nullptr);
1802}
1803
1805 assert(U != nullptr);
1806}
1807
1809 if (isCompileUnit())
1810 return getAsCompileUnit();
1811 else
1812 return getAsTypeUnit();
1813}
1814
1816 return isa<CompileUnit *>(Ptr);
1817}
1818
1820 return isa<TypeUnit *>(Ptr);
1821}
1822
1824 return cast<CompileUnit *>(Ptr);
1825}
1826
1828 return cast<TypeUnit *>(Ptr);
1829}
1830
1832 bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
1833 if (!Dependencies)
1834 Dependencies.reset(new DependencyTracker(*this));
1835
1836 return Dependencies->resolveDependenciesAndMarkLiveness(
1837 InterCUProcessingStarted, HasNewInterconnectedCUs);
1838}
1839
1841 assert(Dependencies.get());
1842
1843 return Dependencies->updateDependenciesCompleteness();
1844}
1845
1847 assert(Dependencies.get());
1848
1849 Dependencies->verifyKeepChain();
1850}
1851
1853 static dwarf::Attribute ODRAttributes[] = {
1854 dwarf::DW_AT_type, dwarf::DW_AT_specification,
1855 dwarf::DW_AT_abstract_origin, dwarf::DW_AT_import};
1856
1857 return ODRAttributes;
1858}
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:622
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
Mark the given Function as meaning that it cannot be changed in any way mark any values that are used as this function s parameters or by its return values(according to Uses) live as well. void DeadArgumentEliminationPass
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define MAX_REFERENCIES_DEPTH
if(PassOpts->AAPipeline)
Basic Register Allocator
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A class that represents an address range.
Definition: AddressRanges.h:22
void insert(AddressRange Range, int64_t Value)
The AddressRanges class helps normalize address range collections.
Collection::const_iterator insert(AddressRange Range)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
iterator end() const
Definition: ArrayRef.h:157
iterator begin() const
Definition: ArrayRef.h:156
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:66
std::pair< KeyDataTy *, bool > insert(const KeyTy &NewValue)
Insert new value NewValue or return already existing entry.
A structured debug information entry.
Definition: DIE.h:819
void setSize(unsigned S)
Definition: DIE.h:931
DWARFDebugInfoEntry - A DIE with only the minimum required data.
std::optional< uint32_t > getParentIdx() const
Returns index of the parent die.
const DWARFAbbreviationDeclaration * getAbbreviationDeclarationPtr() const
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition: DWARFDie.h:42
std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition: DWARFDie.cpp:249
const DWARFDebugInfoEntry * getDebugInfoEntry() const
Definition: DWARFDie.h:53
const char * getName(DINameKind Kind) const
Return the DIE name resolving DW_AT_specification or DW_AT_abstract_origin references if necessary.
Definition: DWARFDie.cpp:462
bool isValid() const
Definition: DWARFDie.h:51
This class represents an Operation in the Expression.
std::optional< unsigned > getSubCode() const
Encoding
Size and signedness of expression operations' operands.
const Description & getDescription() const
uint64_t getRawOperand(unsigned Idx) const
StringRef getData() const
std::optional< uint64_t > getAsSectionOffset() const
std::optional< int64_t > getAsSignedConstant() const
std::optional< uint64_t > getAsRelativeReference() const
getAsFoo functions below return the extracted value as Foo if only DWARFFormValue has form class is s...
std::optional< uint64_t > getAsDebugInfoReference() const
std::optional< uint64_t > getAsUnsignedConstant() const
const DWARFUnit * getUnit() const
const dwarf::FormParams & getFormParams() const
Definition: DWARFUnit.h:322
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
Definition: DWARFUnit.h:443
uint8_t getAddressByteSize() const
Definition: DWARFUnit.h:326
const char * getCompilationDir()
Definition: DWARFUnit.cpp:401
std::optional< uint32_t > getDIEIndexForOffset(uint64_t Offset)
Return the DIE index for a given offset Offset inside the unit's DIE vector.
Definition: DWARFUnit.h:542
Expected< DWARFLocationExpressionsVector > findLoclistFromOffset(uint64_t Offset)
Definition: DWARFUnit.cpp:709
bool isLittleEndian() const
Definition: DWARFUnit.h:317
std::optional< object::SectionedAddress > getAddrOffsetSectionItem(uint32_t Index) const
Definition: DWARFUnit.cpp:215
uint64_t getOffset() const
Definition: DWARFUnit.h:321
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:156
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Definition: DenseMap.h:71
iterator end()
Definition: DenseMap.h:84
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:211
void shrink_and_clear()
Definition: DenseMap.h:832
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
Error takeError()
Take ownership of the stored error.
Definition: Error.h:608
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
size_t size() const
Definition: SmallVector.h:78
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:683
void resize(size_type N)
Definition: SmallVector.h:638
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:229
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:147
iterator begin() const
Definition: StringRef.h:116
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition: StringRef.h:684
iterator end() const
Definition: StringRef.h:118
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
This class represents DWARF information for source file and it's address map.
Definition: DWARFFile.h:25
std::unique_ptr< AddressesMap > Addresses
Helpful address information(list of valid address ranges, relocations).
Definition: DWARFFile.h:42
std::unique_ptr< DWARFContext > Dwarf
Source DWARF information.
Definition: DWARFFile.h:39
const SmallVector< T > & getValues() const
CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR, StringRef ClangModuleName)
This class helps to store information for accelerator entries.
CompileUnit * getAsCompileUnit()
Returns CompileUnit if applicable.
Stores all information related to a compile unit, be it in its original instance of the object file o...
void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset)
Add the low_pc of a label that is relocated by applying offset PCOffset.
Error cloneAndEmitDebugLocations()
Clone and emit debug locations(.debug_loc/.debug_loclists).
void cloneDieAttrExpression(const DWARFExpression &InputExpression, SmallVectorImpl< uint8_t > &OutputExpression, SectionDescriptor &Section, std::optional< int64_t > VarAddressAdjustment, OffsetsPtrVector &PatchesOffsets)
Clone attribute location axpression.
void maybeResetToLoadedStage()
Reset compile units data(results of liveness analysis, clonning) if current stage greater than Stage:...
void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset)
Add a function range [LowPC, HighPC) that is relocated by applying offset PCOffset.
void analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry)
Collect references to parseable Swift interfaces in imported DW_TAG_module blocks.
std::pair< DIE *, TypeEntry * > cloneDIE(const DWARFDebugInfoEntry *InputDieEntry, TypeEntry *ClonedParentTypeDIE, uint64_t OutOffset, std::optional< int64_t > FuncAddressAdjustment, std::optional< int64_t > VarAddressAdjustment, BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit)
void cleanupDataAfterClonning()
Cleanup unneeded resources after compile unit is cloned.
Error assignTypeNames(TypePool &TypePoolRef)
Search for type entries and assign names.
@ Both
Corresponding DIE goes to type table and to plain dwarf.
@ TypeTable
Corresponding DIE goes to the type table only.
@ PlainDwarf
Corresponding DIE goes to the plain dwarf only.
Error cloneAndEmitLineTable(const Triple &TargetTriple)
void updateDieRefPatchesWithClonedOffsets()
After cloning stage the output DIEs offsets are deallocated.
uint64_t getDebugAddrIndex(uint64_t Addr)
Returns index(inside .debug_addr) of an address.
const DWARFFile & getContaingFile() const
Returns DWARFFile containing this compile unit.
bool resolveDependenciesAndMarkLiveness(bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs)
Search for subprograms and variables referencing live code and discover dependend DIEs.
bool updateDependenciesCompleteness()
Check dependend DIEs for incompatible placement.
bool loadInputDIEs()
Load DIEs of input compilation unit.
const RangesTy & getFunctionRanges() const
Returns function ranges of this unit.
Error cloneAndEmitDebugMacro()
Clone and emit debug macros(.debug_macinfo/.debug_macro).
Error cloneAndEmit(std::optional< std::reference_wrapper< const Triple > > TargetTriple, TypeUnit *ArtificialTypeUnit)
Clone and emit this compilation unit.
void setStage(Stage Stage)
Set stage of overall processing.
Stage getStage() const
Returns stage of overall processing.
CompileUnit(LinkingGlobalData &GlobalData, unsigned ID, StringRef ClangModuleName, DWARFFile &File, OffsetToUnitTy UnitFromOffset, dwarf::FormParams Format, llvm::endianness Endianess)
void verifyDependencies()
Check DIEs to have a consistent marking(keep marking, placement marking).
Stage
The stages of new compile unit processing.
@ CreatedNotLoaded
Created, linked with input DWARF file.
std::optional< uint64_t > getLowPc() const
Returns value of DW_AT_low_pc attribute.
std::optional< std::pair< StringRef, StringRef > > getDirAndFilenameFromLineTable(const DWARFFormValue &FileIdxValue)
Returns directory and file from the line table by index.
std::optional< UnitEntryPairTy > resolveDIEReference(const DWARFFormValue &RefValue, ResolveInterCUReferencesMode CanResolveInterCUReferences)
Resolve the DIE attribute reference that has been extracted in RefValue.
StringEntry * getFileName(unsigned FileIdx, StringPool &GlobalStrings)
Returns name of the file for the FileIdx from the unit`s line table.
This class creates clones of input DIE attributes.
This class is a helper to create output DIE tree.
Definition: DIEGenerator.h:22
void addChild(DIE *Child)
Adds a specified Child to the current DIE.
Definition: DIEGenerator.h:42
DIE * createDIE(dwarf::Tag DieTag, uint32_t OutOffset)
Creates a DIE of specified tag DieTag and OutOffset.
Definition: DIEGenerator.h:31
This class discovers DIEs dependencies: marks "live" DIEs, marks DIE locations (whether DIE should be...
Base class for all Dwarf units(Compile unit/Type table unit).
std::string UnitName
The name of this unit.
LinkingGlobalData & getGlobalData()
Return global data.
std::vector< std::unique_ptr< DIEAbbrev > > Abbreviations
Storage for the unique Abbreviations.
std::string SysRoot
The DW_AT_LLVM_sysroot of this unit.
bool isClangModule() const
Return true if this compile unit is from Clang module.
const std::string & getClangModuleName() const
Return Clang module name;.
void setOutUnitDIE(DIE *UnitDie)
Set output unit DIE.
FoldingSet< DIEAbbrev > AbbreviationsSet
FoldingSet that uniques the abbreviations.
StringRef getSysRoot()
Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef.
DIE * getOutUnitDIE()
Returns output unit DIE.
This class keeps data and services common for the whole linking process.
const DWARFLinkerOptions & getOptions() const
Returns linking options.
This class helps to assign indexes for DIE children.
dwarf::FormParams Format
Format for sections.
const dwarf::FormParams & getFormParams() const
Return size of address.
void eraseSections()
Erases data of all sections.
std::optional< const SectionDescriptor * > tryGetSectionDescriptor(DebugSectionKind SectionKind) const
Returns descriptor for the specified section of SectionKind.
void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianness)
Sets output format for all keeping sections.
uint16_t getVersion() const
Return DWARF version.
uint16_t getDebugInfoHeaderSize() const
Return size of header of debug_info table.
llvm::endianness getEndianness() const
Endiannes for the sections.
SectionDescriptor & getOrCreateSectionDescriptor(DebugSectionKind SectionKind)
Returns descriptor for the specified section of SectionKind.
const SectionDescriptor & getSectionDescriptor(DebugSectionKind SectionKind) const
Returns descriptor for the specified section of SectionKind.
The helper class to build type name based on DIE properties.
Error assignName(UnitEntryPairTy InputUnitEntryPair, std::optional< std::pair< size_t, size_t > > ChildIndex)
Create synthetic name for the specified DIE InputUnitEntryPair and assign created name to the DIE typ...
Keeps cloned data for the type DIE.
Definition: TypePool.h:30
std::atomic< DIE * > Die
TypeEntryBody keeps partially cloned DIEs corresponding to this type.
Definition: TypePool.h:59
TypePool keeps type descriptors which contain partially cloned DIE correspinding to each type.
Definition: TypePool.h:111
BumpPtrAllocator & getThreadLocalAllocator()
Return thread local allocator used by pool.
Definition: TypePool.h:161
TypeEntryBody * getOrCreateTypeEntryBody(TypeEntry *Entry, TypeEntry *ParentEntry)
Create or return existing type entry body for the specified Entry.
Definition: TypePool.h:131
TypeEntry * getRoot() const
Return root for all type entries.
Definition: TypePool.h:158
Type Unit is used to represent an artificial compilation unit which keeps all type information.
TypePool & getTypePool()
Returns global type pool.
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:147
void rememberDieOutOffset(uint32_t Idx, uint64_t Offset)
Idx index of the DIE.
TypeEntry * getDieTypeEntry(uint32_t Idx)
Idx index of the DIE.
DIEInfo & getDIEInfo(unsigned Idx)
Idx index of the DIE.
uint64_t getDieOutOffset(uint32_t Idx)
Idx index of the DIE.
const DWARFDebugInfoEntry * getSiblingEntry(const DWARFDebugInfoEntry *Die) const
const DWARFDebugInfoEntry * getFirstChildEntry(const DWARFDebugInfoEntry *Die) const
std::optional< uint32_t > getDIEIndexForOffset(uint64_t Offset)
DWARFDie getDIE(const DWARFDebugInfoEntry *Die)
const DWARFDebugInfoEntry * getDebugInfoEntry(unsigned Index) const
DWARFUnit & getOrigUnit() const
Returns paired compile unit from input DWARF.
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const
std::optional< DWARFFormValue > find(uint32_t DieIdx, ArrayRef< dwarf::Attribute > Attrs) const
Error emitDebugInfo(const Triple &TargetTriple)
Emit .debug_info section for unit DIEs.
Error emitDebugStringOffsetSection()
Emit the .debug_str_offsets section for current unit.
void emitPubAccelerators()
Emit .debug_pubnames and .debug_pubtypes for Unit.
void warn(const Twine &Warning, const DWARFDie *DIE=nullptr)
Error emitDebugLine(const Triple &TargetTriple, const DWARFDebugLine::LineTable &OutLineTable)
Emit .debug_line section.
@ HeaderSize
Definition: BTF.h:61
@ Entry
Definition: COFF.h:844
bool isODRLanguage(uint16_t Language)
ArrayRef< dwarf::Attribute > getODRAttributes()
StringRef guessDeveloperDir(StringRef SysRoot)
Make a best effort to guess the Xcode.app/Contents/Developer path from an SDK path.
Definition: Utils.h:41
DebugSectionKind
List of tracked debug tables.
bool isInToolchainDir(StringRef Path)
Make a best effort to determine whether Path is inside a toolchain.
Definition: Utils.h:77
bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path)
Definition: Utils.h:98
std::optional< uint64_t > toAddress(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an address.
@ DW_MACRO_lo_user
Definition: Dwarf.h:807
@ DW_MACRO_hi_user
Definition: Dwarf.h:808
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.
@ DW_MACINFO_vendor_ext
Definition: Dwarf.h:800
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.
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
@ DW_ARANGES_VERSION
Section version number for .debug_aranges.
Definition: Dwarf.h:64
std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
Definition: Path.cpp:699
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:577
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
Definition: Path.cpp:467
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:456
void swapByteOrder(T &Value)
Definition: SwapByteOrder.h:61
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
Definition: STLExtras.h:2050
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition: STLExtras.h:2115
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
@ Dwarf
DWARF v5 .debug_names.
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
Definition: Alignment.h:197
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition: STLExtras.h:1903
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
bool isCompileUnit(const std::unique_ptr< DWARFUnit > &U)
Definition: DWARFUnit.h:595
endianness
Definition: bit.h:70
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
bool hasFileAtIndex(uint64_t FileIndex) const
bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, std::string &Result) const
Extracts filename by its index in filename table in prologue.
dwarf::FormParams FormParams
Version, address size (starting in v5), and DWARF32/64 format; these parameters affect interpretation...
Standard .debug_line state machine structure.
Description of the encoding of one expression Op.
SmallVector< Encoding > Op
Encoding for Op operands.
Represents a single DWARF expression, whose value is location-dependent.
A helper struct providing information about the byte size of DW_FORM values that vary in size dependi...
Definition: Dwarf.h:1084
DwarfFormat Format
Definition: Dwarf.h:1087
uint8_t getDwarfOffsetByteSize() const
The size of a reference is determined by the DWARF 32/64-bit format.
Definition: Dwarf.h:1102
DWARFLinkerBase::SwiftInterfacesMapTy * ParseableSwiftInterfaces
A list of all .swiftinterface files referenced by the debug info, mapping Module name to path on disk...
SmallVector< DWARFLinkerBase::AccelTableKind, 1 > AccelTables
The accelerator table kinds.
bool NoODR
Do not unique types according to ODR.
This structure is used to update reference to the DIE.
PointerIntPair< CompileUnit *, 1 > RefCU
This structure is used to update location list offset into .debug_loc/.debug_loclists.
This structure is used to update range list offset into .debug_ranges/.debug_rnglists.
bool IsCompileUnitRanges
Indicates patch which points to immediate compile unit's attribute.
This structure is used to update reference to the DIE of ULEB128 form.
dwarf::FormParams getFormParams() const
Returns FormParams used by section.
Definition: DWARFLinker.h:107
This structure is used to keep data of the concrete section.
raw_svector_ostream OS
Stream which stores data to the Contents.
void emitUnitLength(uint64_t Length)
Emit unit length into the current section contents.
void emitOffset(uint64_t Val)
Emit specified offset value into the current section contents.
void emitString(dwarf::Form StringForm, const char *StringVal)
void emitIntVal(uint64_t Val, unsigned Size)
Emit specified integer value into the current section contents.
void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val)
Write specified Value of AttrForm to the PatchOffset.
uint64_t getIntVal(uint64_t PatchOffset, unsigned Size)
Returns integer value of Size located by specified PatchOffset.
This is a helper structure which keeps a debug info entry with it's containing compilation unit.