LLVM: lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

21#include

22

23using namespace llvm;

26

33 AcceleratorRecords(&GlobalData.getAllocator()) {

37}

38

44 OrigUnit(&OrigUnit), getUnitFromOffset(UnitFromOffset),

46 AcceleratorRecords(&GlobalData.getAllocator()) {

49

50 DWARFDie CUDie = OrigUnit.getUnitDIE();

51 if (!CUDie)

52 return;

53

54 if (std::optional Val = CUDie.find(dwarf::DW_AT_language)) {

57 Language = LangVal;

58 }

59

60 if (GlobalData.getOptions().NoODR && Language.has_value())

61 NoODR = false;

62

65 else

68}

69

71 LineTablePtr = File.Dwarf->getLineTableForUnit(&getOrigUnit());

72}

73

75

77 return;

78

79

80

81

82

83

84 for (DIEInfo &Info : DieInfoArray)

85 Info.unsetFlagsWhichSetDuringLiveAnalysis();

86

87 LowPc = std::nullopt;

88 HighPc = 0;

89 Labels.clear();

90 Ranges.clear();

91 Dependencies.reset(nullptr);

92

95 return;

96 }

97

98 AcceleratorRecords.erase();

102 DebugAddrIndexMap.clear();

103

107

109}

110

113 if (!InputUnitDIE)

114 return false;

115

116

117 DieInfoArray.resize(getOrigUnit().getNumDIEs());

118 OutDieOffsetArray.resize(getOrigUnit().getNumDIEs(), 0);

119 if (!NoODR)

120 TypeEntries.resize(getOrigUnit().getNumDIEs());

121 return true;

122}

123

124void CompileUnit::analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,

125 bool IsODRUnavailableFunctionScope) {

127

132 bool ChildIsODRUnavailableFunctionScope = IsODRUnavailableFunctionScope;

133

134 if (DieInfo.getIsInMouduleScope())

135 ChildInfo.setIsInMouduleScope();

136

137 if (DieInfo.getIsInFunctionScope())

138 ChildInfo.setIsInFunctionScope();

139

140 if (DieInfo.getIsInAnonNamespaceScope())

141 ChildInfo.setIsInAnonNamespaceScope();

142

143 switch (CurChild->getTag()) {

144 case dwarf::DW_TAG_module:

145 ChildInfo.setIsInMouduleScope();

146 if (DieEntry->getTag() == dwarf::DW_TAG_compile_unit &&

150 break;

151 case dwarf::DW_TAG_subprogram:

152 ChildInfo.setIsInFunctionScope();

153 if (!ChildIsODRUnavailableFunctionScope &&

154 !ChildInfo.getIsInMouduleScope()) {

155 if (find(CurChild,

156 {dwarf::DW_AT_abstract_origin, dwarf::DW_AT_specification}))

157 ChildIsODRUnavailableFunctionScope = true;

158 }

159 break;

160 case dwarf::DW_TAG_namespace: {

162

163 if (find(CurChild, dwarf::DW_AT_extension))

165

166 if (!NamespaceEntry.CU->find(NamespaceEntry.DieEntry, dwarf::DW_AT_name))

167 ChildInfo.setIsInAnonNamespaceScope();

168 } break;

169 default:

170 break;

171 }

172

174 ChildInfo.setTrackLiveness();

175

176 if ((!ChildInfo.getIsInAnonNamespaceScope() &&

177 !ChildIsODRUnavailableFunctionScope && !NoODR))

178 ChildInfo.setODRAvailable();

179

180 if (CurChild->hasChildren())

181 analyzeDWARFStructureRec(CurChild, ChildIsODRUnavailableFunctionScope);

182 }

183}

184

187 if (LineTablePtr) {

188 if (LineTablePtr->hasFileAtIndex(FileIdx)) {

189

190

192 if (It == ResolvedFullPaths.end()) {

193 std::string OrigFileName;

194 bool FoundFileName = LineTablePtr->getFileNameByIndex(

195 FileIdx, getOrigUnit().getCompilationDir(),

197 OrigFileName);

198 (void)FoundFileName;

199 assert(FoundFileName && "Must get file name from line table");

200

201

202

205

206

207

209 ResolvedParentPaths.find(ParentPath);

210 if (ParentIt == ResolvedParentPaths.end()) {

213 ParentIt =

214 ResolvedParentPaths

215 .insert({ParentPath, GlobalStrings.insert(RealPath).first})

216 .first;

217 }

218

219

222

223 It = ResolvedFullPaths

224 .insert(std::make_pair(

225 FileIdx, GlobalStrings.insert(ResolvedPath).first))

226 .first;

227 }

228

229 return It->second;

230 }

231 }

232

233 return nullptr;

234}

235

238 ResolvedFullPaths.shrink_and_clear();

239 ResolvedParentPaths.clear();

244 Dependencies.reset(nullptr);

246}

247

248

249

251 if (!Language || Language != dwarf::DW_LANG_Swift)

252 return;

253

254 if (GlobalData.getOptions().ParseableSwiftInterfaces)

255 return;

256

259 if (!Path.ends_with(".swiftinterface"))

260 return;

261

267 return;

268

269

271 if (!DeveloperDir.empty() && Path.starts_with(DeveloperDir))

272 return;

274 return;

275 if (std::optional Val = find(DieEntry, dwarf::DW_AT_name)) {

279 return;

280 }

281

282 auto &Entry = (*GlobalData.getOptions().ParseableSwiftInterfaces)[*Name];

283

287 ResolvedPath,

290 if (!Entry.empty() && Entry != ResolvedPath) {

292 warn(Twine("conflicting parseable interfaces for Swift Module ") + *Name +

293 ": " + Entry + " and " + Path + ".",

294 &Die);

295 }

296 Entry = std::string(ResolvedPath);

297 }

298}

299

307

316 continue;

317

318 assert(ChildInfo.getODRAvailable());

320 {this, CurChild},

321 ChildrenIndexAssigner.getChildIndex(*this, CurChild)))

322 return Err;

323

324 if (Error Err = assignTypeNamesRec(CurChild, NameBuilder))

325 return Err;

326 }

327

329}

330

332 if (std::optional<SectionDescriptor *> DebugInfoSection =

334

335 (*DebugInfoSection)

336 ->ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {

337

339 Patch.RefCU.getPointer()->getDieOutOffset(

341 });

342

343 (*DebugInfoSection)

344 ->ListDebugULEB128DieRefPatch.forEach(

346

348 Patch.RefCU.getPointer()->getDieOutOffset(

350 });

351 }

352

353 if (std::optional<SectionDescriptor *> DebugLocSection =

355 (*DebugLocSection)

356 ->ListDebugULEB128DieRefPatch.forEach(

358

360 Patch.RefCU.getPointer()->getDieOutOffset(

362 });

363 }

364

365 if (std::optional<SectionDescriptor *> DebugLocListsSection =

367 (*DebugLocListsSection)

368 ->ListDebugULEB128DieRefPatch.forEach(

370

372 Patch.RefCU.getPointer()->getDieOutOffset(

374 });

375 }

376}

377

384 RefCU = this;

387 RefCU = getUnitFromOffset(*Offset);

388 RefDIEOffset = *Offset;

389 } else {

390 return std::nullopt;

391 }

392

393 if (RefCU == this) {

394

397 } else if (RefCU && CanResolveInterCUReferences) {

398

399

400

402 if (ReferredCUStage < Stage::Loaded || ReferredCUStage > Stage::Cloned)

404

405 if (std::optional<uint32_t> RefDieIdx =

408 } else {

410 }

411 return std::nullopt;

412}

