LLVM: lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

10

20#include

21#include

22#include

23

24using namespace llvm;

25

26namespace {

27struct Atom {

28 unsigned Value;

29};

30

33 if (!Str.empty())

34 return OS << Str;

35 return OS << "DW_ATOM_unknown_" << format("%x", A.Value);

36}

37}

38

39static Atom formatAtom(unsigned Atom) { return {Atom}; }

40

42

45

46

49 "Section too small: cannot read header.");

50

58

59

60

61 if (AccelSection.isValidOffset(getIthBucketBase(Hdr.BucketCount - 1)))

64 "Section too small: cannot read buckets and hashes.");

65

68

69 HashDataEntryLength = 0;

70 auto MakeUnsupportedFormError = [](dwarf::Form Form) {

72 "Unsupported form:" +

74 };

75

76 for (unsigned i = 0; i < NumAtoms; ++i) {

79 HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm));

80

81 std::optional<uint8_t> FormSize =

83 if (!FormSize)

84 return MakeUnsupportedFormError(AtomForm);

85 HashDataEntryLength += *FormSize;

86 }

87

88 IsValid = true;

90}

91

93 return Hdr.BucketCount;

94}

98 return Hdr.HeaderDataLength;

99}

100

101ArrayRef<std::pair<AppleAcceleratorTable::HeaderData::AtomType,

102 AppleAcceleratorTable::HeaderData::Form>>

104 return HdrData.Atoms;

105}

106

110 switch (Atom.first) {

116 FormValue.getForm() == dwarf::DW_FORM_sdata)

117 return false;

118 break;

119 default:

120 break;

121 }

122 }

123 return true;

124}

125

126std::pair<uint64_t, dwarf::Tag>

129 dwarf::Tag DieTag = dwarf::DW_TAG_null;

130

134 switch (Atom.first) {

137 break;

140 break;

141 default:

142 break;

143 }

144 }

145 return {DieOffset, DieTag};

146}

147

148void AppleAcceleratorTable::Header::dump(ScopedPrinter &W) const {

149 DictScope HeaderScope(W, "Header");

150 W.printHex("Magic", Magic);

151 W.printHex("Version", Version);

152 W.printHex("Hash function", HashFunction);

153 W.printNumber("Bucket count", BucketCount);

154 W.printNumber("Hashes count", HashCount);

155 W.printNumber("HeaderData length", HeaderDataLength);

156}

157

158std::optional<uint64_t> AppleAcceleratorTable::HeaderData::extractOffset(

159 std::optional Value) const {

161 return std::nullopt;

162

163 switch (Value->getForm()) {

164 case dwarf::DW_FORM_ref1:

165 case dwarf::DW_FORM_ref2:

166 case dwarf::DW_FORM_ref4:

167 case dwarf::DW_FORM_ref8:

168 case dwarf::DW_FORM_ref_udata:

169 return Value->getRawUValue() + DIEOffsetBase;

170 default:

171 return Value->getAsSectionOffset();

172 }

173}

174

175bool AppleAcceleratorTable::dumpName(ScopedPrinter &W,

176 SmallVectorImpl &AtomForms,

177 uint64_t *DataOffset) const {

178 uint64_t NameOffset = *DataOffset;

179 if (AccelSection.isValidOffsetForDataOfSize(*DataOffset, 4)) {

180 W.printString("Incorrectly terminated list.");

181 return false;

182 }

183 uint64_t StringOffset = AccelSection.getRelocatedValue(4, DataOffset);

184 if (!StringOffset)

185 return false;

186

187 DictScope NameScope(W, ("Name@0x" + Twine::utohexstr(NameOffset)).str());

188 W.startLine() << format("String: 0x%08" PRIx64, StringOffset);

189 W.getOStream() << " \"" << StringSection.getCStr(&StringOffset) << "\"\n";

190

191 unsigned NumData = AccelSection.getU32(DataOffset);

192 for (unsigned Data = 0; Data < NumData; ++Data) {

193 ListScope DataScope(W, ("Data " + Twine(Data)).str());

194 unsigned i = 0;

195 for (auto &Atom : AtomForms) {

196 W.startLine() << format("Atom[%d]: ", i);

197 if (Atom.extractValue(AccelSection, DataOffset, FormParams)) {

198 Atom.dump(W.getOStream());

199 if (std::optional<uint64_t> Val = Atom.getAsUnsignedConstant()) {

201 if (!Str.empty())

202 W.getOStream() << " (" << Str << ")";

203 }

204 } else

205 W.getOStream() << "Error extracting the value";

206 W.getOStream() << "\n";

207 i++;

208 }

209 }

210 return true;

211}

212

214 if (!IsValid)

215 return;

216

218

219 Hdr.dump(W);

220

221 W.printNumber("DIE offset base", HdrData.DIEOffsetBase);

222 W.printNumber("Number of atoms", uint64_t(HdrData.Atoms.size()));

225 {

226 ListScope AtomsScope(W, "Atoms");

227 unsigned i = 0;

228 for (const auto &Atom : HdrData.Atoms) {

229 DictScope AtomScope(W, ("Atom " + Twine(i++)).str());

230 W.startLine() << "Type: " << formatAtom(Atom.first) << '\n';

231 W.startLine() << "Form: " << formatv("{0}", Atom.second) << '\n';

233 }

234 }

