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

1

2

3

4

5

6

7

8

39#include

40

41namespace llvm {

42

45

46

51

52

55 for (auto &Unit : Dwarf.compile_units()) {

56 Size += Unit->getLength();

57 }

59}

60

61

62

66 return LHS < RHS->getOrigUnit().getNextUnitOffset();

67 });

68 return CU != Units.end() ? CU->get() : nullptr;

69}

70

71

72

73

74DWARFDie DWARFLinker::resolveDIEReference(const DWARFFile &File,

76 const DWARFFormValue &RefValue,

77 const DWARFDie &DIE,

78 CompileUnit *&RefCU) {

81 if (std::optional<uint64_t> Off = RefValue.getAsRelativeReference()) {

82 RefOffset = RefValue.getUnit()->getOffset() + *Off;

83 } else if (Off = RefValue.getAsDebugInfoReference(); Off) {

84 RefOffset = *Off;

85 } else {

86 reportWarning("Unsupported reference type", File, &DIE);

87 return DWARFDie();

88 }

90 if (const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) {

91

92

93 if (!RefDie.isNULL())

94 return RefDie;

95 }

96

97 reportWarning("could not find referenced DIE", File, &DIE);

98 return DWARFDie();

99}

100

101

102

104 switch (Attr) {

105 default:

106 return false;

107 case dwarf::DW_AT_type:

108 case dwarf::DW_AT_containing_type:

109 case dwarf::DW_AT_specification:

110 case dwarf::DW_AT_abstract_origin:

111 case dwarf::DW_AT_import:

112 case dwarf::DW_AT_LLVM_alloc_type:

113 return true;

114 }

116}

117

119 switch (Tag) {

120 case dwarf::DW_TAG_array_type:

121 case dwarf::DW_TAG_class_type:

122 case dwarf::DW_TAG_enumeration_type:

123 case dwarf::DW_TAG_pointer_type:

124 case dwarf::DW_TAG_reference_type:

125 case dwarf::DW_TAG_string_type:

126 case dwarf::DW_TAG_structure_type:

127 case dwarf::DW_TAG_subroutine_type:

128 case dwarf::DW_TAG_template_alias:

129 case dwarf::DW_TAG_typedef:

130 case dwarf::DW_TAG_union_type:

131 case dwarf::DW_TAG_ptr_to_member_type:

132 case dwarf::DW_TAG_set_type:

133 case dwarf::DW_TAG_subrange_type:

134 case dwarf::DW_TAG_base_type:

135 case dwarf::DW_TAG_const_type:

136 case dwarf::DW_TAG_constant:

137 case dwarf::DW_TAG_file_type:

138 case dwarf::DW_TAG_namelist:

139 case dwarf::DW_TAG_packed_type:

140 case dwarf::DW_TAG_volatile_type:

141 case dwarf::DW_TAG_restrict_type:

142 case dwarf::DW_TAG_atomic_type:

143 case dwarf::DW_TAG_interface_type:

144 case dwarf::DW_TAG_unspecified_type:

145 case dwarf::DW_TAG_shared_type:

146 case dwarf::DW_TAG_immutable_type:

147 return true;

148 default:

149 break;

150 }

151 return false;

152}

153

154

155

157DWARFLinker::DIECloner::getCanonicalDIEName(DWARFDie Die, const DWARFFile &File,

158 CompileUnit *Unit) {

159 if (!Die)

160 return {};

161

162 std::optional Ref;

163

164 auto GetDieName = [](const DWARFDie &D) -> llvm::StringRef {

165 auto NameForm = D.find(llvm::dwarf::DW_AT_name);

166 if (!NameForm)

167 return {};

168

169 auto NameOrErr = NameForm->getAsCString();

170 if (!NameOrErr) {

172 return {};

173 }

174

175 return *NameOrErr;

176 };

177

178 llvm::StringRef Name = GetDieName(Die);

179 if (Name.empty())

181

182 while (true) {

183 if (!(Ref = Die.find(llvm::dwarf::DW_AT_specification)) &&

184 !(Ref = Die.find(llvm::dwarf::DW_AT_abstract_origin)))

185 break;

186

187 Die = Linker.resolveDIEReference(File, CompileUnits, *Ref, Die, Unit);

188 if (!Die)

189 break;

190

192

193 unsigned SpecIdx = Unit->getOrigUnit().getDIEIndex(Die);

194 CompileUnit::DIEInfo &SpecInfo = Unit->getInfo(SpecIdx);

195 if (SpecInfo.Ctxt && SpecInfo.Ctxt->hasCanonicalDIE()) {

196 if (!SpecInfo.Ctxt->getCanonicalName().empty()) {

197 Name = SpecInfo.Ctxt->getCanonicalName();

198 break;

199 }

200 }

201

202 Name = GetDieName(Die);

203 if (Name.empty())

204 break;

205 }

206

208}

209

210bool DWARFLinker::DIECloner::getDIENames(

212 const DWARFFile &File, CompileUnit &Unit, bool StripTemplate) {

213

214

215

216 if (Die.getTag() == dwarf::DW_TAG_lexical_block)

217 return false;

218

219

220

221

222 if (Info.MangledName)

223 if (const char *MangledName = Die.getLinkageName())

224 Info.MangledName = StringPool.getEntry(MangledName);

225

226

227

228

229 if (Info.Name)

230 if (llvm::StringRef Name = getCanonicalDIEName(Die, File, &Unit);

231 Name.empty())

232 Info.Name = StringPool.getEntry(Name);

233

234 if (Info.MangledName)

235 Info.MangledName = Info.Name;

236

237 if (StripTemplate && Info.Name && Info.MangledName != Info.Name) {

238 StringRef Name = Info.Name.getString();

240 Info.NameWithoutTemplate = StringPool.getEntry(*StrippedName);

241 }

242

243 return Info.Name || Info.MangledName;

244}

245

246

247

251

252

253

257 std::function<void(const Twine &, const DWARFDie &)> ReportWarning) {

258 if (CU.getLanguage() != dwarf::DW_LANG_Swift)

259 return;

260

261 if (!ParseableSwiftInterfaces)

262 return;

263

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

266 return;

267

269 if (SysRoot.empty())

270 SysRoot = CU.getSysRoot();

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

272 return;

273

274

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

277 return;

279 return;

280 std::optional<const char *> Name =

282 if (!Name)

283 return;

284 auto &Entry = (*ParseableSwiftInterfaces)[*Name];

285

286 DWARFDie CUDie = CU.getOrigUnit().getUnitDIE();

291 if (!Entry.empty() && Entry != ResolvedPath)

292 ReportWarning(Twine("Conflicting parseable interfaces for Swift Module ") +

293 *Name + ": " + Entry + " and " + Path,

295 Entry = std::string(ResolvedPath);

296}

297

298

299

305

306

307

308

312 union {

315 };

318

323

329};

330

334

335

336

337

338 Info.Prune &= (Die.getTag() == dwarf::DW_TAG_module) ||

341

342

343

344 if (ModulesEndOffset == 0)

345 Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset();

346 else

347 Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset() > 0 &&

348 Info.Ctxt->getCanonicalDIEOffset() <= ModulesEndOffset;

349

350 return Info.Prune;

351}

352

358

359

360

361

362

363

364

365

366

372 std::function<void(const Twine &, const DWARFDie &)> ReportWarning) {

373

374 std::vector Worklist;

375 Worklist.emplace_back(DIE, CurrentDeclContext, ParentIdx, false);

376

377 while (!Worklist.empty()) {

379 Worklist.pop_back();

380

381 switch (Current.Type) {

384 continue;

387 continue;

389 break;

390 }

391

392 unsigned Idx = CU.getOrigUnit().getDIEIndex(Current.Die);

394

395

396

397

398

399

400

401

402

403

404

405

406

407 if (Current.Die.getTag() == dwarf::DW_TAG_module &&

410 CU.getClangModuleName()) {

413 ReportWarning);

414 }

415

418 if (CU.hasODR() || Info.InModuleScope) {

422 Current.Context = PtrInvalidPair.getPointer();

424 PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();

425 if (Info.Ctxt)

426 Info.Ctxt->setDefinedInClangModule(Info.InModuleScope);

427 } else

429 }

430

432

433

437 Worklist.emplace_back(

439 Worklist.emplace_back(Child, Current.Context, Idx,

441 }

442 }

443}

444

446 switch (Tag) {

447 default:

448 return false;

449 case dwarf::DW_TAG_class_type:

450 case dwarf::DW_TAG_common_block:

451 case dwarf::DW_TAG_lexical_block:

452 case dwarf::DW_TAG_structure_type:

453 case dwarf::DW_TAG_subprogram:

454 case dwarf::DW_TAG_subroutine_type:

455 case dwarf::DW_TAG_union_type:

456 return true;

457 }

459}

460

461void DWARFLinker::cleanupAuxiliarryData(LinkContext &Context) {

462 Context.clear();

463

464 for (DIEBlock *I : DIEBlocks)

465 I->~DIEBlock();

466 for (DIELoc *I : DIELocs)

467 I->~DIELoc();

468

469 DIEBlocks.clear();

470 DIELocs.clear();

471 DIEAlloc.Reset();

472}

473

475 return DW_OP_Code == dwarf::DW_OP_form_tls_address ||

476 DW_OP_Code == dwarf::DW_OP_GNU_push_tls_address;

477}

478

482

483

484 std::map<uint64_t, unsigned> LineTableMapping;

485

486

489

490

491

492 auto StmtAttrs = Unit.getStmtSeqListAttributes();

494 return A.get() < B.get();

495 });

496

497 std::vector SeqStartRows;

498 SeqStartRows.push_back(0);

500 if (Row.EndSequence)

501 SeqStartRows.push_back(I + 1);

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532 ArrayRef StmtAttrsRef(StmtAttrs);

533 ArrayRef SeqStartRowsRef(SeqStartRows);

534

535

536

538 constexpr unsigned DummyVal = UINT32_MAX;

539 LineTableMapping[DummyKey] = DummyVal;

540

541 for (auto [NextSeqOff, NextRow] : LineTableMapping) {

542

543

544 auto StmtAttrSmallerThanNext = [N = NextSeqOff](const PatchLocation &SA) {

545 return SA.get() < N;

546 };

547 auto SeqStartSmallerThanNext = [N = NextRow](const unsigned &Row) {

548 return Row < N;

549 };

550

551

552

553 while (!StmtAttrsRef.empty() && !SeqStartRowsRef.empty() &&

554 StmtAttrSmallerThanNext(StmtAttrsRef.front()) &&

555 SeqStartSmallerThanNext(SeqStartRowsRef.front())) {

556 SeqOffToOrigRow[StmtAttrsRef.consume_front().get()] =

558 }

559

560

561

562 StmtAttrsRef = StmtAttrsRef.drop_while(StmtAttrSmallerThanNext);

563 SeqStartRowsRef = SeqStartRowsRef.drop_while(SeqStartSmallerThanNext);

564

565

566 if (NextSeqOff != DummyKey) {

567 SeqOffToOrigRow[NextSeqOff] = NextRow;

568 }

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583 if (!StmtAttrsRef.empty() && StmtAttrsRef.front().get() == NextSeqOff)

585 if (!SeqStartRowsRef.empty() && SeqStartRowsRef.front() == NextRow)

587 }

588}

589

590std::pair<bool, std::optional<int64_t>>

591DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr,

592 const DWARFDie &DIE) {

593 assert((DIE.getTag() == dwarf::DW_TAG_variable ||

594 DIE.getTag() == dwarf::DW_TAG_constant) &&

595 "Wrong type of input die");

596

597 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();

598

599

600 DWARFUnit *U = DIE.getDwarfUnit();

601 std::optional<uint32_t> LocationIdx =

602 Abbrev->findAttributeIndex(dwarf::DW_AT_location);

603 if (!LocationIdx)

604 return std::make_pair(false, std::nullopt);

605

606

608 Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);

609

610

611 std::optional LocationValue =

612 Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);

613 if (!LocationValue)

614 return std::make_pair(false, std::nullopt);

615

616

617

618

619 std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();

620 if (!Expr)

621 return std::make_pair(false, std::nullopt);

622

623

624 DataExtractor Data(toStringRef(*Expr), U->getContext().isLittleEndian(),

625 U->getAddressByteSize());

626 DWARFExpression Expression(Data, U->getAddressByteSize(),

627 U->getFormParams().Format);

628

629 bool HasLocationAddress = false;