413

417 if (std::optional AttrVal = find(DieEntry, Attr))

419

420 return std::nullopt;

421}

422

424 int64_t PcOffset) {

425 std::lock_guardstd::mutex Guard(RangesMutex);

426

427 Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);

428 if (LowPc)

429 LowPc = std::min(*LowPc, FuncLowPc + PcOffset);

430 else

431 LowPc = FuncLowPc + PcOffset;

432 this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);

433}

434

436 std::lock_guardstd::mutex Guard(LabelsMutex);

437 Labels.insert({LabelLowPc, PcOffset});

438}

439

441 if (getGlobalData().getOptions().UpdateIndexTablesOnly)

443

447 }

448

451}

452

453void CompileUnit::emitLocations(DebugSectionKind LocationSectionKind) {

456

457 if (!DebugInfoSection.ListDebugLocPatch.empty()) {

461

462 uint64_t OffsetAfterUnitLength = emitLocListHeader(OutLocationSection);

463

464 DebugInfoSection.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {

465

466

467 uint64_t InputDebugLocSectionOffset = DebugInfoSection.getIntVal(

472

473 if (!OriginalLocations) {

475 return;

476 }

477

478 LinkedLocationExpressionsVector LinkedLocationExpressions;

480 LinkedLocationExpressionsWithOffsetPatches LinkedExpression;

481

482 if (CurExpression.Range) {

483

484 LinkedExpression.Expression.Range = {

487 }

488

491

495 LinkedExpression.Expression.Expr,

497 LinkedExpression.Patches);

498

499 LinkedLocationExpressions.push_back({LinkedExpression});

500 }

501

502

503 DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,

504 OutLocationSection.OS.tell());

505 emitLocListFragment(LinkedLocationExpressions, OutLocationSection);

506 });

507

508 if (OffsetAfterUnitLength > 0) {

509 assert(OffsetAfterUnitLength -

511 OffsetAfterUnitLength);

512 OutLocationSection.apply(

513 OffsetAfterUnitLength -

515 dwarf::DW_FORM_sec_offset,

516 OutLocationSection.OS.tell() - OffsetAfterUnitLength);

517 }

518 }

519}

520

521

522uint64_t CompileUnit::emitLocListHeader(SectionDescriptor &OutLocationSection) {

524 return 0;

525

526

528 uint64_t OffsetAfterUnitLength = OutLocationSection.OS.tell();

529

530

532

533

535

536

538

539

541

542 return OffsetAfterUnitLength;

543}

544

545

546uint64_t CompileUnit::emitLocListFragment(

547 const LinkedLocationExpressionsVector &LinkedLocationExpression,

549 uint64_t OffsetBeforeLocationExpression = 0;

550

552 uint64_t BaseAddress = 0;

553 if (std::optional<uint64_t> LowPC = getLowPc())

554 BaseAddress = *LowPC;

555

556 for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :

557 LinkedLocationExpression) {

558 if (LocExpression.Expression.Range) {

560 LocExpression.Expression.Range->LowPC - BaseAddress,

563 LocExpression.Expression.Range->HighPC - BaseAddress,

565 }

566

567 OutLocationSection.emitIntVal(LocExpression.Expression.Expr.size(), 2);

568 OffsetBeforeLocationExpression = OutLocationSection.OS.tell();

569 for (uint64_t *OffsetPtr : LocExpression.Patches)

570 *OffsetPtr += OffsetBeforeLocationExpression;

571

572 OutLocationSection.OS

573 << StringRef((const char *)LocExpression.Expression.Expr.data(),

574 LocExpression.Expression.Expr.size());

575 }

576

577

582 return OffsetBeforeLocationExpression;

583 }

584

585 std::optional<uint64_t> BaseAddress;

586 for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :

587 LinkedLocationExpression) {

588 if (LocExpression.Expression.Range) {

589

590

591 if (!BaseAddress) {

592 BaseAddress = LocExpression.Expression.Range->LowPC;

593

594

595 OutLocationSection.emitIntVal(dwarf::DW_LLE_base_addressx, 1);

596 encodeULEB128(DebugAddrIndexMap.getValueIndex(*BaseAddress),

597 OutLocationSection.OS);

598 }

599

600

601 OutLocationSection.emitIntVal(dwarf::DW_LLE_offset_pair, 1);

602

603

604 encodeULEB128(LocExpression.Expression.Range->LowPC - *BaseAddress,

605 OutLocationSection.OS);

606

607

608 encodeULEB128(LocExpression.Expression.Range->HighPC - *BaseAddress,

609 OutLocationSection.OS);

610 } else

611

612 OutLocationSection.emitIntVal(dwarf::DW_LLE_default_location, 1);

613

614 encodeULEB128(LocExpression.Expression.Expr.size(), OutLocationSection.OS);

615 OffsetBeforeLocationExpression = OutLocationSection.OS.tell();

616 for (uint64_t *OffsetPtr : LocExpression.Patches)

617 *OffsetPtr += OffsetBeforeLocationExpression;

618

619 OutLocationSection.OS << StringRef(

620 (const char *)LocExpression.Expression.Expr.data(),

621 LocExpression.Expression.Expr.size());

622 }

623

624

625 OutLocationSection.emitIntVal(dwarf::DW_LLE_end_of_list, 1);

626 return OffsetBeforeLocationExpression;

627}

628

629Error CompileUnit::emitDebugAddrSection() {

630 if (GlobalData.getOptions().UpdateIndexTablesOnly)

632

635

636 if (DebugAddrIndexMap.empty())

638

639 SectionDescriptor &OutAddrSection =

641

642

643

644

646 uint64_t OffsetAfterSectionLength = OutAddrSection.OS.tell();

647

648

650

651

653

654

656

657

658 for (uint64_t AddrValue : DebugAddrIndexMap.getValues())

660

661

662 OutAddrSection.apply(

663 OffsetAfterSectionLength -

665 dwarf::DW_FORM_sec_offset,

666 OutAddrSection.OS.tell() - OffsetAfterSectionLength);

667

669}

670

672 if (getGlobalData().getOptions().UpdateIndexTablesOnly)

674

675

678 LinkedFunctionRanges.insert(

680

681 emitAranges(LinkedFunctionRanges);

682

686 }

687

690}

691

692void CompileUnit::cloneAndEmitRangeList(DebugSectionKind RngSectionKind,

698

699 if (!DebugInfoSection.ListDebugRangePatch.empty()) {

700 std::optional CachedRange;

701 uint64_t OffsetAfterUnitLength = emitRangeListHeader(OutRangeSection);

702

704 DebugInfoSection.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {

706 CompileUnitRangePtr = &Patch;

707 } else {

708

709

711 uint64_t InputDebugRangesSectionOffset = DebugInfoSection.getIntVal(

716 InputDebugRangesSectionOffset)) {

717

718 for (const auto &Range : *InputRanges) {

719 if (!CachedRange || !CachedRange->Range.contains(Range.LowPC))

720 CachedRange =

722

723

724 if (!CachedRange) {

725 warn("inconsistent range data.");

726 continue;

727 }

728

729

730 LinkedRanges.insert({Range.LowPC + CachedRange->Value,

731 Range.HighPC + CachedRange->Value});

732 }

733 } else {

735 warn("invalid range list ignored.");

736 }

737

738

739 DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,

740 OutRangeSection.OS.tell());

741 emitRangeListFragment(LinkedRanges, OutRangeSection);

742 }