235

236

237 uint64_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength;

239 uint64_t OffsetsBase = HashesBase + Hdr.HashCount * 4;

240

241 for (unsigned Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket) {

243

244 ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());

245 if (Index == UINT32_MAX) {

246 W.printString("EMPTY");

247 continue;

248 }

249

250 for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) {

251 uint64_t HashOffset = HashesBase + HashIdx*4;

252 uint64_t OffsetsOffset = OffsetsBase + HashIdx*4;

254

255 if (Hash % Hdr.BucketCount != Bucket)

256 break;

257

260 if (AccelSection.isValidOffset(DataOffset)) {

261 W.printString("Invalid section offset");

262 continue;

263 }

264 while (dumpName(W, AtomForms, &DataOffset))

265 ;

266 }

267 }

268}

269

271 : Table(Table) {

272 Values.reserve(Table.HdrData.Atoms.size());

273 for (const auto &Atom : Table.HdrData.Atoms)

275}

276

277void AppleAcceleratorTable::Entry::extract(uint64_t *Offset) {

278 for (auto &FormValue : Values)

279 FormValue.extractValue(Table.AccelSection, Offset, Table.FormParams);

280}

281

282std::optional

284 for (auto [Atom, FormValue] : zip_equal(Table.HdrData.Atoms, Values))

285 if (Atom.first == AtomToFind)

286 return FormValue;

287 return std::nullopt;

288}

289

290std::optional<uint64_t>

294

298

301 if (Tag)

302 return std::nullopt;

303 if (std::optional<uint64_t> Value = Tag->getAsUnsignedConstant())

305 return std::nullopt;

306}

307

311

312void AppleAcceleratorTable::Iterator::prepareNextEntryOrEnd() {

313 if (NumEntriesToCome == 0)

314 prepareNextStringOrEnd();

315 if (isEnd())

316 return;

318 Current.BaseEntry.extract(&OffsetCopy);

319 NumEntriesToCome--;

320 Offset += getTable().getHashDataEntryLength();

321}

322

323void AppleAcceleratorTable::Iterator::prepareNextStringOrEnd() {

326

327

328 std::optional<uint64_t> OptOffset = Table.readIthOffset(OffsetIdx++);

329 if (!OptOffset)

330 return setToEnd();

332 }

333 std::optional<uint32_t> StrOffset = Table.readStringOffsetAt(Offset);

334 if (!StrOffset)

335 return setToEnd();

336

337

338

339

340 if (*StrOffset == 0) {

342 return prepareNextStringOrEnd();

343 }

344 Current.StrOffset = *StrOffset;

345

346 std::optional<uint32_t> MaybeNumEntries = Table.readU32FromAccel(Offset);

347 if (!MaybeNumEntries || *MaybeNumEntries == 0)

348 return setToEnd();

349 NumEntriesToCome = *MaybeNumEntries;

350}

351

353 bool SetEnd)

354 : Current(Table), Offset(0), NumEntriesToCome(0) {

355 if (SetEnd)

356 setToEnd();

357 else

358 prepareNextEntryOrEnd();

359}

360

363 const auto EmptyRange =

365 if (!IsValid)

366 return EmptyRange;

367

368

370 uint32_t BucketIdx = hashToBucketIdx(SearchHash);

371 std::optional<uint32_t> HashIdx = idxOfHashInBucket(SearchHash, BucketIdx);

372 if (!HashIdx)

373 return EmptyRange;

374

375 std::optional<uint64_t> MaybeDataOffset = readIthOffset(*HashIdx);

376 if (!MaybeDataOffset)

377 return EmptyRange;

378

379 uint64_t DataOffset = *MaybeDataOffset;

381 return EmptyRange;

382

383 std::optional<uint32_t> StrOffset = readStringOffsetAt(DataOffset);

384

385 while (StrOffset && *StrOffset) {

386 std::optional MaybeStr = readStringFromStrSection(*StrOffset);

387 std::optional<uint32_t> NumEntries = this->readU32FromAccel(DataOffset);

388 if (!MaybeStr || !NumEntries)

389 return EmptyRange;

391 if (Key == *MaybeStr)

392 return make_range({*this, DataOffset},

394 DataOffset = EndOffset;

395 StrOffset = readStringOffsetAt(DataOffset);

396 }

397

398 return EmptyRange;

399}

400

401std::optional<uint32_t>

402AppleAcceleratorTable::idxOfHashInBucket(uint32_t HashToFind,

404 std::optional<uint32_t> HashStartIdx = readIthBucket(BucketIdx);

405 if (!HashStartIdx)

406 return std::nullopt;

407

408 for (uint32_t HashIdx = *HashStartIdx; HashIdx < getNumHashes(); HashIdx++) {

409 std::optional<uint32_t> MaybeHash = readIthHash(HashIdx);

410 if (!MaybeHash || !wouldHashBeInBucket(*MaybeHash, BucketIdx))

411 break;

412 if (*MaybeHash == HashToFind)

413 return HashIdx;

414 }

415 return std::nullopt;

416}

417