631 for (DWARFExpression::iterator It = Expression.begin();

632 It != Expression.end(); ++It) {

633 DWARFExpression::iterator NextIt = It;

634 ++NextIt;

635

636 const DWARFExpression::Operation &Op = *It;

638 case dwarf::DW_OP_const2u:

639 case dwarf::DW_OP_const4u:

640 case dwarf::DW_OP_const8u:

641 case dwarf::DW_OP_const2s:

642 case dwarf::DW_OP_const4s:

643 case dwarf::DW_OP_const8s:

644 if (NextIt == Expression.end() || isTlsAddressCode(NextIt->getCode()))

645 break;

646 [[fallthrough]];

647 case dwarf::DW_OP_addr: {

648 HasLocationAddress = true;

649

650 if (std::optional<int64_t> RelocAdjustment =

651 RelocMgr.getExprOpAddressRelocAdjustment(

652 *U, Op, AttrOffset + CurExprOffset,

654 return std::make_pair(HasLocationAddress, *RelocAdjustment);

655 } break;

656 case dwarf::DW_OP_constx:

657 case dwarf::DW_OP_addrx: {

658 HasLocationAddress = true;

659 if (std::optional<uint64_t> AddressOffset =

660 DIE.getDwarfUnit()->getIndexedAddressOffset(

662

663 if (std::optional<int64_t> RelocAdjustment =

664 RelocMgr.getExprOpAddressRelocAdjustment(

665 *U, Op, *AddressOffset,

666 *AddressOffset + DIE.getDwarfUnit()->getAddressByteSize(),

667 Options.Verbose))

668 return std::make_pair(HasLocationAddress, *RelocAdjustment);

669 }

670 } break;

671 default: {

672

673 } break;

674 }

676 }

677

678 return std::make_pair(HasLocationAddress, std::nullopt);

679}

680

681

682

683unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,

684 const DWARFDie &DIE,

685 CompileUnit::DIEInfo &MyInfo,

686 unsigned Flags) {

687 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();

688

689

690 if (!(Flags & TF_InFunctionScope) &&

691 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {

692 MyInfo.InDebugMap = true;

693 return Flags | TF_Keep;

694 }

695

696

697

698

699

700

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

702 getVariableRelocAdjustment(RelocMgr, DIE);

703

704 if (LocExprAddrAndRelocAdjustment.first)

705 MyInfo.HasLocationExpressionAddr = true;

706

707 if (!LocExprAddrAndRelocAdjustment.second)

709

710 MyInfo.AddrAdjust = *LocExprAddrAndRelocAdjustment.second;

711 MyInfo.InDebugMap = true;

712

713 if (((Flags & TF_InFunctionScope) &&

716

717 if (Options.Verbose) {

718 outs() << "Keeping variable DIE:";

719 DIDumpOptions DumpOpts;

720 DumpOpts.ChildRecurseDepth = 0;

721 DumpOpts.Verbose = Options.Verbose;

722 DIE.dump(outs(), 8 , DumpOpts);

723 }

724

725 return Flags | TF_Keep;

726}

727

728

729

730unsigned DWARFLinker::shouldKeepSubprogramDIE(

731 AddressesMap &RelocMgr, const DWARFDie &DIE, const DWARFFile &File,

732 CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags) {

733 Flags |= TF_InFunctionScope;

734

735 auto LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc));

736 if (!LowPc)

738

739 assert(LowPc && "low_pc attribute is not an address.");

740 std::optional<int64_t> RelocAdjustment =

741 RelocMgr.getSubprogramRelocAdjustment(DIE, Options.Verbose);

742 if (!RelocAdjustment)

744

745 MyInfo.AddrAdjust = *RelocAdjustment;

746 MyInfo.InDebugMap = true;

747

748 if (Options.Verbose) {

749 outs() << "Keeping subprogram DIE:";

750 DIDumpOptions DumpOpts;

751 DumpOpts.ChildRecurseDepth = 0;

752 DumpOpts.Verbose = Options.Verbose;

753 DIE.dump(outs(), 8 , DumpOpts);

754 }

755

756 if (DIE.getTag() == dwarf::DW_TAG_label) {

757 if (Unit.hasLabelAt(*LowPc))

759

760 DWARFUnit &OrigUnit = Unit.getOrigUnit();

761

762

763

764

765 if (dwarf::toAddress(OrigUnit.getUnitDIE().find(dwarf::DW_AT_high_pc))

768 Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust);

769 return Flags | TF_Keep;

770 }

771

772 Flags |= TF_Keep;

773

774 std::optional<uint64_t> HighPc = DIE.getHighPC(*LowPc);

775 if (!HighPc) {

776 reportWarning("Function without high_pc. Range will be discarded.\n", File,

777 &DIE);

779 }

780 if (*LowPc > *HighPc) {

781 reportWarning("low_pc greater than high_pc. Range will be discarded.\n",

782 File, &DIE);

784 }

785

786

787 Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust);

789}

790

791

792

793unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr, const DWARFDie &DIE,

794 const DWARFFile &File, CompileUnit &Unit,

795 CompileUnit::DIEInfo &MyInfo,

796 unsigned Flags) {

797 switch (DIE.getTag()) {

798 case dwarf::DW_TAG_constant:

799 case dwarf::DW_TAG_variable:

800 return shouldKeepVariableDIE(RelocMgr, DIE, MyInfo, Flags);

801 case dwarf::DW_TAG_subprogram:

802 case dwarf::DW_TAG_label:

803 return shouldKeepSubprogramDIE(RelocMgr, DIE, File, Unit, MyInfo, Flags);

804 case dwarf::DW_TAG_base_type:

805

806

807 case dwarf::DW_TAG_imported_module:

808 case dwarf::DW_TAG_imported_declaration:

809 case dwarf::DW_TAG_imported_unit:

810

811 return Flags | TF_Keep;

812 default:

813 break;

814 }

815

817}

818

819

820

821

824 switch (Die.getTag()) {

825 case dwarf::DW_TAG_structure_type:

826 case dwarf::DW_TAG_class_type:

827 case dwarf::DW_TAG_union_type:

828 break;

829 default:

830 return;

831 }

832

834

837}

838

839

840

841

844 switch (Die.getTag()) {

845 case dwarf::DW_TAG_typedef:

846 case dwarf::DW_TAG_member:

847 case dwarf::DW_TAG_reference_type:

848 case dwarf::DW_TAG_ptr_to_member_type:

849 case dwarf::DW_TAG_pointer_type:

850 break;

851 default:

852 return;

853 }

854

856

858 return;

859

862}

863

864

865

866void DWARFLinker::lookForChildDIEsToKeep(

867 const DWARFDie &Die, CompileUnit &CU, unsigned Flags,

868 SmallVectorImpl &Worklist) {

869

870

871

872

873

875 Flags &= ~DWARFLinker::TF_ParentWalk;

876

877

878

879 if (!Die.hasChildren() || (Flags & DWARFLinker::TF_ParentWalk))

880 return;

881

882

883

884 for (auto Child : reverse(Die.children())) {

885

886

887 CompileUnit::DIEInfo &ChildInfo = CU.getInfo(Child);

888 Worklist.emplace_back(Die, CU, WorklistItemType::UpdateChildIncompleteness,

889 &ChildInfo);

890 Worklist.emplace_back(Child, CU, Flags);

891 }

892}

893

896

897 if (Info.Ctxt || (Die.getTag() == dwarf::DW_TAG_namespace))

898 return false;

899

900 if (CU.hasODR() && Info.InModuleScope)

901 return false;

902

903 return Info.Incomplete && Info.Ctxt != CU.getInfo(Info.ParentIdx).Ctxt;

904}

905

906void DWARFLinker::markODRCanonicalDie(const DWARFDie &Die, CompileUnit &CU) {

907 CompileUnit::DIEInfo &Info = CU.getInfo(Die);

908

909 Info.ODRMarkingDone = true;

911 Info.Ctxt->hasCanonicalDIE())

912 Info.Ctxt->setHasCanonicalDIE();

913}

914

915

916

917void DWARFLinker::lookForRefDIEsToKeep(

918 const DWARFDie &Die, CompileUnit &CU, unsigned Flags,

919 const UnitListTy &Units, const DWARFFile &File,

920 SmallVectorImpl &Worklist) {

921 bool UseOdr = (Flags & DWARFLinker::TF_DependencyWalk)

922 ? (Flags & DWARFLinker::TF_ODR)

923 : CU.hasODR();

924 DWARFUnit &Unit = CU.getOrigUnit();

925 DWARFDataExtractor Data = Unit.getDebugInfoExtractor();

926 const auto *Abbrev = Die.getAbbreviationDeclarationPtr();

928

930 for (const auto &AttrSpec : Abbrev->attributes()) {

931 DWARFFormValue Val(AttrSpec.Form);

933 AttrSpec.Attr == dwarf::DW_AT_sibling) {

935 Unit.getFormParams());

936 continue;

937 }

938

939 Val.extractValue(Data, &Offset, Unit.getFormParams(), &Unit);

940 CompileUnit *ReferencedCU;

941 if (auto RefDie =

942 resolveDIEReference(File, Units, Val, Die, ReferencedCU)) {

943 CompileUnit::DIEInfo &Info = ReferencedCU->getInfo(RefDie);

944

945

946

947

948

949

950

951

952

953

954 if (AttrSpec.Form != dwarf::DW_FORM_ref_addr &&

956 Info.Ctxt->hasCanonicalDIE())

957 continue;

958

959

961 Info.Ctxt->hasCanonicalDIE()))

962 Info.Prune = false;

963 ReferencedDIEs.emplace_back(RefDie, *ReferencedCU);

964 }

965 }

966

967 unsigned ODRFlag = UseOdr ? DWARFLinker::TF_ODR : 0;

968

969

970

971 for (auto &P : reverse(ReferencedDIEs)) {

972

973

974 CompileUnit::DIEInfo &Info = P.second.getInfo(P.first);

975 Worklist.emplace_back(Die, CU, WorklistItemType::UpdateRefIncompleteness,

977 Worklist.emplace_back(P.first, P.second,

978 DWARFLinker::TF_Keep |

979 DWARFLinker::TF_DependencyWalk | ODRFlag);

980 }

981}

982

983

984void DWARFLinker::lookForParentDIEsToKeep(

985 unsigned AncestorIdx, CompileUnit &CU, unsigned Flags,

986 SmallVectorImpl &Worklist) {

987

988 if (CU.getInfo(AncestorIdx).Keep)

989 return;

990

991 DWARFUnit &Unit = CU.getOrigUnit();

992 DWARFDie ParentDIE = Unit.getDIEAtIndex(AncestorIdx);

993 Worklist.emplace_back(CU.getInfo(AncestorIdx).ParentIdx, CU, Flags);

994 Worklist.emplace_back(ParentDIE, CU, Flags);

995}

996

997

998

999

1000

1001

1002

1003

1004

1005

1006

1007

1008

1009

1010

1011

1012

1013

1014

1015

1016

1017

1018

1019

1020

1021

1022void DWARFLinker::lookForDIEsToKeep(AddressesMap &AddressesMap,

1024 const DWARFDie &Die, const DWARFFile &File,

1025 CompileUnit &Cu, unsigned Flags) {

1026

1028 Worklist.emplace_back(Die, Cu, Flags);

1029

1030 while (!Worklist.empty()) {

1031 WorklistItem Current = Worklist.pop_back_val();

1032

1033

1034 switch (Current.Type) {

1035 case WorklistItemType::UpdateChildIncompleteness:

1037 continue;

1038 case WorklistItemType::UpdateRefIncompleteness:

1040 continue;

1041 case WorklistItemType::LookForChildDIEsToKeep:

1042 lookForChildDIEsToKeep(Current.Die, Current.CU, Current.Flags, Worklist);

1043 continue;

1044 case WorklistItemType::LookForRefDIEsToKeep:

1045 lookForRefDIEsToKeep(Current.Die, Current.CU, Current.Flags, Units, File,

1046 Worklist);

1047 continue;

1048 case WorklistItemType::LookForParentDIEsToKeep:

1049 lookForParentDIEsToKeep(Current.AncestorIdx, Current.CU, Current.Flags,

1050 Worklist);

1051 continue;

1052 case WorklistItemType::MarkODRCanonicalDie:

1053 markODRCanonicalDie(Current.Die, Current.CU);

1054 continue;

1055 case WorklistItemType::LookForDIEsToKeep:

1056 break;

1057 }

1058

1059 unsigned Idx = Current.CU.getOrigUnit().getDIEIndex(Current.Die);

1060 CompileUnit::DIEInfo &MyInfo = Current.CU.getInfo(Idx);

1061

1062 if (MyInfo.Prune) {

1063

1064

1065 if (Current.Flags & TF_DependencyWalk)

1066 MyInfo.Prune = false;

1067 else

1068 continue;

1069 }

1070

1071

1072

1073 bool AlreadyKept = MyInfo.Keep;

1074 if ((Current.Flags & TF_DependencyWalk) && AlreadyKept)

1075 continue;

1076

1077 if (!(Current.Flags & TF_DependencyWalk))

1078 Current.Flags = shouldKeepDIE(AddressesMap, Current.Die, File, Current.CU,

1079 MyInfo, Current.Flags);

1080

1081

1082

1083

1084 if (!(Current.Flags & TF_DependencyWalk) ||

1085 (MyInfo.ODRMarkingDone && !MyInfo.Keep)) {

1086 if (Current.CU.hasODR() || MyInfo.InModuleScope)

1087 Worklist.emplace_back(Current.Die, Current.CU,

1088 WorklistItemType::MarkODRCanonicalDie);

1089 }

1090

1091

1092

1093

1094 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,

1095 WorklistItemType::LookForChildDIEsToKeep);

1096

1097 if (AlreadyKept || !(Current.Flags & TF_Keep))

1098 continue;

1099

1100

1101

1102 MyInfo.Keep = true;

1103

1104

1105 MyInfo.Incomplete =

1106 Current.Die.getTag() != dwarf::DW_TAG_subprogram &&

1107 Current.Die.getTag() != dwarf::DW_TAG_member &&

1108 dwarf::toUnsigned(Current.Die.find(dwarf::DW_AT_declaration), 0);

1109

1110

1111

1112

1113 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,

1114 WorklistItemType::LookForRefDIEsToKeep);

1115

1116 bool UseOdr = (Current.Flags & TF_DependencyWalk) ? (Current.Flags & TF_ODR)

1117 : Current.CU.hasODR();

1118 unsigned ODRFlag = UseOdr ? TF_ODR : 0;

1119 unsigned ParFlags = TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag;

1120

1121

1122 Worklist.emplace_back(MyInfo.ParentIdx, Current.CU, ParFlags);