743 });

744

745 if (CompileUnitRangePtr != nullptr) {

746

747

749 dwarf::DW_FORM_sec_offset,

750 OutRangeSection.OS.tell());

751 emitRangeListFragment(LinkedFunctionRanges, OutRangeSection);

752 }

753

754 if (OffsetAfterUnitLength > 0) {

755 assert(OffsetAfterUnitLength -

757 OffsetAfterUnitLength);

758 OutRangeSection.apply(

759 OffsetAfterUnitLength -

761 dwarf::DW_FORM_sec_offset,

762 OutRangeSection.OS.tell() - OffsetAfterUnitLength);

763 }

764 }

765}

766

767uint64_t CompileUnit::emitRangeListHeader(SectionDescriptor &OutRangeSection) {

769 return 0;

770

771

773 uint64_t OffsetAfterUnitLength = OutRangeSection.OS.tell();

774

775

777

778

780

781

783

784

786

787 return OffsetAfterUnitLength;

788}

789

790void CompileUnit::emitRangeListFragment(const AddressRanges &LinkedRanges,

793

794 uint64_t BaseAddress = 0;

795 if (std::optional<uint64_t> LowPC = getLowPc())

796 BaseAddress = *LowPC;

797

798 for (const AddressRange &Range : LinkedRanges) {

803 }

804

805

808 return;

809 }

810

811 std::optional<uint64_t> BaseAddress;

812 for (const AddressRange &Range : LinkedRanges) {

813 if (!BaseAddress) {

814 BaseAddress = Range.start();

815

816

817 OutRangeSection.emitIntVal(dwarf::DW_RLE_base_addressx, 1);

819 }

820

821

822 OutRangeSection.emitIntVal(dwarf::DW_RLE_offset_pair, 1);

823

824

826

827

829 }

830

831

832 OutRangeSection.emitIntVal(dwarf::DW_RLE_end_of_list, 1);

833}

834

835void CompileUnit::emitAranges(AddressRanges &LinkedFunctionRanges) {

836 if (LinkedFunctionRanges.empty())

837 return;

838

839 SectionDescriptor &DebugInfoSection =

841 SectionDescriptor &OutArangesSection =

843

844

846 sizeof(int32_t) +

847 sizeof(int16_t) +

848 sizeof(int32_t) +

849 sizeof(int8_t) +

850 sizeof(int8_t);

851

854

855 OutArangesSection.emitOffset(0xBADDEF);

856 uint64_t OffsetAfterArangesLengthField = OutArangesSection.OS.tell();

857

859 OutArangesSection.notePatch(

860 DebugOffsetPatch{OutArangesSection.OS.tell(), &DebugInfoSection});

861 OutArangesSection.emitOffset(0xBADDEF);

863 1);

864 OutArangesSection.emitIntVal(0, 1);

865

866 for (size_t Idx = 0; Idx < Padding; Idx++)

867 OutArangesSection.emitIntVal(0, 1);

868

869

870 for (const AddressRange &Range : LinkedFunctionRanges) {

875 }

876

877

880

881 uint64_t OffsetAfterArangesEnd = OutArangesSection.OS.tell();

882

883

884 OutArangesSection.apply(

885 OffsetAfterArangesLengthField -

887 dwarf::DW_FORM_sec_offset,

888 OffsetAfterArangesEnd - OffsetAfterArangesLengthField);

889}

890

894

896 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();

897

898

899 if (std::optional<uint64_t> MacroAttr =

903 emitMacroTableImpl(Table, *MacroAttr, true);

904 }

905 }

906

907

908 if (std::optional<uint64_t> MacroAttr =

912 emitMacroTableImpl(Table, *MacroAttr, false);

913 }

914 }

915

917}

918

919void CompileUnit::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,

921 bool hasDWARFv5Header) {

923 hasDWARFv5Header

926

927 bool DefAttributeIsReported = false;

928 bool UndefAttributeIsReported = false;

929 bool ImportAttributeIsReported = false;

930

931 for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {

932 if (OffsetToMacroTable == List.Offset) {

933

934 if (hasDWARFv5Header) {

935

936 OutSection.emitIntVal(List.Header.Version, sizeof(List.Header.Version));

937

938 uint8_t Flags = List.Header.Flags;

939

940

941 if (Flags &

942 DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {

943 Flags &=

944 ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;

945 warn("opcode_operands_table is not supported yet.");

946 }

947

948

949 std::optional<uint64_t> StmtListOffset;

950 if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {

951

952 for (auto &V : getOutUnitDIE()->values()) {

953 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {

954 StmtListOffset = V.getDIEInteger().getValue();

955 break;

956 }

957 }

958

959 if (!StmtListOffset) {

960 Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;

961 warn("couldn`t find line table for macro table.");

962 }

963 }

964

965

966 OutSection.emitIntVal(Flags, sizeof(Flags));

967

968

969 if (StmtListOffset) {

970 OutSection.notePatch(DebugOffsetPatch{

971 OutSection.OS.tell(),

972 &getOrCreateSectionDescriptor(DebugSectionKind::DebugLine)});

973

974

975 OutSection.emitIntVal(0xBADDEF, List.Header.getOffsetByteSize());

976 }

977 }

978

979

980 for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {

981 if (MacroEntry.Type == 0) {

982 encodeULEB128(MacroEntry.Type, OutSection.OS);

983 continue;

984 }

985

986 uint8_t MacroType = MacroEntry.Type;

987 switch (MacroType) {

988 default: {

989 bool HasVendorSpecificExtension =

990 (!hasDWARFv5Header &&

991 MacroType == dwarf::DW_MACINFO_vendor_ext) ||

992 (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user &&

993 MacroType <= dwarf::DW_MACRO_hi_user));

994

995 if (HasVendorSpecificExtension) {

996

997 OutSection.emitIntVal(MacroType, 1);

998

999

1000 encodeULEB128(MacroEntry.ExtConstant, OutSection.OS);

1001

1002

1003 OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.ExtStr);

1004 } else

1005 warn("unknown macro type. skip.");

1006 } break;

1007

1008

1009

1010

1011

1012

1013 case dwarf::DW_MACRO_define:

1014 case dwarf::DW_MACRO_undef: {

1015

1016 OutSection.emitIntVal(MacroType, 1);

1017

1018

1019 encodeULEB128(MacroEntry.Line, OutSection.OS);

1020

1021

1022 OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.MacroStr);

1023 } break;

1024 case dwarf::DW_MACRO_define_strp:

1025 case dwarf::DW_MACRO_undef_strp:

1026 case dwarf::DW_MACRO_define_strx:

1027 case dwarf::DW_MACRO_undef_strx: {

1028

1029

1030 switch (MacroType) {

1031 case dwarf::DW_MACRO_define_strx: {

1032 MacroType = dwarf::DW_MACRO_define_strp;

1033 if (!DefAttributeIsReported) {

1034 warn("DW_MACRO_define_strx unsupported yet. Convert to "

1035 "DW_MACRO_define_strp.");

1036 DefAttributeIsReported = true;

1037 }

1038 } break;

1039 case dwarf::DW_MACRO_undef_strx: {

1040 MacroType = dwarf::DW_MACRO_undef_strp;

1041 if (!UndefAttributeIsReported) {

1042 warn("DW_MACRO_undef_strx unsupported yet. Convert to "

1043 "DW_MACRO_undef_strp.");

1044 UndefAttributeIsReported = true;

1045 }

1046 } break;

1047 default:

1048

1049 break;

1050 }

1051

1052

1053 OutSection.emitIntVal(MacroType, 1);

1054

1055

1056 encodeULEB128(MacroEntry.Line, OutSection.OS);

1057

1058

1059 OutSection.emitString(dwarf::DW_FORM_strp, MacroEntry.MacroStr);

1060 break;

1061 }

1062 case dwarf::DW_MACRO_start_file: {

1063

1064 OutSection.emitIntVal(MacroType, 1);

1065

1066 encodeULEB128(MacroEntry.Line, OutSection.OS);

1067

1068 encodeULEB128(MacroEntry.File, OutSection.OS);

1069 } break;

1070 case dwarf::DW_MACRO_end_file: {

1071

1072 OutSection.emitIntVal(MacroType, 1);

1073 } break;

1074 case dwarf::DW_MACRO_import:

1075 case dwarf::DW_MACRO_import_sup: {

1076 if (!ImportAttributeIsReported) {

1077 warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported "

1078 "yet. remove.");

1079 ImportAttributeIsReported = true;

1080 }

1081 } break;

1082 }

1083 }