418std::optional AppleAcceleratorTable::readStringFromStrSection(

419 uint64_t StringSectionOffset) const {

421 StringRef Str = StringSection.getCStrRef(&StringSectionOffset, &E);

422 if (E) {

424 return std::nullopt;

425 }

426 return Str;

427}

428

429std::optional<uint32_t>

430AppleAcceleratorTable::readU32FromAccel(uint64_t &Offset,

431 bool UseRelocation) const {

433 uint32_t Data = UseRelocation

436 if (E) {

438 return std::nullopt;

439 }

441}

442

456

461 "parsing .debug_names header at 0x%" PRIx64 ": %s",

463 };

464

467

469 AS.skip(C, 2);

477

478 if (C)

479 return HeaderError(C.takeError());

480

483 "cannot read header augmentation"));

488 return C.takeError();

489}

490

493 W.startLine() << formatv("Tag: {0}\n", Tag);

494

496 W.startLine() << formatv("{0}: {1}\n", Attr.Index, Attr.Form);

497}

498

502

506

510

512 return Abbr.Code == 0;

513}

514

515DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getEmptyKey() {

517}

518

519DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getTombstoneKey() {

520 return DWARFDebugNames::Abbrev(~0, dwarf::Tag(0), 0, {});

521}

522

523ExpectedDWARFDebugNames::AttributeEncoding

524DWARFDebugNames::NameIndex::extractAttributeEncoding(uint64_t *Offset) {

527 "Incorrectly terminated abbreviation table.");

528 }

529

533}

534

535Expected<std::vectorDWARFDebugNames::AttributeEncoding>

536DWARFDebugNames::NameIndex::extractAttributeEncodings(uint64_t *Offset) {

537 std::vector Result;

538 for (;;) {

539 auto AttrEncOr = extractAttributeEncoding(Offset);

540 if (!AttrEncOr)

541 return AttrEncOr.takeError();

543 return std::move(Result);

544

545 Result.emplace_back(*AttrEncOr);

546 }

547}

548

549ExpectedDWARFDebugNames::Abbrev

550DWARFDebugNames::NameIndex::extractAbbrev(uint64_t *Offset) {

553 "Incorrectly terminated abbreviation table.");

554 }

555 const uint64_t AbbrevOffset = *Offset;

557 if (Code == 0)

559

561 auto AttrEncOr = extractAttributeEncodings(Offset);

562 if (!AttrEncOr)

563 return AttrEncOr.takeError();

564 return Abbrev(Code, dwarf::Tag(Tag), AbbrevOffset, std::move(*AttrEncOr));

565}

566

567DWARFDebugNames::DWARFDebugNamesOffsets

572 Ret.CUsBase = EndOfHeaderOffset;

582 return Ret;

583}

584

587 uint64_t EndOfHeaderOffset = Base;

588 if (Error E = Hdr.extract(AS, &EndOfHeaderOffset))

589 return E;

590

593

595 Offsets.EntryOffsetsBase + (Hdr.NameCount * SectionOffsetSize);

596

599 "Section too small: cannot read abbreviations.");

600

601 Offsets.EntriesBase = Offset + Hdr.AbbrevTableSize;

602

603 for (;;) {

604 auto AbbrevOr = extractAbbrev(&Offset);

605 if (!AbbrevOr)

606 return AbbrevOr.takeError();

609

610 if (!Abbrevs.insert(std::move(*AbbrevOr)).second)

612 "Duplicate abbreviation code.");

613 }

614}

615

617 : NameIdx(&NameIdx), Abbr(&Abbr) {

618

619

620 Values.reserve(Abbr.Attributes.size());

622 Values.emplace_back(Attr.Form);

623}

624

625std::optional

627 assert(Abbr->Attributes.size() == Values.size());

629 if (std::get<0>(Tuple).Index == Index)

630 return std::get<1>(Tuple);

631 }

632 return std::nullopt;

633}

634

636 return lookup(dwarf::DW_IDX_parent).has_value();

637}

638

640 if (std::optional Off = lookup(dwarf::DW_IDX_die_offset))

641 return Off->getAsReferenceUVal();

642 return std::nullopt;

643}

644

646

647 if (std::optional Off = lookup(dwarf::DW_IDX_compile_unit))

648 return Off->getAsUnsignedConstant();

649

650

651 if (NameIdx->getCUCount() == 1)

652 return 0;

653 return std::nullopt;

654}

655

657

658

659

660 if (lookup(dwarf::DW_IDX_type_unit).has_value())

661 return std::nullopt;

663}

664

666 std::optional<uint64_t> Index = getCUIndex();

667 if (!Index || *Index >= NameIdx->getCUCount())

668 return std::nullopt;

669 return NameIdx->getCUOffset(*Index);

670}

671

674 if (!Index || *Index >= NameIdx->getCUCount())

675 return std::nullopt;

676 return NameIdx->getCUOffset(*Index);

677}

678

680 std::optional<uint64_t> Index = getTUIndex();

681 if (!Index || *Index >= NameIdx->getLocalTUCount())

682 return std::nullopt;

683 return NameIdx->getLocalTUOffset(*Index);

684}

685

686std::optional<uint64_t>

688 std::optional<uint64_t> Index = getTUIndex();

689 const uint32_t NumLocalTUs = NameIdx->getLocalTUCount();

