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