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