690 if (!Index || *Index < NumLocalTUs)

691 return std::nullopt;

692

693 const uint64_t ForeignTUIndex = *Index - NumLocalTUs;

694 if (ForeignTUIndex >= NameIdx->getForeignTUCount())

695 return std::nullopt;

696 return NameIdx->getForeignTUSignature(ForeignTUIndex);

697}

698

700 if (std::optional Off = lookup(dwarf::DW_IDX_type_unit))

701 return Off->getAsUnsignedConstant();

702 return std::nullopt;

703}

704

707

708 std::optional ParentEntryOff = lookup(dwarf::DW_IDX_parent);

709 assert(ParentEntryOff.has_value() && "hasParentInformation() must be called");

710

711 if (ParentEntryOff->getForm() == dwarf::Form::DW_FORM_flag_present)

712 return std::nullopt;

713 return NameIdx->getEntryAtRelativeOffset(ParentEntryOff->getRawUValue());

714}

715

719 if (!ParentEntry) {

720 W.getOStream() << "";

722 return;

723 }

724

725 if (!ParentEntry->has_value()) {

726 W.getOStream() << "";

727 return;

728 }

729

730 auto AbsoluteOffset = NameIdx->Offsets.EntriesBase + FormValue.getRawUValue();

731 W.getOStream() << "Entry @ 0x" + Twine::utohexstr(AbsoluteOffset);

732}

733

735 W.startLine() << formatv("Abbrev: {0:x}\n", Abbr->Code);

736 W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);

737 assert(Abbr->Attributes.size() == Values.size());

739 auto Index = std::get<0>(Tuple).Index;

740 W.startLine() << formatv("{0}: ", Index);

741

742 auto FormValue = std::get<1>(Tuple);

743 if (Index == dwarf::Index::DW_IDX_parent)

745 else

746 FormValue.dump(W.getOStream());

747 W.getOStream() << '\n';

748 }

749}

750

755

757 assert(CU < Hdr.CompUnitCount);

760 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);

761}

762

764 assert(TU < Hdr.LocalTypeUnitCount);

767 Offsets.CUsBase + SectionOffsetSize * (Hdr.CompUnitCount + TU);

768 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);

769}

770

772 assert(TU < Hdr.ForeignTypeUnitCount);

775 Offsets.CUsBase +

776 SectionOffsetSize * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU;

777 return Section.AccelSection.getU64(&Offset);

778}

779

785 "Incorrectly terminated entry list.");

786

788 if (AbbrevCode == 0)

790

791 const auto AbbrevIt = Abbrevs.find_as(AbbrevCode);

792 if (AbbrevIt == Abbrevs.end())

794

795 Entry E(*this, *AbbrevIt);

796

798 for (auto &Value : E.Values) {

799 if (Value.extractValue(AS, Offset, FormParams))

801 "Error extracting index attribute values.");

802 }

803 return std::move(E);

804}

805

808 assert(0 < Index && Index <= Hdr.NameCount);

810 uint64_t StringOffsetOffset =

811 Offsets.StringOffsetsBase + SectionOffsetSize * (Index - 1);

813 Offsets.EntryOffsetsBase + SectionOffsetSize * (Index - 1);

815

817 AS.getRelocatedValue(SectionOffsetSize, &StringOffsetOffset);

818 uint64_t EntryOffset = AS.getUnsigned(&EntryOffsetOffset, SectionOffsetSize);

819 EntryOffset += Offsets.EntriesBase;

820 return {Section.StringSection, Index, StringOffset, EntryOffset};

821}

822

825 assert(Bucket < Hdr.BucketCount);

826 uint64_t BucketOffset = Offsets.BucketsBase + 4 * Bucket;

827 return Section.AccelSection.getU32(&BucketOffset);

828}

829

831 assert(0 < Index && Index <= Hdr.NameCount);

832 uint64_t HashOffset = Offsets.HashesBase + 4 * (Index - 1);

833 return Section.AccelSection.getU32(&HashOffset);

834}

835

836

837

838

839

840bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W,

843 auto EntryOr = getEntry(Offset);

844 if (!EntryOr) {

846 [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });

847 return false;

848 }

849

851 EntryOr->dump(W);

852 return true;

853}

854

855void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W,

856 const NameTableEntry &NTE,

857 std::optional<uint32_t> Hash) const {

858 DictScope NameScope(W, ("Name " + Twine(NTE.getIndex())).str());

859 if (Hash)

860 W.printHex("Hash", *Hash);

861

862 W.startLine() << format("String: 0x%08" PRIx64, NTE.getStringOffset());

863 W.getOStream() << " \"" << NTE.getString() << "\"\n";

864

865 uint64_t EntryOffset = NTE.getEntryOffset();

866 while (dumpEntry(W, &EntryOffset))

867 ;

868}

869

870void DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const {

871 ListScope CUScope(W, "Compilation Unit offsets");

872 for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU)

873 W.startLine() << format("CU[%u]: 0x%08" PRIx64 "\n", CU, getCUOffset(CU));

874}

875

876void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const {

877 if (Hdr.LocalTypeUnitCount == 0)

878 return;

879

880 ListScope TUScope(W, "Local Type Unit offsets");

881 for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU)

