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

1

2

3

4

5

6

7

8

22#include

23

24using namespace llvm;

25using namespace dwarf_linker;

26using namespace dwarf_linker::parallel;

27

32 : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),

33 getUnitFromOffset(UnitFromOffset), Stage(Stage::CreatedNotLoaded),

34 AcceleratorRecords(&GlobalData.getAllocator()) {

38}

39

44 : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),

45 OrigUnit(&OrigUnit), getUnitFromOffset(UnitFromOffset),

47 AcceleratorRecords(&GlobalData.getAllocator()) {

50

52 if (!CUDie)

53 return;

54

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

58 Language = LangVal;

59 }

60

62 NoODR = false;

63

66 else

69}

70

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

73}

74

76

78 return;

79

80

81

82

83

84

86 Info.unsetFlagsWhichSetDuringLiveAnalysis();

87

88 LowPc = std::nullopt;

89 HighPc = 0;

92 Dependencies.reset(nullptr);

93

96 return;

97 }

98

99 AcceleratorRecords.erase();

103 DebugAddrIndexMap.clear();

104

108 Name = nullptr;

110

112}

113

116 if (!InputUnitDIE)

117 return false;

118

119

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

122 if (!NoODR)

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

124 return true;

125}

126

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

128 bool IsODRUnavailableFunctionScope) {

130

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

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: {

165

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

168

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

170 ChildInfo.setIsInAnonNamespaceScope();

171 } break;

172 default:

173 break;

174 }

175

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

190 if (LineTablePtr) {

192

193

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

196 std::string OrigFileName;

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

205

208

209

210

212 ResolvedParentPaths.find(ParentPath);

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

216 ParentIt =

217 ResolvedParentPaths

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

219 .first;

220 }

221

222

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

242 ResolvedParentPaths.clear();

247 Dependencies.reset(nullptr);

249}

250

251

252

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

255 return;

256

258 return;

259

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

263 return;

264

270 return;

271

272

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

275 return;

277 return;

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

282 return;

283 }

284

286

290 ResolvedPath,

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

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

306

309}

310

319 continue;

320

321 assert(ChildInfo.getODRAvailable());

323 {this, CurChild},

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

325 return Err;

326

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

328 return Err;

329 }

330

332}

333

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

337

338 (*DebugInfoSection)

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

340

344 });

345

346 (*DebugInfoSection)

347 ->ListDebugULEB128DieRefPatch.forEach(

349

353 });

354 }

355

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

358 (*DebugLocSection)

359 ->ListDebugULEB128DieRefPatch.forEach(

361

365 });

366 }

367

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

370 (*DebugLocListsSection)

371 ->ListDebugULEB128DieRefPatch.forEach(

373

377 });

378 }

379}

380

387 RefCU = this;

390 RefCU = getUnitFromOffset(*Offset);

391 RefDIEOffset = *Offset;

392 } else {

393 return std::nullopt;

394 }

395

396 if (RefCU == this) {

397

400 } else if (RefCU && CanResolveInterCUReferences) {

401

402

403

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

407

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

411 } else {

413 }

414 return std::nullopt;

415}

416

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

422

423 return std::nullopt;

424}

425

427 int64_t PcOffset) {

428 std::lock_guardstd::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

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

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

441}

442

444 if (getGlobalData().getOptions().UpdateIndexTablesOnly)

446

450 }

451

454}

455

456void CompileUnit::emitLocations(DebugSectionKind LocationSectionKind) {

459

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

464

465 uint64_t OffsetAfterUnitLength = emitLocListHeader(OutLocationSection);

466

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

468

469

470 uint64_t InputDebugLocSectionOffset = DebugInfoSection.getIntVal(

475

476 if (!OriginalLocations) {

477 warn(OriginalLocations.takeError());

478 return;

479 }

480

481 LinkedLocationExpressionsVector LinkedLocationExpressions;

483 LinkedLocationExpressionsWithOffsetPatches LinkedExpression;

484

485 if (CurExpression.Range) {

486

487 LinkedExpression.Expression.Range = {

490 }

491

494

498 LinkedExpression.Expression.Expr,

500 LinkedExpression.Patches);

501

502 LinkedLocationExpressions.push_back({LinkedExpression});

503 }

504

505

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 -

514 OffsetAfterUnitLength);