1084

1085 return;

1086 }

1087 }

1088}

1089

1093 std::optional<int64_t> VarAddressAdjustment,

1096

1098 uint8_t OrigAddressByteSize = OrigUnit.getAddressByteSize();

1099

1101 for (auto &Op : InputExpression) {

1102 auto Desc = Op.getDescription();

1103

1104

1105 if ((Desc.Op.size() == 2 && Desc.Op[0] == Encoding::BaseTypeRef) ||

1106 (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&

1107 Desc.Op[0] != Encoding::Size1))

1108 warn("unsupported DW_OP encoding.");

1109

1110 if ((Desc.Op.size() == 1 && Desc.Op[0] == Encoding::BaseTypeRef) ||

1111 (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&

1112 Desc.Op[0] == Encoding::Size1)) {

1113

1114 assert(OpOffset < Op.getEndOffset());

1115 uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1;

1116 assert(ULEBsize <= 16);

1117

1118

1119 assert(Op.getSubCode() && "SubOps not yet supported");

1120 OutputExpression.push_back(Op.getCode());

1122 if (Desc.Op.size() == 1) {

1123 RefOffset = Op.getRawOperand(0);

1124 } else {

1125 OutputExpression.push_back(Op.getRawOperand(0));

1126 RefOffset = Op.getRawOperand(1);

1127 }

1130 unsigned RealSize = 0;

1131

1132

1133

1134 if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) {

1135 RefOffset += OrigUnit.getOffset();

1137 if (std::optional<uint32_t> Idx =

1138 OrigUnit.getDIEIndexForOffset(RefOffset))

1139 RefDieIdx = *Idx;

1140

1141

1142

1144

1145 RealSize = encodeULEB128(0xBADDEF, ULEB, ULEBsize);

1146

1147 Section.notePatchWithOffsetUpdate(

1149 RefDieIdx),

1150 PatchesOffsets);

1151 } else

1153

1154 if (RealSize > ULEBsize) {

1155

1157 warn("base type ref doesn't fit.");

1158 }

1159 assert(RealSize == ULEBsize && "padding failed");

1161 OutputExpression.append(ULEBbytes.begin(), ULEBbytes.end());

1162 } else if (getGlobalData().getOptions().UpdateIndexTablesOnly &&

1163 Op.getCode() == dwarf::DW_OP_addrx) {

1164 if (std::optionalobject::SectionedAddress SA =

1165 OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {

1166

1167

1168

1169

1170 OutputExpression.push_back(dwarf::DW_OP_addr);

1171 uint64_t LinkedAddress = SA->Address + VarAddressAdjustment.value_or(0);

1175 reinterpret_cast<const uint8_t *>(&LinkedAddress),

1176 OrigAddressByteSize);

1177 OutputExpression.append(AddressBytes.begin(), AddressBytes.end());

1178 } else

1179 warn("cann't read DW_OP_addrx operand.");

1180 } else if (getGlobalData().getOptions().UpdateIndexTablesOnly &&

1181 Op.getCode() == dwarf::DW_OP_constx) {

1182 if (std::optionalobject::SectionedAddress SA =

1183 OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {

1184

1185

1186

1187

1188 std::optional<uint8_t> OutOperandKind;

1189 switch (OrigAddressByteSize) {

1190 case 2:

1191 OutOperandKind = dwarf::DW_OP_const2u;

1192 break;

1193 case 4:

1194 OutOperandKind = dwarf::DW_OP_const4u;

1195 break;

1196 case 8:

1197 OutOperandKind = dwarf::DW_OP_const8u;

1198 break;

1199 default:

1201 formatv(("unsupported address size: {0}."), OrigAddressByteSize));

1202 break;

1203 }

1204

1205 if (OutOperandKind) {

1206 OutputExpression.push_back(*OutOperandKind);

1208 SA->Address + VarAddressAdjustment.value_or(0);

1212 reinterpret_cast<const uint8_t *>(&LinkedAddress),

1213 OrigAddressByteSize);

1214 OutputExpression.append(AddressBytes.begin(), AddressBytes.end());

1215 }

1216 } else

1217 warn("cann't read DW_OP_constx operand.");

1218 } else {

1219

1221 InputExpression.getData().slice(OpOffset, Op.getEndOffset());

1222 OutputExpression.append(Bytes.begin(), Bytes.end());

1223 }

1224 OpOffset = Op.getEndOffset();

1225 }

1226}

1227

1229 std::optional<std::reference_wrapper> TargetTriple,

1230 TypeUnit *ArtificialTypeUnit) {

1232

1234 if (!OrigUnitDIE.isValid())

1236

1238 if (ArtificialTypeUnit)

1240

1241

1242 std::pair<DIE *, TypeEntry *> OutCUDie = cloneDIE(

1244 std::nullopt, std::nullopt, Allocator, ArtificialTypeUnit);

1246

1247 if (!TargetTriple.has_value() || (OutCUDie.first == nullptr))

1249

1251 return Err;

1252

1254 return Err;

1255

1258 return Err;

1259

1260

1261

1262

1263

1265 return Err;

1266

1268 return Err;

1269

1270 if (Error Err = emitDebugAddrSection())

1271 return Err;

1272

1273

1277

1279 return Err;

1280

1282}

1283

1286 uint64_t OutOffset, std::optional<int64_t> FuncAddressAdjustment,

1287 std::optional<int64_t> VarAddressAdjustment, BumpPtrAllocator &Allocator,