1123 }

1124}

1125

1126#ifndef NDEBUG

1127

1128

1134

1135

1136

1138 std::vector Worklist;

1139 Worklist.push_back(CU.getOrigUnit().getUnitDIE());

1140

1141

1142 std::vector BrokenLinks;

1143

1144 while (!Worklist.empty()) {

1145 const DWARFDie Current = Worklist.back();

1146 Worklist.pop_back();

1147

1148 const bool CurrentDieIsKept = CU.getInfo(Current).Keep;

1149

1151 Worklist.push_back(Child);

1152

1153 const bool ChildDieIsKept = CU.getInfo(Child).Keep;

1154 if (!CurrentDieIsKept && ChildDieIsKept)

1155 BrokenLinks.emplace_back(Current, Child);

1156 }

1157 }

1158

1159 if (!BrokenLinks.empty()) {

1160 for (BrokenLink Link : BrokenLinks) {

1162 "Found invalid link in keep chain between {0:x} and {1:x}\n",

1163 Link.Parent.getOffset(), Link.Child.getOffset());

1164

1165 errs() << "Parent:";

1166 Link.Parent.dump(errs(), 0, {});

1167 CU.getInfo(Link.Parent).dump();

1168

1169 errs() << "Child:";

1170 Link.Child.dump(errs(), 2, {});

1171 CU.getInfo(Link.Child).dump();

1172 }

1174 }

1175}

1176#endif

1177

1178

1179

1180

1181

1182

1183

1184void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) {

1185

1186 FoldingSetNodeID ID;

1187 Abbrev.Profile(ID);

1188 void *InsertToken;

1189 DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken);

1190

1191

1192 if (InSet) {

1193

1194 Abbrev.setNumber(InSet->getNumber());

1195 } else {

1196

1197 Abbreviations.push_back(

1198 std::make_unique(Abbrev.getTag(), Abbrev.hasChildren()));

1199 for (const auto &Attr : Abbrev.getData())

1200 Abbreviations.back()->AddAttribute(Attr);

1201 AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);

1202

1203 Abbrev.setNumber(Abbreviations.size());

1204 Abbreviations.back()->setNumber(Abbreviations.size());

1205 }

1206}

1207

1208unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,

1209 AttributeSpec AttrSpec,

1210 const DWARFFormValue &Val,

1211 const DWARFUnit &U,

1212 AttributesInfo &Info) {

1215 return 0;

1217 if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {

1219 } else {

1221

1222 if (AttrSpec.Attr == dwarf::DW_AT_APPLE_origin) {

1223 Info.HasAppleOrigin = true;

1224 if (std::optional FileName =

1225 ObjFile.Addresses->getLibraryInstallName()) {

1226 StringEntry = DebugStrPool.getEntry(*FileName);

1227 }

1228 }

1229

1230

1231 if (AttrSpec.Attr == dwarf::DW_AT_name)

1233 else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||

1234 AttrSpec.Attr == dwarf::DW_AT_linkage_name)

1236 if (U.getVersion() >= 5) {

1237

1238 auto StringOffsetIndex =

1239 StringOffsetPool.getValueIndex(StringEntry.getOffset());

1240 return Die

1242 dwarf::DW_FORM_strx, DIEInteger(StringOffsetIndex))

1243 ->sizeOf(U.getFormParams());

1244 }

1245

1246 AttrSpec.Form = dwarf::DW_FORM_strp;

1247 }

1248 Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), AttrSpec.Form,

1250 return 4;

1251}

1252

1253unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute(

1254 DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec,

1255 unsigned AttrSize, const DWARFFormValue &Val, const DWARFFile &File,

1256 CompileUnit &Unit) {

1257 const DWARFUnit &U = Unit.getOrigUnit();

1258 uint64_t Ref;

1259 if (std::optional<uint64_t> Off = Val.getAsRelativeReference())

1260 Ref = Val.getUnit()->getOffset() + *Off;

1261 else if (Off = Val.getAsDebugInfoReference(); Off)

1263 else

1264 return 0;

1265

1266 DIE *NewRefDie = nullptr;

1267 CompileUnit *RefUnit = nullptr;

1268

1269 DWARFDie RefDie =

1270 Linker.resolveDIEReference(File, CompileUnits, Val, InputDIE, RefUnit);

1271

1272

1273 if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling)

1274 return 0;

1275

1276 CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(RefDie);

1277

1278

1279

1280 if (isODRAttribute(AttrSpec.Attr) && RefInfo.Ctxt &&

1281 RefInfo.Ctxt->getCanonicalDIEOffset()) {

1282 assert(RefInfo.Ctxt->hasCanonicalDIE() &&

1283 "Offset to canonical die is set, but context is not marked");

1284 DIEInteger Attr(RefInfo.Ctxt->getCanonicalDIEOffset());

1286 dwarf::DW_FORM_ref_addr, Attr);

1287 return U.getRefAddrByteSize();

1288 }

1289

1290 if (!RefInfo.Clone) {

1291

1292

1293 RefInfo.UnclonedReference = true;

1295 }

1296 NewRefDie = RefInfo.Clone;

1297

1298 if (AttrSpec.Form == dwarf::DW_FORM_ref_addr ||

1300

1301

1302

1303

1304

1305 uint64_t Attr;

1306 if (Ref < InputDIE.getOffset() && !RefInfo.UnclonedReference) {

1307

1308 uint32_t NewRefOffset =

1309 RefUnit->getStartOffset() + NewRefDie->getOffset();

1310 Attr = NewRefOffset;

1312 dwarf::DW_FORM_ref_addr, DIEInteger(Attr));

1313 } else {

1314

1315 Attr = 0xBADDEF;

1316 Unit.noteForwardReference(

1317 NewRefDie, RefUnit, RefInfo.Ctxt,

1319 dwarf::DW_FORM_ref_addr, DIEInteger(Attr)));

1320 }

1321 return U.getRefAddrByteSize();

1322 }

1323

1325 dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie));

1326

1327 return AttrSize;

1328}

1329

1330void DWARFLinker::DIECloner::cloneExpression(

1331 DataExtractor &Data, DWARFExpression Expression, const DWARFFile &File,

1332 CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer,

1333 int64_t AddrRelocAdjustment, bool IsLittleEndian) {

1335

1336 uint8_t OrigAddressByteSize = Unit.getOrigUnit().getAddressByteSize();

1337

1338 uint64_t OpOffset = 0;

1339 for (auto &Op : Expression) {

1341

1342

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

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

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

1346 Linker.reportWarning("Unsupported DW_OP encoding.", File);

1347

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

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

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

1351

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

1354 assert(ULEBsize <= 16);

1355

1356

1358 OutputBuffer.push_back(Op.getCode());

1359 uint64_t RefOffset;

1362 } else {

1365 }

1366 uint32_t Offset = 0;

1367

1368

1369

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

1371 RefOffset += Unit.getOrigUnit().getOffset();

1372 auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset);

1373 CompileUnit::DIEInfo &Info = Unit.getInfo(RefDie);

1374 if (DIE *Clone = Info.Clone)

1375 Offset = Clone->getOffset();

1376 else

1377 Linker.reportWarning(

1378 "base type ref doesn't point to DW_TAG_base_type.", File);

1379 }

1380 uint8_t ULEB[16];

1382 if (RealSize > ULEBsize) {

1383

1385 Linker.reportWarning("base type ref doesn't fit.", File);

1386 }

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

1388 ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);

1389 OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());

1390 } else if (!Linker.Options.Update && Op.getCode() == dwarf::DW_OP_addrx) {

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

1392 Unit.getOrigUnit().getAddrOffsetSectionItem(

1394

1395

1396

1397

1398 OutputBuffer.push_back(dwarf::DW_OP_addr);

1399 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;

1402 ArrayRef<uint8_t> AddressBytes(

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

1404 OrigAddressByteSize);

1405 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());

1406 } else

1407 Linker.reportWarning("cannot read DW_OP_addrx operand.", File);

1408 } else if (!Linker.Options.Update && Op.getCode() == dwarf::DW_OP_constx) {

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

1410 Unit.getOrigUnit().getAddrOffsetSectionItem(

1412

1413

1414

1415

1416 std::optional<uint8_t> OutOperandKind;

1417 switch (OrigAddressByteSize) {

1418 case 4:

1419 OutOperandKind = dwarf::DW_OP_const4u;

1420 break;

1421 case 8:

1422 OutOperandKind = dwarf::DW_OP_const8u;

1423 break;

1424 default:

1425 Linker.reportWarning(

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

1427 File);

1428 break;

1429 }

1430

1431 if (OutOperandKind) {

1432 OutputBuffer.push_back(*OutOperandKind);

1433 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;

1436 ArrayRef<uint8_t> AddressBytes(

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

1438 OrigAddressByteSize);

1439 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());

1440 }

1441 } else

1442 Linker.reportWarning("cannot read DW_OP_constx operand.", File);

1443 } else {

1444

1445 StringRef Bytes = Data.getData().slice(OpOffset, Op.getEndOffset());

1446 OutputBuffer.append(Bytes.begin(), Bytes.end());

1447 }

1449 }

1450}

1451

1452unsigned DWARFLinker::DIECloner::cloneBlockAttribute(

1453 DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File,

1454 CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val,

1455 bool IsLittleEndian) {

1456 DIEValueList *Attr;

1458 DIELoc *Loc = nullptr;

1459 DIEBlock *Block = nullptr;

1460 if (AttrSpec.Form == dwarf::DW_FORM_exprloc) {

1461 Loc = new (DIEAlloc) DIELoc;

1462 Linker.DIELocs.push_back(Loc);

1463 } else {

1464 Block = new (DIEAlloc) DIEBlock;

1465 Linker.DIEBlocks.push_back(Block);

1466 }

1467 Attr = Loc ? static_cast<DIEValueList *>(Loc)

1468 : static_cast<DIEValueList *>(Block);

1469

1470 DWARFUnit &OrigUnit = Unit.getOrigUnit();

1471

1472

1473 SmallVector<uint8_t, 32> Buffer;

1474 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();

1478 DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()),

1479 IsLittleEndian, OrigUnit.getAddressByteSize());

1480 DWARFExpression Expr(Data, OrigUnit.getAddressByteSize(),

1481 OrigUnit.getFormParams().Format);

1482 cloneExpression(Data, Expr, File, Unit, Buffer,

1483 Unit.getInfo(InputDIE).AddrAdjust, IsLittleEndian);

1484 Bytes = Buffer;

1485 }

1486 for (auto Byte : Bytes)

1488 dwarf::DW_FORM_data1, DIEInteger(Byte));

1489

1490

1491

1492

1493 if (Loc)

1494 Loc->setSize(Bytes.size());

1495 else

1496 Block->setSize(Bytes.size());

1497

1498 if (Loc)

1501 else {

1502

1503

1504 if ((AttrSpec.Form == dwarf::DW_FORM_block1 &&

1505 (Bytes.size() > UINT8_MAX)) ||

1506 (AttrSpec.Form == dwarf::DW_FORM_block2 &&

1507 (Bytes.size() > UINT16_MAX)) ||

1508 (AttrSpec.Form == dwarf::DW_FORM_block4 && (Bytes.size() > UINT32_MAX)))

1509 AttrSpec.Form = dwarf::DW_FORM_block;

1510

1511 Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),

1512 dwarf::Form(AttrSpec.Form), Block);

1513 }

1514

1515 return Die.addValue(DIEAlloc, Value)->sizeOf(OrigUnit.getFormParams());

1516}

1517

1518unsigned DWARFLinker::DIECloner::cloneAddressAttribute(

1519 DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec,

1520 unsigned AttrSize, const DWARFFormValue &Val, const CompileUnit &Unit,

1521 AttributesInfo &Info) {

1522 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)

1523 Info.HasLowPc = true;

1524

1527 dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));

1528 return AttrSize;

1529 }

1530

1531

1532

1533

1534

1535

1536

1537

1538

1539

1540

1541

1542

1543 std::optional AddrAttribute = InputDIE.find(AttrSpec.Attr);

1544 if (!AddrAttribute)

1546

1547 std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();

1548 if (!Addr) {

1549 Linker.reportWarning("Cann't read address attribute value.", ObjFile);

1550 return 0;

1551 }

1552

1553 if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&

1554 AttrSpec.Attr == dwarf::DW_AT_low_pc) {

1555 if (std::optional<uint64_t> LowPC = Unit.getLowPc())

1556 Addr = *LowPC;

1557 else

1558 return 0;

1559 } else if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&

1560 AttrSpec.Attr == dwarf::DW_AT_high_pc) {

1561 if (uint64_t HighPc = Unit.getHighPc())

1562 Addr = HighPc;

1563 else

1564 return 0;

1565 } else {

1566 *Addr += Info.PCOffset;

1567 }

1568

1569 if (AttrSpec.Form == dwarf::DW_FORM_addr) {

1570 Die.addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr),

1571 AttrSpec.Form, DIEInteger(*Addr));

1572 return Unit.getOrigUnit().getAddressByteSize();

1573 }

1574

1575 auto AddrIndex = AddrPool.getValueIndex(*Addr);

1576

1577 return Die

1578 .addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr),

1579 dwarf::Form::DW_FORM_addrx, DIEInteger(AddrIndex))

1580 ->sizeOf(Unit.getOrigUnit().getFormParams());

1581}

1582