515 OutLocationSection.apply(

516 OffsetAfterUnitLength -

518 dwarf::DW_FORM_sec_offset,

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

520 }

521 }

522}

523

524

527 return 0;

528

529

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

532

533

535

536

538

539

541

542

544

545 return OffsetAfterUnitLength;

546}

547

548

549uint64_t CompileUnit::emitLocListFragment(

550 const LinkedLocationExpressionsVector &LinkedLocationExpression,

552 uint64_t OffsetBeforeLocationExpression = 0;

553

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

557 BaseAddress = *LowPC;

558

559 for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :

560 LinkedLocationExpression) {

561 if (LocExpression.Expression.Range) {

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

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

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

585 return OffsetBeforeLocationExpression;

586 }

587

588 std::optional<uint64_t> BaseAddress;

589 for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :

590 LinkedLocationExpression) {

591 if (LocExpression.Expression.Range) {

592

593

594 if (!BaseAddress) {

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

596

597

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

600 OutLocationSection.OS);

601 }

602

603

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

605

606

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

608 OutLocationSection.OS);

609

610

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

612 OutLocationSection.OS);

613 } else

614

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

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

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

625 }

626

627

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

629 return OffsetBeforeLocationExpression;

630}

631

632Error CompileUnit::emitDebugAddrSection() {

635

638

639 if (DebugAddrIndexMap.empty())

641

644

645

646

647

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

650

651

653

654

656

657

659

660

663

664

665 OutAddrSection.apply(

666 OffsetAfterSectionLength -

668 dwarf::DW_FORM_sec_offset,

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

670

672}

673

675 if (getGlobalData().getOptions().UpdateIndexTablesOnly)

677

678

681 LinkedFunctionRanges.insert(

683

684 emitAranges(LinkedFunctionRanges);

685

689 }

690

693}

694

695void CompileUnit::cloneAndEmitRangeList(DebugSectionKind RngSectionKind,

701

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

703 std::optional CachedRange;

704 uint64_t OffsetAfterUnitLength = emitRangeListHeader(OutRangeSection);

705

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

709 CompileUnitRangePtr = &Patch;

710 } else {

711

712

713 AddressRanges LinkedRanges;

714 uint64_t InputDebugRangesSectionOffset = DebugInfoSection.getIntVal(

715 Patch.PatchOffset,

716 DebugInfoSection.getFormParams().getDwarfOffsetByteSize());

717 if (Expected InputRanges =

718 getOrigUnit().findRnglistFromOffset(

719 InputDebugRangesSectionOffset)) {

720

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

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

723 CachedRange =

724 getFunctionRanges().getRangeThatContains(Range.LowPC);

725

726

727 if (!CachedRange) {

728 warn("inconsistent range data.");

729 continue;

730 }

731

732

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

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

750

752 dwarf::DW_FORM_sec_offset,

753 OutRangeSection.OS.tell());

754 emitRangeListFragment(LinkedFunctionRanges, OutRangeSection);

755 }

756

757 if (OffsetAfterUnitLength > 0) {

758 assert(OffsetAfterUnitLength -

760 OffsetAfterUnitLength);

761 OutRangeSection.apply(

762 OffsetAfterUnitLength -

764 dwarf::DW_FORM_sec_offset,

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

766 }

767 }

768}

769

772 return 0;

773

774

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

777

778

780

781

783

784

786

787

789

790 return OffsetAfterUnitLength;

791}

792

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

796

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

799 BaseAddress = *LowPC;

800

806 }

807

808

811 return;

812 }

813

814 std::optional<uint64_t> BaseAddress;

816 if (!BaseAddress) {

817 BaseAddress = Range.start();

818

819

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

822 }

823

824

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

826

827

829

830

832 }

833

834

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

836}

837

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

839 if (LinkedFunctionRanges.empty())

840 return;

841

846

847

849 sizeof(int32_t) +

850 sizeof(int16_t) +

851 sizeof(int32_t) +

852 sizeof(int8_t) +

853 sizeof(int8_t);

854

857