1288 TypeUnit *ArtificialTypeUnit) {

1291

1292 bool NeedToClonePlainDIE = Info.needToKeepInPlainDwarf();

1293 bool NeedToCloneTypeDIE =

1294 (InputDieEntry->getTag() != dwarf::DW_TAG_compile_unit) &&

1295 Info.needToPlaceInTypeTable();

1296 std::pair<DIE *, TypeEntry *> ClonedDIE;

1297

1298 DIEGenerator PlainDIEGenerator(Allocator, *this);

1299

1300 if (NeedToClonePlainDIE)

1301

1302

1303 ClonedDIE.first = createPlainDIEandCloneAttributes(

1304 InputDieEntry, PlainDIEGenerator, OutOffset, FuncAddressAdjustment,

1305 VarAddressAdjustment);

1306 if (NeedToCloneTypeDIE) {

1307

1308

1309 assert(ArtificialTypeUnit != nullptr);

1312

1313 ClonedDIE.second = createTypeDIEandCloneAttributes(

1314 InputDieEntry, TypeDIEGenerator, ClonedParentTypeDIE,

1315 ArtificialTypeUnit);

1316 }

1318 ClonedDIE.second ? ClonedDIE.second : ClonedParentTypeDIE;

1319

1320 bool HasPlainChildrenToClone =

1321 (ClonedDIE.first && Info.getKeepPlainChildren());

1322

1323 bool HasTypeChildrenToClone =

1324 ((ClonedDIE.second ||

1325 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) &&

1326 Info.getKeepTypeChildren());

1327

1328

1329 if (HasPlainChildrenToClone || HasTypeChildrenToClone) {

1334 std::pair<DIE *, TypeEntry *> ClonedChild = cloneDIE(

1335 CurChild, TypeParentForChild, OutOffset, FuncAddressAdjustment,

1336 VarAddressAdjustment, Allocator, ArtificialTypeUnit);

1337

1338 if (ClonedChild.first) {

1339 OutOffset =

1340 ClonedChild.first->getOffset() + ClonedChild.first->getSize();

1341 PlainDIEGenerator.addChild(ClonedChild.first);

1342 }

1343 }

1344 assert(ClonedDIE.first == nullptr ||

1345 HasPlainChildrenToClone == ClonedDIE.first->hasChildren());

1346

1347

1348 if (HasPlainChildrenToClone)

1349 OutOffset += sizeof(int8_t);

1350 }

1351

1352

1353 if (ClonedDIE.first != nullptr)

1354 ClonedDIE.first->setSize(OutOffset - ClonedDIE.first->getOffset());

1355

1356 return ClonedDIE;

1357}

1358

1359DIE *CompileUnit::createPlainDIEandCloneAttributes(

1361 uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,

1362 std::optional<int64_t> &VarAddressAdjustment) {

1365 DIE *ClonedDIE = nullptr;

1366 bool HasLocationExpressionAddress = false;

1367 if (InputDieEntry->getTag() == dwarf::DW_TAG_subprogram) {

1368

1369 FuncAddressAdjustment =

1371 getDIE(InputDieEntry), false);

1372 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_label) {

1373

1374 std::optional<uint64_t> lowPC =

1376 if (lowPC) {

1378 if (It != Labels.end())

1379 FuncAddressAdjustment = It->second;

1380 }

1381 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_variable) {

1382

1383 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =

1385 getDIE(InputDieEntry), false);

1386

1387 HasLocationExpressionAddress = LocExprAddrAndRelocAdjustment.first;

1388 if (LocExprAddrAndRelocAdjustment.first &&

1389 LocExprAddrAndRelocAdjustment.second)

1390 VarAddressAdjustment = *LocExprAddrAndRelocAdjustment.second;

1391 }

1392

1393 ClonedDIE = PlainDIEGenerator.createDIE(InputDieEntry->getTag(), OutOffset);

1394

1395

1396

1398

1399

1400 DIEAttributeCloner AttributesCloner(ClonedDIE, *this, this, InputDieEntry,

1401 PlainDIEGenerator, FuncAddressAdjustment,

1402 VarAddressAdjustment,

1403 HasLocationExpressionAddress);

1404 AttributesCloner.clone();

1405

1406

1407 AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this, this);

1408 AccelRecordsSaver.save(InputDieEntry, ClonedDIE, AttributesCloner.AttrInfo,

1409 nullptr);

1410

1411 OutOffset =

1412 AttributesCloner.finalizeAbbreviations(Info.getKeepPlainChildren());

1413

1414 return ClonedDIE;

1415}

1416

1417

1418DIE *CompileUnit::allocateTypeDie(TypeEntryBody *TypeDescriptor,

1420 dwarf::Tag DieTag, bool IsDeclaration,

1421 bool IsParentDeclaration) {

1422 DIE *DefinitionDie = TypeDescriptor->Die;

1423

1424 if (DefinitionDie)

1425 return nullptr;

1426

1427 DIE *DeclarationDie = TypeDescriptor->DeclarationDie;

1429

1430 if (IsDeclaration && !DeclarationDie) {

1431

1432 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);

1433 if (TypeDescriptor->DeclarationDie.compare_exchange_strong(DeclarationDie,

1434 NewDie))

1435 return NewDie;

1436 } else if (IsDeclaration && !IsParentDeclaration && OldParentIsDeclaration) {

1437

1438

1440 OldParentIsDeclaration, false)) {

1441 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);

1443 return NewDie;

1444 }

1445 } else if (!IsDeclaration && IsParentDeclaration && !DeclarationDie) {

1446

1447

1448 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);

1449 if (TypeDescriptor->DeclarationDie.compare_exchange_strong(DeclarationDie,

1450 NewDie))

1451 return NewDie;

1452 } else if (!IsDeclaration && !IsParentDeclaration) {

1453

1454 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);

1455 if (TypeDescriptor->Die.compare_exchange_strong(DefinitionDie, NewDie)) {

1457 return NewDie;

1458 }

1459 }

1460

1461 return nullptr;

1462}

1463

1464TypeEntry *CompileUnit::createTypeDIEandCloneAttributes(

1465 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,

1467 assert(ArtificialTypeUnit != nullptr);

1468 uint32_t InputDieIdx = getDIEIndex(InputDieEntry);

1469

1471 assert(Entry != nullptr);

1472 assert(ClonedParentTypeDIE != nullptr);

1473 TypeEntryBody *EntryBody =

1475 Entry, ClonedParentTypeDIE);

1477

1478 bool IsDeclaration =

1480

1481 bool ParentIsDeclaration = false;

1482 if (std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx())

1483 ParentIsDeclaration =

1485

1486 DIE *OutDIE =

1487 allocateTypeDie(EntryBody, TypeDIEGenerator, InputDieEntry->getTag(),

1488 IsDeclaration, ParentIsDeclaration);

1489

1490 if (OutDIE != nullptr) {

1491 assert(ArtificialTypeUnit != nullptr);

1493

1494 DIEAttributeCloner AttributesCloner(OutDIE, *this, ArtificialTypeUnit,

1495 InputDieEntry, TypeDIEGenerator,

1496 std::nullopt, std::nullopt, false);

1497 AttributesCloner.clone();

1498

1499

1500 AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this,

1501 ArtificialTypeUnit);

1502 AccelRecordsSaver.save(InputDieEntry, OutDIE, AttributesCloner.AttrInfo,

1503 Entry);

1504

1505

1506

1507 OutDIE->setSize(AttributesCloner.getOutOffset() + 1);

1508 }

1509

1511}

1512

1516 if (InputLineTable == nullptr) {

1518 warn("cann't load line table.");

1520 }

1521

1523

1524

1527

1528

1529 if (getGlobalData().getOptions().UpdateIndexTablesOnly) {

1530 OutLineTable.Rows = InputLineTable->Rows;

1531

1532

1533 if (OutLineTable.Rows.size() == 1 && OutLineTable.Rows[0].EndSequence)

1534 OutLineTable.Rows.clear();

1535

1537 } else {

1538

1539 std::vectorDWARFDebugLine::Row NewRows;

1540 NewRows.reserve(InputLineTable->Rows.size());

1541

1542

1543

1544 std::vectorDWARFDebugLine::Row Seq;

1545

1547 std::optional CurrRange;

1548

1549

1550

1551

1552

1553

1554

1555

1556

1557

1558

1559

1561

1562

1563

1564

1565

1566 if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address)) {

1567

1568

1570 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;

1571 CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);