1583unsigned DWARFLinker::DIECloner::cloneScalarAttribute(

1584 DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File,

1585 CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val,

1586 unsigned AttrSize, AttributesInfo &Info) {

1588

1589

1590

1591 if (AttrSpec.Attr == dwarf::DW_AT_GNU_dwo_id ||

1592 AttrSpec.Attr == dwarf::DW_AT_dwo_id)

1593 return 0;

1594

1595

1596

1597 if (AttrSpec.Attr == dwarf::DW_AT_macro_info) {

1598 if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {

1599 const llvm::DWARFDebugMacro *Macro = File.Dwarf->getDebugMacinfo();

1601 return 0;

1602 }

1603 }

1604

1605 if (AttrSpec.Attr == dwarf::DW_AT_macros) {

1606 if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {

1607 const llvm::DWARFDebugMacro *Macro = File.Dwarf->getDebugMacro();

1609 return 0;

1610 }

1611 }

1612

1613 if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) {

1614

1615

1616

1617 Info.AttrStrOffsetBaseSeen = true;

1618 return Die

1619 .addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,

1620 dwarf::DW_FORM_sec_offset, DIEInteger(8))

1621 ->sizeOf(Unit.getOrigUnit().getFormParams());

1622 }

1623

1624 if (AttrSpec.Attr == dwarf::DW_AT_LLVM_stmt_sequence) {

1625

1626 auto Patch = Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),

1627 dwarf::DW_FORM_sec_offset,

1628 DIEInteger(*Val.getAsSectionOffset()));

1629

1630

1631 Unit.noteStmtSeqListAttribute(Patch);

1632

1633 return Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();

1634 }

1635

1637 if (auto OptionalValue = Val.getAsUnsignedConstant())

1638 Value = *OptionalValue;

1639 else if (auto OptionalValue = Val.getAsSignedConstant())

1640 Value = *OptionalValue;

1641 else if (auto OptionalValue = Val.getAsSectionOffset())

1642 Value = *OptionalValue;

1643 else {

1644 Linker.reportWarning(

1645 "Unsupported scalar attribute form. Dropping attribute.", File,

1646 &InputDIE);

1647 return 0;

1648 }

1649 if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)

1650 Info.IsDeclaration = true;

1651

1652 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)

1655 else

1658 return AttrSize;

1659 }

1660

1661 [[maybe_unused]] dwarf::Form OriginalForm = AttrSpec.Form;

1662 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {

1663

1664

1665

1666 std::optional<uint64_t> Index = Val.getAsSectionOffset();

1667 if (!Index) {

1668 Linker.reportWarning("Cannot read the attribute. Dropping.", File,

1669 &InputDIE);

1670 return 0;

1671 }

1672 std::optional<uint64_t> Offset =

1673 Unit.getOrigUnit().getRnglistOffset(*Index);

1675 Linker.reportWarning("Cannot read the attribute. Dropping.", File,

1676 &InputDIE);

1677 return 0;

1678 }

1679

1681 AttrSpec.Form = dwarf::DW_FORM_sec_offset;

1682 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();

1683 } else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {

1684

1685

1686

1687 std::optional<uint64_t> Index = Val.getAsSectionOffset();

1688 if (!Index) {

1689 Linker.reportWarning("Cannot read the attribute. Dropping.", File,

1690 &InputDIE);

1691 return 0;

1692 }

1693 std::optional<uint64_t> Offset =

1694 Unit.getOrigUnit().getLoclistOffset(*Index);

1696 Linker.reportWarning("Cannot read the attribute. Dropping.", File,

1697 &InputDIE);

1698 return 0;

1699 }

1700

1702 AttrSpec.Form = dwarf::DW_FORM_sec_offset;

1703 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();

1704 } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&

1705 Die.getTag() == dwarf::DW_TAG_compile_unit) {

1706 std::optional<uint64_t> LowPC = Unit.getLowPc();

1707 if (!LowPC)

1708 return 0;

1709

1710 Value = Unit.getHighPc() - *LowPC;

1711 } else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)

1712 Value = *Val.getAsSectionOffset();

1713 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)

1714 Value = *Val.getAsSignedConstant();

1715 else if (auto OptionalValue = Val.getAsUnsignedConstant())

1716 Value = *OptionalValue;

1717 else {

1718 Linker.reportWarning(

1719 "Unsupported scalar attribute form. Dropping attribute.", File,

1720 &InputDIE);

1721 return 0;

1722 }

1723

1724 DIE::value_iterator Patch =

1727 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||

1728 AttrSpec.Attr == dwarf::DW_AT_start_scope) {

1729 Unit.noteRangeAttribute(Die, Patch);

1730 Info.HasRanges = true;

1734 Unit.getOrigUnit().getVersion())) {

1735

1736 CompileUnit::DIEInfo &LocationDieInfo = Unit.getInfo(InputDIE);

1737 Unit.noteLocationAttribute({Patch, LocationDieInfo.InDebugMap

1738 ? LocationDieInfo.AddrAdjust

1739 : Info.PCOffset});

1740 } else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)

1741 Info.IsDeclaration = true;

1742

1743

1744 assert((Info.HasRanges || (OriginalForm != dwarf::DW_FORM_rnglistx)) &&

1745 "Unhandled DW_FORM_rnglistx attribute");

1746

1747 return AttrSize;

1748}

1749

1750

1751

1752

1753unsigned DWARFLinker::DIECloner::cloneAttribute(

1754 DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File,

1755 CompileUnit &Unit, const DWARFFormValue &Val, const AttributeSpec AttrSpec,

1756 unsigned AttrSize, AttributesInfo &Info, bool IsLittleEndian) {

1757 const DWARFUnit &U = Unit.getOrigUnit();

1758

1759 switch (AttrSpec.Form) {

1760 case dwarf::DW_FORM_strp:

1761 case dwarf::DW_FORM_line_strp:

1762 case dwarf::DW_FORM_string:

1763 case dwarf::DW_FORM_strx:

1764 case dwarf::DW_FORM_strx1:

1765 case dwarf::DW_FORM_strx2:

1766 case dwarf::DW_FORM_strx3:

1767 case dwarf::DW_FORM_strx4:

1768 return cloneStringAttribute(Die, AttrSpec, Val, U, Info);

1769 case dwarf::DW_FORM_ref_addr:

1770 case dwarf::DW_FORM_ref1:

1771 case dwarf::DW_FORM_ref2:

1772 case dwarf::DW_FORM_ref4:

1773 case dwarf::DW_FORM_ref8:

1774 return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,

1775 File, Unit);

1776 case dwarf::DW_FORM_block:

1777 case dwarf::DW_FORM_block1:

1778 case dwarf::DW_FORM_block2:

1779 case dwarf::DW_FORM_block4:

1780 case dwarf::DW_FORM_exprloc:

1781 return cloneBlockAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,

1782 IsLittleEndian);

1783 case dwarf::DW_FORM_addr:

1784 case dwarf::DW_FORM_addrx:

1785 case dwarf::DW_FORM_addrx1:

1786 case dwarf::DW_FORM_addrx2:

1787 case dwarf::DW_FORM_addrx3:

1788 case dwarf::DW_FORM_addrx4:

1789 return cloneAddressAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, Unit,

1791 case dwarf::DW_FORM_data1:

1792 case dwarf::DW_FORM_data2:

1793 case dwarf::DW_FORM_data4:

1794 case dwarf::DW_FORM_data8:

1795 case dwarf::DW_FORM_udata:

1796 case dwarf::DW_FORM_sdata:

1797 case dwarf::DW_FORM_sec_offset:

1798 case dwarf::DW_FORM_flag:

1799 case dwarf::DW_FORM_flag_present:

1800 case dwarf::DW_FORM_rnglistx:

1801 case dwarf::DW_FORM_loclistx:

1802 case dwarf::DW_FORM_implicit_const:

1803 return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,

1804 AttrSize, Info);

1805 default:

1806 Linker.reportWarning("Unsupported attribute form " +

1808 " in cloneAttribute. Dropping.",

1809 File, &InputDIE);

1810 }

1811

1812 return 0;

1813}

1814

1815void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,

1816 const DIE *Die,

1817 DwarfStringPoolEntryRef Name,

1819 bool SkipPubSection) {

1820 std::optional Names =

1822 if (!Names)

1823 return;

1824 Unit.addNameAccelerator(Die, StringPool.getEntry(Names->Selector),

1825 SkipPubSection);

1826 Unit.addObjCAccelerator(Die, StringPool.getEntry(Names->ClassName),

1827 SkipPubSection);

1828 if (Names->ClassNameNoCategory)

1829 Unit.addObjCAccelerator(

1830 Die, StringPool.getEntry(*Names->ClassNameNoCategory), SkipPubSection);

1831 if (Names->MethodNameNoCategory)

1832 Unit.addNameAccelerator(

1833 Die, StringPool.getEntry(*Names->MethodNameNoCategory), SkipPubSection);

1834}

1835

1836static bool

1839 bool SkipPC) {

1840 switch (AttrSpec.Attr) {

1841 default:

1842 return false;

1843 case dwarf::DW_AT_low_pc:

1844 case dwarf::DW_AT_high_pc:

1845 case dwarf::DW_AT_ranges:

1846 return !Update && SkipPC;

1847 case dwarf::DW_AT_rnglists_base:

1848

1849

1850

1851

1852 return !Update;

1853 case dwarf::DW_AT_loclists_base:

1854

1855

1856

1857

1858 return !Update;

1859 case dwarf::DW_AT_location:

1860 case dwarf::DW_AT_frame_base:

1861 return !Update && SkipPC;

1862 }

1863}

1864

1870

1871DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,

1873 int64_t PCOffset, uint32_t OutOffset,

1874 unsigned Flags, bool IsLittleEndian,

1875 DIE *Die) {

1876 DWARFUnit &U = Unit.getOrigUnit();

1877 unsigned Idx = U.getDIEIndex(InputDIE);

1879

1880

1881 if (!Unit.getInfo(Idx).Keep)

1882 return nullptr;

1883

1885 assert(!(Die && Info.Clone) && "Can't supply a DIE and a cloned DIE");

1886 if (!Die) {

1887

1888

1889 if (Info.Clone)

1891 Die = Info.Clone;

1892 }

1893

1897 (Info.Ctxt->getCanonicalDIEOffset() == 0)) {

1898 if (Info.Ctxt->hasCanonicalDIE())

1899 Info.Ctxt->setHasCanonicalDIE();

1900

1901

1902

1903 Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset());

1904 }

1905

1906

1907 DWARFDataExtractor Data = U.getDebugInfoExtractor();

1908

1909

1910

1911 uint64_t NextOffset = (Idx + 1 < U.getNumDIEs())

1912 ? U.getDIEAtIndex(Idx + 1).getOffset()

1913 : U.getNextUnitOffset();

1914 AttributesInfo AttrInfo;

1915

1916

1917

1918

1919 SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset));

1921 DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize());

1922

1923

1924 ObjFile.Addresses->applyValidRelocs(DIECopy, Offset, Data.isLittleEndian());

1925

1926

1927

1929

1932

1933

1934 if (Die->getTag() == dwarf::DW_TAG_subprogram)

1935 PCOffset = Info.AddrAdjust;

1936 AttrInfo.PCOffset = PCOffset;

1937

1938 if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) {

1939 Flags |= TF_InFunctionScope;

1941 Flags |= TF_SkipPC;

1942 } else if (Abbrev->getTag() == dwarf::DW_TAG_variable) {

1943

1944

1945 if ((Flags & TF_InFunctionScope) && Info.InDebugMap)

1946 Flags &= ~TF_SkipPC;

1947

1948

1949 else if (Info.InDebugMap && Info.HasLocationExpressionAddr &&

1951 Flags |= TF_SkipPC;

1952 }

1953

1954 std::optional LibraryInstallName =

1955 ObjFile.Addresses->getLibraryInstallName();

1957 for (const auto &AttrSpec : Abbrev->attributes()) {

1960 U.getFormParams());

1961 continue;

1962 }

1963

1964 AttributeLinkedOffsetFixup CurAttrFixup;

1965 CurAttrFixup.InputAttrStartOffset = InputDIE.getOffset() + Offset;

1966 CurAttrFixup.LinkedOffsetFixupVal =

1967 Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset;

1968

1969 DWARFFormValue Val = AttrSpec.getFormValue();

1970 uint64_t AttrSize = Offset;

1971 Val.extractValue(Data, &Offset, U.getFormParams(), &U);

1972 CurAttrFixup.InputAttrEndOffset = InputDIE.getOffset() + Offset;

1973 AttrSize = Offset - AttrSize;

1974

1975 uint64_t FinalAttrSize =

1976 cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, AttrSize,

1977 AttrInfo, IsLittleEndian);

1978 if (FinalAttrSize != 0 && ObjFile.Addresses->needToSaveValidRelocs())

1979 AttributesFixups.push_back(CurAttrFixup);

1980

1981 OutOffset += FinalAttrSize;

1982 }

1983

1984 uint16_t Tag = InputDIE.getTag();

1985

1986

1987 const bool NeedsAppleOrigin = (Tag == dwarf::DW_TAG_compile_unit) &&

1988 LibraryInstallName.has_value() &&

1989 !AttrInfo.HasAppleOrigin;

1990 if (NeedsAppleOrigin) {

1991 auto StringEntry = DebugStrPool.getEntry(LibraryInstallName.value());

1993 dwarf::DW_FORM_strp, DIEInteger(StringEntry.getOffset()));

1995 OutOffset += 4;

1996 }

1997

1998

1999

2000

2001

2002 if ((Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) &&

2003 Tag != dwarf::DW_TAG_compile_unit &&

2004 getDIENames(InputDIE, AttrInfo, DebugStrPool, File, Unit,

2005 Tag != dwarf::DW_TAG_inlined_subroutine)) {

2006 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)