858 OutArangesSection.emitOffset(0xBADDEF);

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

860

862 OutArangesSection.notePatch(

864 OutArangesSection.emitOffset(0xBADDEF);

866 1);

867 OutArangesSection.emitIntVal(0, 1);

868

870 OutArangesSection.emitIntVal(0, 1);

871

872

878 }

879

880

883

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

885

886

887 OutArangesSection.apply(

888 OffsetAfterArangesLengthField -

890 dwarf::DW_FORM_sec_offset,

891 OffsetAfterArangesEnd - OffsetAfterArangesLengthField);

892}

893

897

900

901

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

906 emitMacroTableImpl(Table, *MacroAttr, true);

907 }

908 }

909

910

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

915 emitMacroTableImpl(Table, *MacroAttr, false);

916 }

917 }

918

920}

921

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

924 bool hasDWARFv5Header) {

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

937 if (hasDWARFv5Header) {

938

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

940

942

943

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

952 std::optional<uint64_t> StmtListOffset;

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

954

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

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

970

971

972 if (StmtListOffset) {

974 OutSection.OS.tell(),

976

977

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

979 }

980 }

981

982

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

984 if (MacroEntry.Type == 0) {

986 continue;

987 }

988

989 uint8_t MacroType = MacroEntry.Type;

990 switch (MacroType) {

991 default: {

992 bool HasVendorSpecificExtension =

993 (!hasDWARFv5Header &&

997

998 if (HasVendorSpecificExtension) {

999

1000 OutSection.emitIntVal(MacroType, 1);

1001

1002

1004

1005

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

1007 } else

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

1009 } break;

1010

1011

1012

1013

1014

1015

1016 case dwarf::DW_MACRO_define:

1017 case dwarf::DW_MACRO_undef: {

1018

1019 OutSection.emitIntVal(MacroType, 1);

1020

1021

1023

1024

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

1032

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

1052 break;

1053 }

1054

1055

1056 OutSection.emitIntVal(MacroType, 1);

1057

1058

1060

1061

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

1063 break;

1064 }

1065 case dwarf::DW_MACRO_start_file: {

1066

1067 OutSection.emitIntVal(MacroType, 1);

1068

1070

1072 } break;

1073 case dwarf::DW_MACRO_end_file: {

1074

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

1096 std::optional<int64_t> VarAddressAdjustment,

1099

1102

1104 for (auto &Op : InputExpression) {

1106

1107

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

1119 assert(ULEBsize <= 16);

1120

1121

1127 } else {

1130 }

1133 unsigned RealSize = 0;

1134

1135

1136

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

1138 RefOffset += OrigUnit.getOffset();

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

1142 RefDieIdx = *Idx;

1143

1144

1145

1147

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

1149

1150 Section.notePatchWithOffsetUpdate(

1152 RefDieIdx),

1153 PatchesOffsets);

1154 } else

1156

1157 if (RealSize > ULEBsize) {

1158

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

1161 }

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

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

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

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

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

1169

1170

1171

1172

1173 OutputExpression.push_back(dwarf::DW_OP_addr);

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

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

1179 OrigAddressByteSize);

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

1181 } else

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

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

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

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

1187

1188

1189

1190

1191 std::optional<uint8_t> OutOperandKind;

1192 switch (OrigAddressByteSize) {

1193 case 2:

1194 OutOperandKind = dwarf::DW_OP_const2u;

1195 break;

1196 case 4:

1197 OutOperandKind = dwarf::DW_OP_const4u;

1198 break;

1199 case 8:

1200 OutOperandKind = dwarf::DW_OP_const8u;

1201 break;

1202 default:

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

1205 break;

1206 }

1207

1208 if (OutOperandKind) {

1209 OutputExpression.push_back(*OutOperandKind);

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

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

1216 OrigAddressByteSize);

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

1218 }

1219 } else

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

1221 } else {

1222

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

1226 }

1228 }

1229}

1230

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