1572 if (StopAddress != -1ULL && !Seq.empty()) {

1573

1574

1575 auto NextLine = Seq.back();

1576 NextLine.Address.Address = StopAddress;

1577 NextLine.EndSequence = 1;

1578 NextLine.PrologueEnd = 0;

1579 NextLine.BasicBlock = 0;

1580 NextLine.EpilogueBegin = 0;

1581 Seq.push_back(NextLine);

1582 insertLineSequence(Seq, NewRows);

1583 }

1584

1585 if (!CurrRange)

1586 continue;

1587 }

1588

1589

1590 if (Row.EndSequence && Seq.empty())

1591 continue;

1592

1593

1594 Row.Address.Address += CurrRange->Value;

1595 Seq.emplace_back(Row);

1596

1597 if (Row.EndSequence)

1598 insertLineSequence(Seq, NewRows);

1599 }

1600

1601 OutLineTable.Rows = std::move(NewRows);

1602 }

1603

1604 return emitDebugLine(TargetTriple, OutLineTable);

1605}

1606

1607void CompileUnit::insertLineSequence(std::vectorDWARFDebugLine::Row &Seq,

1608 std::vectorDWARFDebugLine::Row &Rows) {

1609 if (Seq.empty())

1610 return;

1611

1612 if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {

1614 Seq.clear();

1615 return;

1616 }

1617

1621

1622

1623

1624

1625

1626 if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&

1627 InsertPoint->EndSequence) {

1628 *InsertPoint = Seq.front();

1629 Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());

1630 } else {

1631 Rows.insert(InsertPoint, Seq.begin(), Seq.end());

1632 }

1633

1634 Seq.clear();

1635}

1636

1637#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

1644 break;

1647 break;

1650 break;

1651 case Both:

1653 break;

1654 }

1655

1656 llvm::errs() << " Keep: " << getKeep();

1657 llvm::errs() << " KeepPlainChildren: " << getKeepPlainChildren();

1658 llvm::errs() << " KeepTypeChildren: " << getKeepTypeChildren();

1659 llvm::errs() << " IsInMouduleScope: " << getIsInMouduleScope();

1660 llvm::errs() << " IsInFunctionScope: " << getIsInFunctionScope();

1661 llvm::errs() << " IsInAnonNamespaceScope: " << getIsInAnonNamespaceScope();

1662 llvm::errs() << " ODRAvailable: " << getODRAvailable();

1663 llvm::errs() << " TrackLiveness: " << getTrackLiveness();

1665}

1666#endif

1667

1668std::optional<std::pair<StringRef, StringRef>>

1673 FileIdx = *Val;

1674 else if (std::optional<int64_t> Val = FileIdxValue.getAsSignedConstant())

1675 FileIdx = *Val;

1676 else if (std::optional<uint64_t> Val = FileIdxValue.getAsSectionOffset())

1677 FileIdx = *Val;

1678 else

1679 return std::nullopt;

1680

1682}

1683

1684std::optional<std::pair<StringRef, StringRef>>

1686 FileNamesCache::iterator FileData = FileNames.find(FileIdx);

1687 if (FileData != FileNames.end())

1688 return std::make_pair(StringRef(FileData->second.first),

1689 StringRef(FileData->second.second));

1690

1693 if (LineTable->hasFileAtIndex(FileIdx)) {

1694

1696 LineTable->Prologue.getFileNameEntry(FileIdx);

1697

1699 if (Name) {

1701 return std::nullopt;

1702 }

1703

1704 std::string FileName = *Name;

1706 FileNamesCache::iterator FileData =

1708 .insert(std::make_pair(

1709 FileIdx,

1710 std::make_pair(std::string(""), std::move(FileName))))

1711 .first;

1712 return std::make_pair(StringRef(FileData->second.first),

1713 StringRef(FileData->second.second));

1714 }

1715

1718

1720

1721

1722 if ((Entry.DirIdx != 0) &&

1723 Entry.DirIdx < LineTable->Prologue.IncludeDirectories.size()) {

1725 LineTable->Prologue.IncludeDirectories[Entry.DirIdx]

1726 .getAsCString();

1727 if (DirName)

1728 IncludeDir = *DirName;

1729 else {

1731 return std::nullopt;

1732 }

1733 }

1734 } else {

1735 if (0 < Entry.DirIdx &&

1736 Entry.DirIdx <= LineTable->Prologue.IncludeDirectories.size()) {

1738 LineTable->Prologue.IncludeDirectories[Entry.DirIdx - 1]

1739 .getAsCString();

1740 if (DirName)

1741 IncludeDir = *DirName;

1742 else {

1744 return std::nullopt;

1745 }

1746 }

1747 }

1748

1750

1753 }

1754

1756

1757 FileNamesCache::iterator FileData =

1759 .insert(

1760 std::make_pair(FileIdx, std::make_pair(std::string(FilePath),

1761 std::move(FileName))))

1762 .first;

1763 return std::make_pair(StringRef(FileData->second.first),

1764 StringRef(FileData->second.second));

1765 }

1766 }

1767

1768 return std::nullopt;

1769}

1770

1771#define MAX_REFERENCIES_DEPTH 1000

1774 std::optional RefDiePair;

1775 int refDepth = 0;

1776 do {

1778 CUDiePair.DieEntry, dwarf::DW_AT_extension,

1780 if (!RefDiePair || !RefDiePair->DieEntry)

1781 return CUDiePair;

1782

1783 CUDiePair = *RefDiePair;

1785

1786 return CUDiePair;

1787}

1788

1790 if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx())

1792

1793 return std::nullopt;

1794}

1795

1797 : Ptr(U) {

1798 assert(U != nullptr);

1799}

1800

1802 assert(U != nullptr);

1803}

1804

1811

1815

1819

1823

1827

1829 bool InterCUProcessingStarted, std::atomic &HasNewInterconnectedCUs) {

1830 if (!Dependencies)

1832

1833 return Dependencies->resolveDependenciesAndMarkLiveness(

1834 InterCUProcessingStarted, HasNewInterconnectedCUs);

1835}

1836

1838 assert(Dependencies.get());

1839

1840 return Dependencies->updateDependenciesCompleteness();

1841}

1842

1844 assert(Dependencies.get());

1845

1846 Dependencies->verifyKeepChain();

1847}

1848

1851 dwarf::DW_AT_type, dwarf::DW_AT_specification,

1852 dwarf::DW_AT_abstract_origin, dwarf::DW_AT_import};

1853

1854 return ODRAttributes;

1855}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

Analysis containing CSE Info

#define LLVM_DUMP_METHOD

Mark debug helper function definitions like dump() that should not be stripped from debug builds.

ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))

#define MAX_REFERENCIES_DEPTH

Definition DWARFLinkerCompileUnit.cpp:1771

static bool isValid(const char C)

Returns true if C is a valid mangled character: <0-9a-zA-Z_>.

std::optional< T > getRangeThatContains(uint64_t Addr) const

void insert(AddressRange Range, int64_t Value)

The AddressRanges class helps normalize address range collections.

Collection::const_iterator insert(AddressRange Range)

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

std::pair< KeyDataTy *, bool > insert(const KeyTy &NewValue)