2007 Unit.addNameAccelerator(Die, AttrInfo.MangledName,

2008 Tag == dwarf::DW_TAG_inlined_subroutine);

2009 if (AttrInfo.Name) {

2010 if (AttrInfo.NameWithoutTemplate)

2011 Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate,

2012 true);

2013 Unit.addNameAccelerator(Die, AttrInfo.Name,

2014 Tag == dwarf::DW_TAG_inlined_subroutine);

2015 }

2016 if (AttrInfo.Name)

2017 addObjCAccelerator(Unit, Die, AttrInfo.Name, DebugStrPool,

2018 true);

2019

2020 } else if (Tag == dwarf::DW_TAG_namespace) {

2021 if (!AttrInfo.Name)

2022 AttrInfo.Name = DebugStrPool.getEntry("(anonymous namespace)");

2023 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);

2024 } else if (Tag == dwarf::DW_TAG_imported_declaration && AttrInfo.Name) {

2025 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);

2026 } else if (isTypeTag(Tag) && !AttrInfo.IsDeclaration) {

2027 bool Success = getDIENames(InputDIE, AttrInfo, DebugStrPool, File, Unit);

2028 uint64_t RuntimeLang =

2030 .value_or(0);

2031 bool ObjCClassIsImplementation =

2032 (RuntimeLang == dwarf::DW_LANG_ObjC ||

2033 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&

2035 .value_or(0);

2036 if (Success && AttrInfo.Name && !AttrInfo.Name.getString().empty()) {

2038 Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation,

2039 Hash);

2040 }

2041

2042

2043 if (Success && AttrInfo.MangledName &&

2044 RuntimeLang == dwarf::DW_LANG_Swift &&

2045 !AttrInfo.MangledName.getString().empty() &&

2046 AttrInfo.MangledName != AttrInfo.Name) {

2047 auto Hash = djbHash(AttrInfo.MangledName.getString().data());

2048 Unit.addTypeAccelerator(Die, AttrInfo.MangledName,

2049 ObjCClassIsImplementation, Hash);

2050 }

2051 }

2052

2053

2054 bool HasChildren = false;

2055 for (auto Child : InputDIE.children()) {

2056 unsigned Idx = U.getDIEIndex(Child);

2057 if (Unit.getInfo(Idx).Keep) {

2058 HasChildren = true;

2059 break;

2060 }

2061 }

2062

2063 if (Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen &&

2064 Die->getTag() == dwarf::DW_TAG_compile_unit) {

2065

2066 Die->addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,

2067 dwarf::DW_FORM_sec_offset, DIEInteger(8));

2068 OutOffset += 4;

2069 }

2070

2072 if (HasChildren)

2074

2075 Linker.assignAbbrev(NewAbbrev);

2077

2079

2080

2081 OutOffset += AbbrevNumberSize;

2082

2083

2084 for (AttributeLinkedOffsetFixup &F : AttributesFixups)

2085 F.LinkedOffsetFixupVal += AbbrevNumberSize;

2086

2087 for (AttributeLinkedOffsetFixup &F : AttributesFixups)

2088 ObjFile.Addresses->updateAndSaveValidRelocs(

2089 Unit.getOrigUnit().getVersion() >= 5, Unit.getOrigUnit().getOffset(),

2090 F.LinkedOffsetFixupVal, F.InputAttrStartOffset, F.InputAttrEndOffset);

2091

2092 if (!HasChildren) {

2093

2095 return Die;

2096 }

2097

2098

2099 for (auto Child : InputDIE.children()) {

2100 if (DIE *Clone = cloneDIE(Child, File, Unit, PCOffset, OutOffset, Flags,

2101 IsLittleEndian)) {

2103 OutOffset = Clone->getOffset() + Clone->getSize();

2104 }

2105 }

2106

2107

2108 OutOffset += sizeof(int8_t);

2109

2111 return Die;

2112}

2113

2114

2115

2116

2117void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,

2120 return;

2121

2122 const auto &FunctionRanges = Unit.getFunctionRanges();

2123

2124

2125 AddressRanges LinkedFunctionRanges;

2126 for (const AddressRangeValuePair &Range : FunctionRanges)

2127 LinkedFunctionRanges.insert(

2129

2130

2131 if (!LinkedFunctionRanges.empty())

2132 TheDwarfEmitter->emitDwarfDebugArangesTable(Unit, LinkedFunctionRanges);

2133

2135 std::optional UnitRngListAttribute =

2136 Unit.getUnitRangesAttribute();

2137

2138 if (!AllRngListAttributes.empty() || UnitRngListAttribute) {

2139 std::optional CachedRange;

2140 MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugRangeListHeader(Unit);

2141

2142

2143

2144 for (PatchLocation &AttributePatch : AllRngListAttributes) {

2145

2146

2147 AddressRanges LinkedRanges;

2148 if (Expected OriginalRanges =

2149 Unit.getOrigUnit().findRnglistFromOffset(AttributePatch.get())) {

2150

2151 for (const auto &Range : *OriginalRanges) {

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

2153 CachedRange = FunctionRanges.getRangeThatContains(Range.LowPC);

2154

2155

2156 if (!CachedRange) {

2157 reportWarning("inconsistent range data.", File);

2158 continue;

2159 }

2160

2161

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

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

2164 }

2165 } else {

2167 reportWarning("invalid range list ignored.", File);

2168 }

2169

2170

2171 TheDwarfEmitter->emitDwarfDebugRangeListFragment(

2172 Unit, LinkedRanges, AttributePatch, AddrPool);

2173 }

2174

2175

2176 if (UnitRngListAttribute.has_value())

2177 TheDwarfEmitter->emitDwarfDebugRangeListFragment(

2178 Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool);

2179

2180

2181 TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel);

2182 }

2183}

2184

2185void DWARFLinker::DIECloner::generateUnitLocations(

2186 CompileUnit &Unit, const DWARFFile &File,

2187 ExpressionHandlerRef ExprHandler) {

2189 return;

2190

2192 Unit.getLocationAttributes();

2193

2194 if (AllLocListAttributes.empty())

2195 return;

2196

2197

2198 MCSymbol *EndLabel = Emitter->emitDwarfDebugLocListHeader(Unit);

2199

2200 for (auto &CurLocAttr : AllLocListAttributes) {

2201

2202

2203 Expected OriginalLocations =

2204 Unit.getOrigUnit().findLoclistFromOffset(CurLocAttr.get());

2205

2206 if (!OriginalLocations) {

2208 Linker.reportWarning("Invalid location attribute ignored.", File);

2209 continue;

2210 }

2211

2213 for (DWARFLocationExpression &CurExpression : *OriginalLocations) {

2214 DWARFLocationExpression LinkedExpression;

2215

2216 if (CurExpression.Range) {

2217

2218 LinkedExpression.Range = {

2219 CurExpression.Range->LowPC + CurLocAttr.RelocAdjustment,

2220 CurExpression.Range->HighPC + CurLocAttr.RelocAdjustment};

2221 }

2222

2223

2224 LinkedExpression.Expr.reserve(CurExpression.Expr.size());

2225 ExprHandler(CurExpression.Expr, LinkedExpression.Expr,

2226 CurLocAttr.RelocAdjustment);

2227

2228 LinkedLocationExpressions.push_back(LinkedExpression);

2229 }

2230

2231

2232 Emitter->emitDwarfDebugLocListFragment(Unit, LinkedLocationExpressions,

2233 CurLocAttr, AddrPool);

2234 }

2235

2236

2237 Emitter->emitDwarfDebugLocListFooter(Unit, EndLabel);

2238}

2239

2241 for (auto &V : Die.values())

2242 if (V.getAttribute() == dwarf::DW_AT_addr_base) {

2243 V = DIEValue(V.getAttribute(), V.getForm(), Offset);

2244 return;

2245 }

2246

2247 llvm_unreachable("Didn't find a DW_AT_addr_base in cloned DIE!");

2248}

2249

2250void DWARFLinker::DIECloner::emitDebugAddrSection(

2251 CompileUnit &Unit, const uint16_t DwarfVersion) const {

2252

2254 return;

2255

2256 if (DwarfVersion < 5)

2257 return;

2258

2259 if (AddrPool.getValues().empty())

2260 return;

2261

2262 MCSymbol *EndLabel = Emitter->emitDwarfDebugAddrsHeader(Unit);

2264 DIEInteger(Emitter->getDebugAddrSectionSize()));

2265 Emitter->emitDwarfDebugAddrs(AddrPool.getValues(),

2266 Unit.getOrigUnit().getAddressByteSize());

2267 Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel);

2268}

2269

2270

2271

2272

2273

2279

2280

2281

2283 std::vector &Rows) {

2284 if (Seq.empty())

2285 return;

2286

2287

2288

2289 Seq.front().isStartSeqInOutput = true;

2290

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

2293 Seq.clear();

2294 return;

2295 }

2296

2299 Rows, [=](const TrackedRow &O) { return O.Row.Address < Front; });

2300

2301

2302

2303

2304

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

2306 InsertPoint->Row.EndSequence) {

2307 *InsertPoint = Seq.front();

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

2309 } else {

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

2311 }

2312

2313 Seq.clear();

2314}

2315

2317 for (auto &V : Die.values())

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

2319 V = DIEValue(V.getAttribute(), V.getForm(), Offset);

2320 return;

2321 }

2322

2323 llvm_unreachable("Didn't find DW_AT_stmt_list in cloned DIE!");

2324}

2325

2326void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) {

2327 DWARFUnit &OrigUnit = Unit.getOrigUnit();

2328 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();

2329

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

2332 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));

2333 return;

2334 }

2335

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

2338 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));

2339 return;

2340 }

2341}

2342

2343void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {

2345 return;

2346

2347

2348 DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE();

2350 if (!StmtList)

2351 return;

2352

2353

2354 if (auto *OutputDIE = Unit.getOutputUnitDIE())

2356

2357 if (const DWARFDebugLine::LineTable *LT =

2358 ObjFile.Dwarf->getLineTableForUnit(&Unit.getOrigUnit())) {

2359

2360 DWARFDebugLine::LineTable LineTable;

2361

2362

2363 LineTable.Prologue = LT->Prologue;

2364

2365

2366 if (Linker.Options.Update) {

2367 LineTable.Rows = LT->Rows;

2368

2369

2370 if (LineTable.Rows.size() == 1 && LineTable.Rows[0].EndSequence)

2371 LineTable.Rows.clear();

2372

2373 LineTable.Sequences = LT->Sequences;

2374

2375 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,

2376 DebugLineStrPool);

2377 } else {

2378

2379 std::vector InputRows;

2380 InputRows.reserve(LT->Rows.size());

2381 for (size_t i = 0; i < LT->Rows.size(); i++)

2382 InputRows.emplace_back(TrackedRow{LT->Rows[i], i, false});

2383

2384

2385 std::vector OutputRows;

2386 OutputRows.reserve(InputRows.size());

2387

2388

2389

2390 std::vector Seq;

2391 Seq.reserve(InputRows.size());

2392

2393 const auto &FunctionRanges = Unit.getFunctionRanges();

2394 std::optional CurrRange;

2395

2396

2397

2398

2399

2400

2401

2402

2403

2404

2405

2406

2407 for (size_t i = 0; i < InputRows.size(); i++) {

2408 TrackedRow TR = InputRows[i];

2409

2410

2411

2412

2413

2414

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

2416

2417

2418 uint64_t StopAddress =

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

2420 CurrRange =

2421 FunctionRanges.getRangeThatContains(TR.Row.Address.Address);

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

2423

2424

2425 auto NextLine = Seq.back();

2426 NextLine.Row.Address.Address = StopAddress;

2427 NextLine.Row.EndSequence = 1;

2428 NextLine.Row.PrologueEnd = 0;

2429 NextLine.Row.BasicBlock = 0;

2430 NextLine.Row.EpilogueBegin = 0;

2431 Seq.push_back(NextLine);

2433 }

2434

2435 if (!CurrRange)

2436 continue;

2437 }

2438

2439

2440 if (TR.Row.EndSequence && Seq.empty())

2441 continue;

2442

2443

2444 TR.Row.Address.Address += CurrRange->Value;

2445 Seq.push_back(TR);

2446

2447 if (TR.Row.EndSequence)

2449 }

2450

2451

2452 LineTable.Rows.clear();

2453 LineTable.Rows.reserve(OutputRows.size());

2454 for (auto &TR : OutputRows)

2455 LineTable.Rows.push_back(TR.Row);

2456

2457

2458

2459 std::vector<uint64_t> OutputRowOffsets;

2460

2461

2462

2463 bool hasStmtSeq = Unit.getStmtSeqListAttributes().size() > 0;

2464 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,

2465 DebugLineStrPool,

2466 hasStmtSeq ? &OutputRowOffsets : nullptr);

2467