1233 TypeUnit *ArtificialTypeUnit) {

1235

1237 if (!OrigUnitDIE.isValid())

1239

1241 if (ArtificialTypeUnit)

1243

1244

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

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

1249

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

1252

1254 return Err;

1255

1257 return Err;

1258

1261 return Err;

1262

1263

1264

1265

1266

1268 return Err;

1269

1271 return Err;

1272

1273 if (Error Err = emitDebugAddrSection())

1274 return Err;

1275

1276

1280

1282 return Err;

1283

1285}

1286

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

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

1291 TypeUnit *ArtificialTypeUnit) {

1294

1295 bool NeedToClonePlainDIE = Info.needToKeepInPlainDwarf();

1296 bool NeedToCloneTypeDIE =

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

1298 Info.needToPlaceInTypeTable();

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

1300

1302

1303 if (NeedToClonePlainDIE)

1304

1305

1306 ClonedDIE.first = createPlainDIEandCloneAttributes(

1307 InputDieEntry, PlainDIEGenerator, OutOffset, FuncAddressAdjustment,

1308 VarAddressAdjustment);

1309 if (NeedToCloneTypeDIE) {

1310

1311

1312 assert(ArtificialTypeUnit != nullptr);

1315

1316 ClonedDIE.second = createTypeDIEandCloneAttributes(

1317 InputDieEntry, TypeDIEGenerator, ClonedParentTypeDIE,

1318 ArtificialTypeUnit);

1319 }

1321 ClonedDIE.second ? ClonedDIE.second : ClonedParentTypeDIE;

1322

1323 bool HasPlainChildrenToClone =

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

1325

1326 bool HasTypeChildrenToClone =

1327 ((ClonedDIE.second ||

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

1329 Info.getKeepTypeChildren());

1330

1331

1332 if (HasPlainChildrenToClone || HasTypeChildrenToClone) {

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

1338 CurChild, TypeParentForChild, OutOffset, FuncAddressAdjustment,

1339 VarAddressAdjustment, Allocator, ArtificialTypeUnit);

1340

1341 if (ClonedChild.first) {

1342 OutOffset =

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

1344 PlainDIEGenerator.addChild(ClonedChild.first);

1345 }

1346 }

1347 assert(ClonedDIE.first == nullptr ||

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

1349

1350

1351 if (HasPlainChildrenToClone)

1352 OutOffset += sizeof(int8_t);

1353 }

1354

1355

1356 if (ClonedDIE.first != nullptr)

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

1358

1359 return ClonedDIE;

1360}

1361

1362DIE *CompileUnit::createPlainDIEandCloneAttributes(

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

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

1368 DIE *ClonedDIE = nullptr;

1369 bool HasLocationExpressionAddress = false;

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

1371

1372 FuncAddressAdjustment =

1374 getDIE(InputDieEntry), false);

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

1376

1377 std::optional<uint64_t> lowPC =

1379 if (lowPC) {

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

1382 FuncAddressAdjustment = It->second;

1383 }

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

1385

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

1388 getDIE(InputDieEntry), false);

1389

1390 HasLocationExpressionAddress = LocExprAddrAndRelocAdjustment.first;

1391 if (LocExprAddrAndRelocAdjustment.first &&

1392 LocExprAddrAndRelocAdjustment.second)

1393 VarAddressAdjustment = *LocExprAddrAndRelocAdjustment.second;

1394 }

1395

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

1397

1398

1399

1401

1402

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

1404 PlainDIEGenerator, FuncAddressAdjustment,

1405 VarAddressAdjustment,

1406 HasLocationExpressionAddress);

1407 AttributesCloner.clone();

1408

1409

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

1412 nullptr);

1413

1414 OutOffset =

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

1416

1417 return ClonedDIE;

1418}

1419

1420

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

1423 dwarf::Tag DieTag, bool IsDeclaration,

1424 bool IsParentDeclaration) {

1425 DIE *DefinitionDie = TypeDescriptor->Die;

1426

1427 if (DefinitionDie)

1428 return nullptr;

1429

1432

1433 if (IsDeclaration && !DeclarationDie) {

1434

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

1436 if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,

1437 NewDie))

1438 return NewDie;

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

1440

1441

1443 OldParentIsDeclaration, false)) {

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

1446 return NewDie;

1447 }

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

1449

1450

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

1452 if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,

1453 NewDie))

1454 return NewDie;

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