882 W.startLine() << format("LocalTU[%u]: 0x%08" PRIx64 "\n", TU,

883 getLocalTUOffset(TU));

884}

885

886void DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const {

887 if (Hdr.ForeignTypeUnitCount == 0)

888 return;

889

890 ListScope TUScope(W, "Foreign Type Unit signatures");

891 for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) {

892 W.startLine() << format("ForeignTU[%u]: 0x%016" PRIx64 "\n", TU,

893 getForeignTUSignature(TU));

894 }

895}

896

897void DWARFDebugNames::NameIndex::dumpAbbreviations(ScopedPrinter &W) const {

898 ListScope AbbrevsScope(W, "Abbreviations");

899 std::vector<const Abbrev *> AbbrevsVect;

900 for (const DWARFDebugNames::Abbrev &Abbr : Abbrevs)

901 AbbrevsVect.push_back(&Abbr);

903 return LHS->AbbrevOffset < RHS->AbbrevOffset;

904 });

905 for (const DWARFDebugNames::Abbrev *Abbr : AbbrevsVect)

906 Abbr->dump(W);

907}

908

909void DWARFDebugNames::NameIndex::dumpBucket(ScopedPrinter &W,

910 uint32_t Bucket) const {

911 ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());

912 uint32_t Index = getBucketArrayEntry(Bucket);

913 if (Index == 0) {

914 W.printString("EMPTY");

915 return;

916 }

917 if (Index > Hdr.NameCount) {

918 W.printString("Name index is invalid");

919 return;

920 }

921

922 for (; Index <= Hdr.NameCount; ++Index) {

923 uint32_t Hash = getHashArrayEntry(Index);

924 if (Hash % Hdr.BucketCount != Bucket)

925 break;

926

927 dumpName(W, getNameTableEntry(Index), Hash);

928 }

929}

930

933 Hdr.dump(W);

934 dumpCUs(W);

935 dumpLocalTUs(W);

936 dumpForeignTUs(W);

937 dumpAbbreviations(W);

938

939 if (Hdr.BucketCount > 0) {

940 for (uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket)

941 dumpBucket(W, Bucket);

942 return;

943 }

944

945 W.startLine() << "Hash table not present\n";

947 dumpName(W, NTE, std::nullopt);

948}

949

955 return E;

957 NameIndices.push_back(std::move(Next));

958 }

960}

961

966

969 for (const NameIndex &NI : NameIndices)

970 NI.dump(W);

971}

972

973std::optional<uint64_t>

974DWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() {

975 const Header &Hdr = CurrentIndex->Hdr;

976 if (Hdr.BucketCount == 0) {

977

978 for (const NameTableEntry &NTE : *CurrentIndex) {

979 if (NTE.sameNameAs(Key))

980 return NTE.getEntryOffset();

981 }

982 return std::nullopt;

983 }

984

985

986

987 if (!Hash)

989 uint32_t Bucket = *Hash % Hdr.BucketCount;

990 uint32_t Index = CurrentIndex->getBucketArrayEntry(Bucket);

991 if (Index == 0)

992 return std::nullopt;

993

994 for (; Index <= Hdr.NameCount; ++Index) {

995 uint32_t HashAtIndex = CurrentIndex->getHashArrayEntry(Index);

996 if (HashAtIndex % Hdr.BucketCount != Bucket)

997 return std::nullopt;

998

999 if (HashAtIndex != Hash)

1000 continue;

1001

1002 NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index);

1003 if (NTE.sameNameAs(Key))

1005 }

1006 return std::nullopt;

1007}

1008

1009bool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() {

1010 auto EntryOr = CurrentIndex->getEntry(&DataOffset);

1011 if (!EntryOr) {

1013 return false;

1014 }

1015 CurrentEntry = std::move(*EntryOr);

1016 return true;

1017}

1018

1019bool DWARFDebugNames::ValueIterator::findInCurrentIndex() {

1020 std::optional<uint64_t> Offset = findEntryOffsetInCurrentIndex();

1022 return false;

1023 DataOffset = *Offset;

1024 return getEntryAtCurrentOffset();

1025}

1026

1027void DWARFDebugNames::ValueIterator::searchFromStartOfCurrentIndex() {

1028 for (const NameIndex *End = CurrentIndex->Section.NameIndices.end();

1029 CurrentIndex != End; ++CurrentIndex) {

1030 if (findInCurrentIndex())

1031 return;

1032 }

1033 setEnd();

1034}

1035

1036void DWARFDebugNames::ValueIterator::next() {

1037 assert(CurrentIndex && "Incrementing an end() iterator?");

1038

1039

1040 if (getEntryAtCurrentOffset())

1041 return;

1042

1043

1044 if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) {

1045 setEnd();

1046 return;

1047 }

1048

1049

1050 ++CurrentIndex;

1051 searchFromStartOfCurrentIndex();

1052}

1053

1057 Key(std::string(Key)) {

1058 searchFromStartOfCurrentIndex();

1059}

1060

1063 : CurrentIndex(&NI), IsLocal(true), Key(std::string(Key)) {

1064 if (!findInCurrentIndex())

1065 setEnd();

1066}

1067

1070 if (NameIndices.empty())

1073}