2468 if (hasStmtSeq) {

2469 assert(OutputRowOffsets.size() == OutputRows.size() &&

2470 "must have an offset for each row");

2471

2472

2473 DenseMap<uint64_t, unsigned> SeqOffToOrigRow;

2474

2475

2476

2477

2478 if (LT->Rows.empty())

2480

2481

2482 DenseMap<size_t, size_t> OrigRowToNewRow;

2483 for (size_t i = 0; i < OutputRows.size(); ++i)

2484 OrigRowToNewRow[OutputRows[i].OriginalRowIndex] = i;

2485

2486

2487

2488 for (const auto &StmtSeq : Unit.getStmtSeqListAttributes()) {

2489 uint64_t OrigStmtSeq = StmtSeq.get();

2490

2491 auto OrigRowIter = SeqOffToOrigRow.find(OrigStmtSeq);

2492 const uint64_t InvalidOffset =

2493 Unit.getOrigUnit().getFormParams().getDwarfMaxOffset();

2494

2495

2496

2497 if (OrigRowIter == SeqOffToOrigRow.end()) {

2498 StmtSeq.set(InvalidOffset);

2499 continue;

2500 }

2501 size_t OrigRowIndex = OrigRowIter->second;

2502

2503

2504 auto NewRowIter = OrigRowToNewRow.find(OrigRowIndex);

2505 if (NewRowIter == OrigRowToNewRow.end()) {

2506

2507

2508 StmtSeq.set(InvalidOffset);

2509 continue;

2510 }

2511

2512

2513 assert(NewRowIter->second < OutputRowOffsets.size() &&

2514 "New row index out of bounds");

2515 uint64_t NewStmtSeqOffset = OutputRowOffsets[NewRowIter->second];

2516

2517

2518 StmtSeq.set(NewStmtSeqOffset);

2519 }

2520 }

2521 }

2522

2523 } else

2524 Linker.reportWarning("Cann't load line table.", ObjFile);

2525}

2526

2527void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {

2531

2532 for (const auto &Namespace : Unit.getNamespaces())

2533 AppleNamespaces.addName(Namespace.Name, Namespace.Die->getOffset() +

2534 Unit.getStartOffset());

2535

2536 for (const auto &Pubname : Unit.getPubnames())

2537 AppleNames.addName(Pubname.Name,

2538 Pubname.Die->getOffset() + Unit.getStartOffset());

2539

2540 for (const auto &Pubtype : Unit.getPubtypes())

2541 AppleTypes.addName(

2542 Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(),

2543 Pubtype.Die->getTag(),

2545 : 0,

2546 Pubtype.QualifiedNameHash);

2547

2548 for (const auto &ObjC : Unit.getObjC())

2549 AppleObjc.addName(ObjC.Name,

2550 ObjC.Die->getOffset() + Unit.getStartOffset());

2551 } break;

2553 TheDwarfEmitter->emitPubNamesForUnit(Unit);

2554 TheDwarfEmitter->emitPubTypesForUnit(Unit);

2555 } break;

2557 for (const auto &Namespace : Unit.getNamespaces())

2558 DebugNames.addName(

2562 Unit.getTag() == dwarf::DW_TAG_type_unit);

2563 for (const auto &Pubname : Unit.getPubnames())

2564 DebugNames.addName(

2565 Pubname.Name, Pubname.Die->getOffset(),

2567 Pubname.Die->getTag(), Unit.getUniqueID(),

2568 Unit.getTag() == dwarf::DW_TAG_type_unit);

2569 for (const auto &Pubtype : Unit.getPubtypes())

2570 DebugNames.addName(

2571 Pubtype.Name, Pubtype.Die->getOffset(),

2573 Pubtype.Die->getTag(), Unit.getUniqueID(),

2574 Unit.getTag() == dwarf::DW_TAG_type_unit);

2575 } break;

2576 }

2577 }

2578}

2579

2580

2581

2582

2583

2584

2585

2586void DWARFLinker::patchFrameInfoForObject(LinkContext &Context) {

2587 DWARFContext &OrigDwarf = *Context.File.Dwarf;

2588 unsigned SrcAddrSize = OrigDwarf.getDWARFObj().getAddressSize();

2589

2590 StringRef FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;

2592 return;

2593

2595 for (std::unique_ptr &Unit : Context.CompileUnits) {

2596 for (auto CurRange : Unit->getFunctionRanges())

2597 AllUnitsRanges.insert(CurRange.Range, CurRange.Value);

2598 }

2599

2600 DataExtractor Data(FrameData, OrigDwarf.isLittleEndian(), 0);

2601 uint64_t InputOffset = 0;

2602

2603

2604

2605 DenseMap<uint64_t, StringRef> LocalCIES;

2606

2607 while (Data.isValidOffset(InputOffset)) {

2608 uint64_t EntryOffset = InputOffset;

2609 uint32_t InitialLength = Data.getU32(&InputOffset);

2610 if (InitialLength == 0xFFFFFFFF)

2611 return reportWarning("Dwarf64 bits no supported", Context.File);

2612

2613 uint32_t CIEId = Data.getU32(&InputOffset);

2614 if (CIEId == 0xFFFFFFFF) {

2615

2616 StringRef CIEData = FrameData.substr(EntryOffset, InitialLength + 4);

2617 LocalCIES[EntryOffset] = CIEData;

2618

2619 InputOffset += InitialLength - 4;

2620 continue;

2621 }

2622

2623 uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize);

2624

2625

2626

2627

2628

2629 std::optional Range =

2630 AllUnitsRanges.getRangeThatContains(Loc);

2632

2633 InputOffset = EntryOffset + InitialLength + 4;

2634 continue;

2635 }

2636

2637

2638

2639 StringRef CIEData = LocalCIES[CIEId];

2640 if (CIEData.empty())

2641 return reportWarning("Inconsistent debug_frame content. Dropping.",

2643

2644

2645

2646 auto IteratorInserted = EmittedCIEs.insert(

2647 std::make_pair(CIEData, TheDwarfEmitter->getFrameSectionSize()));

2648

2649 if (IteratorInserted.second) {

2650 LastCIEOffset = TheDwarfEmitter->getFrameSectionSize();

2651 IteratorInserted.first->getValue() = LastCIEOffset;

2652 TheDwarfEmitter->emitCIE(CIEData);

2653 }

2654

2655

2656

2657

2658 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);

2659 TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), SrcAddrSize,

2660 Loc + Range->Value,

2661 FrameData.substr(InputOffset, FDERemainingBytes));

2662 InputOffset += FDERemainingBytes;

2663 }

2664}

2665

2666uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,

2667 CompileUnit &U,

2668 const DWARFFile &File,

2669 int ChildRecurseDepth) {

2670 const char *Name = nullptr;

2671 DWARFUnit *OrigUnit = &U.getOrigUnit();

2672 CompileUnit *CU = &U;

2673 std::optional Ref;

2674

2675 while (true) {

2677 Name = CurrentName;

2678

2679 if (!(Ref = DIE.find(dwarf::DW_AT_specification)) &&

2680 !(Ref = DIE.find(dwarf::DW_AT_abstract_origin)))

2681 break;

2682

2684 break;

2685

2686 CompileUnit *RefCU;

2687 if (auto RefDIE =

2688 Linker.resolveDIEReference(File, CompileUnits, *Ref, DIE, RefCU)) {

2689 CU = RefCU;

2690 OrigUnit = &RefCU->getOrigUnit();

2691 DIE = RefDIE;

2692 }

2693 }

2694

2695 unsigned Idx = OrigUnit->getDIEIndex(DIE);

2696 if (!Name && DIE.getTag() == dwarf::DW_TAG_namespace)

2697 Name = "(anonymous namespace)";

2698

2699 if (CU->getInfo(Idx).ParentIdx == 0 ||

2700

2701 CU->getOrigUnit().getDIEAtIndex(CU->getInfo(Idx).ParentIdx).getTag() ==

2702 dwarf::DW_TAG_module)

2703 return djbHash(Name ? Name : "", djbHash(ChildRecurseDepth ? "" : "::"));

2704

2705 DWARFDie Die = OrigUnit->getDIEAtIndex(CU->getInfo(Idx).ParentIdx);

2707 (Name ? Name : ""),

2708 djbHash((Name ? "::" : ""),

2710}

2711

2714 CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));

2715 if (DwoId)

2716 return *DwoId;

2717 return 0;

2718}

2719

2720static std::string

2723 if (ObjectPrefixMap.empty())

2724 return Path.str();

2725

2727 for (const auto &Entry : ObjectPrefixMap)

2729 break;

2730 return p.str().str();

2731}

2732

2733static std::string

2737 CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");

2738

2739 if (PCMFile.empty())

2740 return PCMFile;

2741

2742 if (ObjectPrefixMap)

2743 PCMFile = remapPath(PCMFile, *ObjectPrefixMap);

2744

2745 return PCMFile;

2746}

2747

2748std::pair<bool, bool> DWARFLinker::isClangModuleRef(const DWARFDie &CUDie,

2749 std::string &PCMFile,

2750 LinkContext &Context,

2751 unsigned Indent,

2753 if (PCMFile.empty())

2754 return std::make_pair(false, false);

2755

2756

2758

2759 std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");

2760 if (Name.empty()) {

2762 reportWarning("Anonymous module skeleton CU for " + PCMFile,

2763 Context.File);

2764 return std::make_pair(true, true);

2765 }

2766

2767 if (Quiet && Options.Verbose) {

2769 outs() << "Found clang module reference " << PCMFile;

2770 }

2771

2772 auto Cached = ClangModules.find(PCMFile);

2773 if (Cached != ClangModules.end()) {

2774

2775

2776

2777 if (Quiet && Options.Verbose && (Cached->second != DwoId))

2778 reportWarning(Twine("hash mismatch: this object file was built against a "

2779 "different version of the module ") +

2780 PCMFile,

2782 if (Quiet && Options.Verbose)

2783 outs() << " [cached].\n";

2784 return std::make_pair(true, true);

2785 }

2786

2787 return std::make_pair(true, false);

2788}

2789

2790bool DWARFLinker::registerModuleReference(const DWARFDie &CUDie,

2794 unsigned Indent) {

2795 std::string PCMFile = getPCMFile(CUDie, Options.ObjectPrefixMap);

2796 std::pair<bool, bool> IsClangModuleRef =

2797 isClangModuleRef(CUDie, PCMFile, Context, Indent, false);

2798

2799 if (!IsClangModuleRef.first)

2800 return false;

2801

2802 if (IsClangModuleRef.second)

2803 return true;

2804

2805 if (Options.Verbose)

2806 outs() << " ...\n";

2807

2808

2809

2810 ClangModules.insert({PCMFile, getDwoId(CUDie)});

2811

2812 if (Error E = loadClangModule(Loader, CUDie, PCMFile, Context, OnCUDieLoaded,

2813 Indent + 2)) {

2815 return false;

2816 }

2817 return true;

2818}

2819

2820Error DWARFLinker::loadClangModule(

2821 ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile,

2823

2824 uint64_t DwoId = getDwoId(CUDie);

2825 std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");

2826

2827

2828 SmallString<0> Path(Options.PrependPath);

2832

2833

2834

2835 if (Loader == nullptr) {

2836 reportError("Could not load clang module: loader is not specified.\n",

2839 }

2840

2841 auto ErrOrObj = Loader(Context.File.FileName, Path);

2842 if (!ErrOrObj)

2844

2845 std::unique_ptr Unit;

2846 for (const auto &CU : ErrOrObj->Dwarf->compile_units()) {

2847 OnCUDieLoaded(*CU);

2848

2849 auto ChildCUDie = CU->getUnitDIE();

2850 if (!ChildCUDie)

2851 continue;

2852 if (!registerModuleReference(ChildCUDie, Context, Loader, OnCUDieLoaded,

2853 Indent)) {

2854 if (Unit) {

2855 std::string Err =

2856 (PCMFile +

2857 ": Clang modules are expected to have exactly 1 compile unit.\n");

2858 reportError(Err, Context.File);

2860 }

2861

2862

2863

2864 uint64_t PCMDwoId = getDwoId(ChildCUDie);

2865 if (PCMDwoId != DwoId) {

2866 if (Options.Verbose)

2867 reportWarning(

2868 Twine("hash mismatch: this object file was built against a "

2869 "different version of the module ") +

2870 PCMFile,

2872

2873 ClangModules[PCMFile] = PCMDwoId;

2874 }

2875

2876

2877 Unit = std::make_unique(*CU, UniqueUnitID++, !Options.NoODR,

2878 ModuleName);

2879 }

2880 }

2881

2882 if (Unit)

2883 Context.ModuleUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});

2884

2886}

2887

2888uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(

2889 DWARFContext &DwarfContext, const DWARFFile &File, bool IsLittleEndian) {

2890 uint64_t OutputDebugInfoSize =

2891 (Emitter == nullptr) ? 0 : Emitter->getDebugInfoSectionSize();

2892 const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;

2893

2894 for (auto &CurrentUnit : CompileUnits) {

2895 const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();

2896 const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;

2897 auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();

2898 CurrentUnit->setStartOffset(OutputDebugInfoSize);

2899 if (!InputDIE) {

2900 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);

2901 continue;

2902 }

2903 if (CurrentUnit->getInfo(0).Keep) {

2904

2905

2906 CurrentUnit->createOutputDIE();

2907 rememberUnitForMacroOffset(*CurrentUnit);

2908 cloneDIE(InputDIE, File, *CurrentUnit, 0 , UnitHeaderSize,

2909 0, IsLittleEndian, CurrentUnit->getOutputUnitDIE());

2910 }

2911

2912 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);

2913

2914 if (Emitter != nullptr) {

2915

2916 generateLineTableForUnit(*CurrentUnit);

2917

2918 Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);

2919

2921 continue;

2922

2923 Linker.generateUnitRanges(*CurrentUnit, File, AddrPool);

2924

2925 auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,

2926 SmallVectorImpl<uint8_t> &OutBytes,

2927 int64_t RelocAdjustment) {

2928 DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();

2929 DataExtractor Data(SrcBytes, IsLittleEndian,

2930 OrigUnit.getAddressByteSize());

2931 cloneExpression(Data,

2932 DWARFExpression(Data, OrigUnit.getAddressByteSize(),

2933 OrigUnit.getFormParams().Format),

2934 File, *CurrentUnit, OutBytes, RelocAdjustment,

2935 IsLittleEndian);

2936 };

