summaryrefslogtreecommitdiff
path: root/include/llvm/DebugInfo/DWARF
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
commiteb11fae6d08f479c0799db45860a98af528fa6e7 (patch)
tree44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /include/llvm/DebugInfo/DWARF
parentb8a2042aa938069e862750553db0e4d82d25822c (diff)
Notes
Diffstat (limited to 'include/llvm/DebugInfo/DWARF')
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h524
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFAddressRange.h68
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h8
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFContext.h44
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h7
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h1
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h278
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugLine.h118
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h3
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h45
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h60
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDie.h38
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFExpression.h14
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFFormValue.h63
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFListTable.h278
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFObject.h4
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h20
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFUnit.h241
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFVerifier.h58
20 files changed, 1574 insertions, 300 deletions
diff --git a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index 0bade10f6201..1d448728338f 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H
#define LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
@@ -20,18 +21,76 @@
namespace llvm {
class raw_ostream;
+class ScopedPrinter;
+
+/// The accelerator tables are designed to allow efficient random access
+/// (using a symbol name as a key) into debug info by providing an index of the
+/// debug info DIEs. This class implements the common functionality of Apple and
+/// DWARF 5 accelerator tables.
+/// TODO: Generalize the rest of the AppleAcceleratorTable interface and move it
+/// to this class.
+class DWARFAcceleratorTable {
+protected:
+ DWARFDataExtractor AccelSection;
+ DataExtractor StringSection;
+
+public:
+ /// An abstract class representing a single entry in the accelerator tables.
+ class Entry {
+ protected:
+ SmallVector<DWARFFormValue, 3> Values;
+
+ Entry() = default;
+
+ // Make these protected so only (final) subclasses can be copied around.
+ Entry(const Entry &) = default;
+ Entry(Entry &&) = default;
+ Entry &operator=(const Entry &) = default;
+ Entry &operator=(Entry &&) = default;
+ ~Entry() = default;
+
+
+ public:
+ /// Returns the Offset of the Compilation Unit associated with this
+ /// Accelerator Entry or None if the Compilation Unit offset is not recorded
+ /// in this Accelerator Entry.
+ virtual Optional<uint64_t> getCUOffset() const = 0;
+
+ /// Returns the Tag of the Debug Info Entry associated with this
+ /// Accelerator Entry or None if the Tag is not recorded in this
+ /// Accelerator Entry.
+ virtual Optional<dwarf::Tag> getTag() const = 0;
+
+ /// Returns the raw values of fields in the Accelerator Entry. In general,
+ /// these can only be interpreted with the help of the metadata in the
+ /// owning Accelerator Table.
+ ArrayRef<DWARFFormValue> getValues() const { return Values; }
+ };
+
+ DWARFAcceleratorTable(const DWARFDataExtractor &AccelSection,
+ DataExtractor StringSection)
+ : AccelSection(AccelSection), StringSection(StringSection) {}
+ virtual ~DWARFAcceleratorTable();
+
+ virtual llvm::Error extract() = 0;
+ virtual void dump(raw_ostream &OS) const = 0;
+
+ DWARFAcceleratorTable(const DWARFAcceleratorTable &) = delete;
+ void operator=(const DWARFAcceleratorTable &) = delete;
+};
/// This implements the Apple accelerator table format, a precursor of the
/// DWARF 5 accelerator table format.
-/// TODO: Factor out a common base class for both formats.
-class DWARFAcceleratorTable {
+class AppleAcceleratorTable : public DWARFAcceleratorTable {
struct Header {
uint32_t Magic;
uint16_t Version;
uint16_t HashFunction;
- uint32_t NumBuckets;
- uint32_t NumHashes;
+ uint32_t BucketCount;
+ uint32_t HashCount;
uint32_t HeaderDataLength;
+
+ void dump(ScopedPrinter &W) const;
};
struct HeaderData {
@@ -40,22 +99,51 @@ class DWARFAcceleratorTable {
uint32_t DIEOffsetBase;
SmallVector<std::pair<AtomType, Form>, 3> Atoms;
+
+ Optional<uint64_t> extractOffset(Optional<DWARFFormValue> Value) const;
};
struct Header Hdr;
struct HeaderData HdrData;
- DWARFDataExtractor AccelSection;
- DataExtractor StringSection;
bool IsValid = false;
+ /// Returns true if we should continue scanning for entries or false if we've
+ /// reached the last (sentinel) entry of encountered a parsing error.
+ bool dumpName(ScopedPrinter &W, SmallVectorImpl<DWARFFormValue> &AtomForms,
+ uint32_t *DataOffset) const;
+
public:
- /// An iterator for the entries associated with one key. Each entry can have
- /// multiple DWARFFormValues.
- class ValueIterator : public std::iterator<std::input_iterator_tag,
- ArrayRef<DWARFFormValue>> {
- const DWARFAcceleratorTable *AccelTable = nullptr;
- SmallVector<DWARFFormValue, 3> AtomForms; ///< The decoded data entry.
+ /// Apple-specific implementation of an Accelerator Entry.
+ class Entry final : public DWARFAcceleratorTable::Entry {
+ const HeaderData *HdrData = nullptr;
+
+ Entry(const HeaderData &Data);
+ Entry() = default;
+
+ void extract(const AppleAcceleratorTable &AccelTable, uint32_t *Offset);
+
+ public:
+ Optional<uint64_t> getCUOffset() const override;
+
+ /// Returns the Section Offset of the Debug Info Entry associated with this
+ /// Accelerator Entry or None if the DIE offset is not recorded in this
+ /// Accelerator Entry. The returned offset is relative to the start of the
+ /// Section containing the DIE.
+ Optional<uint64_t> getDIESectionOffset() const;
+ Optional<dwarf::Tag> getTag() const override;
+
+ /// Returns the value of the Atom in this Accelerator Entry, if the Entry
+ /// contains such Atom.
+ Optional<DWARFFormValue> lookup(HeaderData::AtomType Atom) const;
+
+ friend class AppleAcceleratorTable;
+ friend class ValueIterator;
+ };
+
+ class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> {
+ const AppleAcceleratorTable *AccelTable = nullptr;
+ Entry Current; ///< The current entry.
unsigned DataOffset = 0; ///< Offset into the section.
unsigned Data = 0; ///< Current data entry.
unsigned NumData = 0; ///< Number of data entries.
@@ -64,13 +152,11 @@ public:
void Next();
public:
/// Construct a new iterator for the entries at \p DataOffset.
- ValueIterator(const DWARFAcceleratorTable &AccelTable, unsigned DataOffset);
+ ValueIterator(const AppleAcceleratorTable &AccelTable, unsigned DataOffset);
/// End marker.
ValueIterator() = default;
- const ArrayRef<DWARFFormValue> operator*() const {
- return AtomForms;
- }
+ const Entry &operator*() const { return Current; }
ValueIterator &operator++() { Next(); return *this; }
ValueIterator operator++(int) {
ValueIterator I = *this;
@@ -85,16 +171,18 @@ public:
}
};
-
- DWARFAcceleratorTable(const DWARFDataExtractor &AccelSection,
+ AppleAcceleratorTable(const DWARFDataExtractor &AccelSection,
DataExtractor StringSection)
- : AccelSection(AccelSection), StringSection(StringSection) {}
+ : DWARFAcceleratorTable(AccelSection, StringSection) {}
- llvm::Error extract();
+ llvm::Error extract() override;
uint32_t getNumBuckets();
uint32_t getNumHashes();
uint32_t getSizeHdr();
uint32_t getHeaderDataLength();
+
+ /// Return the Atom description, which can be used to interpret the raw values
+ /// of the Accelerator Entries in this table.
ArrayRef<std::pair<HeaderData::AtomType, HeaderData::Form>> getAtomsDesc();
bool validateForms();
@@ -107,10 +195,404 @@ public:
/// related to the input hash data offset.
/// DieTag is the tag of the DIE
std::pair<uint32_t, dwarf::Tag> readAtoms(uint32_t &HashDataOffset);
- void dump(raw_ostream &OS) const;
+ void dump(raw_ostream &OS) const override;
+
+ /// Look up all entries in the accelerator table matching \c Key.
+ iterator_range<ValueIterator> equal_range(StringRef Key) const;
+};
+
+/// .debug_names section consists of one or more units. Each unit starts with a
+/// header, which is followed by a list of compilation units, local and foreign
+/// type units.
+///
+/// These may be followed by an (optional) hash lookup table, which consists of
+/// an array of buckets and hashes similar to the apple tables above. The only
+/// difference is that the hashes array is 1-based, and consequently an empty
+/// bucket is denoted by 0 and not UINT32_MAX.
+///
+/// Next is the name table, which consists of an array of names and array of
+/// entry offsets. This is different from the apple tables, which store names
+/// next to the actual entries.
+///
+/// The structure of the entries is described by an abbreviations table, which
+/// comes after the name table. Unlike the apple tables, which have a uniform
+/// entry structure described in the header, each .debug_names entry may have
+/// different index attributes (DW_IDX_???) attached to it.
+///
+/// The last segment consists of a list of entries, which is a 0-terminated list
+/// referenced by the name table and interpreted with the help of the
+/// abbreviation table.
+class DWARFDebugNames : public DWARFAcceleratorTable {
+ /// The fixed-size part of a Dwarf 5 Name Index header
+ struct HeaderPOD {
+ uint32_t UnitLength;
+ uint16_t Version;
+ uint16_t Padding;
+ uint32_t CompUnitCount;
+ uint32_t LocalTypeUnitCount;
+ uint32_t ForeignTypeUnitCount;
+ uint32_t BucketCount;
+ uint32_t NameCount;
+ uint32_t AbbrevTableSize;
+ uint32_t AugmentationStringSize;
+ };
+
+public:
+ class NameIndex;
+ class NameIterator;
+ class ValueIterator;
+
+ /// Dwarf 5 Name Index header.
+ struct Header : public HeaderPOD {
+ SmallString<8> AugmentationString;
+
+ Error extract(const DWARFDataExtractor &AS, uint32_t *Offset);
+ void dump(ScopedPrinter &W) const;
+ };
+
+ /// Index attribute and its encoding.
+ struct AttributeEncoding {
+ dwarf::Index Index;
+ dwarf::Form Form;
+
+ constexpr AttributeEncoding(dwarf::Index Index, dwarf::Form Form)
+ : Index(Index), Form(Form) {}
+
+ friend bool operator==(const AttributeEncoding &LHS,
+ const AttributeEncoding &RHS) {
+ return LHS.Index == RHS.Index && LHS.Form == RHS.Form;
+ }
+ };
+
+ /// Abbreviation describing the encoding of Name Index entries.
+ struct Abbrev {
+ uint32_t Code; ///< Abbreviation code
+ dwarf::Tag Tag; ///< Dwarf Tag of the described entity.
+ std::vector<AttributeEncoding> Attributes; ///< List of index attributes.
+
+ Abbrev(uint32_t Code, dwarf::Tag Tag,
+ std::vector<AttributeEncoding> Attributes)
+ : Code(Code), Tag(Tag), Attributes(std::move(Attributes)) {}
+
+ void dump(ScopedPrinter &W) const;
+ };
+
+ /// DWARF v5-specific implementation of an Accelerator Entry.
+ class Entry final : public DWARFAcceleratorTable::Entry {
+ const NameIndex *NameIdx;
+ const Abbrev *Abbr;
+
+ Entry(const NameIndex &NameIdx, const Abbrev &Abbr);
+
+ public:
+ Optional<uint64_t> getCUOffset() const override;
+ Optional<dwarf::Tag> getTag() const override { return tag(); }
+
+ /// Returns the Index into the Compilation Unit list of the owning Name
+ /// Index or None if this Accelerator Entry does not have an associated
+ /// Compilation Unit. It is up to the user to verify that the returned Index
+ /// is valid in the owning NameIndex (or use getCUOffset(), which will
+ /// handle that check itself). Note that entries in NameIndexes which index
+ /// just a single Compilation Unit are implicitly associated with that unit,
+ /// so this function will return 0 even without an explicit
+ /// DW_IDX_compile_unit attribute.
+ Optional<uint64_t> getCUIndex() const;
+
+ /// .debug_names-specific getter, which always succeeds (DWARF v5 index
+ /// entries always have a tag).
+ dwarf::Tag tag() const { return Abbr->Tag; }
+
+ /// Returns the Offset of the DIE within the containing CU or TU.
+ Optional<uint64_t> getDIEUnitOffset() const;
+
+ /// Return the Abbreviation that can be used to interpret the raw values of
+ /// this Accelerator Entry.
+ const Abbrev &getAbbrev() const { return *Abbr; }
+
+ /// Returns the value of the Index Attribute in this Accelerator Entry, if
+ /// the Entry contains such Attribute.
+ Optional<DWARFFormValue> lookup(dwarf::Index Index) const;
+
+ void dump(ScopedPrinter &W) const;
+
+ friend class NameIndex;
+ friend class ValueIterator;
+ };
+
+ /// Error returned by NameIndex::getEntry to report it has reached the end of
+ /// the entry list.
+ class SentinelError : public ErrorInfo<SentinelError> {
+ public:
+ static char ID;
+
+ void log(raw_ostream &OS) const override { OS << "Sentinel"; }
+ std::error_code convertToErrorCode() const override;
+ };
+
+private:
+ /// DenseMapInfo for struct Abbrev.
+ struct AbbrevMapInfo {
+ static Abbrev getEmptyKey();
+ static Abbrev getTombstoneKey();
+ static unsigned getHashValue(uint32_t Code) {
+ return DenseMapInfo<uint32_t>::getHashValue(Code);
+ }
+ static unsigned getHashValue(const Abbrev &Abbr) {
+ return getHashValue(Abbr.Code);
+ }
+ static bool isEqual(uint32_t LHS, const Abbrev &RHS) {
+ return LHS == RHS.Code;
+ }
+ static bool isEqual(const Abbrev &LHS, const Abbrev &RHS) {
+ return LHS.Code == RHS.Code;
+ }
+ };
+
+public:
+ /// A single entry in the Name Table (Dwarf 5 sect. 6.1.1.4.6) of the Name
+ /// Index.
+ class NameTableEntry {
+ DataExtractor StrData;
+
+ uint32_t Index;
+ uint32_t StringOffset;
+ uint32_t EntryOffset;
+
+ public:
+ NameTableEntry(const DataExtractor &StrData, uint32_t Index,
+ uint32_t StringOffset, uint32_t EntryOffset)
+ : StrData(StrData), Index(Index), StringOffset(StringOffset),
+ EntryOffset(EntryOffset) {}
+
+ /// Return the index of this name in the parent Name Index.
+ uint32_t getIndex() const { return Index; }
+
+ /// Returns the offset of the name of the described entities.
+ uint32_t getStringOffset() const { return StringOffset; }
+
+ /// Return the string referenced by this name table entry or nullptr if the
+ /// string offset is not valid.
+ const char *getString() const {
+ uint32_t Off = StringOffset;
+ return StrData.getCStr(&Off);
+ }
+
+ /// Returns the offset of the first Entry in the list.
+ uint32_t getEntryOffset() const { return EntryOffset; }
+ };
+
+ /// Represents a single accelerator table within the Dwarf 5 .debug_names
+ /// section.
+ class NameIndex {
+ DenseSet<Abbrev, AbbrevMapInfo> Abbrevs;
+ struct Header Hdr;
+ const DWARFDebugNames &Section;
+
+ // Base of the whole unit and of various important tables, as offsets from
+ // the start of the section.
+ uint32_t Base;
+ uint32_t CUsBase;
+ uint32_t BucketsBase;
+ uint32_t HashesBase;
+ uint32_t StringOffsetsBase;
+ uint32_t EntryOffsetsBase;
+ uint32_t EntriesBase;
+
+ void dumpCUs(ScopedPrinter &W) const;
+ void dumpLocalTUs(ScopedPrinter &W) const;
+ void dumpForeignTUs(ScopedPrinter &W) const;
+ void dumpAbbreviations(ScopedPrinter &W) const;
+ bool dumpEntry(ScopedPrinter &W, uint32_t *Offset) const;
+ void dumpName(ScopedPrinter &W, const NameTableEntry &NTE,
+ Optional<uint32_t> Hash) const;
+ void dumpBucket(ScopedPrinter &W, uint32_t Bucket) const;
+
+ Expected<AttributeEncoding> extractAttributeEncoding(uint32_t *Offset);
+
+ Expected<std::vector<AttributeEncoding>>
+ extractAttributeEncodings(uint32_t *Offset);
+
+ Expected<Abbrev> extractAbbrev(uint32_t *Offset);
+
+ public:
+ NameIndex(const DWARFDebugNames &Section, uint32_t Base)
+ : Section(Section), Base(Base) {}
+
+ /// Reads offset of compilation unit CU. CU is 0-based.
+ uint32_t getCUOffset(uint32_t CU) const;
+ uint32_t getCUCount() const { return Hdr.CompUnitCount; }
+
+ /// Reads offset of local type unit TU, TU is 0-based.
+ uint32_t getLocalTUOffset(uint32_t TU) const;
+ uint32_t getLocalTUCount() const { return Hdr.LocalTypeUnitCount; }
+
+ /// Reads signature of foreign type unit TU. TU is 0-based.
+ uint64_t getForeignTUSignature(uint32_t TU) const;
+ uint32_t getForeignTUCount() const { return Hdr.ForeignTypeUnitCount; }
+
+ /// Reads an entry in the Bucket Array for the given Bucket. The returned
+ /// value is a (1-based) index into the Names, StringOffsets and
+ /// EntryOffsets arrays. The input Bucket index is 0-based.
+ uint32_t getBucketArrayEntry(uint32_t Bucket) const;
+ uint32_t getBucketCount() const { return Hdr.BucketCount; }
+
+ /// Reads an entry in the Hash Array for the given Index. The input Index
+ /// is 1-based.
+ uint32_t getHashArrayEntry(uint32_t Index) const;
+
+ /// Reads an entry in the Name Table for the given Index. The Name Table
+ /// consists of two arrays -- String Offsets and Entry Offsets. The returned
+ /// offsets are relative to the starts of respective sections. Input Index
+ /// is 1-based.
+ NameTableEntry getNameTableEntry(uint32_t Index) const;
+
+ uint32_t getNameCount() const { return Hdr.NameCount; }
+
+ const DenseSet<Abbrev, AbbrevMapInfo> &getAbbrevs() const {
+ return Abbrevs;
+ }
+
+ Expected<Entry> getEntry(uint32_t *Offset) const;
+
+ /// Look up all entries in this Name Index matching \c Key.
+ iterator_range<ValueIterator> equal_range(StringRef Key) const;
+
+ NameIterator begin() const { return NameIterator(this, 1); }
+ NameIterator end() const { return NameIterator(this, getNameCount() + 1); }
+
+ llvm::Error extract();
+ uint32_t getUnitOffset() const { return Base; }
+ uint32_t getNextUnitOffset() const { return Base + 4 + Hdr.UnitLength; }
+ void dump(ScopedPrinter &W) const;
+
+ friend class DWARFDebugNames;
+ };
+
+ class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> {
+
+ /// The Name Index we are currently iterating through. The implementation
+ /// relies on the fact that this can also be used as an iterator into the
+ /// "NameIndices" vector in the Accelerator section.
+ const NameIndex *CurrentIndex = nullptr;
+
+ /// Whether this is a local iterator (searches in CurrentIndex only) or not
+ /// (searches all name indices).
+ bool IsLocal;
+
+ Optional<Entry> CurrentEntry;
+ unsigned DataOffset = 0; ///< Offset into the section.
+ std::string Key; ///< The Key we are searching for.
+ Optional<uint32_t> Hash; ///< Hash of Key, if it has been computed.
+
+ bool getEntryAtCurrentOffset();
+ Optional<uint32_t> findEntryOffsetInCurrentIndex();
+ bool findInCurrentIndex();
+ void searchFromStartOfCurrentIndex();
+ void next();
+
+ /// Set the iterator to the "end" state.
+ void setEnd() { *this = ValueIterator(); }
+
+ public:
+ /// Create a "begin" iterator for looping over all entries in the
+ /// accelerator table matching Key. The iterator will run through all Name
+ /// Indexes in the section in sequence.
+ ValueIterator(const DWARFDebugNames &AccelTable, StringRef Key);
+
+ /// Create a "begin" iterator for looping over all entries in a specific
+ /// Name Index. Other indices in the section will not be visited.
+ ValueIterator(const NameIndex &NI, StringRef Key);
+
+ /// End marker.
+ ValueIterator() = default;
+
+ const Entry &operator*() const { return *CurrentEntry; }
+ ValueIterator &operator++() {
+ next();
+ return *this;
+ }
+ ValueIterator operator++(int) {
+ ValueIterator I = *this;
+ next();
+ return I;
+ }
+
+ friend bool operator==(const ValueIterator &A, const ValueIterator &B) {
+ return A.CurrentIndex == B.CurrentIndex && A.DataOffset == B.DataOffset;
+ }
+ friend bool operator!=(const ValueIterator &A, const ValueIterator &B) {
+ return !(A == B);
+ }
+ };
+
+ class NameIterator {
+
+ /// The Name Index we are iterating through.
+ const NameIndex *CurrentIndex;
+
+ /// The current name in the Name Index.
+ uint32_t CurrentName;
+
+ void next() {
+ assert(CurrentName <= CurrentIndex->getNameCount());
+ ++CurrentName;
+ }
+
+ public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = NameTableEntry;
+ using difference_type = uint32_t;
+ using pointer = NameTableEntry *;
+ using reference = NameTableEntry; // We return entries by value.
+
+ /// Creates an iterator whose initial position is name CurrentName in
+ /// CurrentIndex.
+ NameIterator(const NameIndex *CurrentIndex, uint32_t CurrentName)
+ : CurrentIndex(CurrentIndex), CurrentName(CurrentName) {}
+
+ NameTableEntry operator*() const {
+ return CurrentIndex->getNameTableEntry(CurrentName);
+ }
+ NameIterator &operator++() {
+ next();
+ return *this;
+ }
+ NameIterator operator++(int) {
+ NameIterator I = *this;
+ next();
+ return I;
+ }
+
+ friend bool operator==(const NameIterator &A, const NameIterator &B) {
+ return A.CurrentIndex == B.CurrentIndex && A.CurrentName == B.CurrentName;
+ }
+ friend bool operator!=(const NameIterator &A, const NameIterator &B) {
+ return !(A == B);
+ }
+ };
+
+private:
+ SmallVector<NameIndex, 0> NameIndices;
+ DenseMap<uint32_t, const NameIndex *> CUToNameIndex;
+
+public:
+ DWARFDebugNames(const DWARFDataExtractor &AccelSection,
+ DataExtractor StringSection)
+ : DWARFAcceleratorTable(AccelSection, StringSection) {}
+
+ llvm::Error extract() override;
+ void dump(raw_ostream &OS) const override;
/// Look up all entries in the accelerator table matching \c Key.
iterator_range<ValueIterator> equal_range(StringRef Key) const;
+
+ using const_iterator = SmallVector<NameIndex, 0>::const_iterator;
+ const_iterator begin() const { return NameIndices.begin(); }
+ const_iterator end() const { return NameIndices.end(); }
+
+ /// Return the Name Index covering the compile unit at CUOffset, or nullptr if
+ /// there is no Name Index covering that unit.
+ const NameIndex *getCUNameIndex(uint32_t CUOffset);
};
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h b/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h
new file mode 100644
index 000000000000..5a7df5c353e8
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h
@@ -0,0 +1,68 @@
+//===- DWARFAddressRange.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFADDRESSRANGE_H
+#define LLVM_DEBUGINFO_DWARF_DWARFADDRESSRANGE_H
+
+#include "llvm/DebugInfo/DIContext.h"
+#include <cstdint>
+#include <tuple>
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+struct DWARFAddressRange {
+ uint64_t LowPC;
+ uint64_t HighPC;
+ uint64_t SectionIndex;
+
+ DWARFAddressRange() = default;
+
+ /// Used for unit testing.
+ DWARFAddressRange(uint64_t LowPC, uint64_t HighPC, uint64_t SectionIndex = 0)
+ : LowPC(LowPC), HighPC(HighPC), SectionIndex(SectionIndex) {}
+
+ /// Returns true if LowPC is smaller or equal to HighPC. This accounts for
+ /// dead-stripped ranges.
+ bool valid() const { return LowPC <= HighPC; }
+
+ /// Returns true if [LowPC, HighPC) intersects with [RHS.LowPC, RHS.HighPC).
+ bool intersects(const DWARFAddressRange &RHS) const {
+ assert(valid() && RHS.valid());
+ // Empty ranges can't intersect.
+ if (LowPC == HighPC || RHS.LowPC == RHS.HighPC)
+ return false;
+ return LowPC < RHS.HighPC && RHS.LowPC < HighPC;
+ }
+
+ /// Returns true if [LowPC, HighPC) fully contains [RHS.LowPC, RHS.HighPC).
+ bool contains(const DWARFAddressRange &RHS) const {
+ assert(valid() && RHS.valid());
+ return LowPC <= RHS.LowPC && RHS.HighPC <= HighPC;
+ }
+
+ void dump(raw_ostream &OS, uint32_t AddressSize,
+ DIDumpOptions DumpOpts = {}) const;
+};
+
+static inline bool operator<(const DWARFAddressRange &LHS,
+ const DWARFAddressRange &RHS) {
+ return std::tie(LHS.LowPC, LHS.HighPC) < std::tie(RHS.LowPC, RHS.HighPC);
+}
+
+raw_ostream &operator<<(raw_ostream &OS, const DWARFAddressRange &R);
+
+/// DWARFAddressRangesVector - represents a set of absolute address ranges.
+using DWARFAddressRangesVector = std::vector<DWARFAddressRange>;
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFADDRESSRANGE_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
index a18adf87bf8e..c219ca75e640 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
@@ -18,13 +18,13 @@ namespace llvm {
class DWARFCompileUnit : public DWARFUnit {
public:
DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFUnitHeader &Header,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, const DWARFSection &SOS,
const DWARFSection *AOS, const DWARFSection &LS, bool LE,
- bool IsDWO, const DWARFUnitSectionBase &UnitSection,
- const DWARFUnitIndex::Entry *Entry)
- : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
- UnitSection, Entry) {}
+ bool IsDWO, const DWARFUnitSectionBase &UnitSection)
+ : DWARFUnit(Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
+ UnitSection) {}
// VTable anchor.
~DWARFCompileUnit() override;
diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h
index 2ddbc4b91ba2..fe7430c9f04c 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -34,6 +34,7 @@
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Host.h"
#include <cstdint>
@@ -43,7 +44,6 @@
namespace llvm {
-class DataExtractor;
class MCRegisterInfo;
class MemoryBuffer;
class raw_ostream;
@@ -69,10 +69,11 @@ class DWARFContext : public DIContext {
std::unique_ptr<DWARFDebugFrame> DebugFrame;
std::unique_ptr<DWARFDebugFrame> EHFrame;
std::unique_ptr<DWARFDebugMacro> Macro;
- std::unique_ptr<DWARFAcceleratorTable> AppleNames;
- std::unique_ptr<DWARFAcceleratorTable> AppleTypes;
- std::unique_ptr<DWARFAcceleratorTable> AppleNamespaces;
- std::unique_ptr<DWARFAcceleratorTable> AppleObjC;
+ std::unique_ptr<DWARFDebugNames> Names;
+ std::unique_ptr<AppleAcceleratorTable> AppleNames;
+ std::unique_ptr<AppleAcceleratorTable> AppleTypes;
+ std::unique_ptr<AppleAcceleratorTable> AppleNamespaces;
+ std::unique_ptr<AppleAcceleratorTable> AppleObjC;
DWARFUnitSection<DWARFCompileUnit> DWOCUs;
std::deque<DWARFUnitSection<DWARFTypeUnit>> DWOTUs;
@@ -204,6 +205,9 @@ public:
DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
+ /// Return the compile unit that includes an offset (relative to .debug_info).
+ DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
+
/// Get a DIE given an exact offset.
DWARFDie getDIEForOffset(uint32_t Offset);
@@ -243,19 +247,36 @@ public:
const DWARFDebugMacro *getDebugMacro();
/// Get a reference to the parsed accelerator table object.
- const DWARFAcceleratorTable &getAppleNames();
+ const DWARFDebugNames &getDebugNames();
/// Get a reference to the parsed accelerator table object.
- const DWARFAcceleratorTable &getAppleTypes();
+ const AppleAcceleratorTable &getAppleNames();
/// Get a reference to the parsed accelerator table object.
- const DWARFAcceleratorTable &getAppleNamespaces();
+ const AppleAcceleratorTable &getAppleTypes();
/// Get a reference to the parsed accelerator table object.
- const DWARFAcceleratorTable &getAppleObjC();
+ const AppleAcceleratorTable &getAppleNamespaces();
+
+ /// Get a reference to the parsed accelerator table object.
+ const AppleAcceleratorTable &getAppleObjC();
+
+ /// Get a pointer to a parsed line table corresponding to a compile unit.
+ /// Report any parsing issues as warnings on stderr.
+ const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U);
/// Get a pointer to a parsed line table corresponding to a compile unit.
- const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *cu);
+ /// Report any recoverable parsing problems using the callback.
+ Expected<const DWARFDebugLine::LineTable *>
+ getLineTableForUnit(DWARFUnit *U,
+ std::function<void(Error)> RecoverableErrorCallback);
+
+ DataExtractor getStringExtractor() const {
+ return DataExtractor(DObj->getStringSection(), false, 0);
+ }
+ DataExtractor getLineStringExtractor() const {
+ return DataExtractor(DObj->getLineStringSection(), false, 0);
+ }
/// Wraps the returned DIEs for a given address.
struct DIEsForAddress {
@@ -303,9 +324,6 @@ public:
Error loadRegisterInfo(const object::ObjectFile &Obj);
private:
- /// Return the compile unit that includes an offset (relative to .debug_info).
- DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
-
/// Return the compile unit which contains instruction with provided
/// address.
DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h b/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
index a379d9c85b38..10e146b70ec7 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
@@ -44,6 +44,13 @@ public:
uint64_t getRelocatedAddress(uint32_t *Off, uint64_t *SecIx = nullptr) const {
return getRelocatedValue(getAddressSize(), Off, SecIx);
}
+
+ /// Extracts a DWARF-encoded pointer in \p Offset using \p Encoding.
+ /// There is a DWARF encoding that uses a PC-relative adjustment.
+ /// For these values, \p AbsPosOffset is used to fix them, which should
+ /// reflect the absolute address of this pointer.
+ Optional<uint64_t> getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
+ uint64_t AbsPosOffset = 0) const;
};
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
index dfbbb95076e8..ab46fac39f7c 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
@@ -43,6 +43,7 @@ public:
uint64_t Length;
uint64_t getEndAddress() const { return Address + Length; }
+ void dump(raw_ostream &OS, uint32_t AddressSize) const;
};
private:
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
index a711fb295444..ff1c7fb38389 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
@@ -10,40 +10,290 @@
#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
-#include "llvm/Support/DataExtractor.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/Support/Error.h"
#include <memory>
#include <vector>
namespace llvm {
-class FrameEntry;
class raw_ostream;
-/// \brief A parsed .debug_frame or .eh_frame section
-///
+namespace dwarf {
+
+/// Represent a sequence of Call Frame Information instructions that, when read
+/// in order, construct a table mapping PC to frame state. This can also be
+/// referred to as "CFI rules" in DWARF literature to avoid confusion with
+/// computer programs in the broader sense, and in this context each instruction
+/// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5
+/// manual, "6.4.1 Structure of Call Frame Information".
+class CFIProgram {
+public:
+ typedef SmallVector<uint64_t, 2> Operands;
+
+ /// An instruction consists of a DWARF CFI opcode and an optional sequence of
+ /// operands. If it refers to an expression, then this expression has its own
+ /// sequence of operations and operands handled separately by DWARFExpression.
+ struct Instruction {
+ Instruction(uint8_t Opcode) : Opcode(Opcode) {}
+
+ uint8_t Opcode;
+ Operands Ops;
+ // Associated DWARF expression in case this instruction refers to one
+ Optional<DWARFExpression> Expression;
+ };
+
+ using InstrList = std::vector<Instruction>;
+ using iterator = InstrList::iterator;
+ using const_iterator = InstrList::const_iterator;
+
+ iterator begin() { return Instructions.begin(); }
+ const_iterator begin() const { return Instructions.begin(); }
+ iterator end() { return Instructions.end(); }
+ const_iterator end() const { return Instructions.end(); }
+
+ unsigned size() const { return (unsigned)Instructions.size(); }
+ bool empty() const { return Instructions.empty(); }
+
+ CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor)
+ : CodeAlignmentFactor(CodeAlignmentFactor),
+ DataAlignmentFactor(DataAlignmentFactor) {}
+
+ /// Parse and store a sequence of CFI instructions from Data,
+ /// starting at *Offset and ending at EndOffset. *Offset is updated
+ /// to EndOffset upon successful parsing, or indicates the offset
+ /// where a problem occurred in case an error is returned.
+ Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset);
+
+ void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
+ unsigned IndentLevel = 1) const;
+
+private:
+ std::vector<Instruction> Instructions;
+ const uint64_t CodeAlignmentFactor;
+ const int64_t DataAlignmentFactor;
+
+ /// Convenience method to add a new instruction with the given opcode.
+ void addInstruction(uint8_t Opcode) {
+ Instructions.push_back(Instruction(Opcode));
+ }
+
+ /// Add a new single-operand instruction.
+ void addInstruction(uint8_t Opcode, uint64_t Operand1) {
+ Instructions.push_back(Instruction(Opcode));
+ Instructions.back().Ops.push_back(Operand1);
+ }
+
+ /// Add a new instruction that has two operands.
+ void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
+ Instructions.push_back(Instruction(Opcode));
+ Instructions.back().Ops.push_back(Operand1);
+ Instructions.back().Ops.push_back(Operand2);
+ }
+
+ /// Types of operands to CFI instructions
+ /// In DWARF, this type is implicitly tied to a CFI instruction opcode and
+ /// thus this type doesn't need to be explictly written to the file (this is
+ /// not a DWARF encoding). The relationship of instrs to operand types can
+ /// be obtained from getOperandTypes() and is only used to simplify
+ /// instruction printing.
+ enum OperandType {
+ OT_Unset,
+ OT_None,
+ OT_Address,
+ OT_Offset,
+ OT_FactoredCodeOffset,
+ OT_SignedFactDataOffset,
+ OT_UnsignedFactDataOffset,
+ OT_Register,
+ OT_Expression
+ };
+
+ /// Retrieve the array describing the types of operands according to the enum
+ /// above. This is indexed by opcode.
+ static ArrayRef<OperandType[2]> getOperandTypes();
+
+ /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
+ void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
+ const Instruction &Instr, unsigned OperandIdx,
+ uint64_t Operand) const;
+};
+
+/// An entry in either debug_frame or eh_frame. This entry can be a CIE or an
+/// FDE.
+class FrameEntry {
+public:
+ enum FrameKind { FK_CIE, FK_FDE };
+
+ FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign,
+ int64_t DataAlign)
+ : Kind(K), Offset(Offset), Length(Length), CFIs(CodeAlign, DataAlign) {}
+
+ virtual ~FrameEntry() {}
+
+ FrameKind getKind() const { return Kind; }
+ uint64_t getOffset() const { return Offset; }
+ uint64_t getLength() const { return Length; }
+ const CFIProgram &cfis() const { return CFIs; }
+ CFIProgram &cfis() { return CFIs; }
+
+ /// Dump the instructions in this CFI fragment
+ virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ bool IsEH) const = 0;
+
+protected:
+ const FrameKind Kind;
+
+ /// Offset of this entry in the section.
+ const uint64_t Offset;
+
+ /// Entry length as specified in DWARF.
+ const uint64_t Length;
+
+ CFIProgram CFIs;
+};
+
+/// DWARF Common Information Entry (CIE)
+class CIE : public FrameEntry {
+public:
+ // CIEs (and FDEs) are simply container classes, so the only sensible way to
+ // create them is by providing the full parsed contents in the constructor.
+ CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
+ SmallString<8> Augmentation, uint8_t AddressSize,
+ uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
+ int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
+ SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
+ uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality,
+ Optional<uint32_t> PersonalityEnc)
+ : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor,
+ DataAlignmentFactor),
+ Version(Version), Augmentation(std::move(Augmentation)),
+ AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize),
+ CodeAlignmentFactor(CodeAlignmentFactor),
+ DataAlignmentFactor(DataAlignmentFactor),
+ ReturnAddressRegister(ReturnAddressRegister),
+ AugmentationData(std::move(AugmentationData)),
+ FDEPointerEncoding(FDEPointerEncoding),
+ LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality),
+ PersonalityEnc(PersonalityEnc) {}
+
+ static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; }
+
+ StringRef getAugmentationString() const { return Augmentation; }
+ uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
+ int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
+ uint8_t getVersion() const { return Version; }
+ uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; }
+ Optional<uint64_t> getPersonalityAddress() const { return Personality; }
+ Optional<uint32_t> getPersonalityEncoding() const { return PersonalityEnc; }
+
+ uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; }
+
+ uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; }
+
+ void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ bool IsEH) const override;
+
+private:
+ /// The following fields are defined in section 6.4.1 of the DWARF standard v4
+ const uint8_t Version;
+ const SmallString<8> Augmentation;
+ const uint8_t AddressSize;
+ const uint8_t SegmentDescriptorSize;
+ const uint64_t CodeAlignmentFactor;
+ const int64_t DataAlignmentFactor;
+ const uint64_t ReturnAddressRegister;
+
+ // The following are used when the CIE represents an EH frame entry.
+ const SmallString<8> AugmentationData;
+ const uint32_t FDEPointerEncoding;
+ const uint32_t LSDAPointerEncoding;
+ const Optional<uint64_t> Personality;
+ const Optional<uint32_t> PersonalityEnc;
+};
+
+/// DWARF Frame Description Entry (FDE)
+class FDE : public FrameEntry {
+public:
+ // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
+ // an offset to the CIE (provided by parsing the FDE header). The CIE itself
+ // is obtained lazily once it's actually required.
+ FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
+ uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie,
+ Optional<uint64_t> LSDAAddress)
+ : FrameEntry(FK_FDE, Offset, Length,
+ Cie ? Cie->getCodeAlignmentFactor() : 0,
+ Cie ? Cie->getDataAlignmentFactor() : 0),
+ LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation),
+ AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {}
+
+ ~FDE() override = default;
+
+ const CIE *getLinkedCIE() const { return LinkedCIE; }
+ uint64_t getInitialLocation() const { return InitialLocation; }
+ uint64_t getAddressRange() const { return AddressRange; }
+ Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; }
+
+ void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ bool IsEH) const override;
+
+ static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; }
+
+private:
+ /// The following fields are defined in section 6.4.1 of the DWARF standard v3
+ const uint64_t LinkedCIEOffset;
+ const uint64_t InitialLocation;
+ const uint64_t AddressRange;
+ const CIE *LinkedCIE;
+ const Optional<uint64_t> LSDAAddress;
+};
+
+} // end namespace dwarf
+
+/// A parsed .debug_frame or .eh_frame section
class DWARFDebugFrame {
// True if this is parsing an eh_frame section.
- bool IsEH;
+ const bool IsEH;
+ // Not zero for sane pointer values coming out of eh_frame
+ const uint64_t EHFrameAddress;
+
+ std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries;
+ using iterator = pointee_iterator<decltype(Entries)::const_iterator>;
+
+ /// Return the entry at the given offset or nullptr.
+ dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const;
public:
- DWARFDebugFrame(bool IsEH);
+ // If IsEH is true, assume it is a .eh_frame section. Otherwise,
+ // it is a .debug_frame section. EHFrameAddress should be different
+ // than zero for correct parsing of .eh_frame addresses when they
+ // use a PC-relative encoding.
+ DWARFDebugFrame(bool IsEH = false, uint64_t EHFrameAddress = 0);
~DWARFDebugFrame();
/// Dump the section data into the given stream.
- void dump(raw_ostream &OS, Optional<uint64_t> Offset) const;
+ void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ Optional<uint64_t> Offset) const;
- /// \brief Parse the section from raw data.
- /// data is assumed to be pointing to the beginning of the section.
- void parse(DataExtractor Data);
+ /// Parse the section from raw data. \p Data is assumed to contain the whole
+ /// frame section contents to be parsed.
+ void parse(DWARFDataExtractor Data);
/// Return whether the section has any entries.
bool empty() const { return Entries.empty(); }
- /// Return the entry at the given offset or nullptr.
- FrameEntry *getEntryAtOffset(uint64_t Offset) const;
+ /// DWARF Frame entries accessors
+ iterator begin() const { return Entries.begin(); }
+ iterator end() const { return Entries.end(); }
+ iterator_range<iterator> entries() const {
+ return iterator_range<iterator>(Entries.begin(), Entries.end());
+ }
-private:
- std::vector<std::unique_ptr<FrameEntry>> Entries;
+ uint64_t getEHFrameAddress() const { return EHFrameAddress; }
};
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
index de8ad4e5ef3c..5b2af34bbcf5 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
@@ -10,11 +10,14 @@
#ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H
#define LLVM_DEBUGINFO_DWARFDEBUGLINE_H
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/Support/MD5.h"
#include <cstdint>
#include <map>
@@ -31,11 +34,30 @@ public:
struct FileNameEntry {
FileNameEntry() = default;
- StringRef Name;
+ DWARFFormValue Name;
uint64_t DirIdx = 0;
uint64_t ModTime = 0;
uint64_t Length = 0;
MD5::MD5Result Checksum;
+ DWARFFormValue Source;
+ };
+
+ /// Tracks which optional content types are present in a DWARF file name
+ /// entry format.
+ struct ContentTypeTracker {
+ ContentTypeTracker() = default;
+
+ /// Whether filename entries provide a modification timestamp.
+ bool HasModTime = false;
+ /// Whether filename entries provide a file size.
+ bool HasLength = false;
+ /// For v5, whether filename entries provide an MD5 checksum.
+ bool HasMD5 = false;
+ /// For v5, whether filename entries provide source text.
+ bool HasSource = false;
+
+ /// Update tracked content types with \p ContentType.
+ void trackContentType(dwarf::LineNumberEntryFormat ContentType);
};
struct Prologue {
@@ -47,7 +69,7 @@ public:
/// Version, address size (starting in v5), and DWARF32/64 format; these
/// parameters affect interpretation of forms (used in the directory and
/// file tables starting with v5).
- DWARFFormParams FormParams;
+ dwarf::FormParams FormParams;
/// The number of bytes following the prologue_length field to the beginning
/// of the first byte of the statement program itself.
uint64_t PrologueLength;
@@ -68,13 +90,13 @@ public:
uint8_t LineRange;
/// The number assigned to the first special opcode.
uint8_t OpcodeBase;
- /// For v5, whether filename entries provide an MD5 checksum.
- bool HasMD5;
+ /// This tracks which optional file format content types are present.
+ ContentTypeTracker ContentTypes;
std::vector<uint8_t> StandardOpcodeLengths;
- std::vector<StringRef> IncludeDirectories;
+ std::vector<DWARFFormValue> IncludeDirectories;
std::vector<FileNameEntry> FileNames;
- const DWARFFormParams getFormParams() const { return FormParams; }
+ const dwarf::FormParams getFormParams() const { return FormParams; }
uint16_t getVersion() const { return FormParams.Version; }
uint8_t getAddressSize() const { return FormParams.AddrSize; }
bool isDWARF64() const { return FormParams.Format == dwarf::DWARF64; }
@@ -83,6 +105,8 @@ public:
uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; }
+ bool totalLengthIsValid() const;
+
/// Length of the prologue in bytes.
uint32_t getLength() const {
return PrologueLength + sizeofTotalLength() + sizeof(getVersion()) +
@@ -99,9 +123,9 @@ public:
}
void clear();
- void dump(raw_ostream &OS) const;
- bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
- const DWARFUnit *U = nullptr);
+ void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const;
+ Error parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
+ const DWARFContext &Ctx, const DWARFUnit *U = nullptr);
};
/// Standard .debug_line state machine structure.
@@ -219,12 +243,14 @@ public:
DILineInfoSpecifier::FileLineInfoKind Kind,
DILineInfo &Result) const;
- void dump(raw_ostream &OS) const;
+ void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const;
void clear();
/// Parse prologue and all rows.
- bool parse(DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
- const DWARFUnit *U, raw_ostream *OS = nullptr);
+ Error parse(DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
+ const DWARFContext &Ctx, const DWARFUnit *U,
+ std::function<void(Error)> RecoverableErrorCallback = warn,
+ raw_ostream *OS = nullptr);
using RowVector = std::vector<Row>;
using RowIter = RowVector::const_iterator;
@@ -238,11 +264,75 @@ public:
private:
uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq,
uint64_t Address) const;
+ Optional<StringRef>
+ getSourceByIndex(uint64_t FileIndex,
+ DILineInfoSpecifier::FileLineInfoKind Kind) const;
};
const LineTable *getLineTable(uint32_t Offset) const;
- const LineTable *getOrParseLineTable(DWARFDataExtractor &DebugLineData,
- uint32_t Offset, const DWARFUnit *U);
+ Expected<const LineTable *> getOrParseLineTable(
+ DWARFDataExtractor &DebugLineData, uint32_t Offset,
+ const DWARFContext &Ctx, const DWARFUnit *U,
+ std::function<void(Error)> RecoverableErrorCallback = warn);
+
+ /// Helper to allow for parsing of an entire .debug_line section in sequence.
+ class SectionParser {
+ public:
+ using cu_range = DWARFUnitSection<DWARFCompileUnit>::iterator_range;
+ using tu_range =
+ iterator_range<std::deque<DWARFUnitSection<DWARFTypeUnit>>::iterator>;
+ using LineToUnitMap = std::map<uint64_t, DWARFUnit *>;
+
+ SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, cu_range CUs,
+ tu_range TUs);
+
+ /// Get the next line table from the section. Report any issues via the
+ /// callbacks.
+ ///
+ /// \param RecoverableErrorCallback - any issues that don't prevent further
+ /// parsing of the table will be reported through this callback.
+ /// \param UnrecoverableErrorCallback - any issues that prevent further
+ /// parsing of the table will be reported through this callback.
+ /// \param OS - if not null, the parser will print information about the
+ /// table as it parses it.
+ LineTable
+ parseNext(function_ref<void(Error)> RecoverableErrorCallback = warn,
+ function_ref<void(Error)> UnrecoverableErrorCallback = warn,
+ raw_ostream *OS = nullptr);
+
+ /// Skip the current line table and go to the following line table (if
+ /// present) immediately.
+ ///
+ /// \param ErrorCallback - report any prologue parsing issues via this
+ /// callback.
+ void skip(function_ref<void(Error)> ErrorCallback = warn);
+
+ /// Indicates if the parser has parsed as much as possible.
+ ///
+ /// \note Certain problems with the line table structure might mean that
+ /// parsing stops before the end of the section is reached.
+ bool done() const { return Done; }
+
+ /// Get the offset the parser has reached.
+ uint32_t getOffset() const { return Offset; }
+
+ private:
+ DWARFUnit *prepareToParse(uint32_t Offset);
+ void moveToNextTable(uint32_t OldOffset, const Prologue &P);
+
+ LineToUnitMap LineToUnit;
+
+ DWARFDataExtractor &DebugLineData;
+ const DWARFContext &Context;
+ uint32_t Offset = 0;
+ bool Done = false;
+ };
+
+ /// Helper function for DWARFDebugLine parse functions, to report issues
+ /// identified during parsing.
+ ///
+ /// \param Err The Error to report.
+ static void warn(Error Err);
private:
struct ParsingState {
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
index a6d319a90457..9a73745fb6b4 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
@@ -42,7 +42,8 @@ public:
SmallVector<Entry, 2> Entries;
/// Dump this list on OS.
void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize,
- const MCRegisterInfo *MRI, unsigned Indent) const;
+ const MCRegisterInfo *MRI, uint64_t BaseAddress,
+ unsigned Indent) const;
};
private:
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h b/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
index 761871dc6255..cae4804e61d3 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
@@ -32,7 +32,7 @@ public:
/// The name of the object as given by the DW_AT_name attribute of the
/// referenced DIE.
- const char *Name;
+ StringRef Name;
};
/// Each table consists of sets of variable length entries. Each set describes
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
index f9ec96366a53..ce7436d9faa3 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
@@ -10,8 +10,8 @@
#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H
#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H
+#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
-#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include <cassert>
#include <cstdint>
#include <vector>
@@ -21,47 +21,6 @@ namespace llvm {
struct BaseAddress;
class raw_ostream;
-struct DWARFAddressRange {
- uint64_t LowPC;
- uint64_t HighPC;
- uint64_t SectionIndex;
-
- DWARFAddressRange() = default;
-
- /// Used for unit testing.
- DWARFAddressRange(uint64_t LowPC, uint64_t HighPC, uint64_t SectionIndex = 0)
- : LowPC(LowPC), HighPC(HighPC), SectionIndex(SectionIndex) {}
-
- /// Returns true if LowPC is smaller or equal to HighPC. This accounts for
- /// dead-stripped ranges.
- bool valid() const { return LowPC <= HighPC; }
-
- /// Returns true if [LowPC, HighPC) intersects with [RHS.LowPC, RHS.HighPC).
- bool intersects(const DWARFAddressRange &RHS) const {
- // Empty ranges can't intersect.
- if (LowPC == HighPC || RHS.LowPC == RHS.HighPC)
- return false;
- return (LowPC < RHS.HighPC) && (HighPC > RHS.LowPC);
- }
-
- /// Returns true if [LowPC, HighPC) fully contains [RHS.LowPC, RHS.HighPC).
- bool contains(const DWARFAddressRange &RHS) const {
- if (LowPC <= RHS.LowPC && RHS.LowPC <= HighPC)
- return LowPC <= RHS.HighPC && RHS.HighPC <= HighPC;
- return false;
- }
-};
-
-static inline bool operator<(const DWARFAddressRange &LHS,
- const DWARFAddressRange &RHS) {
- return std::tie(LHS.LowPC, LHS.HighPC) < std::tie(RHS.LowPC, RHS.HighPC);
-}
-
-raw_ostream &operator<<(raw_ostream &OS, const DWARFAddressRange &R);
-
-/// DWARFAddressRangesVector - represents a set of absolute address ranges.
-using DWARFAddressRangesVector = std::vector<DWARFAddressRange>;
-
class DWARFDebugRangeList {
public:
struct RangeListEntry {
@@ -112,7 +71,7 @@ public:
void clear();
void dump(raw_ostream &OS) const;
- bool extract(const DWARFDataExtractor &data, uint32_t *offset_ptr);
+ Error extract(const DWARFDataExtractor &data, uint32_t *offset_ptr);
const std::vector<RangeListEntry> &getEntries() { return Entries; }
/// getAbsoluteRanges - Returns absolute address ranges defined by this range
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
new file mode 100644
index 000000000000..e2e8ab5ed219
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
@@ -0,0 +1,60 @@
+//===- DWARFDebugRnglists.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H
+#define LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H
+
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFListTable.h"
+#include <cstdint>
+#include <map>
+#include <vector>
+
+namespace llvm {
+
+class Error;
+class raw_ostream;
+
+/// A class representing a single range list entry.
+struct RangeListEntry : public DWARFListEntryBase {
+ /// The values making up the range list entry. Most represent a range with
+ /// a start and end address or a start address and a length. Others are
+ /// single value base addresses or end-of-list with no values. The unneeded
+ /// values are semantically undefined, but initialized to 0.
+ uint64_t Value0;
+ uint64_t Value1;
+
+ Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr);
+ void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
+ uint64_t &CurrentBase, DIDumpOptions DumpOpts) const;
+ bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; }
+};
+
+/// A class representing a single rangelist.
+class DWARFDebugRnglist : public DWARFListType<RangeListEntry> {
+public:
+ /// Build a DWARFAddressRangesVector from a rangelist.
+ DWARFAddressRangesVector
+ getAbsoluteRanges(llvm::Optional<BaseAddress> BaseAddr) const;
+};
+
+class DWARFDebugRnglistTable : public DWARFListTableBase<DWARFDebugRnglist> {
+public:
+ DWARFDebugRnglistTable()
+ : DWARFListTableBase(/* SectionName = */ ".debug_rnglists",
+ /* HeaderString = */ "ranges:",
+ /* ListTypeString = */ "range") {}
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDie.h b/include/llvm/DebugInfo/DWARF/DWARFDie.h
index 75fc5995c5b2..6e6b57cbcbd4 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDie.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDie.h
@@ -16,9 +16,9 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFAttribute.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include <cassert>
#include <cstdint>
#include <iterator>
@@ -104,12 +104,24 @@ public:
/// invalid DWARFDie instance if it doesn't.
DWARFDie getSibling() const;
+ /// Get the previous sibling of this DIE object.
+ ///
+ /// \returns a valid DWARFDie instance if this object has a sibling or an
+ /// invalid DWARFDie instance if it doesn't.
+ DWARFDie getPreviousSibling() const;
+
/// Get the first child of this DIE object.
///
/// \returns a valid DWARFDie instance if this object has children or an
/// invalid DWARFDie instance if it doesn't.
DWARFDie getFirstChild() const;
+ /// Get the last child of this DIE object.
+ ///
+ /// \returns a valid null DWARFDie instance if this object has children or an
+ /// invalid DWARFDie instance if it doesn't.
+ DWARFDie getLastChild() const;
+
/// Dump the DIE and all of its attributes to the supplied stream.
///
/// \param OS the stream to use for output.
@@ -207,7 +219,7 @@ public:
///
/// \returns a address range vector that might be empty if no address range
/// information is available.
- DWARFAddressRangesVector getAddressRanges() const;
+ Expected<DWARFAddressRangesVector> getAddressRanges() const;
/// Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any
/// of its children.
@@ -288,6 +300,7 @@ public:
explicit attribute_iterator(DWARFDie D, bool End);
attribute_iterator &operator++();
+ attribute_iterator &operator--();
explicit operator bool() const { return AttrValue.isValid(); }
const DWARFAttribute &operator*() const { return AttrValue; }
bool operator==(const attribute_iterator &X) const { return Index == X.Index; }
@@ -306,26 +319,23 @@ inline bool operator<(const DWARFDie &LHS, const DWARFDie &RHS) {
return LHS.getOffset() < RHS.getOffset();
}
-class DWARFDie::iterator : public iterator_facade_base<iterator,
- std::forward_iterator_tag,
- const DWARFDie> {
+class DWARFDie::iterator
+ : public iterator_facade_base<iterator, std::bidirectional_iterator_tag,
+ const DWARFDie> {
DWARFDie Die;
- void skipNull() {
- if (Die && Die.isNULL())
- Die = DWARFDie();
- }
public:
iterator() = default;
explicit iterator(DWARFDie D) : Die(D) {
- // If we start out with only a Null DIE then invalidate.
- skipNull();
}
iterator &operator++() {
Die = Die.getSibling();
- // Don't include the NULL die when iterating.
- skipNull();
+ return *this;
+ }
+
+ iterator &operator--() {
+ Die = Die.getPreviousSibling();
return *this;
}
@@ -341,7 +351,7 @@ inline DWARFDie::iterator DWARFDie::begin() const {
}
inline DWARFDie::iterator DWARFDie::end() const {
- return iterator();
+ return iterator(getLastChild());
}
inline iterator_range<DWARFDie::iterator> DWARFDie::children() const {
diff --git a/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/include/llvm/DebugInfo/DWARF/DWARFExpression.h
index dcd486f3fb13..3fad68a9b48b 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFExpression.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFExpression.h
@@ -93,12 +93,13 @@ public:
/// An iterator to go through the expression operations.
class iterator
- : public iterator_facade_base<iterator, std::forward_iterator_tag, Operation> {
+ : public iterator_facade_base<iterator, std::forward_iterator_tag,
+ Operation> {
friend class DWARFExpression;
- DWARFExpression *Expr;
+ const DWARFExpression *Expr;
uint32_t Offset;
Operation Op;
- iterator(DWARFExpression *Expr, uint32_t Offset)
+ iterator(const DWARFExpression *Expr, uint32_t Offset)
: Expr(Expr), Offset(Offset) {
Op.Error =
Offset >= Expr->Data.getData().size() ||
@@ -127,10 +128,11 @@ public:
assert(AddressSize == 8 || AddressSize == 4);
}
- iterator begin() { return iterator(this, 0); }
- iterator end() { return iterator(this, Data.getData().size()); }
+ iterator begin() const { return iterator(this, 0); }
+ iterator end() const { return iterator(this, Data.getData().size()); }
- void print(raw_ostream &OS, const MCRegisterInfo *RegInfo);
+ void print(raw_ostream &OS, const MCRegisterInfo *RegInfo,
+ bool IsEH = false) const;
private:
DataExtractor Data;
diff --git a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
index d32053519ec4..1b5f71c946f9 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
@@ -20,38 +20,10 @@
namespace llvm {
+class DWARFContext;
class DWARFUnit;
class raw_ostream;
-/// A helper struct for DWARFFormValue methods, providing information that
-/// allows it to know the byte size of DW_FORM values that vary in size
-/// depending on the DWARF version, address byte size, or DWARF32/DWARF64.
-struct DWARFFormParams {
- uint16_t Version;
- uint8_t AddrSize;
- dwarf::DwarfFormat Format;
-
- /// The definition of the size of form DW_FORM_ref_addr depends on the
- /// version. In DWARF v2 it's the size of an address; after that, it's the
- /// size of a reference.
- uint8_t getRefAddrByteSize() const {
- if (Version == 2)
- return AddrSize;
- return getDwarfOffsetByteSize();
- }
-
- /// The size of a reference is determined by the DWARF 32/64-bit format.
- uint8_t getDwarfOffsetByteSize() const {
- switch (Format) {
- case dwarf::DwarfFormat::DWARF32:
- return 4;
- case dwarf::DwarfFormat::DWARF64:
- return 8;
- }
- llvm_unreachable("Invalid Format value");
- }
-};
-
class DWARFFormValue {
public:
enum FormClass {
@@ -83,7 +55,7 @@ private:
dwarf::Form Form; /// Form for this value.
ValueType Value; /// Contains all data for the form.
const DWARFUnit *U = nullptr; /// Remember the DWARFUnit at extract time.
-
+ const DWARFContext *C = nullptr; /// Context for extract time.
public:
DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F) {}
@@ -106,10 +78,17 @@ public:
/// Extracts a value in \p Data at offset \p *OffsetPtr. The information
/// in \p FormParams is needed to interpret some forms. The optional
- /// \p Unit allows extracting information if the form refers to other
- /// sections (e.g., .debug_str).
+ /// \p Context and \p Unit allows extracting information if the form refers
+ /// to other sections (e.g., .debug_str).
bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr,
- DWARFFormParams FormParams, const DWARFUnit *U = nullptr);
+ dwarf::FormParams FormParams,
+ const DWARFContext *Context = nullptr,
+ const DWARFUnit *Unit = nullptr);
+
+ bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr,
+ dwarf::FormParams FormParams, const DWARFUnit *U) {
+ return extractValue(Data, OffsetPtr, FormParams, nullptr, U);
+ }
bool isInlinedCStr() const {
return Value.data != nullptr && Value.data == (const uint8_t *)Value.cstr;
@@ -127,19 +106,6 @@ public:
Optional<uint64_t> getAsCStringOffset() const;
Optional<uint64_t> getAsReferenceUVal() const;
- /// Get the fixed byte size for a given form.
- ///
- /// If the form has a fixed byte size, then an Optional with a value will be
- /// returned. If the form is always encoded using a variable length storage
- /// format (ULEB or SLEB numbers or blocks) then None will be returned.
- ///
- /// \param Form DWARF form to get the fixed byte size for.
- /// \param FormParams DWARF parameters to help interpret forms.
- /// \returns Optional<uint8_t> value with the fixed byte size or None if
- /// \p Form doesn't have a fixed byte size.
- static Optional<uint8_t> getFixedByteSize(dwarf::Form Form,
- const DWARFFormParams FormParams);
-
/// Skip a form's value in \p DebugInfoData at the offset specified by
/// \p OffsetPtr.
///
@@ -150,7 +116,7 @@ public:
/// \param Params DWARF parameters to help interpret forms.
/// \returns true on success, false if the form was not skipped.
bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr,
- const DWARFFormParams Params) const {
+ const dwarf::FormParams Params) const {
return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, Params);
}
@@ -165,7 +131,8 @@ public:
/// \param FormParams DWARF parameters to help interpret forms.
/// \returns true on success, false if the form was not skipped.
static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
- uint32_t *OffsetPtr, const DWARFFormParams FormParams);
+ uint32_t *OffsetPtr,
+ const dwarf::FormParams FormParams);
private:
void dumpString(raw_ostream &OS) const;
diff --git a/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/include/llvm/DebugInfo/DWARF/DWARFListTable.h
new file mode 100644
index 000000000000..ab12f3bc08b0
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARF/DWARFListTable.h
@@ -0,0 +1,278 @@
+//===- DWARFListTable.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFLISTTABLE_H
+#define LLVM_DEBUGINFO_DWARFLISTTABLE_H
+
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+#include <map>
+#include <vector>
+
+namespace llvm {
+
+/// A base class for DWARF list entries, such as range or location list
+/// entries.
+struct DWARFListEntryBase {
+ /// The offset at which the entry is located in the section.
+ uint32_t Offset;
+ /// The DWARF encoding (DW_RLE_* or DW_LLE_*).
+ uint8_t EntryKind;
+ /// The index of the section this entry belongs to.
+ uint64_t SectionIndex;
+};
+
+/// A base class for lists of entries that are extracted from a particular
+/// section, such as range lists or location lists.
+template <typename ListEntryType> class DWARFListType {
+ using EntryType = ListEntryType;
+ using ListEntries = std::vector<EntryType>;
+
+protected:
+ ListEntries Entries;
+
+public:
+ // FIXME: We need to consolidate the various verions of "createError"
+ // that are used in the DWARF consumer. Until then, this is a workaround.
+ Error createError(const char *, const char *, uint32_t);
+
+ const ListEntries &getEntries() const { return Entries; }
+ bool empty() const { return Entries.empty(); }
+ void clear() { Entries.clear(); }
+ Error extract(DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End,
+ uint32_t *OffsetPtr, StringRef SectionName,
+ StringRef ListStringName);
+};
+
+/// A class representing the header of a list table such as the range list
+/// table in the .debug_rnglists section.
+class DWARFListTableHeader {
+ struct Header {
+ /// The total length of the entries for this table, not including the length
+ /// field itself.
+ uint32_t Length = 0;
+ /// The DWARF version number.
+ uint16_t Version;
+ /// The size in bytes of an address on the target architecture. For
+ /// segmented addressing, this is the size of the offset portion of the
+ /// address.
+ uint8_t AddrSize;
+ /// The size in bytes of a segment selector on the target architecture.
+ /// If the target system uses a flat address space, this value is 0.
+ uint8_t SegSize;
+ /// The number of offsets that follow the header before the range lists.
+ uint32_t OffsetEntryCount;
+ };
+
+ Header HeaderData;
+ /// The offset table, which contains offsets to the individual list entries.
+ /// It is used by forms such as DW_FORM_rnglistx.
+ /// FIXME: Generate the table and use the appropriate forms.
+ std::vector<uint32_t> Offsets;
+ /// The table's format, either DWARF32 or DWARF64.
+ dwarf::DwarfFormat Format;
+ /// The offset at which the header (and hence the table) is located within
+ /// its section.
+ uint32_t HeaderOffset;
+ /// The name of the section the list is located in.
+ StringRef SectionName;
+ /// A characterization of the list for dumping purposes, e.g. "range" or
+ /// "location".
+ StringRef ListTypeString;
+
+public:
+ DWARFListTableHeader(StringRef SectionName, StringRef ListTypeString)
+ : SectionName(SectionName), ListTypeString(ListTypeString) {}
+
+ void clear() {
+ HeaderData = {};
+ Offsets.clear();
+ }
+ uint32_t getHeaderOffset() const { return HeaderOffset; }
+ uint8_t getAddrSize() const { return HeaderData.AddrSize; }
+ uint32_t getLength() const { return HeaderData.Length; }
+ StringRef getSectionName() const { return SectionName; }
+ StringRef getListTypeString() const { return ListTypeString; }
+ dwarf::DwarfFormat getFormat() const { return Format; }
+
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
+ Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
+ if (Index < Offsets.size())
+ return Offsets[Index];
+ return None;
+ }
+
+ /// Extract the table header and the array of offsets.
+ Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
+
+ /// Returns the length of the table, including the length field, or 0 if the
+ /// length has not been determined (e.g. because the table has not yet been
+ /// parsed, or there was a problem in parsing).
+ uint32_t length() const;
+};
+
+/// A class representing a table of lists as specified in the DWARF v5
+/// standard for location lists and range lists. The table consists of a header
+/// followed by an array of offsets into a DWARF section, followed by zero or
+/// more list entries. The list entries are kept in a map where the keys are
+/// the lists' section offsets.
+template <typename DWARFListType> class DWARFListTableBase {
+ DWARFListTableHeader Header;
+ /// A mapping between file offsets and lists. It is used to find a particular
+ /// list based on an offset (obtained from DW_AT_ranges, for example).
+ std::map<uint32_t, DWARFListType> ListMap;
+ /// This string is displayed as a heading before the list is dumped
+ /// (e.g. "ranges:").
+ StringRef HeaderString;
+
+protected:
+ DWARFListTableBase(StringRef SectionName, StringRef HeaderString,
+ StringRef ListTypeString)
+ : Header(SectionName, ListTypeString), HeaderString(HeaderString) {}
+
+public:
+ void clear() {
+ Header.clear();
+ ListMap.clear();
+ }
+ /// Extract the table header and the array of offsets.
+ Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint32_t *OffsetPtr) {
+ return Header.extract(Data, OffsetPtr);
+ }
+ /// Extract an entire table, including all list entries.
+ Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
+ /// Look up a list based on a given offset. Extract it and enter it into the
+ /// list map if necessary.
+ Expected<DWARFListType> findList(DWARFDataExtractor Data, uint32_t Offset);
+
+ uint32_t getHeaderOffset() const { return Header.getHeaderOffset(); }
+ uint8_t getAddrSize() const { return Header.getAddrSize(); }
+
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
+
+ /// Return the contents of the offset entry designated by a given index.
+ Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
+ return Header.getOffsetEntry(Index);
+ }
+ /// Return the size of the table header including the length but not including
+ /// the offsets. This is dependent on the table format, which is unambiguously
+ /// derived from parsing the table.
+ uint8_t getHeaderSize() const {
+ switch (Header.getFormat()) {
+ case dwarf::DwarfFormat::DWARF32:
+ return 12;
+ case dwarf::DwarfFormat::DWARF64:
+ return 20;
+ }
+ llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64");
+ }
+
+ uint32_t length() { return Header.length(); }
+};
+
+template <typename DWARFListType>
+Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data,
+ uint32_t *OffsetPtr) {
+ clear();
+ if (Error E = extractHeaderAndOffsets(Data, OffsetPtr))
+ return E;
+
+ Data.setAddressSize(Header.getAddrSize());
+ uint32_t End = getHeaderOffset() + Header.length();
+ while (*OffsetPtr < End) {
+ DWARFListType CurrentList;
+ uint32_t Off = *OffsetPtr;
+ if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr,
+ Header.getSectionName(),
+ Header.getListTypeString()))
+ return E;
+ ListMap[Off] = CurrentList;
+ }
+
+ assert(*OffsetPtr == End &&
+ "mismatch between expected length of table and length "
+ "of extracted data");
+ return Error::success();
+}
+
+template <typename ListEntryType>
+Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data,
+ uint32_t HeaderOffset, uint32_t End,
+ uint32_t *OffsetPtr,
+ StringRef SectionName,
+ StringRef ListTypeString) {
+ if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End)
+ return createError("invalid %s list offset 0x%" PRIx32,
+ ListTypeString.data(), *OffsetPtr);
+ Entries.clear();
+ while (*OffsetPtr < End) {
+ ListEntryType Entry;
+ if (Error E = Entry.extract(Data, End, OffsetPtr))
+ return E;
+ Entries.push_back(Entry);
+ if (Entry.isSentinel())
+ return Error::success();
+ }
+ return createError("no end of list marker detected at end of %s table "
+ "starting at offset 0x%" PRIx32,
+ SectionName.data(), HeaderOffset);
+}
+
+template <typename DWARFListType>
+void DWARFListTableBase<DWARFListType>::dump(raw_ostream &OS,
+ DIDumpOptions DumpOpts) const {
+ Header.dump(OS, DumpOpts);
+ OS << HeaderString << "\n";
+
+ // Determine the length of the longest encoding string we have in the table,
+ // so we can align the output properly. We only need this in verbose mode.
+ size_t MaxEncodingStringLength = 0;
+ if (DumpOpts.Verbose) {
+ for (const auto &List : ListMap)
+ for (const auto &Entry : List.second.getEntries())
+ MaxEncodingStringLength =
+ std::max(MaxEncodingStringLength,
+ dwarf::RangeListEncodingString(Entry.EntryKind).size());
+ }
+
+ uint64_t CurrentBase = 0;
+ for (const auto &List : ListMap)
+ for (const auto &Entry : List.second.getEntries())
+ Entry.dump(OS, getAddrSize(), MaxEncodingStringLength, CurrentBase,
+ DumpOpts);
+}
+
+template <typename DWARFListType>
+Expected<DWARFListType>
+DWARFListTableBase<DWARFListType>::findList(DWARFDataExtractor Data,
+ uint32_t Offset) {
+ auto Entry = ListMap.find(Offset);
+ if (Entry != ListMap.end())
+ return Entry->second;
+
+ // Extract the list from the section and enter it into the list map.
+ DWARFListType List;
+ uint32_t End = getHeaderOffset() + Header.length();
+ uint32_t StartingOffset = Offset;
+ if (Error E =
+ List.extract(Data, getHeaderOffset(), End, &Offset,
+ Header.getSectionName(), Header.getListTypeString()))
+ return std::move(E);
+ ListMap[StartingOffset] = List;
+ return List;
+}
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFLISTTABLE_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFObject.h b/include/llvm/DebugInfo/DWARF/DWARFObject.h
index 167eb2da5ba0..6e8f370f4aea 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFObject.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFObject.h
@@ -42,8 +42,10 @@ public:
virtual StringRef getDebugFrameSection() const { return ""; }
virtual StringRef getEHFrameSection() const { return ""; }
virtual const DWARFSection &getLineSection() const { return Dummy; }
+ virtual StringRef getLineStringSection() const { return ""; }
virtual StringRef getStringSection() const { return ""; }
virtual const DWARFSection &getRangeSection() const { return Dummy; }
+ virtual const DWARFSection &getRnglistsSection() const { return Dummy; }
virtual StringRef getMacinfoSection() const { return ""; }
virtual StringRef getPubNamesSection() const { return ""; }
virtual StringRef getPubTypesSection() const { return ""; }
@@ -61,12 +63,14 @@ public:
return Dummy;
}
virtual const DWARFSection &getRangeDWOSection() const { return Dummy; }
+ virtual const DWARFSection &getRnglistsDWOSection() const { return Dummy; }
virtual const DWARFSection &getAddrSection() const { return Dummy; }
virtual const DWARFSection &getAppleNamesSection() const { return Dummy; }
virtual const DWARFSection &getAppleTypesSection() const { return Dummy; }
virtual const DWARFSection &getAppleNamespacesSection() const {
return Dummy;
}
+ virtual const DWARFSection &getDebugNamesSection() const { return Dummy; }
virtual const DWARFSection &getAppleObjCSection() const { return Dummy; }
virtual StringRef getCUIndexSection() const { return ""; }
virtual StringRef getGdbIndexSection() const { return ""; }
diff --git a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
index a7842454f435..cb5a78ee3dbf 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
@@ -24,29 +24,21 @@ struct DWARFSection;
class raw_ostream;
class DWARFTypeUnit : public DWARFUnit {
-private:
- uint64_t TypeHash;
- uint32_t TypeOffset;
-
public:
DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFUnitHeader &Header,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
const DWARFSection &LS, bool LE, bool IsDWO,
- const DWARFUnitSectionBase &UnitSection,
- const DWARFUnitIndex::Entry *Entry)
- : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
- UnitSection, Entry) {}
+ const DWARFUnitSectionBase &UnitSection)
+ : DWARFUnit(Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
+ UnitSection) {}
- uint32_t getHeaderSize() const override {
- return DWARFUnit::getHeaderSize() + 12;
- }
+ uint64_t getTypeHash() const { return getHeader().getTypeHash(); }
+ uint32_t getTypeOffset() const { return getHeader().getTypeOffset(); }
void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {});
static const DWARFSectionKind Section = DW_SECT_TYPES;
-
-protected:
- bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override;
};
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index 3cec58383f87..988a7958184c 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -18,6 +18,7 @@
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
@@ -40,6 +41,66 @@ class DWARFContext;
class DWARFDebugAbbrev;
class DWARFUnit;
+/// Base class describing the header of any kind of "unit." Some information
+/// is specific to certain unit types. We separate this class out so we can
+/// parse the header before deciding what specific kind of unit to construct.
+class DWARFUnitHeader {
+ // Offset within section.
+ uint32_t Offset = 0;
+ // Version, address size, and DWARF format.
+ dwarf::FormParams FormParams;
+ uint32_t Length = 0;
+ uint64_t AbbrOffset = 0;
+
+ // For DWO units only.
+ const DWARFUnitIndex::Entry *IndexEntry = nullptr;
+
+ // For type units only.
+ uint64_t TypeHash = 0;
+ uint32_t TypeOffset = 0;
+
+ // For v5 split or skeleton compile units only.
+ Optional<uint64_t> DWOId;
+
+ // Unit type as parsed, or derived from the section kind.
+ uint8_t UnitType = 0;
+
+ // Size as parsed. uint8_t for compactness.
+ uint8_t Size = 0;
+
+public:
+ /// Parse a unit header from \p debug_info starting at \p offset_ptr.
+ bool extract(DWARFContext &Context, const DWARFDataExtractor &debug_info,
+ uint32_t *offset_ptr, DWARFSectionKind Kind = DW_SECT_INFO,
+ const DWARFUnitIndex *Index = nullptr);
+ uint32_t getOffset() const { return Offset; }
+ const dwarf::FormParams &getFormParams() const { return FormParams; }
+ uint16_t getVersion() const { return FormParams.Version; }
+ dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
+ uint8_t getAddressByteSize() const { return FormParams.AddrSize; }
+ uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); }
+ uint8_t getDwarfOffsetByteSize() const {
+ return FormParams.getDwarfOffsetByteSize();
+ }
+ uint32_t getLength() const { return Length; }
+ uint64_t getAbbrOffset() const { return AbbrOffset; }
+ Optional<uint64_t> getDWOId() const { return DWOId; }
+ void setDWOId(uint64_t Id) {
+ assert((!DWOId || *DWOId == Id) && "setting DWOId to a different value");
+ DWOId = Id;
+ }
+ const DWARFUnitIndex::Entry *getIndexEntry() const { return IndexEntry; }
+ uint64_t getTypeHash() const { return TypeHash; }
+ uint32_t getTypeOffset() const { return TypeOffset; }
+ uint8_t getUnitType() const { return UnitType; }
+ bool isTypeUnit() const {
+ return UnitType == dwarf::DW_UT_type || UnitType == dwarf::DW_UT_split_type;
+ }
+ uint8_t getSize() const { return Size; }
+ // FIXME: Support DWARF64.
+ uint32_t getNextUnitOffset() const { return Offset + Length + 4; }
+};
+
/// Base class for all DWARFUnitSection classes. This provides the
/// functionality common to all unit types.
class DWARFUnitSectionBase {
@@ -56,7 +117,8 @@ public:
protected:
~DWARFUnitSectionBase() = default;
- virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section,
+ virtual void parseImpl(DWARFContext &Context, const DWARFObject &Obj,
+ const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, const DWARFSection &SOS,
const DWARFSection *AOS, const DWARFSection &LS,
@@ -116,14 +178,14 @@ public:
}
private:
- void parseImpl(DWARFContext &Context, const DWARFSection &Section,
- const DWARFDebugAbbrev *DA, const DWARFSection *RS,
- StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
- const DWARFSection &LS, bool LE, bool IsDWO,
- bool Lazy) override {
+ void parseImpl(DWARFContext &Context, const DWARFObject &Obj,
+ const DWARFSection &Section, const DWARFDebugAbbrev *DA,
+ const DWARFSection *RS, StringRef SS, const DWARFSection &SOS,
+ const DWARFSection *AOS, const DWARFSection &LS, bool LE,
+ bool IsDWO, bool Lazy) override {
if (Parsed)
return;
- DataExtractor Data(Section.Data, LE, 0);
+ DWARFDataExtractor Data(Obj, Section, LE, 0);
if (!Parser) {
const DWARFUnitIndex *Index = nullptr;
if (IsDWO)
@@ -132,11 +194,12 @@ private:
&LS](uint32_t Offset) -> std::unique_ptr<UnitType> {
if (!Data.isValidOffset(Offset))
return nullptr;
- auto U = llvm::make_unique<UnitType>(
- Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, *this,
- Index ? Index->getFromOffset(Offset) : nullptr);
- if (!U->extract(Data, &Offset))
+ DWARFUnitHeader Header;
+ if (!Header.extract(Context, Data, &Offset, UnitType::Section, Index))
return nullptr;
+ auto U = llvm::make_unique<UnitType>(
+ Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
+ *this);
return U;
};
}
@@ -168,9 +231,10 @@ struct BaseAddress {
/// Represents a unit's contribution to the string offsets table.
struct StrOffsetsContributionDescriptor {
uint64_t Base = 0;
+ /// The contribution size not including the header.
uint64_t Size = 0;
/// Format and version.
- DWARFFormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32};
+ dwarf::FormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32};
StrOffsetsContributionDescriptor(uint64_t Base, uint64_t Size,
uint8_t Version, dwarf::DwarfFormat Format)
@@ -193,6 +257,7 @@ class DWARFUnit {
/// Section containing this DWARFUnit.
const DWARFSection &InfoSection;
+ DWARFUnitHeader Header;
const DWARFDebugAbbrev *Abbrev;
const DWARFSection *RangeSection;
uint32_t RangeSectionBase;
@@ -205,63 +270,28 @@ class DWARFUnit {
bool isDWO;
const DWARFUnitSectionBase &UnitSection;
- // Version, address size, and DWARF format.
- DWARFFormParams FormParams;
/// Start, length, and DWARF format of the unit's contribution to the string
/// offsets table (DWARF v5).
Optional<StrOffsetsContributionDescriptor> StringOffsetsTableContribution;
- uint32_t Offset;
- uint32_t Length;
+ /// A table of range lists (DWARF v5 and later).
+ Optional<DWARFDebugRnglistTable> RngListTable;
+
mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
- uint64_t AbbrOffset;
- uint8_t UnitType;
llvm::Optional<BaseAddress> BaseAddr;
/// The compile unit debug information entry items.
std::vector<DWARFDebugInfoEntry> DieArray;
- /// The vector of inlined subroutine DIEs that we can map directly to from
- /// their subprogram below.
- std::vector<DWARFDie> InlinedSubroutineDIEs;
-
- /// A type representing a subprogram DIE and a map (built using a sorted
- /// vector) into that subprogram's inlined subroutine DIEs.
- struct SubprogramDIEAddrInfo {
- DWARFDie SubprogramDIE;
-
- uint64_t SubprogramBasePC;
-
- /// A vector sorted to allow mapping from a relative PC to the inlined
- /// subroutine DIE with the most specific address range covering that PC.
- ///
- /// The PCs are relative to the `SubprogramBasePC`.
- ///
- /// The vector is sorted in ascending order of the first int which
- /// represents the relative PC for an interval in the map. The second int
- /// represents the index into the `InlinedSubroutineDIEs` vector of the DIE
- /// that interval maps to. An index of '-1` indicates an empty mapping. The
- /// interval covered is from the `.first` relative PC to the next entry's
- /// `.first` relative PC.
- std::vector<std::pair<uint32_t, int32_t>> InlinedSubroutineDIEAddrMap;
- };
-
- /// Vector of the subprogram DIEs and their subroutine address maps.
- std::vector<SubprogramDIEAddrInfo> SubprogramDIEAddrInfos;
-
- /// A vector sorted to allow mapping from a PC to the subprogram DIE (and
- /// associated addr map) index. Subprograms with overlapping PC ranges aren't
- /// supported here. Nothing will crash, but the mapping may be inaccurate.
- /// This vector may also contain "empty" ranges marked by an address with
- /// a DIE index of '-1'.
- std::vector<std::pair<uint64_t, int64_t>> SubprogramDIEAddrMap;
+ /// Map from range's start address to end address and corresponding DIE.
+ /// IntervalMap does not support range removal, as a result, we use the
+ /// std::map::upper_bound for address range lookup.
+ std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap;
using die_iterator_range =
iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>;
std::shared_ptr<DWARFUnit> DWO;
- const DWARFUnitIndex::Entry *IndexEntry;
-
uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) {
auto First = DieArray.data();
assert(Die >= First && Die < First + DieArray.size());
@@ -269,10 +299,10 @@ class DWARFUnit {
}
protected:
- virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr);
+ const DWARFUnitHeader &getHeader() const { return Header; }
- /// Size in bytes of the unit header.
- virtual uint32_t getHeaderSize() const { return getVersion() <= 4 ? 11 : 12; }
+ /// Size in bytes of the parsed unit header.
+ uint32_t getHeaderSize() const { return Header.getSize(); }
/// Find the unit's contribution to the string offsets table and determine its
/// length and form. The given offset is expected to be derived from the unit
@@ -291,16 +321,28 @@ protected:
public:
DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFUnitHeader &Header,
const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS,
const DWARFSection &SOS, const DWARFSection *AOS,
const DWARFSection &LS, bool LE, bool IsDWO,
- const DWARFUnitSectionBase &UnitSection,
- const DWARFUnitIndex::Entry *IndexEntry = nullptr);
+ const DWARFUnitSectionBase &UnitSection);
virtual ~DWARFUnit();
DWARFContext& getContext() const { return Context; }
-
+ uint32_t getOffset() const { return Header.getOffset(); }
+ const dwarf::FormParams &getFormParams() const {
+ return Header.getFormParams();
+ }
+ uint16_t getVersion() const { return Header.getVersion(); }
+ uint8_t getAddressByteSize() const { return Header.getAddressByteSize(); }
+ uint8_t getRefAddrByteSize() const { return Header.getRefAddrByteSize(); }
+ uint8_t getDwarfOffsetByteSize() const {
+ return Header.getDwarfOffsetByteSize();
+ }
+ uint32_t getLength() const { return Header.getLength(); }
+ uint8_t getUnitType() const { return Header.getUnitType(); }
+ uint32_t getNextUnitOffset() const { return Header.getNextUnitOffset(); }
const DWARFSection &getLineSection() const { return LineSection; }
StringRef getStringSection() const { return StringSection; }
const DWARFSection &getStringOffsetSection() const {
@@ -312,6 +354,9 @@ public:
AddrOffsetSectionBase = Base;
}
+ /// Recursively update address to Die map.
+ void updateAddressDieMap(DWARFDie Die);
+
void setRangesSection(const DWARFSection *RS, uint32_t Base) {
RangeSection = RS;
RangeSectionBase = Base;
@@ -326,31 +371,18 @@ public:
return DataExtractor(StringSection, false, 0);
}
-
- bool extract(DataExtractor debug_info, uint32_t* offset_ptr);
-
- /// extractRangeList - extracts the range list referenced by this compile
- /// unit from .debug_ranges section. Returns true on success.
- /// Requires that compile unit is already extracted.
- bool extractRangeList(uint32_t RangeListOffset,
- DWARFDebugRangeList &RangeList) const;
+ /// Extract the range list referenced by this compile unit from the
+ /// .debug_ranges section. If the extraction is unsuccessful, an error
+ /// is returned. Successful extraction requires that the compile unit
+ /// has already been extracted.
+ Error extractRangeList(uint32_t RangeListOffset,
+ DWARFDebugRangeList &RangeList) const;
void clear();
- uint32_t getOffset() const { return Offset; }
- uint32_t getNextUnitOffset() const { return Offset + Length + 4; }
- uint32_t getLength() const { return Length; }
const Optional<StrOffsetsContributionDescriptor> &
getStringOffsetsTableContribution() const {
return StringOffsetsTableContribution;
}
- const DWARFFormParams &getFormParams() const { return FormParams; }
- uint16_t getVersion() const { return FormParams.Version; }
- dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
- uint8_t getAddressByteSize() const { return FormParams.AddrSize; }
- uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); }
- uint8_t getDwarfOffsetByteSize() const {
- return FormParams.getDwarfOffsetByteSize();
- }
uint8_t getDwarfStringOffsetsByteSize() const {
assert(StringOffsetsTableContribution);
@@ -364,8 +396,6 @@ public:
const DWARFAbbreviationDeclarationSet *getAbbreviations() const;
- uint8_t getUnitType() const { return UnitType; }
-
static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) {
switch (UnitType) {
case dwarf::DW_UT_compile:
@@ -383,7 +413,7 @@ public:
return false;
}
- /// \brief Return the number of bytes for the header of a unit of
+ /// Return the number of bytes for the header of a unit of
/// UnitType type.
///
/// This function must be called with a valid unit type which in
@@ -403,9 +433,7 @@ public:
llvm_unreachable("Invalid UnitType.");
}
- llvm::Optional<BaseAddress> getBaseAddress() const { return BaseAddr; }
-
- void setBaseAddress(BaseAddress BaseAddr) { this->BaseAddr = BaseAddr; }
+ llvm::Optional<BaseAddress> getBaseAddress();
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
extractDIEsIfNeeded(ExtractUnitDIEOnly);
@@ -415,7 +443,29 @@ public:
}
const char *getCompilationDir();
- Optional<uint64_t> getDWOId();
+ Optional<uint64_t> getDWOId() {
+ extractDIEsIfNeeded(/*CUDieOnly*/ true);
+ return getHeader().getDWOId();
+ }
+ void setDWOId(uint64_t NewID) { Header.setDWOId(NewID); }
+
+ /// Return a vector of address ranges resulting from a (possibly encoded)
+ /// range list starting at a given offset in the appropriate ranges section.
+ Expected<DWARFAddressRangesVector> findRnglistFromOffset(uint32_t Offset);
+
+ /// Return a vector of address ranges retrieved from an encoded range
+ /// list whose offset is found via a table lookup given an index (DWARF v5
+ /// and later).
+ Expected<DWARFAddressRangesVector> findRnglistFromIndex(uint32_t Index);
+
+ /// Return a rangelist's offset based on an index. The index designates
+ /// an entry in the rangelist table's offset array and is supplied by
+ /// DW_FORM_rnglistx.
+ Optional<uint32_t> getRnglistOffset(uint32_t Index) {
+ if (RngListTable)
+ return RngListTable->getOffsetEntry(Index);
+ return None;
+ }
void collectAddressRanges(DWARFAddressRangesVector &CURanges);
@@ -433,14 +483,14 @@ public:
/// getUnitSection - Return the DWARFUnitSection containing this unit.
const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; }
- /// \brief Returns the number of DIEs in the unit. Parses the unit
+ /// Returns the number of DIEs in the unit. Parses the unit
/// if necessary.
unsigned getNumDIEs() {
extractDIEsIfNeeded(false);
return DieArray.size();
}
- /// \brief Return the index of a DIE inside the unit's DIE vector.
+ /// Return the index of a DIE inside the unit's DIE vector.
///
/// It is illegal to call this method with a DIE that hasn't be
/// created by this unit. In other word, it's illegal to call this
@@ -450,7 +500,7 @@ public:
return getDIEIndex(D.getDebugInfoEntry());
}
- /// \brief Return the DIE object at the given index.
+ /// Return the DIE object at the given index.
DWARFDie getDIEAtIndex(unsigned Index) {
assert(Index < DieArray.size());
return DWARFDie(this, &DieArray[Index]);
@@ -458,9 +508,11 @@ public:
DWARFDie getParent(const DWARFDebugInfoEntry *Die);
DWARFDie getSibling(const DWARFDebugInfoEntry *Die);
+ DWARFDie getPreviousSibling(const DWARFDebugInfoEntry *Die);
DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die);
+ DWARFDie getLastChild(const DWARFDebugInfoEntry *Die);
- /// \brief Return the DIE object for a given offset inside the
+ /// Return the DIE object for a given offset inside the
/// unit's DIE vector.
///
/// The unit needs to have its DIEs extracted for this method to work.
@@ -478,7 +530,7 @@ public:
}
uint32_t getLineTableOffset() const {
- if (IndexEntry)
+ if (auto IndexEntry = Header.getIndexEntry())
if (const auto *Contrib = IndexEntry->getOffset(DW_SECT_LINE))
return Contrib->Offset;
return 0;
@@ -491,7 +543,9 @@ public:
private:
/// Size in bytes of the .debug_info data associated with this compile unit.
- size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); }
+ size_t getDebugInfoSize() const {
+ return Header.getLength() + 4 - getHeaderSize();
+ }
/// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
/// hasn't already been done. Returns the number of DIEs parsed at this call.
@@ -507,9 +561,6 @@ private:
/// parseDWO - Parses .dwo file for current compile unit. Returns true if
/// it was actually constructed.
bool parseDWO();
-
- void buildSubprogramDIEAddrMap();
- void buildInlinedSubroutineDIEAddrMap(SubprogramDIEAddrInfo &SPInfo);
};
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
index 0d920abe3231..a829510a219d 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
@@ -11,7 +11,8 @@
#define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
#include "llvm/DebugInfo/DIContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include <cstdint>
@@ -24,7 +25,7 @@ struct DWARFAttribute;
class DWARFContext;
class DWARFDie;
class DWARFUnit;
-class DWARFAcceleratorTable;
+class DWARFCompileUnit;
class DWARFDataExtractor;
class DWARFDebugAbbrev;
class DataExtractor;
@@ -109,7 +110,7 @@ private:
/// \param Abbrev Pointer to the abbreviations section we are verifying
/// Abbrev can be a pointer to either .debug_abbrev or debug_abbrev.dwo.
///
- /// \returns The number of errors that occured during verification.
+ /// \returns The number of errors that occurred during verification.
unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev);
/// Verifies the header of a unit in the .debug_info section.
@@ -151,14 +152,14 @@ private:
/// type of the unit DIE.
///
/// \returns true if the content is verified successfully, false otherwise.
- bool verifyUnitContents(DWARFUnit Unit, uint8_t UnitType = 0);
+ bool verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType = 0);
/// Verify that all Die ranges are valid.
///
/// This function currently checks for:
/// - cases in which lowPC >= highPC
///
- /// \returns Number of errors that occured during verification.
+ /// \returns Number of errors that occurred during verification.
unsigned verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI);
/// Verifies the attribute's DWARF attribute and its value.
@@ -170,7 +171,7 @@ private:
/// \param Die The DWARF DIE that owns the attribute value
/// \param AttrValue The DWARF attribute value to check
///
- /// \returns NumErrors The number of errors occured during verification of
+ /// \returns NumErrors The number of errors occurred during verification of
/// attributes' values in a .debug_info section unit
unsigned verifyDebugInfoAttribute(const DWARFDie &Die,
DWARFAttribute &AttrValue);
@@ -185,7 +186,7 @@ private:
/// \param Die The DWARF DIE that owns the attribute value
/// \param AttrValue The DWARF attribute value to check
///
- /// \returns NumErrors The number of errors occured during verification of
+ /// \returns NumErrors The number of errors occurred during verification of
/// attributes' forms in a .debug_info section unit
unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue);
@@ -197,11 +198,11 @@ private:
/// around, that it doesn't create invalid references by failing to relocate
/// CU relative and absolute references.
///
- /// \returns NumErrors The number of errors occured during verification of
+ /// \returns NumErrors The number of errors occurred during verification of
/// references for the .debug_info section
unsigned verifyDebugInfoReferences();
- /// Verify the the DW_AT_stmt_list encoding and value and ensure that no
+ /// Verify the DW_AT_stmt_list encoding and value and ensure that no
/// compile units that have the same DW_AT_stmt_list value.
void verifyDebugLineStmtOffsets();
@@ -228,9 +229,42 @@ private:
/// \param StrData pointer to the string section
/// \param SectionName the name of the table we're verifying
///
- /// \returns The number of errors occured during verification
- unsigned verifyAccelTable(const DWARFSection *AccelSection,
- DataExtractor *StrData, const char *SectionName);
+ /// \returns The number of errors occurred during verification
+ unsigned verifyAppleAccelTable(const DWARFSection *AccelSection,
+ DataExtractor *StrData,
+ const char *SectionName);
+
+ unsigned verifyDebugNamesCULists(const DWARFDebugNames &AccelTable);
+ unsigned verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI,
+ const DataExtractor &StrData);
+ unsigned verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI);
+ unsigned verifyNameIndexAttribute(const DWARFDebugNames::NameIndex &NI,
+ const DWARFDebugNames::Abbrev &Abbr,
+ DWARFDebugNames::AttributeEncoding AttrEnc);
+ unsigned verifyNameIndexEntries(const DWARFDebugNames::NameIndex &NI,
+ const DWARFDebugNames::NameTableEntry &NTE);
+ unsigned verifyNameIndexCompleteness(const DWARFDie &Die,
+ const DWARFDebugNames::NameIndex &NI);
+
+ /// Verify that the DWARF v5 accelerator table is valid.
+ ///
+ /// This function currently checks that:
+ /// - Headers individual Name Indices fit into the section and can be parsed.
+ /// - Abbreviation tables can be parsed and contain valid index attributes
+ /// with correct form encodings.
+ /// - The CU lists reference existing compile units.
+ /// - The buckets have a valid index, or they are empty.
+ /// - All names are reachable via the hash table (they have the correct hash,
+ /// and the hash is in the correct bucket).
+ /// - Information in the index entries is complete (all required entries are
+ /// present) and consistent with the debug_info section DIEs.
+ ///
+ /// \param AccelSection section containing the acceleration table
+ /// \param StrData string section
+ ///
+ /// \returns The number of errors occurred during verification
+ unsigned verifyDebugNames(const DWARFSection &AccelSection,
+ const DataExtractor &StrData);
public:
DWARFVerifier(raw_ostream &S, DWARFContext &D,