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