2937 generateUnitLocations(*CurrentUnit, File, ProcessExpr);

2938 emitDebugAddrSection(*CurrentUnit, DwarfVersion);

2939 }

2940 AddrPool.clear();

2941 }

2942

2943 if (Emitter != nullptr) {

2945

2946 Emitter->emitMacroTables(File.Dwarf.get(), UnitMacroMap, DebugStrPool);

2947

2948

2949 for (auto &CurrentUnit : CompileUnits) {

2950 CurrentUnit->fixupForwardReferences();

2951

2952 if (!CurrentUnit->getOutputUnitDIE())

2953 continue;

2954

2955 unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();

2956

2958 CurrentUnit->getStartOffset());

2959 Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);

2960 Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());

2962 CurrentUnit->computeNextUnitOffset(DwarfVersion));

2963 }

2964 }

2965

2966 return OutputDebugInfoSize - StartOutputDebugInfoSize;

2967}

2968

2969void DWARFLinker::copyInvariantDebugSection(DWARFContext &Dwarf) {

2970 TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getLocSection().Data,

2972 TheDwarfEmitter->emitSectionContents(

2973 Dwarf.getDWARFObj().getRangesSection().Data,

2975 TheDwarfEmitter->emitSectionContents(

2977 TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getArangesSection(),

2979 TheDwarfEmitter->emitSectionContents(

2981 TheDwarfEmitter->emitSectionContents(

2982 Dwarf.getDWARFObj().getRnglistsSection().Data,

2984 TheDwarfEmitter->emitSectionContents(

2985 Dwarf.getDWARFObj().getLoclistsSection().Data,

2987}

2988

2991 ObjectContexts.emplace_back(LinkContext(File));

2992

2993 if (ObjectContexts.back().File.Dwarf) {

2994 for (const std::unique_ptr &CU :

2995 ObjectContexts.back().File.Dwarf->compile_units()) {

2997

2998 if (!CUDie)

2999 continue;

3000

3001 OnCUDieLoaded(*CU);

3002

3004 registerModuleReference(CUDie, ObjectContexts.back(), Loader,

3005 OnCUDieLoaded);

3006 }

3007 }

3008}

3009

3011 assert((Options.TargetDWARFVersion != 0) &&

3012 "TargetDWARFVersion should be set");

3013

3014

3015

3016 unsigned NumObjects = ObjectContexts.size();

3017

3018

3019

3020

3024

3025

3027

3028 for (LinkContext &OptContext : ObjectContexts) {

3029 if (Options.Verbose)

3030 outs() << "DEBUG MAP OBJECT: " << OptContext.File.FileName << "\n";

3031

3032 if (!OptContext.File.Dwarf)

3033 continue;

3034

3035 if (Options.VerifyInputDWARF)

3036 verifyInput(OptContext.File);

3037

3038

3039

3040

3041

3043 !OptContext.File.Addresses->hasValidRelocs()) {

3044 if (Options.Verbose)

3045 outs() << "No valid relocations found. Skipping.\n";

3046

3047

3048

3049 OptContext.Skip = true;

3050 continue;

3051 }

3052

3053

3054 if (!OptContext.File.Dwarf)

3055 continue;

3056

3057

3058 if (!OptContext.File.Dwarf->types_section_units().empty()) {

3059 reportWarning("type units are not currently supported: file will "

3060 "be skipped",

3061 OptContext.File);

3062 OptContext.Skip = true;

3063 continue;

3064 }

3065

3066

3067

3068 OptContext.CompileUnits.reserve(

3069 OptContext.File.Dwarf->getNumCompileUnits());

3070 for (const auto &CU : OptContext.File.Dwarf->compile_units()) {

3071 auto CUDie = CU->getUnitDIE(true);

3072 if (Options.Verbose) {

3073 outs() << "Input compilation unit:";

3076 DumpOpts.Verbose = Options.Verbose;

3077 CUDie.dump(outs(), 0, DumpOpts);

3078 }

3079 }

3080

3081 for (auto &CU : OptContext.ModuleUnits) {

3082 if (Error Err = cloneModuleUnit(OptContext, CU, ODRContexts, DebugStrPool,

3083 DebugLineStrPool, StringOffsetPool))

3084 reportWarning(toString(std::move(Err)), CU.File);

3085 }

3086 }

3087

3088

3089

3090

3091

3092

3093 const uint64_t ModulesEndOffset =

3094 (TheDwarfEmitter == nullptr) ? 0

3095 : TheDwarfEmitter->getDebugInfoSectionSize();

3096

3097

3098

3099 std::mutex ProcessedFilesMutex;

3100 std::condition_variable ProcessedFilesConditionVariable;

3101 BitVector ProcessedFiles(NumObjects, false);

3102

3103

3104

3105 auto AnalyzeLambda = [&](size_t I) {

3106 auto &Context = ObjectContexts[I];

3107

3108 if (Context.Skip || !Context.File.Dwarf)

3109 return;

3110

3111 for (const auto &CU : Context.File.Dwarf->compile_units()) {

3112

3113

3114 auto CUDie = CU->getUnitDIE(false);

3115 std::string PCMFile = getPCMFile(CUDie, Options.ObjectPrefixMap);

3116

3118 !isClangModuleRef(CUDie, PCMFile, Context, 0, true).first) {

3119 Context.CompileUnits.push_back(std::make_unique(

3120 *CU, UniqueUnitID++, !Options.NoODR && !Options.Update, ""));

3121 }

3122 }

3123

3124

3125 for (auto &CurrentUnit : Context.CompileUnits) {

3126 auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE();

3127 if (!CUDie)

3128 continue;

3130 *CurrentUnit, &ODRContexts.getRoot(), ODRContexts,

3131 ModulesEndOffset, Options.ParseableSwiftInterfaces,

3133 reportWarning(Warning, Context.File, &DIE);

3134 });

3135 }

3136 };

3137

3138

3140

3141

3142

3143

3144

3145 auto CloneLambda = [&](size_t I) {

3146 auto &OptContext = ObjectContexts[I];

3147 if (OptContext.Skip || !OptContext.File.Dwarf)

3148 return;

3149

3150

3151

3152

3153

3154

3156 for (auto &CurrentUnit : OptContext.CompileUnits)

3157 CurrentUnit->markEverythingAsKept();

3158 copyInvariantDebugSection(*OptContext.File.Dwarf);

3159 } else {

3160 for (auto &CurrentUnit : OptContext.CompileUnits) {

3161 lookForDIEsToKeep(*OptContext.File.Addresses, OptContext.CompileUnits,

3162 CurrentUnit->getOrigUnit().getUnitDIE(),

3163 OptContext.File, *CurrentUnit, 0);

3164#ifndef NDEBUG

3166#endif

3167 }

3168 }

3169

3170

3171

3172

3173 if (OptContext.File.Addresses->hasValidRelocs() ||

3175 SizeByObject[OptContext.File.FileName].Input =

3177 SizeByObject[OptContext.File.FileName].Output =

3178 DIECloner(*this, TheDwarfEmitter, OptContext.File, DIEAlloc,

3179 OptContext.CompileUnits, Options.Update, DebugStrPool,

3180 DebugLineStrPool, StringOffsetPool)

3181 .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,

3182 OptContext.File.Dwarf->isLittleEndian());

3183 }

3184 if ((TheDwarfEmitter != nullptr) && !OptContext.CompileUnits.empty() &&

3186 patchFrameInfoForObject(OptContext);

3187

3188

3189 cleanupAuxiliarryData(OptContext);

3190 };

3191

3192 auto EmitLambda = [&]() {

3193

3194 if (TheDwarfEmitter != nullptr) {

3195 TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);

3196 TheDwarfEmitter->emitStrings(DebugStrPool);

3197 TheDwarfEmitter->emitStringOffsets(StringOffsetPool.getValues(),

3198 Options.TargetDWARFVersion);

3199 TheDwarfEmitter->emitLineStrings(DebugLineStrPool);

3200 for (AccelTableKind TableKind : Options.AccelTables) {

3201 switch (TableKind) {

3203 TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces);

3204 TheDwarfEmitter->emitAppleNames(AppleNames);

3205 TheDwarfEmitter->emitAppleTypes(AppleTypes);

3206 TheDwarfEmitter->emitAppleObjc(AppleObjc);

3207 break;

3209

3210

3211 break;

3213 TheDwarfEmitter->emitDebugNames(DebugNames);

3214 break;

3215 }

3216 }

3217 }

3218 };

3219

3220 auto AnalyzeAll = [&]() {

3221 for (unsigned I = 0, E = NumObjects; I != E; ++I) {

3222 AnalyzeLambda(I);

3223

3224 std::unique_lockstd::mutex LockGuard(ProcessedFilesMutex);

3225 ProcessedFiles.set(I);

3226 ProcessedFilesConditionVariable.notify_one();

3227 }

3228 };

3229

3230 auto CloneAll = [&]() {

3231 for (unsigned I = 0, E = NumObjects; I != E; ++I) {

3232 {

3233 std::unique_lockstd::mutex LockGuard(ProcessedFilesMutex);

3234 if (!ProcessedFiles[I]) {

3235 ProcessedFilesConditionVariable.wait(

3236 LockGuard, [&]() { return ProcessedFiles[I]; });

3237 }

3238 }

3239

3240 CloneLambda(I);

3241 }

3242 EmitLambda();

3243 };

3244

3245

3246

3247

3248 if (Options.Threads == 1) {

3249 for (unsigned I = 0, E = NumObjects; I != E; ++I) {

3250 AnalyzeLambda(I);

3251 CloneLambda(I);

3252 }

3253 EmitLambda();

3254 } else {

3256 Pool.async(AnalyzeAll);

3257 Pool.async(CloneAll);

3258 Pool.wait();

3259 }

3260

3261 if (Options.Statistics) {

3262

3263 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;

3264 for (auto &E : SizeByObject)

3265 Sorted.emplace_back(E.first(), E.second);

3267 return LHS.second.Output > RHS.second.Output;

3268 });

3269

3270 auto ComputePercentange = [](int64_t Input, int64_t Output) -> float {

3271 const float Difference = Output - Input;

3272 const float Sum = Input + Output;

3273 if (Sum == 0)

3274 return 0;

3275 return (Difference / (Sum / 2));

3276 };

3277

3278 int64_t InputTotal = 0;

3279 int64_t OutputTotal = 0;

3280 const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n";

3281

3282

3283 outs() << ".debug_info section size (in bytes)\n";

3284 outs() << "----------------------------------------------------------------"

3285 "---------------\n";

3286 outs() << "Filename Object "

3287 " dSYM Change\n";

3288 outs() << "----------------------------------------------------------------"

3289 "---------------\n";

3290

3291

3292 for (auto &E : Sorted) {

3293 InputTotal += E.second.Input;

3294 OutputTotal += E.second.Output;

3297 E.second.Output, ComputePercentange(E.second.Input, E.second.Output));

3298 }

3299

3300 outs() << "----------------------------------------------------------------"

3301 "---------------\n";

3302 llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal,

3303 ComputePercentange(InputTotal, OutputTotal));

3304 outs() << "----------------------------------------------------------------"

3305 "---------------\n\n";

3306 }

3307

3309}

3310

3311Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,

3316 unsigned Indent) {

3317 assert(Unit.Unit.get() != nullptr);

3318

3319 if (!Unit.Unit->getOrigUnit().getUnitDIE().hasChildren())

3321

3324 outs() << "cloning .debug_info from " << Unit.File.FileName << "\n";

3325 }

3326

3327

3328 analyzeContextInfo(Unit.Unit->getOrigUnit().getUnitDIE(), 0, *(Unit.Unit),

3329 &ODRContexts.getRoot(), ODRContexts, 0,

3330 Options.ParseableSwiftInterfaces,

3332 reportWarning(Warning, Context.File, &DIE);

3333 });

3334

3335 Unit.Unit->markEverythingAsKept();

3336

3337

3339 CompileUnits.emplace_back(std::move(Unit.Unit));

3340 assert(TheDwarfEmitter);

3341 DIECloner(*this, TheDwarfEmitter, Unit.File, DIEAlloc, CompileUnits,

3342 Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool)

3343 .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,

3344 Unit.File.Dwarf->isLittleEndian());

3346}

3347

3348void DWARFLinker::verifyInput(const DWARFFile &File) {

3350

3351 std::string Buffer;

3355 if (Options.InputVerificationHandler)

3356 Options.InputVerificationHandler(File, OS.str());

3357 }

3358}

3359

3360}

for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))

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

static uint32_t hashFullyQualifiedName(CompileUnit &InputCU, DWARFDie &InputDIE, int ChildRecurseDepth=0)

This file implements the BitVector class.

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

Analysis containing CSE Info

#define LLVM_UNLIKELY(EXPR)

#define LLVM_LIKELY(EXPR)

dxil DXContainer Global Emitter

Provides ErrorOr smart pointer.

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

The Input class is used to parse a yaml document into in-memory structs and vectors.

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

ArrayRef< T > drop_while(PredicateT Pred) const

Return a copy of *this with the first N elements satisfying the given predicate removed.

const T & front() const

front - Get the first element.

bool empty() const

empty - Check if the array is empty.

const T & consume_front()

consume_front() - Returns the first element and drops it from ArrayRef.

void setChildrenFlag(bool hasChild)

value_iterator addValue(BumpPtrAllocator &Alloc, const DIEValue &V)

A structured debug information entry.

unsigned getAbbrevNumber() const