1074

1077 if (UnitOffsetToNameIndex.size() == 0 && NameIndices.size() > 0) {

1078 for (const auto &NI : *this) {

1080 UnitOffsetToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);

1081 for (uint32_t TU = 0; TU < NI.getLocalTUCount(); ++TU)

1082 UnitOffsetToNameIndex.try_emplace(NI.getLocalTUOffset(TU), &NI);

1083 }

1084 }

1085 return UnitOffsetToNameIndex.lookup(UnitOffset);

1086}

1087

1089 return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') &&

1090 (Name[1] == '[');

1091}

1092

1095 return std::nullopt;

1096

1097 StringRef ClassNameStart(Name.drop_front(2));

1098 size_t FirstSpace = ClassNameStart.find(' ');

1100 return std::nullopt;

1101

1103 if (!SelectorStart.size())

1104 return std::nullopt;

1105

1109

1110

1115

1117

1118

1120 }

1121 }

1122 return Ans;

1123}

1124

1126

1127

1128

1129

1130

1131

1132 if (!Name.ends_with(">") || Name.count("<") == 0 || Name.ends_with("<=>"))

1133 return {};

1134

1135

1136 size_t NumLeftAnglesToSkip = 1;

1137

1138

1139 NumLeftAnglesToSkip += Name.count("<=>");

1140

1141 size_t RightAngleCount = Name.count('>');

1142 size_t LeftAngleCount = Name.count('<');

1143

1144

1145

1146 if (LeftAngleCount > RightAngleCount)

1147 NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;

1148

1149 size_t StartOfTemplate = 0;

1150 while (NumLeftAnglesToSkip--)

1151 StartOfTemplate = Name.find('<', StartOfTemplate) + 1;

1152

1153 return Name.substr(0, StartOfTemplate - 1);

1154}

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

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

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

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

#define LLVM_DUMP_METHOD

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

static constexpr DWARFDebugNames::AttributeEncoding sentinelAttrEnc()

Definition DWARFAcceleratorTable.cpp:499

static bool isSentinel(const DWARFDebugNames::AttributeEncoding &AE)

Definition DWARFAcceleratorTable.cpp:503

static DWARFDebugNames::Abbrev sentinelAbbrev()

Definition DWARFAcceleratorTable.cpp:507

static bool isObjCSelector(StringRef Name)

Definition DWARFAcceleratorTable.cpp:1088

static Atom formatAtom(unsigned Atom)

Definition DWARFAcceleratorTable.cpp:39

This file contains constants used for implementing Dwarf debug support.

static bool lookup(const GsymReader &GR, DataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs, llvm::Error &Err)

A Lookup helper functions.

#define offsetof(TYPE, MEMBER)

This file defines the SmallVector class.

This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...

std::optional< DWARFFormValue > lookup(HeaderData::AtomType Atom) const

Returns the value of the Atom in this Accelerator Entry, if the Entry contains such Atom.

Definition DWARFAcceleratorTable.cpp:283

std::optional< uint64_t > getDIESectionOffset() const

Returns the Section Offset of the Debug Info Entry associated with this Accelerator Entry or std::nul...

Definition DWARFAcceleratorTable.cpp:291

std::optional< dwarf::Tag > getTag() const override

Returns the Tag of the Debug Info Entry associated with this Accelerator Entry or std::nullopt if the...

Definition DWARFAcceleratorTable.cpp:299

std::optional< uint64_t > getCUOffset() const override

Returns the Offset of the Compilation Unit associated with this Accelerator Entry or std::nullopt if ...

Definition DWARFAcceleratorTable.cpp:295

LLVM_ABI Iterator(const AppleAcceleratorTable &Table, bool SetEnd=false)

Definition DWARFAcceleratorTable.cpp:352

An iterator for Entries all having the same string as key.

LLVM_ABI SameNameIterator(const AppleAcceleratorTable &AccelTable, uint64_t DataOffset)

Construct a new iterator for the entries at DataOffset.

Definition DWARFAcceleratorTable.cpp:308

This implements the Apple accelerator table format, a precursor of the DWARF 5 accelerator table form...

Error extract() override

Definition DWARFAcceleratorTable.cpp:43

iterator_range< SameNameIterator > equal_range(StringRef Key) const

Look up all entries in the accelerator table matching Key.

Definition DWARFAcceleratorTable.cpp:362

AppleAcceleratorTable(const DWARFDataExtractor &AccelSection, DataExtractor StringSection)

uint32_t getNumBuckets() const

Definition DWARFAcceleratorTable.cpp:92

bool validateForms()

Definition DWARFAcceleratorTable.cpp:107

uint32_t getSizeHdr() const

Definition DWARFAcceleratorTable.cpp:96

std::pair< uint64_t, dwarf::Tag > readAtoms(uint64_t *HashDataOffset)

Return information related to the DWARF DIE we're looking for when performing a lookup by name.

Definition DWARFAcceleratorTable.cpp:127

uint32_t getNumHashes() const

Definition DWARFAcceleratorTable.cpp:95

uint32_t getHashDataEntryLength() const

Returns the size of one HashData entry.

void dump(raw_ostream &OS) const override

Definition DWARFAcceleratorTable.cpp:213