Insert new value NewValue or return already existing entry.

A structured debug information entry.

DWARFDebugInfoEntry - A DIE with only the minimum required data.

dwarf::Tag getTag() const

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.

LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const

Extract the specified attribute from this DIE.

const DWARFDebugInfoEntry * getDebugInfoEntry() const

LLVM_ABI const char * getName(DINameKind Kind) const

Return the DIE name resolving DW_AT_specification or DW_AT_abstract_origin references if necessary.

Encoding

Size and signedness of expression operations' operands.

StringRef getData() const

LLVM_ABI std::optional< uint64_t > getAsSectionOffset() const

LLVM_ABI std::optional< int64_t > getAsSignedConstant() const

LLVM_ABI std::optional< uint64_t > getAsRelativeReference() const

getAsFoo functions below return the extracted value as Foo if only DWARFFormValue has form class is s...

LLVM_ABI std::optional< uint64_t > getAsDebugInfoReference() const

LLVM_ABI std::optional< uint64_t > getAsUnsignedConstant() const

const DWARFUnit * getUnit() const

const dwarf::FormParams & getFormParams() const

DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)

uint8_t getAddressByteSize() const

const char * getCompilationDir()

Expected< DWARFLocationExpressionsVector > findLoclistFromOffset(uint64_t Offset)

bool isLittleEndian() const

uint64_t getOffset() const

iterator find(const_arg_type_t< KeyT > Val)

DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator

DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator

std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void append(ItTy in_start, ItTy in_end)

Add the specified range to the end of the SmallVector.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringMapIterBase< ValueTy, false > iterator

StringRef - Represent a constant reference to a string, i.e.

std::string str() const

str - Get the contents as an std::string.

constexpr bool empty() const

empty - Check if the string is empty.

StringRef slice(size_t Start, size_t End) const

Return a reference to the substring from [Start, End).

Triple - Helper class for working with autoconf configuration names.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

This class represents DWARF information for source file and it's address map.

std::unique_ptr< AddressesMap > Addresses

Helpful address information(list of valid address ranges, relocations).

std::unique_ptr< DWARFContext > Dwarf

Source DWARF information.

@ Pub

.debug_pubnames, .debug_pubtypes

CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR, StringRef ClangModuleName)

TypeUnit * getAsTypeUnit()

Returns TypeUnit if applicable.

Definition DWARFLinkerCompileUnit.cpp:1824

bool isTypeUnit()

Definition DWARFLinkerCompileUnit.cpp:1816

DwarfUnit * operator->()

Accessor for common functionality.

Definition DWARFLinkerCompileUnit.cpp:1805

PointerUnion< CompileUnit *, TypeUnit * > Ptr

CompileUnit * getAsCompileUnit()

Returns CompileUnit if applicable.

Definition DWARFLinkerCompileUnit.cpp:1820

OutputUnitVariantPtr(CompileUnit *U)

Definition DWARFLinkerCompileUnit.cpp:1796

bool isCompileUnit()

Definition DWARFLinkerCompileUnit.cpp:1812

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).

Definition DWARFLinkerCompileUnit.cpp:440

void cloneDieAttrExpression(const DWARFExpression &InputExpression, SmallVectorImpl< uint8_t > &OutputExpression, SectionDescriptor &Section, std::optional< int64_t > VarAddressAdjustment, OffsetsPtrVector &PatchesOffsets)

Clone attribute location axpression.

Definition DWARFLinkerCompileUnit.cpp:1090

void maybeResetToLoadedStage()

Reset compile units data(results of liveness analysis, clonning) if current stage greater than Stage:...

Definition DWARFLinkerCompileUnit.cpp:74

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.

Definition DWARFLinkerCompileUnit.cpp:250

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)

Definition DWARFLinkerCompileUnit.cpp:1284

void cleanupDataAfterClonning()

Cleanup unneeded resources after compile unit is cloned.

Definition DWARFLinkerCompileUnit.cpp:236

Error assignTypeNames(TypePool &TypePoolRef)

Search for type entries and assign names.

Definition DWARFLinkerCompileUnit.cpp:300

@ TypeTable

Corresponding DIE goes to the type table only.

@ PlainDwarf

Corresponding DIE goes to the plain dwarf only.

Error cloneAndEmitLineTable(const Triple &TargetTriple)

Definition DWARFLinkerCompileUnit.cpp:1513

Error cloneAndEmitRanges()

Clone and emit ranges.

Definition DWARFLinkerCompileUnit.cpp:671

void updateDieRefPatchesWithClonedOffsets()

After cloning stage the output DIEs offsets are deallocated.

Definition DWARFLinkerCompileUnit.cpp:331

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.

Definition DWARFLinkerCompileUnit.cpp:1828

bool updateDependenciesCompleteness()

Check dependend DIEs for incompatible placement.

Definition DWARFLinkerCompileUnit.cpp:1837

bool loadInputDIEs()

Load DIEs of input compilation unit.

Definition DWARFLinkerCompileUnit.cpp:111

const RangesTy & getFunctionRanges() const

Returns function ranges of this unit.

Error cloneAndEmitDebugMacro()

Clone and emit debug macros(.debug_macinfo/.debug_macro).

Definition DWARFLinkerCompileUnit.cpp:891

Error cloneAndEmit(std::optional< std::reference_wrapper< const Triple > > TargetTriple, TypeUnit *ArtificialTypeUnit)

Clone and emit this compilation unit.

Definition DWARFLinkerCompileUnit.cpp:1228

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)

Definition DWARFLinkerCompileUnit.cpp:27

void verifyDependencies()

Check DIEs to have a consistent marking(keep marking, placement marking).

Definition DWARFLinkerCompileUnit.cpp:1843

Stage

The stages of new compile unit processing.

@ Cloned

Output DWARF is generated.

@ CreatedNotLoaded

Created, linked with input DWARF file.

@ Loaded

Input DWARF is loaded.

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.

Definition DWARFLinkerCompileUnit.cpp:1669

std::optional< UnitEntryPairTy > resolveDIEReference(const DWARFFormValue &RefValue, ResolveInterCUReferencesMode CanResolveInterCUReferences)

Resolve the DIE attribute reference that has been extracted in RefValue.

Definition DWARFLinkerCompileUnit.cpp:378

void loadLineTable()

Loads unit line table.

Definition DWARFLinkerCompileUnit.cpp:70

StringEntry * getFileName(unsigned FileIdx, StringPool &GlobalStrings)

