Changeset View
Changeset View
Standalone View
Standalone View
lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
Show All 36 Lines | |||||
37 | } | 37 | } | ||
38 | } // namespace | 38 | } // namespace | ||
39 | 39 | | |||
40 | static Atom formatAtom(unsigned Atom) { return {Atom}; } | 40 | static Atom formatAtom(unsigned Atom) { return {Atom}; } | ||
41 | 41 | | |||
42 | DWARFAcceleratorTable::~DWARFAcceleratorTable() = default; | 42 | DWARFAcceleratorTable::~DWARFAcceleratorTable() = default; | ||
43 | 43 | | |||
44 | Error AppleAcceleratorTable::extract() { | 44 | Error AppleAcceleratorTable::extract() { | ||
45 | uint64_t Offset = 0; | 45 | DataExtractor::Cursor C(0); | ||
46 | 46 | | |||
47 | // Check that we can at least read the header. | 47 | Hdr.Magic = AccelSection.getU32(C); | ||
48 | if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength) + 4)) | 48 | Hdr.Version = AccelSection.getU16(C); | ||
49 | return createStringError(errc::illegal_byte_sequence, | 49 | Hdr.HashFunction = AccelSection.getU16(C); | ||
50 | "Section too small: cannot read header."); | 50 | Hdr.BucketCount = AccelSection.getU32(C); | ||
51 | Hdr.HashCount = AccelSection.getU32(C); | ||||
52 | Hdr.HeaderDataLength = AccelSection.getU32(C); | ||||
51 | 53 | | |||
52 | Hdr.Magic = AccelSection.getU32(&Offset); | 54 | HdrData.DIEOffsetBase = AccelSection.getU32(C); | ||
53 | Hdr.Version = AccelSection.getU16(&Offset); | 55 | uint32_t NumAtoms = AccelSection.getU32(C); | ||
54 | Hdr.HashFunction = AccelSection.getU16(&Offset); | 56 | | ||
55 | Hdr.BucketCount = AccelSection.getU32(&Offset); | 57 | for (unsigned i = 0; i < NumAtoms; ++i) { | ||
56 | Hdr.HashCount = AccelSection.getU32(&Offset); | 58 | uint16_t AtomType = AccelSection.getU16(C); | ||
57 | Hdr.HeaderDataLength = AccelSection.getU32(&Offset); | 59 | auto AtomForm = static_cast<dwarf::Form>(AccelSection.getU16(C)); | ||
60 | HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm)); | ||||
61 | } | ||||
62 | | ||||
63 | if (Error E = C.takeError()) | ||||
64 | return E; | ||||
58 | 65 | | |||
59 | // Check that we can read all the hashes and offsets from the | 66 | // Check that we can read all the hashes and offsets from the | ||
60 | // section (see SourceLevelDebugging.rst for the structure of the index). | 67 | // section (see SourceLevelDebugging.rst for the structure of the index). | ||
61 | // We need to substract one because we're checking for an *offset* which is | 68 | // We need to substract one because we're checking for an *offset* which is | ||
62 | // equal to the size for an empty table and hence pointer after the section. | 69 | // equal to the size for an empty table and hence pointer after the section. | ||
63 | if (!AccelSection.isValidOffset(sizeof(Hdr) + Hdr.HeaderDataLength + | 70 | if (!AccelSection.isValidOffset(sizeof(Hdr) + Hdr.HeaderDataLength + | ||
64 | Hdr.BucketCount * 4 + Hdr.HashCount * 8 - 1)) | 71 | Hdr.BucketCount * 4 + Hdr.HashCount * 8 - 1)) | ||
65 | return createStringError( | 72 | return createStringError( | ||
66 | errc::illegal_byte_sequence, | 73 | errc::illegal_byte_sequence, | ||
67 | "Section too small: cannot read buckets and hashes."); | 74 | "Section too small: cannot read buckets and hashes."); | ||
68 | 75 | | |||
69 | HdrData.DIEOffsetBase = AccelSection.getU32(&Offset); | | |||
70 | uint32_t NumAtoms = AccelSection.getU32(&Offset); | | |||
71 | | ||||
72 | for (unsigned i = 0; i < NumAtoms; ++i) { | | |||
73 | uint16_t AtomType = AccelSection.getU16(&Offset); | | |||
74 | auto AtomForm = static_cast<dwarf::Form>(AccelSection.getU16(&Offset)); | | |||
75 | HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm)); | | |||
76 | } | | |||
77 | | ||||
78 | IsValid = true; | 76 | IsValid = true; | ||
79 | return Error::success(); | 77 | return Error::success(); | ||
80 | } | 78 | } | ||
81 | 79 | | |||
82 | uint32_t AppleAcceleratorTable::getNumBuckets() { return Hdr.BucketCount; } | 80 | uint32_t AppleAcceleratorTable::getNumBuckets() { return Hdr.BucketCount; } | ||
83 | uint32_t AppleAcceleratorTable::getNumHashes() { return Hdr.HashCount; } | 81 | uint32_t AppleAcceleratorTable::getNumHashes() { return Hdr.HashCount; } | ||
84 | uint32_t AppleAcceleratorTable::getSizeHdr() { return sizeof(Hdr); } | 82 | uint32_t AppleAcceleratorTable::getSizeHdr() { return sizeof(Hdr); } | ||
85 | uint32_t AppleAcceleratorTable::getHeaderDataLength() { | 83 | uint32_t AppleAcceleratorTable::getHeaderDataLength() { | ||
▲ Show 20 Lines • Show All 285 Lines • ▼ Show 20 Line(s) | 363 | void DWARFDebugNames::Header::dump(ScopedPrinter &W) const { | |||
371 | W.printNumber("Local TU count", LocalTypeUnitCount); | 369 | W.printNumber("Local TU count", LocalTypeUnitCount); | ||
372 | W.printNumber("Foreign TU count", ForeignTypeUnitCount); | 370 | W.printNumber("Foreign TU count", ForeignTypeUnitCount); | ||
373 | W.printNumber("Bucket count", BucketCount); | 371 | W.printNumber("Bucket count", BucketCount); | ||
374 | W.printNumber("Name count", NameCount); | 372 | W.printNumber("Name count", NameCount); | ||
375 | W.printHex("Abbreviations table size", AbbrevTableSize); | 373 | W.printHex("Abbreviations table size", AbbrevTableSize); | ||
376 | W.startLine() << "Augmentation: '" << AugmentationString << "'\n"; | 374 | W.startLine() << "Augmentation: '" << AugmentationString << "'\n"; | ||
377 | } | 375 | } | ||
378 | 376 | | |||
379 | Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS, | 377 | void DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS, | ||
380 | uint64_t *Offset) { | 378 | DataExtractor::Cursor &C) { | ||
381 | // Check that we can read the fixed-size part. | 379 | UnitLength = AS.getU32(C); | ||
382 | if (!AS.isValidOffset(*Offset + sizeof(HeaderPOD) - 1)) | 380 | Version = AS.getU16(C); | ||
383 | return createStringError(errc::illegal_byte_sequence, | 381 | Padding = AS.getU16(C); | ||
384 | "Section too small: cannot read header."); | 382 | CompUnitCount = AS.getU32(C); | ||
385 | 383 | LocalTypeUnitCount = AS.getU32(C); | |||
386 | UnitLength = AS.getU32(Offset); | 384 | ForeignTypeUnitCount = AS.getU32(C); | ||
387 | Version = AS.getU16(Offset); | 385 | BucketCount = AS.getU32(C); | ||
388 | Padding = AS.getU16(Offset); | 386 | NameCount = AS.getU32(C); | ||
389 | CompUnitCount = AS.getU32(Offset); | 387 | AbbrevTableSize = AS.getU32(C); | ||
390 | LocalTypeUnitCount = AS.getU32(Offset); | | |||
391 | ForeignTypeUnitCount = AS.getU32(Offset); | | |||
392 | BucketCount = AS.getU32(Offset); | | |||
393 | NameCount = AS.getU32(Offset); | | |||
394 | AbbrevTableSize = AS.getU32(Offset); | | |||
395 | AugmentationStringSize = alignTo(AS.getU32(Offset), 4); | | |||
396 | 388 | | |||
397 | if (!AS.isValidOffsetForDataOfSize(*Offset, AugmentationStringSize)) | 389 | AugmentationStringSize = alignTo(AS.getU32(C), 4); | ||
398 | return createStringError( | 390 | AS.getU8(C, AugmentationString, AugmentationStringSize); | ||
399 | errc::illegal_byte_sequence, | | |||
400 | "Section too small: cannot read header augmentation."); | | |||
401 | AugmentationString.resize(AugmentationStringSize); | | |||
402 | AS.getU8(Offset, reinterpret_cast<uint8_t *>(AugmentationString.data()), | | |||
403 | AugmentationStringSize); | | |||
404 | return Error::success(); | | |||
405 | } | 391 | } | ||
406 | 392 | | |||
407 | void DWARFDebugNames::Abbrev::dump(ScopedPrinter &W) const { | 393 | void DWARFDebugNames::Abbrev::dump(ScopedPrinter &W) const { | ||
408 | DictScope AbbrevScope(W, ("Abbreviation 0x" + Twine::utohexstr(Code)).str()); | 394 | DictScope AbbrevScope(W, ("Abbreviation 0x" + Twine::utohexstr(Code)).str()); | ||
409 | W.startLine() << formatv("Tag: {0}\n", Tag); | 395 | W.startLine() << formatv("Tag: {0}\n", Tag); | ||
410 | 396 | | |||
411 | for (const auto &Attr : Attributes) | 397 | for (const auto &Attr : Attributes) | ||
412 | W.startLine() << formatv("{0}: {1}\n", Attr.Index, Attr.Form); | 398 | W.startLine() << formatv("{0}: {1}\n", Attr.Index, Attr.Form); | ||
Show All 18 Lines | |||||
431 | DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getEmptyKey() { | 417 | DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getEmptyKey() { | ||
432 | return sentinelAbbrev(); | 418 | return sentinelAbbrev(); | ||
433 | } | 419 | } | ||
434 | 420 | | |||
435 | DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getTombstoneKey() { | 421 | DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getTombstoneKey() { | ||
436 | return DWARFDebugNames::Abbrev(~0, dwarf::Tag(0), {}); | 422 | return DWARFDebugNames::Abbrev(~0, dwarf::Tag(0), {}); | ||
437 | } | 423 | } | ||
438 | 424 | | |||
439 | Expected<DWARFDebugNames::AttributeEncoding> | 425 | DWARFDebugNames::AttributeEncoding | ||
440 | DWARFDebugNames::NameIndex::extractAttributeEncoding(uint64_t *Offset) { | 426 | DWARFDebugNames::NameIndex::extractAttributeEncoding(DataExtractor::Cursor &C) { | ||
441 | if (*Offset >= EntriesBase) { | 427 | uint32_t Index = Section.AccelSection.getULEB128(C); | ||
442 | return createStringError(errc::illegal_byte_sequence, | 428 | uint32_t Form = Section.AccelSection.getULEB128(C); | ||
443 | "Incorrectly terminated abbreviation table."); | | |||
444 | } | | |||
445 | | ||||
446 | uint32_t Index = Section.AccelSection.getULEB128(Offset); | | |||
447 | uint32_t Form = Section.AccelSection.getULEB128(Offset); | | |||
448 | return AttributeEncoding(dwarf::Index(Index), dwarf::Form(Form)); | 429 | return AttributeEncoding(dwarf::Index(Index), dwarf::Form(Form)); | ||
449 | } | 430 | } | ||
450 | 431 | | |||
451 | Expected<std::vector<DWARFDebugNames::AttributeEncoding>> | 432 | std::vector<DWARFDebugNames::AttributeEncoding> | ||
452 | DWARFDebugNames::NameIndex::extractAttributeEncodings(uint64_t *Offset) { | 433 | DWARFDebugNames::NameIndex::extractAttributeEncodings( | ||
434 | DataExtractor::Cursor &C) { | ||||
453 | std::vector<AttributeEncoding> Result; | 435 | std::vector<AttributeEncoding> Result; | ||
454 | for (;;) { | 436 | for (;;) { | ||
455 | auto AttrEncOr = extractAttributeEncoding(Offset); | 437 | AttributeEncoding AttrEnc = extractAttributeEncoding(C); | ||
456 | if (!AttrEncOr) | 438 | if (isSentinel(AttrEnc)) | ||
457 | return AttrEncOr.takeError(); | 439 | return Result; | ||
458 | if (isSentinel(*AttrEncOr)) | | |||
459 | return std::move(Result); | | |||
460 | 440 | | |||
461 | Result.emplace_back(*AttrEncOr); | 441 | Result.emplace_back(AttrEnc); | ||
462 | } | 442 | } | ||
463 | } | 443 | } | ||
464 | 444 | | |||
465 | Expected<DWARFDebugNames::Abbrev> | 445 | DWARFDebugNames::Abbrev | ||
466 | DWARFDebugNames::NameIndex::extractAbbrev(uint64_t *Offset) { | 446 | DWARFDebugNames::NameIndex::extractAbbrev(DataExtractor::Cursor &C) { | ||
467 | if (*Offset >= EntriesBase) { | 447 | uint32_t Code = Section.AccelSection.getULEB128(C); | ||
468 | return createStringError(errc::illegal_byte_sequence, | | |||
469 | "Incorrectly terminated abbreviation table."); | | |||
470 | } | | |||
471 | | ||||
472 | uint32_t Code = Section.AccelSection.getULEB128(Offset); | | |||
473 | if (Code == 0) | 448 | if (Code == 0) | ||
474 | return sentinelAbbrev(); | 449 | return sentinelAbbrev(); | ||
475 | 450 | | |||
476 | uint32_t Tag = Section.AccelSection.getULEB128(Offset); | 451 | uint32_t Tag = Section.AccelSection.getULEB128(C); | ||
477 | auto AttrEncOr = extractAttributeEncodings(Offset); | 452 | std::vector<AttributeEncoding> AttrEnc = extractAttributeEncodings(C); | ||
478 | if (!AttrEncOr) | 453 | return Abbrev(Code, dwarf::Tag(Tag), std::move(AttrEnc)); | ||
479 | return AttrEncOr.takeError(); | | |||
480 | return Abbrev(Code, dwarf::Tag(Tag), std::move(*AttrEncOr)); | | |||
481 | } | 454 | } | ||
482 | 455 | | |||
483 | Error DWARFDebugNames::NameIndex::extract() { | 456 | Error DWARFDebugNames::NameIndex::extract() { | ||
484 | const DWARFDataExtractor &AS = Section.AccelSection; | 457 | const DWARFDataExtractor &AS = Section.AccelSection; | ||
485 | uint64_t Offset = Base; | 458 | DataExtractor::Cursor C(Base); | ||
486 | if (Error E = Hdr.extract(AS, &Offset)) | 459 | Hdr.extract(AS, C); | ||
487 | return E; | | |||
488 | 460 | | |||
489 | CUsBase = Offset; | 461 | CUsBase = C.tell(); | ||
490 | Offset += Hdr.CompUnitCount * 4; | 462 | AS.skip(C, Hdr.CompUnitCount * 4); | ||
491 | Offset += Hdr.LocalTypeUnitCount * 4; | 463 | AS.skip(C, Hdr.LocalTypeUnitCount * 4); | ||
492 | Offset += Hdr.ForeignTypeUnitCount * 8; | 464 | AS.skip(C, Hdr.ForeignTypeUnitCount * 8); | ||
493 | BucketsBase = Offset; | 465 | BucketsBase = C.tell(); | ||
494 | Offset += Hdr.BucketCount * 4; | 466 | AS.skip(C, Hdr.BucketCount * 4); | ||
495 | HashesBase = Offset; | 467 | HashesBase = C.tell(); | ||
496 | if (Hdr.BucketCount > 0) | 468 | if (Hdr.BucketCount > 0) | ||
497 | Offset += Hdr.NameCount * 4; | 469 | AS.skip(C, Hdr.NameCount * 4); | ||
498 | StringOffsetsBase = Offset; | 470 | StringOffsetsBase = C.tell(); | ||
499 | Offset += Hdr.NameCount * 4; | 471 | AS.skip(C, Hdr.NameCount * 4); | ||
500 | EntryOffsetsBase = Offset; | 472 | EntryOffsetsBase = C.tell(); | ||
501 | Offset += Hdr.NameCount * 4; | 473 | AS.skip(C, Hdr.NameCount * 4); | ||
502 | 474 | | |||
503 | if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize)) | 475 | if (llvm::Error E = C.takeError()) | ||
476 | return E; | ||||
477 | uint64_t AbbrevBase = C.tell(); | ||||
478 | if (!AS.isValidOffsetForDataOfSize(AbbrevBase, Hdr.AbbrevTableSize)) | ||||
504 | return createStringError(errc::illegal_byte_sequence, | 479 | return createStringError(errc::illegal_byte_sequence, | ||
505 | "Section too small: cannot read abbreviations."); | 480 | "Section too small: cannot read abbreviations."); | ||
506 | 481 | | |||
507 | EntriesBase = Offset + Hdr.AbbrevTableSize; | 482 | EntriesBase = C.tell() + Hdr.AbbrevTableSize; | ||
508 | 483 | | |||
509 | for (;;) { | 484 | for (;;) { | ||
510 | auto AbbrevOr = extractAbbrev(&Offset); | 485 | Abbrev Abbr = extractAbbrev(C); | ||
511 | if (!AbbrevOr) | 486 | if (llvm::Error E = C.takeError()) | ||
512 | return AbbrevOr.takeError(); | 487 | return E; | ||
513 | if (isSentinel(*AbbrevOr)) | 488 | if (isSentinel(Abbr)) | ||
514 | return Error::success(); | 489 | break; | ||
515 | 490 | | |||
516 | if (!Abbrevs.insert(std::move(*AbbrevOr)).second) | 491 | if (!Abbrevs.insert(std::move(Abbr)).second) | ||
517 | return createStringError(errc::invalid_argument, | 492 | return createStringError(errc::invalid_argument, | ||
518 | "Duplicate abbreviation code."); | 493 | "Duplicate abbreviation code."); | ||
519 | } | 494 | } | ||
495 | if (C.tell() > EntriesBase) | ||||
496 | return createStringError(errc::illegal_byte_sequence, | ||||
497 | "Incorrectly terminated abbreviation table."); | ||||
498 | return Error::success(); | ||||
520 | } | 499 | } | ||
521 | 500 | | |||
522 | DWARFDebugNames::Entry::Entry(const NameIndex &NameIdx, const Abbrev &Abbr) | 501 | DWARFDebugNames::Entry::Entry(const NameIndex &NameIdx, const Abbrev &Abbr) | ||
523 | : NameIdx(&NameIdx), Abbr(&Abbr) { | 502 | : NameIdx(&NameIdx), Abbr(&Abbr) { | ||
524 | // This merely creates form values. It is up to the caller | 503 | // This merely creates form values. It is up to the caller | ||
525 | // (NameIndex::getEntry) to populate them. | 504 | // (NameIndex::getEntry) to populate them. | ||
526 | Values.reserve(Abbr.Attributes.size()); | 505 | Values.reserve(Abbr.Attributes.size()); | ||
527 | for (const auto &Attr : Abbr.Attributes) | 506 | for (const auto &Attr : Abbr.Attributes) | ||
▲ Show 20 Lines • Show All 362 Lines • Show Last 20 Lines |