ArrayRef< std::pair< HeaderData::AtomType, HeaderData::Form > > getAtomsDesc()

Return the Atom description, which can be used to interpret the raw values of the Accelerator Entries...

Definition DWARFAcceleratorTable.cpp:103

uint32_t getHeaderDataLength() const

Definition DWARFAcceleratorTable.cpp:97

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

SmallVector< DWARFFormValue, 3 > Values

DataExtractor StringSection

virtual ~DWARFAcceleratorTable()

DWARFDataExtractor AccelSection

DWARF v5-specific implementation of an Accelerator Entry.

std::optional< uint64_t > getForeignTUTypeSignature() const override

Returns the type signature of the Type Unit associated with this Accelerator Entry or std::nullopt if...

Definition DWARFAcceleratorTable.cpp:687

std::optional< uint64_t > getRelatedCUIndex() const

Similar functionality to getCUIndex() but without the DW_IDX_type_unit restriction.

Definition DWARFAcceleratorTable.cpp:645

std::optional< uint64_t > getCUIndex() const

Returns the Index into the Compilation Unit list of the owning Name Index or std::nullopt if this Acc...

Definition DWARFAcceleratorTable.cpp:656

std::optional< uint64_t > getRelatedCUOffset() const

Definition DWARFAcceleratorTable.cpp:672

std::optional< uint64_t > getCUOffset() const override

Returns the Offset of the Compilation Unit associated with this Accelerator Entry or std::nullopt if ...

Definition DWARFAcceleratorTable.cpp:665

std::optional< uint64_t > getDIEUnitOffset() const

Returns the Offset of the DIE within the containing CU or TU.

Definition DWARFAcceleratorTable.cpp:639

Expected< std::optional< DWARFDebugNames::Entry > > getParentDIEEntry() const

Returns the Entry corresponding to the parent of the DIE represented by this Entry.

Definition DWARFAcceleratorTable.cpp:706

bool hasParentInformation() const