Returns name of the file for the FileIdx from the unit`s line table.

Definition DWARFLinkerCompileUnit.cpp:185

This class is a helper to create output DIE tree.

void addChild(DIE *Child)

Adds a specified Child to the current DIE.

DIE * createDIE(dwarf::Tag DieTag, uint32_t OutOffset)

Creates a DIE of specified tag DieTag and OutOffset.

This class discovers DIEs dependencies: marks "live" DIEs, marks DIE locations (whether DIE should be...

std::string UnitName

The name of this unit.

LinkingGlobalData & getGlobalData()

Return global data.

std::vector< std::unique_ptr< DIEAbbrev > > Abbreviations

Storage for the unique Abbreviations.

DIE * OutUnitDIE

Output unit DIE.

std::string SysRoot

The DW_AT_LLVM_sysroot of this unit.

bool isClangModule() const

Return true if this compile unit is from Clang module.

unsigned ID

Unique ID for the unit.

const std::string & getClangModuleName() const

Return Clang module name;.

void setOutUnitDIE(DIE *UnitDie)

Set output unit DIE.

DwarfUnit(LinkingGlobalData &GlobalData, unsigned ID, StringRef ClangModuleName)

std::string ClangModuleName

If this is a Clang module, this holds the module's name.

FoldingSet< DIEAbbrev > AbbreviationsSet

FoldingSet that uniques the abbreviations.

StringRef getSysRoot()

Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef.

DIE * getOutUnitDIE()

Returns output unit DIE.

This class keeps data and services common for the whole linking process.

This class helps to assign indexes for DIE children.

LinkingGlobalData & GlobalData

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.

std::atomic< bool > ParentIsDeclaration

std::atomic< DIE * > DeclarationDie

std::atomic< DIE * > Die

TypeEntryBody keeps partially cloned DIEs corresponding to this type.

TypePool keeps type descriptors which contain partially cloned DIE correspinding to each type.

BumpPtrAllocator & getThreadLocalAllocator()

Return thread local allocator used by pool.

TypeEntryBody * getOrCreateTypeEntryBody(TypeEntry *Entry, TypeEntry *ParentEntry)

Create or return existing type entry body for the specified Entry.

TypeEntry * getRoot() const

Return root for all type entries.

Type Unit is used to represent an artificial compilation unit which keeps all type information.

TypePool & getTypePool()

Returns global type pool.

uint64_t tell() const

tell - Return the current offset with the file.

void rememberDieOutOffset(uint32_t Idx, uint64_t Offset)

Idx index of the DIE.

TypeEntry * getDieTypeEntry(uint32_t Idx)

Idx index of the DIE.

DIEInfo & getDIEInfo(unsigned Idx)

Idx index of the DIE.

const DWARFDebugInfoEntry * getSiblingEntry(const DWARFDebugInfoEntry *Die) const

const DWARFDebugInfoEntry * getFirstChildEntry(const DWARFDebugInfoEntry *Die) const

std::optional< uint32_t > getDIEIndexForOffset(uint64_t Offset)

DWARFDie getDIE(const DWARFDebugInfoEntry *Die)

const DWARFDebugInfoEntry * getDebugInfoEntry(unsigned Index) const

DWARFUnit & getOrigUnit() const

Returns paired compile unit from input DWARF.

DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)

uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const

std::optional< DWARFFormValue > find(uint32_t DieIdx, ArrayRef< dwarf::Attribute > Attrs) const

Error emitDebugInfo(const Triple &TargetTriple)

Emit .debug_info section for unit DIEs.

Error emitDebugStringOffsetSection()

Emit the .debug_str_offsets section for current unit.

void emitPubAccelerators()

Emit .debug_pubnames and .debug_pubtypes for Unit.

void warn(const Twine &Warning, const DWARFDie *DIE=nullptr)

Error emitAbbreviations()

Error emitDebugLine(const Triple &TargetTriple, const DWARFDebugLine::LineTable &OutLineTable)

Emit .debug_line section.

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

bool isODRLanguage(uint16_t Language)

function_ref< CompileUnit *(uint64_t Offset)> OffsetToUnitTy

SmallVector< uint64_t * > OffsetsPtrVector

Type for list of pointers to patches offsets.

StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry

ArrayRef< dwarf::Attribute > getODRAttributes()

Definition DWARFLinkerCompileUnit.cpp:1849

ResolveInterCUReferencesMode

StringRef guessDeveloperDir(StringRef SysRoot)

Make a best effort to guess the Xcode.app/Contents/Developer path from an SDK path.

DebugSectionKind

List of tracked debug tables.

StringMapEntry< EmptyStringSetTag > StringEntry

StringEntry keeps data of the string: the length, external offset and a string body which is placed r...

bool isInToolchainDir(StringRef Path)

Make a best effort to determine whether Path is inside a toolchain.

bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path)

std::optional< uint64_t > toAddress(const std::optional< DWARFFormValue > &V)

Take an optional DWARFFormValue and try to extract an address.

std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)

Take an optional DWARFFormValue and try to extract a string value from it.

std::optional< uint64_t > toSectionOffset(const std::optional< DWARFFormValue > &V)

Take an optional DWARFFormValue and try to extract an section offset.

StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})

Take an optional DWARFFormValue and try to extract a string value from it.

std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)

Take an optional DWARFFormValue and try to extract an unsigned constant.

@ DW_ARANGES_VERSION

Section version number for .debug_aranges.

LLVM_ABI std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)

Collapse all .

LLVM_ABI StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get parent path.

LLVM_ABI bool is_relative(const Twine &path, Style style=Style::native)

Is path relative?

LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get filename.

LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")

Append to path.

void swapByteOrder(T &Value)

This is an optimization pass for GlobalISel generic memory operations.

auto find(R &&Range, const T &Val)

Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.

void fill(R &&Range, T &&Value)

Provide wrappers to std::fill which take ranges instead of having to pass begin/end explicitly.

auto partition_point(R &&Range, Predicate P)

Binary search for the first iterator in a range where a predicate is false.

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)

@ Dwarf

DWARF v5 .debug_names.

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

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...

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

DWARFExpression::Operation Op

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)

Utility function to encode a ULEB128 value to an output stream.

bool isCompileUnit(const std::unique_ptr< DWARFUnit > &U)

BumpPtrAllocatorImpl<> BumpPtrAllocator

The standard BumpPtrAllocator which just uses the default template parameters.

void consumeError(Error Err)

Consume a Error without doing anything.

dwarf::FormParams FormParams

Version, address size (starting in v5), and DWARF32/64 format; these parameters affect interpretation...

Standard .debug_line state machine structure.

Represents a single DWARF expression, whose value is location-dependent.

A helper struct providing information about the byte size of DW_FORM values that vary in size dependi...

uint8_t getDwarfOffsetByteSize() const

The size of a reference is determined by the DWARF 32/64-bit format.

Information gathered about source DIEs.

LLVM_DUMP_METHOD void dump()

bool needToPlaceInTypeTable() const

DieOutputPlacement getPlacement() const

This structure is used to update reference to the DIE.

uint64_t RefDieIdxOrClonedOffset

PointerIntPair< CompileUnit *, 1 > RefCU

This structure is used to update location list offset into .debug_loc/.debug_loclists.

int64_t AddrAdjustmentValue

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.

uint64_t RefDieIdxOrClonedOffset

PointerIntPair< CompileUnit *, 1 > RefCU

dwarf::FormParams getFormParams() const

Returns FormParams used by section.

This structure is used to keep data of the concrete section.

raw_svector_ostream OS

Stream which stores data to the Contents.

void emitUnitLength(uint64_t Length)

Emit unit length into the current section contents.

void emitOffset(uint64_t Val)

Emit specified offset value into the current section contents.

void emitIntVal(uint64_t Val, unsigned Size)

Emit specified integer value into the current section contents.

void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val)

Write specified Value of AttrForm to the PatchOffset.

uint64_t getIntVal(uint64_t PatchOffset, unsigned Size)

Returns integer value of Size located by specified PatchOffset.

This is a helper structure which keeps a debug info entry with it's containing compilation unit.

UnitEntryPairTy()=default

std::optional< UnitEntryPairTy > getParent()

Definition DWARFLinkerCompileUnit.cpp:1789

UnitEntryPairTy getNamespaceOrigin()

Definition DWARFLinkerCompileUnit.cpp:1772

const DWARFDebugInfoEntry * DieEntry