1456

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

1458 if (TypeDescriptor->Die.compare_exchange_weak(DefinitionDie, NewDie)) {

1460 return NewDie;

1461 }

1462 }

1463

1464 return nullptr;

1465}

1466

1467TypeEntry *CompileUnit::createTypeDIEandCloneAttributes(

1470 assert(ArtificialTypeUnit != nullptr);

1472

1474 assert(Entry != nullptr);

1475 assert(ClonedParentTypeDIE != nullptr);

1478 Entry, ClonedParentTypeDIE);

1480

1481 bool IsDeclaration =

1483

1484 bool ParentIsDeclaration = false;

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

1486 ParentIsDeclaration =

1488

1489 DIE *OutDIE =

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

1491 IsDeclaration, ParentIsDeclaration);

1492

1493 if (OutDIE != nullptr) {

1494 assert(ArtificialTypeUnit != nullptr);

1496

1497 DIEAttributeCloner AttributesCloner(OutDIE, *this, ArtificialTypeUnit,

1498 InputDieEntry, TypeDIEGenerator,

1499 std::nullopt, std::nullopt, false);

1500 AttributesCloner.clone();

1501

1502

1504 ArtificialTypeUnit);

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

1506 Entry);

1507

1508

1509

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

1511 }

1512

1514}

1515

1519 if (InputLineTable == nullptr) {

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

1523 }

1524

1526

1527

1530

1531

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

1533 OutLineTable.Rows = InputLineTable->Rows;

1534

1535

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

1537 OutLineTable.Rows.clear();

1538

1540 } else {

1541

1542 std::vectorDWARFDebugLine::Row NewRows;

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

1544

1545

1546

1547 std::vectorDWARFDebugLine::Row Seq;

1548

1550 std::optional CurrRange;

1551

1552

1553

1554

1555

1556

1557

1558

1559

1560

1561

1562

1564

1565

1566

1567

1568

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

1570

1571

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

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

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

1576

1577

1578 auto NextLine = Seq.back();

1579 NextLine.Address.Address = StopAddress;

1580 NextLine.EndSequence = 1;

1581 NextLine.PrologueEnd = 0;

1582 NextLine.BasicBlock = 0;

1583 NextLine.EpilogueBegin = 0;

1584 Seq.push_back(NextLine);

1585 insertLineSequence(Seq, NewRows);

1586 }

1587

1588 if (!CurrRange)

1589 continue;

1590 }

1591

1592

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

1594 continue;

1595

1596

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

1598 Seq.emplace_back(Row);

1599

1600 if (Row.EndSequence)

1601 insertLineSequence(Seq, NewRows);

1602 }

1603

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

1605 }

1606

1607 return emitDebugLine(TargetTriple, OutLineTable);

1608}

1609

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

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

1612 if (Seq.empty())

1613 return;

1614

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

1617 Seq.clear();

1618 return;

1619 }

1620

1624

1625

1626

1627

1628

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

1630 InsertPoint->EndSequence) {

1631 *InsertPoint = Seq.front();

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

1633 } else {

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

1635 }

1636

1637 Seq.clear();

1638}

1639

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

1647 break;

1650 break;

1653 break;

1656 break;

1657 }

1658

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

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

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

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

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

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

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

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

1668}

1669#endif

1670

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

1676 FileIdx = *Val;

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

1678 FileIdx = *Val;

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

1680 FileIdx = *Val;

1681 else

1682 return std::nullopt;

1683

1685}

1686

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

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

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

1693

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

1697

1699 LineTable->Prologue.getFileNameEntry(FileIdx);

1700

1702 if (Name) {

1704 return std::nullopt;

1705 }

1706

1707 std::string FileName = *Name;

1711 .insert(std::make_pair(

1712 FileIdx,

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

1714 .first;

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

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

1717 }

1718

1721

1723

1724

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

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

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

1729 .getAsCString();

1730 if (DirName)

1731 IncludeDir = *DirName;

1732 else {

1734 return std::nullopt;

1735 }

1736 }

1737 } else {

1738 if (0 < Entry.DirIdx &&

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

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

1742 .getAsCString();

1743 if (DirName)

1744 IncludeDir = *DirName;

1745 else {

1747 return std::nullopt;

1748 }

1749 }

1750 }