Returns true if this Entry has information about its parent DIE (i.e.

Definition DWARFAcceleratorTable.cpp:635

std::optional< uint64_t > getTUIndex() const

Returns the index of the Type Unit of the owning Name Index or std::nullopt if this Accelerator Entry...

Definition DWARFAcceleratorTable.cpp:699

std::optional< DWARFFormValue > lookup(dwarf::Index Index) const

Returns the value of the Index Attribute in this Accelerator Entry, if the Entry contains such Attrib...

Definition DWARFAcceleratorTable.cpp:626

std::optional< uint64_t > getLocalTUOffset() const override

Returns the Offset of the Type Unit associated with this Accelerator Entry or std::nullopt if the Typ...

Definition DWARFAcceleratorTable.cpp:679

void dumpParentIdx(ScopedPrinter &W, const DWARFFormValue &FormValue) const

Definition DWARFAcceleratorTable.cpp:716

void dump(ScopedPrinter &W) const

Definition DWARFAcceleratorTable.cpp:734

Represents a single accelerator table within the DWARF v5 .debug_names section.

LLVM_ABI uint32_t getHashArrayEntry(uint32_t Index) const

Reads an entry in the Hash Array for the given Index.

Definition DWARFAcceleratorTable.cpp:830

LLVM_ABI uint64_t getLocalTUOffset(uint32_t TU) const

Reads offset of local type unit TU, TU is 0-based.

Definition DWARFAcceleratorTable.cpp:763

LLVM_ABI uint32_t getBucketArrayEntry(uint32_t Bucket) const

Reads an entry in the Bucket Array for the given Bucket.

Definition DWARFAcceleratorTable.cpp:824

LLVM_ABI void dump(ScopedPrinter &W) const

Definition DWARFAcceleratorTable.cpp:931

LLVM_ABI iterator_range< ValueIterator > equal_range(StringRef Key) const

Look up all entries in this Name Index matching Key.

Definition DWARFAcceleratorTable.cpp:963

LLVM_ABI uint64_t getCUOffset(uint32_t CU) const

Reads offset of compilation unit CU. CU is 0-based.

Definition DWARFAcceleratorTable.cpp:756

LLVM_ABI Expected< Entry > getEntry(uint64_t *Offset) const

Definition DWARFAcceleratorTable.cpp:781

LLVM_ABI NameTableEntry getNameTableEntry(uint32_t Index) const

Reads an entry in the Name Table for the given Index.

Definition DWARFAcceleratorTable.cpp:807

LLVM_ABI Error extract()

Definition DWARFAcceleratorTable.cpp:585

LLVM_ABI uint64_t getForeignTUSignature(uint32_t TU) const

Reads signature of foreign type unit TU. TU is 0-based.

Definition DWARFAcceleratorTable.cpp:771

A single entry in the Name Table (DWARF v5 sect.

uint64_t getEntryOffset() const

Returns the offset of the first Entry in the list.

Error returned by NameIndex::getEntry to report it has reached the end of the entry list.

std::error_code convertToErrorCode() const override

Convert this error to a std::error_code.

Definition DWARFAcceleratorTable.cpp:752

ValueIterator()=default

End marker.

const_iterator begin() const

DWARFDebugNames(const DWARFDataExtractor &AccelSection, DataExtractor StringSection)

Error extract() override

Definition DWARFAcceleratorTable.cpp:950

iterator_range< ValueIterator > equal_range(StringRef Key) const

Look up all entries in the accelerator table matching Key.

Definition DWARFAcceleratorTable.cpp:1069

const NameIndex * getCUOrTUNameIndex(uint64_t UnitOffset)

Return the Name Index covering the compile unit or local type unit at UnitOffset, or nullptr if there...

Definition DWARFAcceleratorTable.cpp:1076

void dump(raw_ostream &OS) const override

Definition DWARFAcceleratorTable.cpp:967

LLVM_ABI bool isFormClass(FormClass FC) const

LLVM_ABI bool extractValue(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, dwarf::FormParams FormParams, const DWARFContext *Context=nullptr, const DWARFUnit *Unit=nullptr)

Extracts a value in Data at offset *OffsetPtr.

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

dwarf::Form getForm() const

uint64_t getRawUValue() const

Base class for error info classes.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

void push_back(const T &Elt)

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

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

static constexpr size_t npos

StringRef drop_front(size_t N=1) const

Return a StringRef equal to 'this' but with the first N elements dropped.

char back() const

back - Get the last character in the string.

constexpr size_t size() const

size - Get the string size.

StringRef take_front(size_t N=1) const

Return a StringRef equal to 'this' but with only the first N elements remaining.

size_t find(char C, size_t From=0) const

Search for the first character C in the string.

StringRef drop_back(size_t N=1) const

Return a StringRef equal to 'this' but with the last N elements dropped.

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

static Twine utohexstr(uint64_t Val)

LLVM Value Representation.

A range adaptor for a pair of iterators.

This class implements an extremely fast bulk output stream that can only output to a stream.

LLVM_ABI StringRef FormEncodingString(unsigned Encoding)

LLVM_ABI StringRef AtomTypeString(unsigned Atom)

LLVM_ABI StringRef FormatString(DwarfFormat Format)

@ C

The default llvm calling convention, compatible with C.

Offsets

Offsets in bytes from the start of the input buffer.

LLVM_ABI StringRef AtomValueString(uint16_t Atom, unsigned Val)

Returns the symbolic string representing Val when used as a value for atom Atom.

LLVM_ABI DWARFDebugNames::DWARFDebugNamesOffsets findDebugNamesOffsets(uint64_t EndOfHeaderOffset, const DWARFDebugNames::Header &Hdr)

Definition DWARFAcceleratorTable.cpp:568

const uint32_t DW_INVALID_OFFSET

Identifier of an invalid DIE offset in the .debug_info section.

LLVM_ABI std::optional< uint8_t > getFixedFormByteSize(dwarf::Form Form, FormParams Params)

Get the fixed byte size for a given form.

uint8_t getDwarfOffsetByteSize(DwarfFormat Format)

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

@ DW_ATOM_die_offset

Marker as the end of a list of atoms.

NodeAddr< CodeNode * > Code

This is an optimization pass for GlobalISel generic memory operations.

detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)

zip iterator that assumes that all iteratees have the same length.

void handleAllErrors(Error E, HandlerTs &&... Handlers)

Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...

LLVM_ABI std::error_code inconvertibleErrorCode()

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

SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

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

Wrapper function to append range R to container C.

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

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

FunctionAddr VTableAddr uintptr_t uintptr_t Version

detail::zippy< detail::zip_first, T, U, Args... > zip_first(T &&t, U &&u, Args &&...args)

zip iterator that, for the sake of efficiency, assumes the first iteratee to be the shortest.

void sort(IteratorTy Start, IteratorTy End)

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

Definition DWARFAcceleratorTable.cpp:1125

format_object< Ts... > format(const char *Fmt, const Ts &... Vals)

These are helper functions used to produce formatted output.

LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key

Error make_error(ArgTs &&... Args)

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

FunctionAddr VTableAddr uintptr_t uintptr_t Data

LLVM_ABI uint32_t caseFoldingDjbHash(StringRef Buffer, uint32_t H=5381)

Computes the Bernstein hash after folding the input according to the Dwarf 5 standard case folding ru...

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

FunctionAddr VTableAddr Next

raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)

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

Definition DWARFAcceleratorTable.cpp:1093

void consumeError(Error Err)

Consume a Error without doing anything.

Implement std::hash so that hash_code can be used in STL containers.

Abbreviation describing the encoding of Name Index entries.

LLVM_ABI void dump(ScopedPrinter &W) const

Definition DWARFAcceleratorTable.cpp:491

uint32_t Code

< Abbreviation offset in the .debug_names section

std::vector< AttributeEncoding > Attributes

List of index attributes.

dwarf::Tag Tag

Dwarf Tag of the described entity.

Index attribute and its encoding.

Offsets for the start of various important tables from the start of the section.

uint64_t EntryOffsetsBase

uint64_t StringOffsetsBase

StringRef ClassName

For "-[A(Category) method:]", this would be "A(category)".

std::optional< std::string > MethodNameNoCategory

For "-[A(Category) method:]", this would be "A method:".

StringRef Selector

For "-[A(Category) method:]", this would be "method:".

std::optional< StringRef > ClassNameNoCategory

For "-[A(Category) method:]", this would be "A".

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