DIE & addChild(DIE *Child)

Add a child to the DIE.

LLVM_ABI DIEAbbrev generateAbbrev() const

Generate the abbreviation for this DIE.

static DIE * get(BumpPtrAllocator &Alloc, dwarf::Tag Tag)

void setAbbrevNumber(unsigned I)

Set the abbreviation number for this DIE.

unsigned getOffset() const

Get the compile/type unit relative offset of this DIE.

void setOffset(unsigned O)

dwarf::Tag getTag() const

static LLVM_ABI std::optional< uint64_t > getDefiningParentDieOffset(const DIE &Die)

If Die has a non-null parent and the parent is not a declaration, return its offset.

DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...

Utility class that carries the DWARF compile/type unit and the debug info entry in an object.

uint64_t getOffset() const

Get the absolute offset into the debug info or types section.

iterator_range< iterator > children() const

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

Extract the specified attribute from this DIE.

const DWARFAbbreviationDeclaration * getAbbreviationDeclarationPtr() const

Get the abbreviation declaration for this DIE.

dwarf::Tag getTag() const

LLVM_ABI 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

bool skipValue(DataExtractor DebugInfoData, uint64_t *OffsetPtr, const dwarf::FormParams Params) const

Skip a form's value in DebugInfoData at the offset specified by OffsetPtr.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

void wait() override

Blocking wait for all the tasks to execute first.

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

StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...

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

constexpr bool empty() const

empty - Check if the string is empty.

auto async(Function &&F, Args &&...ArgList)

Asynchronous submission of a task to the pool.

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

static LLVM_ABI raw_ostream & error()

Convenience method for printing "error: " to stderr.

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

std::map< std::string, std::string > ObjectPrefixMapTy

function_ref< void(const DWARFUnit &Unit)> CompileUnitHandlerTy

AccelTableKind

The kind of accelerator tables to be emitted.

@ DebugNames

.debug_names.

@ Apple

.apple_names, .apple_namespaces, .apple_types, .apple_objc.

@ Pub

.debug_pubnames, .debug_pubtypes

std::map< std::string, std::string > SwiftInterfacesMapTy

std::function< ErrorOr< DWARFFile & >( StringRef ContainerName, StringRef Path)> ObjFileLoaderTy

const SmallVector< T > & getValues() const

Stores all information relating to a compile unit, be it in its original instance in the object file ...

void addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader=nullptr, CompileUnitHandlerTy OnCUDieLoaded=[](const DWARFUnit &) {}) override

Add object file to be linked.

Definition DWARFLinker.cpp:2989

Error link() override

Link debug info for added objFiles. Object files are linked all together.

Definition DWARFLinker.cpp:3010

This class gives a tree-like API to the DenseMap that stores the DeclContext objects.

PointerIntPair< DeclContext *, 1 > getChildDeclContext(DeclContext &Context, const DWARFDie &DIE, CompileUnit &Unit, bool InClangModule)

Get the child of Context described by DIE in Unit.

A DeclContext is a named program scope that is used for ODR uniquing of types.

raw_ostream & indent(unsigned NumSpaces)

indent - Insert 'NumSpaces' spaces.

A raw_ostream that writes to an std::string.

LLVM_ABI StringRef FormEncodingString(unsigned Encoding)

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

SmallVector< PatchLocation > RngListAttributesTy

std::vector< std::unique_ptr< CompileUnit > > UnitListTy

IndexedValuesMap< uint64_t > DebugDieValuePool

AddressRangesMap RangesTy

Mapped value in the address map is the offset to apply to the linked address.

SmallVector< PatchLocation > LocListAttributesTy

StringRef guessDeveloperDir(StringRef SysRoot)

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

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.

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.

LLVM_ABI bool doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC, uint16_t DwarfVersion)

Check whether specified Form belongs to the FC class.

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.

@ DW_FLAG_type_implementation

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

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

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 bool replace_path_prefix(SmallVectorImpl< char > &Path, StringRef OldPrefix, StringRef NewPrefix, Style style=Style::native)

Replace matching path prefix with another path.

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

Append to path.

constexpr bool IsLittleEndianHost

void swapByteOrder(T &Value)

This is an optimization pass for GlobalISel generic memory operations.

ThreadPoolStrategy hardware_concurrency(unsigned ThreadCount=0)

Returns a default thread strategy where all available hardware resources are to be used,...

static void verifyKeepChain(CompileUnit &CU)

Verify the keep chain by looking for DIEs that are kept but who's parent isn't.

Definition DWARFLinker.cpp:1137

FunctionAddr VTableAddr Value

static void updateRefIncompleteness(const DWARFDie &Die, CompileUnit &CU, CompileUnit::DIEInfo &RefInfo)

Helper that updates the completeness of the current DIE based on the completeness of the DIEs it refe...

Definition DWARFLinker.cpp:842

static bool isTlsAddressCode(uint8_t DW_OP_Code)

Definition DWARFLinker.cpp:474

auto enumerate(FirstRange &&First, RestRanges &&...Rest)

Given two or more input ranges, returns a new range whose values are tuples (A, B,...

LLVM_ABI std::error_code inconvertibleErrorCode()

The value returned by this function can be returned from convertToErrorCode for Error values where no...

LLVM_ABI raw_fd_ostream & outs()

This returns a reference to a raw_fd_ostream for standard output.

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.

static void patchAddrBase(DIE &Die, DIEInteger Offset)

Definition DWARFLinker.cpp:2240

static std::string remapPath(StringRef Path, const DWARFLinkerBase::ObjectPrefixMapTy &ObjectPrefixMap)

Definition DWARFLinker.cpp:2721

auto upper_bound(R &&Range, T &&Value)

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

static CompileUnit * getUnitForOffset(const UnitListTy &Units, uint64_t Offset)

Similar to DWARFUnitSection::getUnitForOffset(), but returning our CompileUnit object instead.

Definition DWARFLinker.cpp:63

static void insertLineSequence(std::vector< TrackedRow > &Seq, std::vector< TrackedRow > &Rows)

Insert the new line info sequence Seq into the current set of already linked line info Rows.

Definition DWARFLinker.cpp:2282

static void resolveRelativeObjectPath(SmallVectorImpl< char > &Buf, DWARFDie CU)

Resolve the relative path to a build artifact referenced by DWARF by applying DW_AT_comp_dir.

Definition DWARFLinker.cpp:248

static std::string getPCMFile(const DWARFDie &CUDie, const DWARFLinkerBase::ObjectPrefixMapTy *ObjectPrefixMap)

Definition DWARFLinker.cpp:2734

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

static bool shouldSkipAttribute(bool Update, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, bool SkipPC)

Definition DWARFLinker.cpp:1837

auto reverse(ContainerTy &&C)

void sort(IteratorTy Start, IteratorTy End)

static uint64_t getDebugInfoSize(DWARFContext &Dwarf)

Compute the total size of the debug info.

Definition DWARFLinker.cpp:53

static bool isTypeTag(uint16_t Tag)

Definition DWARFLinker.cpp:118

@ Dwarf

DWARF v5 .debug_names.

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

LLVM_ABI std::optional< StringRef > StripTemplateParameters(StringRef Name)

If Name is the name of a templated function that includes template parameters, returns a substring of...

static uint64_t getDwoId(const DWARFDie &CUDie)

Definition DWARFLinker.cpp:2712

class LLVM_GSL_OWNER SmallVector

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

static bool updatePruning(const DWARFDie &Die, CompileUnit &CU, uint64_t ModulesEndOffset)

Definition DWARFLinker.cpp:331

@ Success

The lock was released successfully.

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

@ Ref

The access may reference the value stored in memory.

LLVM_ABI unsigned getULEB128Size(uint64_t Value)

Utility function to get the size of the ULEB128-encoded value.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

static void updateChildIncompleteness(const DWARFDie &Die, CompileUnit &CU, CompileUnit::DIEInfo &ChildInfo)

Helper that updates the completeness of the current DIE based on the completeness of one of its child...

Definition DWARFLinker.cpp:822

SingleThreadExecutor DefaultThreadPool

DWARFExpression::Operation Op

static void updateChildPruning(const DWARFDie &Die, CompileUnit &CU, CompileUnit::DIEInfo &ChildInfo)

Definition DWARFLinker.cpp:353

ArrayRef(const T &OneElt) -> ArrayRef< T >

uint32_t djbHash(StringRef Buffer, uint32_t H=5381)

The Bernstein hash function used by the DWARF accelerator tables.

std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)

LLVM_ABI std::optional< ObjCSelectorNames > getObjCNamesIfSelector(StringRef Name)

If Name is the AT_name of a DIE which refers to an Objective-C selector, returns an instance of ObjCS...

static void analyzeContextInfo(const DWARFDie &DIE, unsigned ParentIdx, CompileUnit &CU, DeclContext *CurrentDeclContext, DeclContextTree &Contexts, uint64_t ModulesEndOffset, DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces, std::function< void(const Twine &, const DWARFDie &)> ReportWarning)

Recursive helper to build the global DeclContext information and gather the child->parent relationshi...

Definition DWARFLinker.cpp:367

static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag)

Definition DWARFLinker.cpp:445

StrongType< NonRelocatableStringpool, OffsetsTag > OffsetsStringPool

static bool isODRCanonicalCandidate(const DWARFDie &Die, CompileUnit &CU)

Definition DWARFLinker.cpp:894

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

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

static void analyzeImportedModule(const DWARFDie &DIE, CompileUnit &CU, DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces, std::function< void(const Twine &, const DWARFDie &)> ReportWarning)

Collect references to parseable Swift interfaces in imported DW_TAG_module blocks.

Definition DWARFLinker.cpp:254

ContextWorklistItemType

The distinct types of work performed by the work loop in analyzeContextInfo.

Definition DWARFLinker.cpp:300

@ UpdateChildPruning

Definition DWARFLinker.cpp:302

@ AnalyzeContextInfo

Definition DWARFLinker.cpp:301

@ UpdatePruning

Definition DWARFLinker.cpp:303

void consumeError(Error Err)

Consume a Error without doing anything.

StringRef toStringRef(bool B)

Construct a string ref from a boolean.

static bool isODRAttribute(uint16_t Attr)

Definition DWARFLinker.cpp:103

static void constructSeqOffsettoOrigRowMapping(CompileUnit &Unit, const DWARFDebugLine::LineTable &LT, DenseMap< uint64_t, unsigned > &SeqOffToOrigRow)

Definition DWARFLinker.cpp:479

static void patchStmtList(DIE &Die, DIEInteger Offset)

Definition DWARFLinker.cpp:2316

std::vector< DWARFLocationExpression > DWARFLocationExpressionsVector

Represents a set of absolute location expressions.

Definition DWARFLinker.cpp:1865

int64_t LinkedOffsetFixupVal

Definition DWARFLinker.cpp:1866

uint64_t InputAttrStartOffset

Definition DWARFLinker.cpp:1867

uint64_t InputAttrEndOffset

Definition DWARFLinker.cpp:1868

A broken link in the keep chain.

Definition DWARFLinker.cpp:1129

DWARFDie Parent

Definition DWARFLinker.cpp:1131

BrokenLink(DWARFDie Parent, DWARFDie Child)

Definition DWARFLinker.cpp:1130

DWARFDie Child

Definition DWARFLinker.cpp:1132

This class represents an item in the work list.

Definition DWARFLinker.cpp:309

CompileUnit::DIEInfo * OtherInfo

Definition DWARFLinker.cpp:313

ContextWorklistItem(DWARFDie Die, DeclContext *Context, unsigned ParentIdx, bool InImportedModule)

Definition DWARFLinker.cpp:324

unsigned ParentIdx

Definition DWARFLinker.cpp:311

bool InImportedModule

Definition DWARFLinker.cpp:317

ContextWorklistItemType Type

Definition DWARFLinker.cpp:316

ContextWorklistItem(DWARFDie Die, ContextWorklistItemType T, CompileUnit::DIEInfo *OtherInfo=nullptr)

Definition DWARFLinker.cpp:319

DWARFDie Die

Definition DWARFLinker.cpp:310

DeclContext * Context

Definition DWARFLinker.cpp:314

Container for dump options that control which debug information will be dumped.

DIDumpOptions noImplicitRecursion() const

Return the options with RecurseDepth set to 0 unless explicitly required.

unsigned ChildRecurseDepth

static LLVM_ABI bool mayHaveLocationList(dwarf::Attribute Attr)

Identify DWARF attributes that may contain a pointer to a location list.

static LLVM_ABI bool mayHaveLocationExpr(dwarf::Attribute Attr)

Identifies DWARF attributes that may contain a reference to a DWARF expression.

Standard .debug_line state machine structure.

Represents a series of contiguous machine instructions.

uint64_t StmtSeqOffset

The offset into the line table where this sequence begins.

SmallVector< Encoding > Op

Encoding for Op operands.

Hold the input and output of the debug info size in bytes.

Definition DWARFLinker.cpp:47

uint64_t Input

Definition DWARFLinker.cpp:48

uint64_t Output

Definition DWARFLinker.cpp:49

A helper struct to help keep track of the association between the input and output rows during line t...

Definition DWARFLinker.cpp:2274

DWARFDebugLine::Row Row

Definition DWARFLinker.cpp:2275

size_t OriginalRowIndex

Definition DWARFLinker.cpp:2276

bool isStartSeqInOutput

Definition DWARFLinker.cpp:2277

Information gathered about a DIE in the object file.

bool Prune

Is this a pure forward declaration we can strip?

bool Incomplete

Does DIE transitively refer an incomplete decl?