1751

1753

1756 }

1757

1759

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

1764 std::move(FileName))))

1765 .first;

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

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

1768 }

1769 }

1770

1771 return std::nullopt;

1772}

1773

1774#define MAX_REFERENCIES_DEPTH 1000

1777 std::optional RefDiePair;

1778 int refDepth = 0;

1779 do {

1781 CUDiePair.DieEntry, dwarf::DW_AT_extension,

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

1784 return CUDiePair;

1785

1786 CUDiePair = *RefDiePair;

1788

1789 return CUDiePair;

1790}

1791

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

1795

1796 return std::nullopt;

1797}

1798

1800 : Ptr(U) {

1801 assert(U != nullptr);

1802}

1803

1805 assert(U != nullptr);

1806}

1807

1810 return getAsCompileUnit();

1811 else

1812 return getAsTypeUnit();

1813}

1814

1816 return isa<CompileUnit *>(Ptr);

1817}

1818

1820 return isa<TypeUnit *>(Ptr);

1821}

1822

1824 return cast<CompileUnit *>(Ptr);

1825}

1826

1828 return cast<TypeUnit *>(Ptr);

1829}

1830

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

1833 if (!Dependencies)

1835

1836 return Dependencies->resolveDependenciesAndMarkLiveness(

1837 InterCUProcessingStarted, HasNewInterconnectedCUs);

1838}

1839

1841 assert(Dependencies.get());

1842

1843 return Dependencies->updateDependenciesCompleteness();

1844}

1845

1847 assert(Dependencies.get());

1848

1849 Dependencies->verifyKeepChain();

1850}

1851

1854 dwarf::DW_AT_type, dwarf::DW_AT_specification,

1855 dwarf::DW_AT_abstract_origin, dwarf::DW_AT_import};

1856

1857 return ODRAttributes;

1858}

Analysis containing CSE Info

#define LLVM_DUMP_METHOD

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

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

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.

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

Allocate memory in an ever growing pool, as if by bump-pointer.

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.

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

Extract the specified attribute from this DIE.

const DWARFDebugInfoEntry * getDebugInfoEntry() const

const char * getName(DINameKind Kind) const

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

This class represents an Operation in the Expression.

std::optional< unsigned > getSubCode() const

uint64_t getEndOffset() 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

DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)

uint8_t getAddressByteSize() const

const char * getCompilationDir()

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

Return the DIE index for a given offset Offset inside the unit's DIE vector.

Expected< DWARFLocationExpressionsVector > findLoclistFromOffset(uint64_t Offset)

bool isLittleEndian() const

std::optional< object::SectionedAddress > getAddrOffsetSectionItem(uint32_t Index) const

uint64_t getOffset() const

iterator find(const_arg_type_t< KeyT > Val)

DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > 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.

StringMapEntry - This is used to represent one value that is inserted into a StringMap.

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

uint64_t getValueIndex(T Value)

const SmallVector< T > & getValues() const

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

This class helps to store information for accelerator entries.

TypeUnit * getAsTypeUnit()

Returns TypeUnit if applicable.

DwarfUnit * operator->()

Accessor for common functionality.

CompileUnit * getAsCompileUnit()

Returns CompileUnit if applicable.

OutputUnitVariantPtr(CompileUnit *U)

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)

Error cloneAndEmitRanges()

Clone and emit ranges.

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.

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

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

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

void loadLineTable()

Loads unit line table.

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.

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

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.

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.

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.

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.

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 emitAbbreviations()

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

Emit .debug_line section.

bool isODRLanguage(uint16_t Language)

ArrayRef< dwarf::Attribute > getODRAttributes()

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.

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.

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

Collapse all .

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

Get parent path.

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

Is path relative?

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

Get filename.

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

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

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.

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)

This struct is a compact representation of a valid (non-zero power of two) alignment.

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

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

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.

bool UpdateIndexTablesOnly

Update index tables.

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

std::optional< UnitEntryPairTy > getParent()

UnitEntryPairTy getNamespaceOrigin()

const DWARFDebugInfoEntry * DieEntry