summaryrefslogtreecommitdiff
path: root/third_party/llvm-project/include/llvm/DebugInfo/DWARF
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/llvm-project/include/llvm/DebugInfo/DWARF')
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h183
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h599
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h61
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAttribute.h49
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h38
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFContext.h382
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h64
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h87
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h97
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h75
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h84
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h308
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h62
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h392
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h121
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h62
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h80
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h83
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h64
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDie.h468
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFExpression.h159
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFFormValue.h321
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h82
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFListTable.h290
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFObject.h85
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h38
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFSection.h27
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h46
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFUnit.h527
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h105
-rw-r--r--third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFVerifier.h336
31 files changed, 5375 insertions, 0 deletions
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
new file mode 100644
index 000000000..39ae53c4e
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
@@ -0,0 +1,183 @@
+//===- DWARFAbbreviationDeclaration.h ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
+#define LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/Support/DataExtractor.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+
+namespace llvm {
+
+class DWARFFormValue;
+class DWARFUnit;
+class raw_ostream;
+
+class DWARFAbbreviationDeclaration {
+public:
+ struct AttributeSpec {
+ AttributeSpec(dwarf::Attribute A, dwarf::Form F, int64_t Value)
+ : Attr(A), Form(F), Value(Value) {
+ assert(isImplicitConst());
+ }
+ AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<uint8_t> ByteSize)
+ : Attr(A), Form(F) {
+ assert(!isImplicitConst());
+ this->ByteSize.HasByteSize = ByteSize.hasValue();
+ if (this->ByteSize.HasByteSize)
+ this->ByteSize.ByteSize = *ByteSize;
+ }
+
+ dwarf::Attribute Attr;
+ dwarf::Form Form;
+
+ private:
+ /// The following field is used for ByteSize for non-implicit_const
+ /// attributes and as value for implicit_const ones, indicated by
+ /// Form == DW_FORM_implicit_const.
+ /// The following cases are distinguished:
+ /// * Form != DW_FORM_implicit_const and HasByteSize is true:
+ /// ByteSize contains the fixed size in bytes for the Form in this
+ /// object.
+ /// * Form != DW_FORM_implicit_const and HasByteSize is false:
+ /// byte size of Form either varies according to the DWARFUnit
+ /// that it is contained in or the value size varies and must be
+ /// decoded from the debug information in order to determine its size.
+ /// * Form == DW_FORM_implicit_const:
+ /// Value contains value for the implicit_const attribute.
+ struct ByteSizeStorage {
+ bool HasByteSize;
+ uint8_t ByteSize;
+ };
+ union {
+ ByteSizeStorage ByteSize;
+ int64_t Value;
+ };
+
+ public:
+ bool isImplicitConst() const {
+ return Form == dwarf::DW_FORM_implicit_const;
+ }
+
+ int64_t getImplicitConstValue() const {
+ assert(isImplicitConst());
+ return Value;
+ }
+
+ /// Get the fixed byte size of this Form if possible. This function might
+ /// use the DWARFUnit to calculate the size of the Form, like for
+ /// DW_AT_address and DW_AT_ref_addr, so this isn't just an accessor for
+ /// the ByteSize member.
+ Optional<int64_t> getByteSize(const DWARFUnit &U) const;
+ };
+ using AttributeSpecVector = SmallVector<AttributeSpec, 8>;
+
+ DWARFAbbreviationDeclaration();
+
+ uint32_t getCode() const { return Code; }
+ uint8_t getCodeByteSize() const { return CodeByteSize; }
+ dwarf::Tag getTag() const { return Tag; }
+ bool hasChildren() const { return HasChildren; }
+
+ using attr_iterator_range =
+ iterator_range<AttributeSpecVector::const_iterator>;
+
+ attr_iterator_range attributes() const {
+ return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end());
+ }
+
+ dwarf::Form getFormByIndex(uint32_t idx) const {
+ assert(idx < AttributeSpecs.size());
+ return AttributeSpecs[idx].Form;
+ }
+
+ size_t getNumAttributes() const {
+ return AttributeSpecs.size();
+ }
+
+ dwarf::Attribute getAttrByIndex(uint32_t idx) const {
+ assert(idx < AttributeSpecs.size());
+ return AttributeSpecs[idx].Attr;
+ }
+
+ /// Get the index of the specified attribute.
+ ///
+ /// Searches the this abbreviation declaration for the index of the specified
+ /// attribute.
+ ///
+ /// \param attr DWARF attribute to search for.
+ /// \returns Optional index of the attribute if found, None otherwise.
+ Optional<uint32_t> findAttributeIndex(dwarf::Attribute attr) const;
+
+ /// Extract a DWARF form value from a DIE specified by DIE offset.
+ ///
+ /// Extract an attribute value for a DWARFUnit given the DIE offset and the
+ /// attribute.
+ ///
+ /// \param DIEOffset the DIE offset that points to the ULEB128 abbreviation
+ /// code in the .debug_info data.
+ /// \param Attr DWARF attribute to search for.
+ /// \param U the DWARFUnit the contains the DIE.
+ /// \returns Optional DWARF form value if the attribute was extracted.
+ Optional<DWARFFormValue> getAttributeValue(const uint64_t DIEOffset,
+ const dwarf::Attribute Attr,
+ const DWARFUnit &U) const;
+
+ bool extract(DataExtractor Data, uint64_t* OffsetPtr);
+ void dump(raw_ostream &OS) const;
+
+ // Return an optional byte size of all attribute data in this abbreviation
+ // if a constant byte size can be calculated given a DWARFUnit. This allows
+ // DWARF parsing to be faster as many DWARF DIEs have a fixed byte size.
+ Optional<size_t> getFixedAttributesByteSize(const DWARFUnit &U) const;
+
+private:
+ void clear();
+
+ /// A helper structure that can quickly determine the size in bytes of an
+ /// abbreviation declaration.
+ struct FixedSizeInfo {
+ /// The fixed byte size for fixed size forms.
+ uint16_t NumBytes = 0;
+ /// Number of DW_FORM_address forms in this abbrevation declaration.
+ uint8_t NumAddrs = 0;
+ /// Number of DW_FORM_ref_addr forms in this abbrevation declaration.
+ uint8_t NumRefAddrs = 0;
+ /// Number of 4 byte in DWARF32 and 8 byte in DWARF64 forms.
+ uint8_t NumDwarfOffsets = 0;
+
+ FixedSizeInfo() = default;
+
+ /// Calculate the fixed size in bytes given a DWARFUnit.
+ ///
+ /// \param U the DWARFUnit to use when determing the byte size.
+ /// \returns the size in bytes for all attribute data in this abbreviation.
+ /// The returned size does not include bytes for the ULEB128 abbreviation
+ /// code
+ size_t getByteSize(const DWARFUnit &U) const;
+ };
+
+ uint32_t Code;
+ dwarf::Tag Tag;
+ uint8_t CodeByteSize;
+ bool HasChildren;
+ AttributeSpecVector AttributeSpecs;
+ /// If this abbreviation has a fixed byte size then FixedAttributeSize member
+ /// variable below will have a value.
+ Optional<FixedSizeInfo> FixedAttributeSize;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
new file mode 100644
index 000000000..c9042e593
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -0,0 +1,599 @@
+//===- DWARFAcceleratorTable.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include <cstdint>
+#include <utility>
+
+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 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.
+class AppleAcceleratorTable : public DWARFAcceleratorTable {
+ struct Header {
+ uint32_t Magic;
+ uint16_t Version;
+ uint16_t HashFunction;
+ uint32_t BucketCount;
+ uint32_t HashCount;
+ uint32_t HeaderDataLength;
+
+ void dump(ScopedPrinter &W) const;
+ };
+
+ struct HeaderData {
+ using AtomType = uint16_t;
+ using Form = dwarf::Form;
+
+ uint64_t DIEOffsetBase;
+ SmallVector<std::pair<AtomType, Form>, 3> Atoms;
+
+ Optional<uint64_t> extractOffset(Optional<DWARFFormValue> Value) const;
+ };
+
+ struct Header Hdr;
+ struct HeaderData HdrData;
+ 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,
+ uint64_t *DataOffset) const;
+
+public:
+ /// 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, uint64_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.
+ uint64_t DataOffset = 0; ///< Offset into the section.
+ unsigned Data = 0; ///< Current data entry.
+ unsigned NumData = 0; ///< Number of data entries.
+
+ /// Advance the iterator.
+ void Next();
+ public:
+ /// Construct a new iterator for the entries at \p DataOffset.
+ ValueIterator(const AppleAcceleratorTable &AccelTable, uint64_t DataOffset);
+ /// End marker.
+ ValueIterator() = default;
+
+ const Entry &operator*() const { return Current; }
+ 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.NumData == B.NumData && A.DataOffset == B.DataOffset;
+ }
+ friend bool operator!=(const ValueIterator &A, const ValueIterator &B) {
+ return !(A == B);
+ }
+ };
+
+ AppleAcceleratorTable(const DWARFDataExtractor &AccelSection,
+ DataExtractor StringSection)
+ : DWARFAcceleratorTable(AccelSection, StringSection) {}
+
+ 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();
+
+ /// Return information related to the DWARF DIE we're looking for when
+ /// performing a lookup by name.
+ ///
+ /// \param HashDataOffset an offset into the hash data table
+ /// \returns <DieOffset, DieTag>
+ /// DieOffset is the offset into the .debug_info section for the DIE
+ /// related to the input hash data offset.
+ /// DieTag is the tag of the DIE
+ std::pair<uint64_t, dwarf::Tag> readAtoms(uint64_t *HashDataOffset);
+ 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 v5 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 v5 Name Index header.
+ struct Header : public HeaderPOD {
+ SmallString<8> AugmentationString;
+
+ Error extract(const DWARFDataExtractor &AS, uint64_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 v5 sect. 6.1.1.4.6) of the Name
+ /// Index.
+ class NameTableEntry {
+ DataExtractor StrData;
+
+ uint32_t Index;
+ uint64_t StringOffset;
+ uint64_t EntryOffset;
+
+ public:
+ NameTableEntry(const DataExtractor &StrData, uint32_t Index,
+ uint64_t StringOffset, uint64_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.
+ uint64_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 {
+ uint64_t Off = StringOffset;
+ return StrData.getCStr(&Off);
+ }
+
+ /// Returns the offset of the first Entry in the list.
+ uint64_t getEntryOffset() const { return EntryOffset; }
+ };
+
+ /// Represents a single accelerator table within the DWARF v5 .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.
+ uint64_t Base;
+ uint64_t CUsBase;
+ uint64_t BucketsBase;
+ uint64_t HashesBase;
+ uint64_t StringOffsetsBase;
+ uint64_t EntryOffsetsBase;
+ uint64_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, uint64_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(uint64_t *Offset);
+
+ Expected<std::vector<AttributeEncoding>>
+ extractAttributeEncodings(uint64_t *Offset);
+
+ Expected<Abbrev> extractAbbrev(uint64_t *Offset);
+
+ public:
+ NameIndex(const DWARFDebugNames &Section, uint64_t Base)
+ : Section(Section), Base(Base) {}
+
+ /// Reads offset of compilation unit CU. CU is 0-based.
+ uint64_t getCUOffset(uint32_t CU) const;
+ uint32_t getCUCount() const { return Hdr.CompUnitCount; }
+
+ /// Reads offset of local type unit TU, TU is 0-based.
+ uint64_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(uint64_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); }
+
+ Error extract();
+ uint64_t getUnitOffset() const { return Base; }
+ uint64_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;
+ uint64_t 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<uint64_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<uint64_t, const NameIndex *> CUToNameIndex;
+
+public:
+ DWARFDebugNames(const DWARFDataExtractor &AccelSection,
+ DataExtractor StringSection)
+ : DWARFAcceleratorTable(AccelSection, StringSection) {}
+
+ 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(uint64_t CUOffset);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h
new file mode 100644
index 000000000..2d5f9f3c7
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h
@@ -0,0 +1,61 @@
+//===- DWARFAddressRange.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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;
+ }
+
+ 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/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAttribute.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAttribute.h
new file mode 100644
index 000000000..dfc778346
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFAttribute.h
@@ -0,0 +1,49 @@
+//===- DWARFAttribute.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFATTRIBUTE_H
+#define LLVM_DEBUGINFO_DWARFATTRIBUTE_H
+
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include <cstdint>
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+/// Encapsulates a DWARF attribute value and all of the data required to
+/// describe the attribute value.
+///
+/// This class is designed to be used by clients that want to iterate across all
+/// attributes in a DWARFDie.
+struct DWARFAttribute {
+ /// The debug info/types offset for this attribute.
+ uint64_t Offset = 0;
+ /// The debug info/types section byte size of the data for this attribute.
+ uint32_t ByteSize = 0;
+ /// The attribute enumeration of this attribute.
+ dwarf::Attribute Attr = dwarf::Attribute(0);
+ /// The form and value for this attribute.
+ DWARFFormValue Value;
+
+ bool isValid() const {
+ return Offset != 0 && Attr != dwarf::Attribute(0);
+ }
+
+ explicit operator bool() const {
+ return isValid();
+ }
+
+ /// Identifies DWARF attributes that may contain a reference to a
+ /// DWARF expression.
+ static bool mayHaveLocationDescription(dwarf::Attribute Attr);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFATTRIBUTE_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
new file mode 100644
index 000000000..16b9bfb5d
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
@@ -0,0 +1,38 @@
+//===- DWARFCompileUnit.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
+#define LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
+
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+
+namespace llvm {
+
+class DWARFCompileUnit : public DWARFUnit {
+public:
+ DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA,
+ const DWARFSection *RS, const DWARFSection *LocSection,
+ StringRef SS, const DWARFSection &SOS,
+ const DWARFSection *AOS, const DWARFSection &LS, bool LE,
+ bool IsDWO, const DWARFUnitVector &UnitVector)
+ : DWARFUnit(Context, Section, Header, DA, RS, LocSection, SS, SOS, AOS,
+ LS, LE, IsDWO, UnitVector) {}
+
+ /// VTable anchor.
+ ~DWARFCompileUnit() override;
+ /// Dump this compile unit to \p OS.
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override;
+ /// Enable LLVM-style RTTI.
+ static bool classof(const DWARFUnit *U) { return !U->isTypeUnit(); }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFContext.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFContext.h
new file mode 100644
index 000000000..2dec107d1
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -0,0 +1,382 @@
+//===- DWARFContext.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===/
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
+#define LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
+#include "llvm/DebugInfo/DWARF/DWARFObject.h"
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#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>
+#include <deque>
+#include <map>
+#include <memory>
+
+namespace llvm {
+
+class MCRegisterInfo;
+class MemoryBuffer;
+class raw_ostream;
+
+/// Used as a return value for a error callback passed to DWARF context.
+/// Callback should return Halt if client application wants to stop
+/// object parsing, or should return Continue otherwise.
+enum class ErrorPolicy { Halt, Continue };
+
+/// DWARFContext
+/// This data structure is the top level entity that deals with dwarf debug
+/// information parsing. The actual data is supplied through DWARFObj.
+class DWARFContext : public DIContext {
+ DWARFUnitVector NormalUnits;
+ std::unique_ptr<DWARFUnitIndex> CUIndex;
+ std::unique_ptr<DWARFGdbIndex> GdbIndex;
+ std::unique_ptr<DWARFUnitIndex> TUIndex;
+ std::unique_ptr<DWARFDebugAbbrev> Abbrev;
+ std::unique_ptr<DWARFDebugLoc> Loc;
+ std::unique_ptr<DWARFDebugAranges> Aranges;
+ std::unique_ptr<DWARFDebugLine> Line;
+ std::unique_ptr<DWARFDebugFrame> DebugFrame;
+ std::unique_ptr<DWARFDebugFrame> EHFrame;
+ std::unique_ptr<DWARFDebugMacro> Macro;
+ 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;
+
+ DWARFUnitVector DWOUnits;
+ std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
+
+ /// The maximum DWARF version of all units.
+ unsigned MaxVersion = 0;
+
+ struct DWOFile {
+ object::OwningBinary<object::ObjectFile> File;
+ std::unique_ptr<DWARFContext> Context;
+ };
+ StringMap<std::weak_ptr<DWOFile>> DWOFiles;
+ std::weak_ptr<DWOFile> DWP;
+ bool CheckedForDWP = false;
+ std::string DWPName;
+
+ std::unique_ptr<MCRegisterInfo> RegInfo;
+
+ /// Read compile units from the debug_info section (if necessary)
+ /// and type units from the debug_types sections (if necessary)
+ /// and store them in NormalUnits.
+ void parseNormalUnits();
+
+ /// Read compile units from the debug_info.dwo section (if necessary)
+ /// and type units from the debug_types.dwo section (if necessary)
+ /// and store them in DWOUnits.
+ /// If \p Lazy is true, set up to parse but don't actually parse them.
+ enum { EagerParse = false, LazyParse = true };
+ void parseDWOUnits(bool Lazy = false);
+
+ std::unique_ptr<const DWARFObject> DObj;
+
+public:
+ DWARFContext(std::unique_ptr<const DWARFObject> DObj,
+ std::string DWPName = "");
+ ~DWARFContext();
+
+ DWARFContext(DWARFContext &) = delete;
+ DWARFContext &operator=(DWARFContext &) = delete;
+
+ const DWARFObject &getDWARFObj() const { return *DObj; }
+
+ static bool classof(const DIContext *DICtx) {
+ return DICtx->getKind() == CK_DWARF;
+ }
+
+ /// Dump a textual representation to \p OS. If any \p DumpOffsets are present,
+ /// dump only the record at the specified offset.
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
+ std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets);
+
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override {
+ std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets;
+ dump(OS, DumpOpts, DumpOffsets);
+ }
+
+ bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override;
+
+ using unit_iterator_range = DWARFUnitVector::iterator_range;
+
+ /// Get units from .debug_info in this context.
+ unit_iterator_range info_section_units() {
+ parseNormalUnits();
+ return unit_iterator_range(NormalUnits.begin(),
+ NormalUnits.begin() +
+ NormalUnits.getNumInfoUnits());
+ }
+
+ /// Get units from .debug_types in this context.
+ unit_iterator_range types_section_units() {
+ parseNormalUnits();
+ return unit_iterator_range(
+ NormalUnits.begin() + NormalUnits.getNumInfoUnits(), NormalUnits.end());
+ }
+
+ /// Get compile units in this context.
+ unit_iterator_range compile_units() { return info_section_units(); }
+
+ /// Get type units in this context.
+ unit_iterator_range type_units() { return types_section_units(); }
+
+ /// Get all normal compile/type units in this context.
+ unit_iterator_range normal_units() {
+ parseNormalUnits();
+ return unit_iterator_range(NormalUnits.begin(), NormalUnits.end());
+ }
+
+ /// Get units from .debug_info..dwo in the DWO context.
+ unit_iterator_range dwo_info_section_units() {
+ parseDWOUnits();
+ return unit_iterator_range(DWOUnits.begin(),
+ DWOUnits.begin() + DWOUnits.getNumInfoUnits());
+ }
+
+ /// Get units from .debug_types.dwo in the DWO context.
+ unit_iterator_range dwo_types_section_units() {
+ parseDWOUnits();
+ return unit_iterator_range(DWOUnits.begin() + DWOUnits.getNumInfoUnits(),
+ DWOUnits.end());
+ }
+
+ /// Get compile units in the DWO context.
+ unit_iterator_range dwo_compile_units() { return dwo_info_section_units(); }
+
+ /// Get type units in the DWO context.
+ unit_iterator_range dwo_type_units() { return dwo_types_section_units(); }
+
+ /// Get all units in the DWO context.
+ unit_iterator_range dwo_units() {
+ parseDWOUnits();
+ return unit_iterator_range(DWOUnits.begin(), DWOUnits.end());
+ }
+
+ /// Get the number of compile units in this context.
+ unsigned getNumCompileUnits() {
+ parseNormalUnits();
+ return NormalUnits.getNumInfoUnits();
+ }
+
+ /// Get the number of type units in this context.
+ unsigned getNumTypeUnits() {
+ parseNormalUnits();
+ return NormalUnits.getNumTypesUnits();
+ }
+
+ /// Get the number of compile units in the DWO context.
+ unsigned getNumDWOCompileUnits() {
+ parseDWOUnits();
+ return DWOUnits.getNumInfoUnits();
+ }
+
+ /// Get the number of type units in the DWO context.
+ unsigned getNumDWOTypeUnits() {
+ parseDWOUnits();
+ return DWOUnits.getNumTypesUnits();
+ }
+
+ /// Get the unit at the specified index.
+ DWARFUnit *getUnitAtIndex(unsigned index) {
+ parseNormalUnits();
+ return NormalUnits[index].get();
+ }
+
+ /// Get the unit at the specified index for the DWO units.
+ DWARFUnit *getDWOUnitAtIndex(unsigned index) {
+ parseDWOUnits();
+ return DWOUnits[index].get();
+ }
+
+ DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
+
+ /// Return the compile unit that includes an offset (relative to .debug_info).
+ DWARFCompileUnit *getCompileUnitForOffset(uint64_t Offset);
+
+ /// Get a DIE given an exact offset.
+ DWARFDie getDIEForOffset(uint64_t Offset);
+
+ unsigned getMaxVersion() {
+ // Ensure info units have been parsed to discover MaxVersion
+ info_section_units();
+ return MaxVersion;
+ }
+
+ unsigned getMaxDWOVersion() {
+ // Ensure DWO info units have been parsed to discover MaxVersion
+ dwo_info_section_units();
+ return MaxVersion;
+ }
+
+ void setMaxVersionIfGreater(unsigned Version) {
+ if (Version > MaxVersion)
+ MaxVersion = Version;
+ }
+
+ const DWARFUnitIndex &getCUIndex();
+ DWARFGdbIndex &getGdbIndex();
+ const DWARFUnitIndex &getTUIndex();
+
+ /// Get a pointer to the parsed DebugAbbrev object.
+ const DWARFDebugAbbrev *getDebugAbbrev();
+
+ /// Get a pointer to the parsed DebugLoc object.
+ const DWARFDebugLoc *getDebugLoc();
+
+ /// Get a pointer to the parsed dwo abbreviations object.
+ const DWARFDebugAbbrev *getDebugAbbrevDWO();
+
+ /// Get a pointer to the parsed DebugAranges object.
+ const DWARFDebugAranges *getDebugAranges();
+
+ /// Get a pointer to the parsed frame information object.
+ const DWARFDebugFrame *getDebugFrame();
+
+ /// Get a pointer to the parsed eh frame information object.
+ const DWARFDebugFrame *getEHFrame();
+
+ /// Get a pointer to the parsed DebugMacro object.
+ const DWARFDebugMacro *getDebugMacro();
+
+ /// Get a reference to the parsed accelerator table object.
+ const DWARFDebugNames &getDebugNames();
+
+ /// Get a reference to the parsed accelerator table object.
+ const AppleAcceleratorTable &getAppleNames();
+
+ /// Get a reference to the parsed accelerator table object.
+ const AppleAcceleratorTable &getAppleTypes();
+
+ /// Get a reference to the parsed accelerator table object.
+ 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.
+ /// 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->getStrSection(), false, 0);
+ }
+ DataExtractor getLineStringExtractor() const {
+ return DataExtractor(DObj->getLineStrSection(), false, 0);
+ }
+
+ /// Wraps the returned DIEs for a given address.
+ struct DIEsForAddress {
+ DWARFCompileUnit *CompileUnit = nullptr;
+ DWARFDie FunctionDIE;
+ DWARFDie BlockDIE;
+ explicit operator bool() const { return CompileUnit != nullptr; }
+ };
+
+ /// Get the compilation unit, the function DIE and lexical block DIE for the
+ /// given address where applicable.
+ /// TODO: change input parameter from "uint64_t Address"
+ /// into "SectionedAddress Address"
+ DIEsForAddress getDIEsForAddress(uint64_t Address);
+
+ DILineInfo getLineInfoForAddress(
+ object::SectionedAddress Address,
+ DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
+ DILineInfoTable getLineInfoForAddressRange(
+ object::SectionedAddress Address, uint64_t Size,
+ DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
+ DIInliningInfo getInliningInfoForAddress(
+ object::SectionedAddress Address,
+ DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
+
+ std::vector<DILocal>
+ getLocalsForAddress(object::SectionedAddress Address) override;
+
+ bool isLittleEndian() const { return DObj->isLittleEndian(); }
+ static bool isSupportedVersion(unsigned version) {
+ return version == 2 || version == 3 || version == 4 || version == 5;
+ }
+
+ std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
+
+ const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); }
+
+ /// Function used to handle default error reporting policy. Prints a error
+ /// message and returns Continue, so DWARF context ignores the error.
+ static ErrorPolicy defaultErrorHandler(Error E);
+ static std::unique_ptr<DWARFContext>
+ create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
+ function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler,
+ std::string DWPName = "");
+
+ static std::unique_ptr<DWARFContext>
+ create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
+ uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost);
+
+ /// Loads register info for the architecture of the provided object file.
+ /// Improves readability of dumped DWARF expressions. Requires the caller to
+ /// have initialized the relevant target descriptions.
+ Error loadRegisterInfo(const object::ObjectFile &Obj);
+
+ /// Get address size from CUs.
+ /// TODO: refactor compile_units() to make this const.
+ uint8_t getCUAddrSize();
+
+ /// Dump Error as warning message to stderr.
+ static void dumpWarning(Error Warning);
+
+ Triple::ArchType getArch() const {
+ return getDWARFObj().getFile()->getArch();
+ }
+
+private:
+ /// Return the compile unit which contains instruction with provided
+ /// address.
+ /// TODO: change input parameter from "uint64_t Address"
+ /// into "SectionedAddress Address"
+ DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
+ void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die,
+ std::vector<DILocal> &Result);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
new file mode 100644
index 000000000..980724c52
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
@@ -0,0 +1,64 @@
+//===- DWARFDataExtractor.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFDATAEXTRACTOR_H
+#define LLVM_DEBUGINFO_DWARFDATAEXTRACTOR_H
+
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/Support/DataExtractor.h"
+
+namespace llvm {
+class DWARFObject;
+
+/// A DataExtractor (typically for an in-memory copy of an object-file section)
+/// plus a relocation map for that section, if there is one.
+class DWARFDataExtractor : public DataExtractor {
+ const DWARFObject *Obj = nullptr;
+ const DWARFSection *Section = nullptr;
+
+public:
+ /// Constructor for the normal case of extracting data from a DWARF section.
+ /// The DWARFSection's lifetime must be at least as long as the extractor's.
+ DWARFDataExtractor(const DWARFObject &Obj, const DWARFSection &Section,
+ bool IsLittleEndian, uint8_t AddressSize)
+ : DataExtractor(Section.Data, IsLittleEndian, AddressSize), Obj(&Obj),
+ Section(&Section) {}
+
+ /// Constructor for cases when there are no relocations.
+ DWARFDataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize)
+ : DataExtractor(Data, IsLittleEndian, AddressSize) {}
+
+ /// Extracts a value and applies a relocation to the result if
+ /// one exists for the given offset.
+ uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off,
+ uint64_t *SectionIndex = nullptr,
+ Error *Err = nullptr) const;
+
+ /// Extracts an address-sized value and applies a relocation to the result if
+ /// one exists for the given offset.
+ uint64_t getRelocatedAddress(uint64_t *Off, uint64_t *SecIx = nullptr) const {
+ return getRelocatedValue(getAddressSize(), Off, SecIx);
+ }
+ uint64_t getRelocatedAddress(Cursor &C, uint64_t *SecIx = nullptr) const {
+ return getRelocatedValue(getAddressSize(), &getOffset(C), SecIx,
+ &getError(C));
+ }
+
+ /// 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(uint64_t *Offset, uint8_t Encoding,
+ uint64_t AbsPosOffset = 0) const;
+
+ size_t size() const { return Section == nullptr ? 0 : Section->Data.size(); }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFDATAEXTRACTOR_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
new file mode 100644
index 000000000..1398e1625
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
@@ -0,0 +1,87 @@
+//===- DWARFDebugAbbrev.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGABBREV_H
+#define LLVM_DEBUGINFO_DWARFDEBUGABBREV_H
+
+#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
+#include "llvm/Support/DataExtractor.h"
+#include <cstdint>
+#include <map>
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+class DWARFAbbreviationDeclarationSet {
+ uint64_t Offset;
+ /// Code of the first abbreviation, if all abbreviations in the set have
+ /// consecutive codes. UINT32_MAX otherwise.
+ uint32_t FirstAbbrCode;
+ std::vector<DWARFAbbreviationDeclaration> Decls;
+
+ using const_iterator =
+ std::vector<DWARFAbbreviationDeclaration>::const_iterator;
+
+public:
+ DWARFAbbreviationDeclarationSet();
+
+ uint64_t getOffset() const { return Offset; }
+ void dump(raw_ostream &OS) const;
+ bool extract(DataExtractor Data, uint64_t *OffsetPtr);
+
+ const DWARFAbbreviationDeclaration *
+ getAbbreviationDeclaration(uint32_t AbbrCode) const;
+
+ const_iterator begin() const {
+ return Decls.begin();
+ }
+
+ const_iterator end() const {
+ return Decls.end();
+ }
+
+private:
+ void clear();
+};
+
+class DWARFDebugAbbrev {
+ using DWARFAbbreviationDeclarationSetMap =
+ std::map<uint64_t, DWARFAbbreviationDeclarationSet>;
+
+ mutable DWARFAbbreviationDeclarationSetMap AbbrDeclSets;
+ mutable DWARFAbbreviationDeclarationSetMap::const_iterator PrevAbbrOffsetPos;
+ mutable Optional<DataExtractor> Data;
+
+public:
+ DWARFDebugAbbrev();
+
+ const DWARFAbbreviationDeclarationSet *
+ getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const;
+
+ void dump(raw_ostream &OS) const;
+ void parse() const;
+ void extract(DataExtractor Data);
+
+ DWARFAbbreviationDeclarationSetMap::const_iterator begin() const {
+ parse();
+ return AbbrDeclSets.begin();
+ }
+
+ DWARFAbbreviationDeclarationSetMap::const_iterator end() const {
+ return AbbrDeclSets.end();
+ }
+
+private:
+ void clear();
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFDEBUGABBREV_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h
new file mode 100644
index 000000000..4539b9c9d
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h
@@ -0,0 +1,97 @@
+//===- DWARFDebugAddr.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGADDR_H
+#define LLVM_DEBUGINFO_DWARFDEBUGADDR_H
+
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <map>
+#include <vector>
+
+namespace llvm {
+
+class Error;
+class raw_ostream;
+
+/// A class representing an address table as specified in DWARF v5.
+/// The table consists of a header followed by an array of address values from
+/// .debug_addr section.
+class DWARFDebugAddrTable {
+public:
+ 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 = 5;
+ /// 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 = 0;
+ };
+
+private:
+ dwarf::DwarfFormat Format;
+ uint64_t HeaderOffset;
+ Header HeaderData;
+ uint32_t DataSize = 0;
+ std::vector<uint64_t> Addrs;
+
+public:
+ void clear();
+
+ /// Extract an entire table, including all addresses.
+ Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr,
+ uint16_t Version, uint8_t AddrSize,
+ std::function<void(Error)> WarnCallback);
+
+ uint64_t getHeaderOffset() const { return HeaderOffset; }
+ uint8_t getAddrSize() const { return HeaderData.AddrSize; }
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
+
+ /// Return the address based on a given index.
+ Expected<uint64_t> getAddrEntry(uint32_t Index) const;
+
+ /// Return the size of the table header including the length
+ /// but not including the addresses.
+ uint8_t getHeaderSize() const {
+ switch (Format) {
+ case dwarf::DwarfFormat::DWARF32:
+ return 8; // 4 + 2 + 1 + 1
+ case dwarf::DwarfFormat::DWARF64:
+ return 16; // 12 + 2 + 1 + 1
+ }
+ llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64)");
+ }
+
+ /// Returns the length of this 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 getLength() const;
+
+ /// Verify that the given length is valid for this table.
+ bool hasValidLength() const { return getLength() != 0; }
+
+ /// Invalidate Length field to stop further processing.
+ void invalidateLength() { HeaderData.Length = 0; }
+
+ /// Returns the length of the array of addresses.
+ uint32_t getDataSize() const;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFDEBUGADDR_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
new file mode 100644
index 000000000..ebe4ad6e2
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
@@ -0,0 +1,75 @@
+//===- DWARFDebugArangeSet.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGARANGESET_H
+#define LLVM_DEBUGINFO_DWARFDEBUGARANGESET_H
+
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/DataExtractor.h"
+#include <cstdint>
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+class DWARFDebugArangeSet {
+public:
+ struct Header {
+ /// The total length of the entries for that set, not including the length
+ /// field itself.
+ uint32_t Length;
+ /// The offset from the beginning of the .debug_info section of the
+ /// compilation unit entry referenced by the table.
+ uint32_t CuOffset;
+ /// 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 descriptor on the target architecture.
+ /// If the target system uses a flat address space, this value is 0.
+ uint8_t SegSize;
+ };
+
+ struct Descriptor {
+ uint64_t Address;
+ uint64_t Length;
+
+ uint64_t getEndAddress() const { return Address + Length; }
+ void dump(raw_ostream &OS, uint32_t AddressSize) const;
+ };
+
+private:
+ using DescriptorColl = std::vector<Descriptor>;
+ using desc_iterator_range = iterator_range<DescriptorColl::const_iterator>;
+
+ uint64_t Offset;
+ Header HeaderData;
+ DescriptorColl ArangeDescriptors;
+
+public:
+ DWARFDebugArangeSet() { clear(); }
+
+ void clear();
+ bool extract(DataExtractor data, uint64_t *offset_ptr);
+ void dump(raw_ostream &OS) const;
+
+ uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; }
+
+ const Header &getHeader() const { return HeaderData; }
+
+ desc_iterator_range descriptors() const {
+ return desc_iterator_range(ArangeDescriptors.begin(),
+ ArangeDescriptors.end());
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFDEBUGARANGESET_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h
new file mode 100644
index 000000000..172f1d2c9
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h
@@ -0,0 +1,84 @@
+//===- DWARFDebugAranges.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGARANGES_H
+#define LLVM_DEBUGINFO_DWARFDEBUGARANGES_H
+
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/Support/DataExtractor.h"
+#include <cstdint>
+#include <vector>
+
+namespace llvm {
+
+class DWARFContext;
+
+class DWARFDebugAranges {
+public:
+ void generate(DWARFContext *CTX);
+ uint32_t findAddress(uint64_t Address) const;
+
+private:
+ void clear();
+ void extract(DataExtractor DebugArangesData);
+
+ /// Call appendRange multiple times and then call construct.
+ void appendRange(uint64_t CUOffset, uint64_t LowPC, uint64_t HighPC);
+ void construct();
+
+ struct Range {
+ explicit Range(uint64_t LowPC = -1ULL, uint64_t HighPC = -1ULL,
+ uint32_t CUOffset = -1U)
+ : LowPC(LowPC), Length(HighPC - LowPC), CUOffset(CUOffset) {}
+
+ void setHighPC(uint64_t HighPC) {
+ if (HighPC == -1ULL || HighPC <= LowPC)
+ Length = 0;
+ else
+ Length = HighPC - LowPC;
+ }
+
+ uint64_t HighPC() const {
+ if (Length)
+ return LowPC + Length;
+ return -1ULL;
+ }
+
+ bool operator<(const Range &other) const {
+ return LowPC < other.LowPC;
+ }
+
+ uint64_t LowPC; /// Start of address range.
+ uint32_t Length; /// End of address range (not including this address).
+ uint32_t CUOffset; /// Offset of the compile unit or die.
+ };
+
+ struct RangeEndpoint {
+ uint64_t Address;
+ uint64_t CUOffset;
+ bool IsRangeStart;
+
+ RangeEndpoint(uint64_t Address, uint64_t CUOffset, bool IsRangeStart)
+ : Address(Address), CUOffset(CUOffset), IsRangeStart(IsRangeStart) {}
+
+ bool operator<(const RangeEndpoint &Other) const {
+ return Address < Other.Address;
+ }
+ };
+
+ using RangeColl = std::vector<Range>;
+ using RangeCollIterator = RangeColl::const_iterator;
+
+ std::vector<RangeEndpoint> Endpoints;
+ RangeColl Aranges;
+ DenseSet<uint64_t> ParsedCUOffsets;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFDEBUGARANGES_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
new file mode 100644
index 000000000..c6539df0d
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
@@ -0,0 +1,308 @@
+//===- DWARFDebugFrame.h - Parsing of .debug_frame --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
+#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Triple.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 raw_ostream;
+
+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,
+ Triple::ArchType Arch)
+ : CodeAlignmentFactor(CodeAlignmentFactor),
+ DataAlignmentFactor(DataAlignmentFactor),
+ Arch(Arch) {}
+
+ /// 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(DWARFDataExtractor Data, uint64_t *Offset, uint64_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;
+ Triple::ArchType Arch;
+
+ /// 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, Triple::ArchType Arch)
+ : Kind(K), Offset(Offset), Length(Length),
+ CFIs(CodeAlign, DataAlign, Arch) {}
+
+ 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, Triple::ArchType Arch)
+ : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor,
+ DataAlignmentFactor, Arch),
+ 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, Triple::ArchType Arch)
+ : FrameEntry(FK_FDE, Offset, Length,
+ Cie ? Cie->getCodeAlignmentFactor() : 0,
+ Cie ? Cie->getDataAlignmentFactor() : 0,
+ Arch),
+ 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 {
+ const Triple::ArchType Arch;
+ // True if this is parsing an eh_frame section.
+ 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:
+ // 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(Triple::ArchType Arch,
+ bool IsEH = false, uint64_t EHFrameAddress = 0);
+ ~DWARFDebugFrame();
+
+ /// Dump the section data into the given stream.
+ void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ Optional<uint64_t> Offset) const;
+
+ /// 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(); }
+
+ /// 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());
+ }
+
+ uint64_t getEHFrameAddress() const { return EHFrameAddress; }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
new file mode 100644
index 000000000..ded960337
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
@@ -0,0 +1,62 @@
+//===- DWARFDebugInfoEntry.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
+#define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
+
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include <cstdint>
+
+namespace llvm {
+
+class DataExtractor;
+class DWARFUnit;
+
+/// DWARFDebugInfoEntry - A DIE with only the minimum required data.
+class DWARFDebugInfoEntry {
+ /// Offset within the .debug_info of the start of this entry.
+ uint64_t Offset = 0;
+
+ /// The integer depth of this DIE within the compile unit DIEs where the
+ /// compile/type unit DIE has a depth of zero.
+ uint32_t Depth = 0;
+
+ const DWARFAbbreviationDeclaration *AbbrevDecl = nullptr;
+
+public:
+ DWARFDebugInfoEntry() = default;
+
+ /// Extracts a debug info entry, which is a child of a given unit,
+ /// starting at a given offset. If DIE can't be extracted, returns false and
+ /// doesn't change OffsetPtr.
+ bool extractFast(const DWARFUnit &U, uint64_t *OffsetPtr);
+
+ /// High performance extraction should use this call.
+ bool extractFast(const DWARFUnit &U, uint64_t *OffsetPtr,
+ const DWARFDataExtractor &DebugInfoData, uint64_t UEndOffset,
+ uint32_t Depth);
+
+ uint64_t getOffset() const { return Offset; }
+ uint32_t getDepth() const { return Depth; }
+
+ dwarf::Tag getTag() const {
+ return AbbrevDecl ? AbbrevDecl->getTag() : dwarf::DW_TAG_null;
+ }
+
+ bool hasChildren() const { return AbbrevDecl && AbbrevDecl->hasChildren(); }
+
+ const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const {
+ return AbbrevDecl;
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
new file mode 100644
index 000000000..c2be8304a
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
@@ -0,0 +1,392 @@
+//===- DWARFDebugLine.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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 "llvm/Support/Path.h"
+#include <cstdint>
+#include <map>
+#include <string>
+#include <vector>
+
+namespace llvm {
+
+class DWARFUnit;
+class raw_ostream;
+
+class DWARFDebugLine {
+public:
+ struct FileNameEntry {
+ FileNameEntry() = default;
+
+ 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 {
+ Prologue();
+
+ /// The size in bytes of the statement information for this compilation unit
+ /// (not including the total_length field itself).
+ uint64_t TotalLength;
+ /// 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).
+ 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;
+ /// In v5, size in bytes of a segment selector.
+ uint8_t SegSelectorSize;
+ /// The size in bytes of the smallest target machine instruction. Statement
+ /// program opcodes that alter the address register first multiply their
+ /// operands by this value.
+ uint8_t MinInstLength;
+ /// The maximum number of individual operations that may be encoded in an
+ /// instruction.
+ uint8_t MaxOpsPerInst;
+ /// The initial value of theis_stmtregister.
+ uint8_t DefaultIsStmt;
+ /// This parameter affects the meaning of the special opcodes. See below.
+ int8_t LineBase;
+ /// This parameter affects the meaning of the special opcodes. See below.
+ uint8_t LineRange;
+ /// The number assigned to the first special opcode.
+ uint8_t OpcodeBase;
+ /// This tracks which optional file format content types are present.
+ ContentTypeTracker ContentTypes;
+ std::vector<uint8_t> StandardOpcodeLengths;
+ std::vector<DWARFFormValue> IncludeDirectories;
+ std::vector<FileNameEntry> FileNames;
+
+ 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; }
+
+ uint32_t sizeofTotalLength() const { return isDWARF64() ? 12 : 4; }
+
+ 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()) +
+ sizeofPrologueLength();
+ }
+
+ /// Length of the line table data in bytes (not including the prologue).
+ uint32_t getStatementTableLength() const {
+ return TotalLength + sizeofTotalLength() - getLength();
+ }
+
+ int32_t getMaxLineIncrementForSpecialOpcode() const {
+ return LineBase + (int8_t)LineRange - 1;
+ }
+
+ /// Get DWARF-version aware access to the file name entry at the provided
+ /// index.
+ const llvm::DWARFDebugLine::FileNameEntry &
+ getFileNameEntry(uint64_t Index) const;
+
+ bool hasFileAtIndex(uint64_t FileIndex) const;
+
+ bool
+ getFileNameByIndex(uint64_t FileIndex, StringRef CompDir,
+ DILineInfoSpecifier::FileLineInfoKind Kind,
+ std::string &Result,
+ sys::path::Style Style = sys::path::Style::native) const;
+
+ void clear();
+ void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const;
+ Error parse(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr,
+ const DWARFContext &Ctx, const DWARFUnit *U = nullptr);
+ };
+
+ /// Standard .debug_line state machine structure.
+ struct Row {
+ explicit Row(bool DefaultIsStmt = false);
+
+ /// Called after a row is appended to the matrix.
+ void postAppend();
+ void reset(bool DefaultIsStmt);
+ void dump(raw_ostream &OS) const;
+
+ static void dumpTableHeader(raw_ostream &OS);
+
+ static bool orderByAddress(const Row &LHS, const Row &RHS) {
+ return std::tie(LHS.Address.SectionIndex, LHS.Address.Address) <
+ std::tie(RHS.Address.SectionIndex, RHS.Address.Address);
+ }
+
+ /// The program-counter value corresponding to a machine instruction
+ /// generated by the compiler and section index pointing to the section
+ /// containg this PC. If relocation information is present then section
+ /// index is the index of the section which contains above address.
+ /// Otherwise this is object::SectionedAddress::Undef value.
+ object::SectionedAddress Address;
+ /// An unsigned integer indicating a source line number. Lines are numbered
+ /// beginning at 1. The compiler may emit the value 0 in cases where an
+ /// instruction cannot be attributed to any source line.
+ uint32_t Line;
+ /// An unsigned integer indicating a column number within a source line.
+ /// Columns are numbered beginning at 1. The value 0 is reserved to indicate
+ /// that a statement begins at the 'left edge' of the line.
+ uint16_t Column;
+ /// An unsigned integer indicating the identity of the source file
+ /// corresponding to a machine instruction.
+ uint16_t File;
+ /// An unsigned integer representing the DWARF path discriminator value
+ /// for this location.
+ uint32_t Discriminator;
+ /// An unsigned integer whose value encodes the applicable instruction set
+ /// architecture for the current instruction.
+ uint8_t Isa;
+ /// A boolean indicating that the current instruction is the beginning of a
+ /// statement.
+ uint8_t IsStmt : 1,
+ /// A boolean indicating that the current instruction is the
+ /// beginning of a basic block.
+ BasicBlock : 1,
+ /// A boolean indicating that the current address is that of the
+ /// first byte after the end of a sequence of target machine
+ /// instructions.
+ EndSequence : 1,
+ /// A boolean indicating that the current address is one (of possibly
+ /// many) where execution should be suspended for an entry breakpoint
+ /// of a function.
+ PrologueEnd : 1,
+ /// A boolean indicating that the current address is one (of possibly
+ /// many) where execution should be suspended for an exit breakpoint
+ /// of a function.
+ EpilogueBegin : 1;
+ };
+
+ /// Represents a series of contiguous machine instructions. Line table for
+ /// each compilation unit may consist of multiple sequences, which are not
+ /// guaranteed to be in the order of ascending instruction address.
+ struct Sequence {
+ Sequence();
+
+ /// Sequence describes instructions at address range [LowPC, HighPC)
+ /// and is described by line table rows [FirstRowIndex, LastRowIndex).
+ uint64_t LowPC;
+ uint64_t HighPC;
+ /// If relocation information is present then this is the index of the
+ /// section which contains above addresses. Otherwise this is
+ /// object::SectionedAddress::Undef value.
+ uint64_t SectionIndex;
+ unsigned FirstRowIndex;
+ unsigned LastRowIndex;
+ bool Empty;
+
+ void reset();
+
+ static bool orderByHighPC(const Sequence &LHS, const Sequence &RHS) {
+ return std::tie(LHS.SectionIndex, LHS.HighPC) <
+ std::tie(RHS.SectionIndex, RHS.HighPC);
+ }
+
+ bool isValid() const {
+ return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex);
+ }
+
+ bool containsPC(object::SectionedAddress PC) const {
+ return SectionIndex == PC.SectionIndex &&
+ (LowPC <= PC.Address && PC.Address < HighPC);
+ }
+ };
+
+ struct LineTable {
+ LineTable();
+
+ /// Represents an invalid row
+ const uint32_t UnknownRowIndex = UINT32_MAX;
+
+ void appendRow(const DWARFDebugLine::Row &R) { Rows.push_back(R); }
+
+ void appendSequence(const DWARFDebugLine::Sequence &S) {
+ Sequences.push_back(S);
+ }
+
+ /// Returns the index of the row with file/line info for a given address,
+ /// or UnknownRowIndex if there is no such row.
+ uint32_t lookupAddress(object::SectionedAddress Address) const;
+
+ bool lookupAddressRange(object::SectionedAddress Address, uint64_t Size,
+ std::vector<uint32_t> &Result) const;
+
+ bool hasFileAtIndex(uint64_t FileIndex) const {
+ return Prologue.hasFileAtIndex(FileIndex);
+ }
+
+ /// Extracts filename by its index in filename table in prologue.
+ /// In Dwarf 4, the files are 1-indexed and the current compilation file
+ /// name is not represented in the list. In DWARF v5, the files are
+ /// 0-indexed and the primary source file has the index 0.
+ /// Returns true on success.
+ bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir,
+ DILineInfoSpecifier::FileLineInfoKind Kind,
+ std::string &Result) const {
+ return Prologue.getFileNameByIndex(FileIndex, CompDir, Kind, Result);
+ }
+
+ /// Fills the Result argument with the file and line information
+ /// corresponding to Address. Returns true on success.
+ bool getFileLineInfoForAddress(object::SectionedAddress Address,
+ const char *CompDir,
+ DILineInfoSpecifier::FileLineInfoKind Kind,
+ DILineInfo &Result) const;
+
+ void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const;
+ void clear();
+
+ /// Parse prologue and all rows.
+ Error parse(
+ DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr,
+ const DWARFContext &Ctx, const DWARFUnit *U,
+ std::function<void(Error)> RecoverableErrorCallback,
+ raw_ostream *OS = nullptr);
+
+ using RowVector = std::vector<Row>;
+ using RowIter = RowVector::const_iterator;
+ using SequenceVector = std::vector<Sequence>;
+ using SequenceIter = SequenceVector::const_iterator;
+
+ struct Prologue Prologue;
+ RowVector Rows;
+ SequenceVector Sequences;
+
+ private:
+ uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq,
+ object::SectionedAddress Address) const;
+ Optional<StringRef>
+ getSourceByIndex(uint64_t FileIndex,
+ DILineInfoSpecifier::FileLineInfoKind Kind) const;
+
+ uint32_t lookupAddressImpl(object::SectionedAddress Address) const;
+
+ bool lookupAddressRangeImpl(object::SectionedAddress Address, uint64_t Size,
+ std::vector<uint32_t> &Result) const;
+ };
+
+ const LineTable *getLineTable(uint64_t Offset) const;
+ Expected<const LineTable *> getOrParseLineTable(
+ DWARFDataExtractor &DebugLineData, uint64_t Offset,
+ const DWARFContext &Ctx, const DWARFUnit *U,
+ std::function<void(Error)> RecoverableErrorCallback);
+
+ /// Helper to allow for parsing of an entire .debug_line section in sequence.
+ class SectionParser {
+ public:
+ using cu_range = DWARFUnitVector::iterator_range;
+ using tu_range = DWARFUnitVector::iterator_range;
+ 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,
+ function_ref<void(Error)> UnrecoverableErrorCallback,
+ 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);
+
+ /// 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.
+ uint64_t getOffset() const { return Offset; }
+
+ private:
+ DWARFUnit *prepareToParse(uint64_t Offset);
+ void moveToNextTable(uint64_t OldOffset, const Prologue &P);
+
+ LineToUnitMap LineToUnit;
+
+ DWARFDataExtractor &DebugLineData;
+ const DWARFContext &Context;
+ uint64_t Offset = 0;
+ bool Done = false;
+ };
+
+private:
+ struct ParsingState {
+ ParsingState(struct LineTable *LT);
+
+ void resetRowAndSequence();
+ void appendRowToMatrix();
+
+ /// Line table we're currently parsing.
+ struct LineTable *LineTable;
+ struct Row Row;
+ struct Sequence Sequence;
+ };
+
+ using LineTableMapTy = std::map<uint64_t, LineTable>;
+ using LineTableIter = LineTableMapTy::iterator;
+ using LineTableConstIter = LineTableMapTy::const_iterator;
+
+ LineTableMapTy LineTableMap;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFDEBUGLINE_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
new file mode 100644
index 000000000..25b771317
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
@@ -0,0 +1,121 @@
+//===- DWARFDebugLoc.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
+#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include <cstdint>
+
+namespace llvm {
+class DWARFUnit;
+class MCRegisterInfo;
+class raw_ostream;
+
+class DWARFDebugLoc {
+public:
+ /// A single location within a location list.
+ struct Entry {
+ /// The beginning address of the instruction range.
+ uint64_t Begin;
+ /// The ending address of the instruction range.
+ uint64_t End;
+ /// The location of the variable within the specified range.
+ SmallVector<uint8_t, 4> Loc;
+ };
+
+ /// A list of locations that contain one variable.
+ struct LocationList {
+ /// The beginning offset where this location list is stored in the debug_loc
+ /// section.
+ uint64_t Offset;
+ /// All the locations in which the variable is stored.
+ SmallVector<Entry, 2> Entries;
+ /// Dump this list on OS.
+ void dump(raw_ostream &OS, uint64_t BaseAddress, bool IsLittleEndian,
+ unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U,
+ DIDumpOptions DumpOpts,
+ unsigned Indent) const;
+ };
+
+private:
+ using LocationLists = SmallVector<LocationList, 4>;
+
+ /// A list of all the variables in the debug_loc section, each one describing
+ /// the locations in which the variable is stored.
+ LocationLists Locations;
+
+ unsigned AddressSize;
+
+ bool IsLittleEndian;
+
+public:
+ /// Print the location lists found within the debug_loc section.
+ void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, DIDumpOptions DumpOpts,
+ Optional<uint64_t> Offset) const;
+
+ /// Parse the debug_loc section accessible via the 'data' parameter using the
+ /// address size also given in 'data' to interpret the address ranges.
+ void parse(const DWARFDataExtractor &data);
+
+ /// Return the location list at the given offset or nullptr.
+ LocationList const *getLocationListAtOffset(uint64_t Offset) const;
+
+ Expected<LocationList>
+ parseOneLocationList(const DWARFDataExtractor &Data, uint64_t *Offset);
+};
+
+class DWARFDebugLoclists {
+public:
+ // Unconstructible.
+ DWARFDebugLoclists() = delete;
+
+ struct Entry {
+ uint8_t Kind;
+ uint64_t Offset;
+ uint64_t Value0;
+ uint64_t Value1;
+ SmallVector<uint8_t, 4> Loc;
+ void dump(raw_ostream &OS, uint64_t &BaseAddr, bool IsLittleEndian,
+ unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U,
+ DIDumpOptions DumpOpts, unsigned Indent, size_t MaxEncodingStringLength) const;
+ };
+
+ /// Call the user-provided callback for each entry (including the end-of-list
+ /// entry) in the location list starting at \p Offset. The callback can return
+ /// false to terminate the iteration early. Returns an error if it was unable
+ /// to parse the entire location list correctly. Upon successful termination
+ /// \p Offset will be updated point past the end of the list.
+ static Error visitLocationList(const DWARFDataExtractor &Data,
+ uint64_t *Offset, uint16_t Version,
+ llvm::function_ref<bool(const Entry &)> F);
+
+ /// Dump the location list at the given \p Offset. The function returns true
+ /// iff it has successfully reched the end of the list. This means that one
+ /// can attempt to parse another list after the current one (\p Offset will be
+ /// updated to point past the end of the current list).
+ static bool dumpLocationList(const DWARFDataExtractor &Data, uint64_t *Offset,
+ uint16_t Version, raw_ostream &OS,
+ uint64_t BaseAddr, const MCRegisterInfo *MRI,
+ DWARFUnit *U, DIDumpOptions DumpOpts,
+ unsigned Indent);
+
+ /// Dump all location lists within the given range.
+ static void dumpRange(const DWARFDataExtractor &Data, uint64_t StartOffset,
+ uint64_t Size, uint16_t Version, raw_ostream &OS,
+ uint64_t BaseAddr, const MCRegisterInfo *MRI,
+ DIDumpOptions DumpOpts);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
new file mode 100644
index 000000000..7880bcdf6
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
@@ -0,0 +1,62 @@
+//===- DWARFDebugMacro.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H
+#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/DataExtractor.h"
+#include <cstdint>
+
+namespace llvm {
+
+class raw_ostream;
+
+class DWARFDebugMacro {
+ /// A single macro entry within a macro list.
+ struct Entry {
+ /// The type of the macro entry.
+ uint32_t Type;
+ union {
+ /// The source line where the macro is defined.
+ uint64_t Line;
+ /// Vendor extension constant value.
+ uint64_t ExtConstant;
+ };
+
+ union {
+ /// The string (name, value) of the macro entry.
+ const char *MacroStr;
+ // An unsigned integer indicating the identity of the source file.
+ uint64_t File;
+ /// Vendor extension string.
+ const char *ExtStr;
+ };
+ };
+
+ using MacroList = SmallVector<Entry, 4>;
+
+ /// A list of all the macro entries in the debug_macinfo section.
+ std::vector<MacroList> MacroLists;
+
+public:
+ DWARFDebugMacro() = default;
+
+ /// Print the macro list found within the debug_macinfo section.
+ void dump(raw_ostream &OS) const;
+
+ /// Parse the debug_macinfo section accessible via the 'data' parameter.
+ void parse(DataExtractor data);
+
+ /// Return whether the section has any entries.
+ bool empty() const { return MacroLists.empty(); }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
new file mode 100644
index 000000000..ae57306b9
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
@@ -0,0 +1,80 @@
+//===- DWARFDebugPubTable.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGPUBTABLE_H
+#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGPUBTABLE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFObject.h"
+#include <cstdint>
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+/// Represents structure for holding and parsing .debug_pub* tables.
+class DWARFDebugPubTable {
+public:
+ struct Entry {
+ /// Section offset from the beginning of the compilation unit.
+ uint64_t SecOffset;
+
+ /// An entry of the various gnu_pub* debug sections.
+ dwarf::PubIndexEntryDescriptor Descriptor;
+
+ /// The name of the object as given by the DW_AT_name attribute of the
+ /// referenced DIE.
+ StringRef Name;
+ };
+
+ /// Each table consists of sets of variable length entries. Each set describes
+ /// the names of global objects and functions, or global types, respectively,
+ /// whose definitions are represented by debugging information entries owned
+ /// by a single compilation unit.
+ struct Set {
+ /// The total length of the entries for that set, not including the length
+ /// field itself.
+ uint32_t Length;
+
+ /// This number is specific to the name lookup table and is independent of
+ /// the DWARF version number.
+ uint16_t Version;
+
+ /// The offset from the beginning of the .debug_info section of the
+ /// compilation unit header referenced by the set.
+ uint64_t Offset;
+
+ /// The size in bytes of the contents of the .debug_info section generated
+ /// to represent that compilation unit.
+ uint32_t Size;
+
+ std::vector<Entry> Entries;
+ };
+
+private:
+ std::vector<Set> Sets;
+
+ /// gnu styled tables contains additional information.
+ /// This flag determines whether or not section we parse is debug_gnu* table.
+ bool GnuStyle;
+
+public:
+ DWARFDebugPubTable(const DWARFObject &Obj, const DWARFSection &Sec,
+ bool LittleEndian, bool GnuStyle);
+
+ void dump(raw_ostream &OS) const;
+
+ ArrayRef<Set> getData() { return Sets; }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGPUBTABLE_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
new file mode 100644
index 000000000..2f72c642a
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
@@ -0,0 +1,83 @@
+//===- DWARFDebugRangeList.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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 <cassert>
+#include <cstdint>
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+class DWARFDebugRangeList {
+public:
+ struct RangeListEntry {
+ /// A beginning address offset. This address offset has the size of an
+ /// address and is relative to the applicable base address of the
+ /// compilation unit referencing this range list. It marks the beginning
+ /// of an address range.
+ uint64_t StartAddress;
+ /// An ending address offset. This address offset again has the size of
+ /// an address and is relative to the applicable base address of the
+ /// compilation unit referencing this range list. It marks the first
+ /// address past the end of the address range. The ending address must
+ /// be greater than or equal to the beginning address.
+ uint64_t EndAddress;
+ /// A section index this range belongs to.
+ uint64_t SectionIndex;
+
+ /// The end of any given range list is marked by an end of list entry,
+ /// which consists of a 0 for the beginning address offset
+ /// and a 0 for the ending address offset.
+ bool isEndOfListEntry() const {
+ return (StartAddress == 0) && (EndAddress == 0);
+ }
+
+ /// A base address selection entry consists of:
+ /// 1. The value of the largest representable address offset
+ /// (for example, 0xffffffff when the size of an address is 32 bits).
+ /// 2. An address, which defines the appropriate base address for
+ /// use in interpreting the beginning and ending address offsets of
+ /// subsequent entries of the location list.
+ bool isBaseAddressSelectionEntry(uint8_t AddressSize) const {
+ assert(AddressSize == 4 || AddressSize == 8);
+ if (AddressSize == 4)
+ return StartAddress == -1U;
+ return StartAddress == -1ULL;
+ }
+ };
+
+private:
+ /// Offset in .debug_ranges section.
+ uint64_t Offset;
+ uint8_t AddressSize;
+ std::vector<RangeListEntry> Entries;
+
+public:
+ DWARFDebugRangeList() { clear(); }
+
+ void clear();
+ void dump(raw_ostream &OS) const;
+ Error extract(const DWARFDataExtractor &data, uint64_t *offset_ptr);
+ const std::vector<RangeListEntry> &getEntries() { return Entries; }
+
+ /// getAbsoluteRanges - Returns absolute address ranges defined by this range
+ /// list. Has to be passed base address of the compile unit referencing this
+ /// range list.
+ DWARFAddressRangesVector
+ getAbsoluteRanges(llvm::Optional<object::SectionedAddress> BaseAddr) const;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
new file mode 100644
index 000000000..952c41e18
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
@@ -0,0 +1,64 @@
+//===- DWARFDebugRnglists.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H
+#define LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H
+
+#include "llvm/ADT/Optional.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;
+class DWARFUnit;
+
+/// 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, uint64_t End, uint64_t *OffsetPtr);
+ void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
+ uint64_t &CurrentBase, DIDumpOptions DumpOpts,
+ llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
+ LookupPooledAddress) 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<object::SectionedAddress> BaseAddr,
+ DWARFUnit &U) 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/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDie.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDie.h
new file mode 100644
index 000000000..f7f08b4a4
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFDie.h
@@ -0,0 +1,468 @@
+//===- DWARFDie.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFDIE_H
+#define LLVM_DEBUGINFO_DWARFDIE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/iterator.h"
+#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 <cassert>
+#include <cstdint>
+#include <iterator>
+
+namespace llvm {
+
+class DWARFUnit;
+class raw_ostream;
+
+//===----------------------------------------------------------------------===//
+/// Utility class that carries the DWARF compile/type unit and the debug info
+/// entry in an object.
+///
+/// When accessing information from a debug info entry we always need to DWARF
+/// compile/type unit in order to extract the info correctly as some information
+/// is relative to the compile/type unit. Prior to this class the DWARFUnit and
+/// the DWARFDebugInfoEntry was passed around separately and there was the
+/// possibility for error if the wrong DWARFUnit was used to extract a unit
+/// relative offset. This class helps to ensure that this doesn't happen and
+/// also simplifies the attribute extraction calls by not having to specify the
+/// DWARFUnit for each call.
+class DWARFDie {
+ DWARFUnit *U = nullptr;
+ const DWARFDebugInfoEntry *Die = nullptr;
+
+public:
+ DWARFDie() = default;
+ DWARFDie(DWARFUnit *Unit, const DWARFDebugInfoEntry *D) : U(Unit), Die(D) {}
+
+ bool isValid() const { return U && Die; }
+ explicit operator bool() const { return isValid(); }
+ const DWARFDebugInfoEntry *getDebugInfoEntry() const { return Die; }
+ DWARFUnit *getDwarfUnit() const { return U; }
+
+ /// Get the abbreviation declaration for this DIE.
+ ///
+ /// \returns the abbreviation declaration or NULL for null tags.
+ const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const {
+ assert(isValid() && "must check validity prior to calling");
+ return Die->getAbbreviationDeclarationPtr();
+ }
+
+ /// Get the absolute offset into the debug info or types section.
+ ///
+ /// \returns the DIE offset or -1U if invalid.
+ uint64_t getOffset() const {
+ assert(isValid() && "must check validity prior to calling");
+ return Die->getOffset();
+ }
+
+ dwarf::Tag getTag() const {
+ auto AbbrevDecl = getAbbreviationDeclarationPtr();
+ if (AbbrevDecl)
+ return AbbrevDecl->getTag();
+ return dwarf::DW_TAG_null;
+ }
+
+ bool hasChildren() const {
+ assert(isValid() && "must check validity prior to calling");
+ return Die->hasChildren();
+ }
+
+ /// Returns true for a valid DIE that terminates a sibling chain.
+ bool isNULL() const { return getAbbreviationDeclarationPtr() == nullptr; }
+
+ /// Returns true if DIE represents a subprogram (not inlined).
+ bool isSubprogramDIE() const;
+
+ /// Returns true if DIE represents a subprogram or an inlined subroutine.
+ bool isSubroutineDIE() const;
+
+ /// Get the parent of this DIE object.
+ ///
+ /// \returns a valid DWARFDie instance if this object has a parent or an
+ /// invalid DWARFDie instance if it doesn't.
+ DWARFDie getParent() const;
+
+ /// Get the 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 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.
+ /// \param indent the number of characters to indent each line that is output.
+ void dump(raw_ostream &OS, unsigned indent = 0,
+ DIDumpOptions DumpOpts = DIDumpOptions()) const;
+
+ /// Convenience zero-argument overload for debugging.
+ LLVM_DUMP_METHOD void dump() const;
+
+ /// Extract the specified attribute from this DIE.
+ ///
+ /// Extract an attribute value from this DIE only. This call doesn't look
+ /// for the attribute value in any DW_AT_specification or
+ /// DW_AT_abstract_origin referenced DIEs.
+ ///
+ /// \param Attr the attribute to extract.
+ /// \returns an optional DWARFFormValue that will have the form value if the
+ /// attribute was successfully extracted.
+ Optional<DWARFFormValue> find(dwarf::Attribute Attr) const;
+
+ /// Extract the first value of any attribute in Attrs from this DIE.
+ ///
+ /// Extract the first attribute that matches from this DIE only. This call
+ /// doesn't look for the attribute value in any DW_AT_specification or
+ /// DW_AT_abstract_origin referenced DIEs. The attributes will be searched
+ /// linearly in the order they are specified within Attrs.
+ ///
+ /// \param Attrs an array of DWARF attribute to look for.
+ /// \returns an optional that has a valid DWARFFormValue for the first
+ /// matching attribute in Attrs, or None if none of the attributes in Attrs
+ /// exist in this DIE.
+ Optional<DWARFFormValue> find(ArrayRef<dwarf::Attribute> Attrs) const;
+
+ /// Extract the first value of any attribute in Attrs from this DIE and
+ /// recurse into any DW_AT_specification or DW_AT_abstract_origin referenced
+ /// DIEs.
+ ///
+ /// \param Attrs an array of DWARF attribute to look for.
+ /// \returns an optional that has a valid DWARFFormValue for the first
+ /// matching attribute in Attrs, or None if none of the attributes in Attrs
+ /// exist in this DIE or in any DW_AT_specification or DW_AT_abstract_origin
+ /// DIEs.
+ Optional<DWARFFormValue>
+ findRecursively(ArrayRef<dwarf::Attribute> Attrs) const;
+
+ /// Extract the specified attribute from this DIE as the referenced DIE.
+ ///
+ /// Regardless of the reference type, return the correct DWARFDie instance if
+ /// the attribute exists. The returned DWARFDie object might be from another
+ /// DWARFUnit, but that is all encapsulated in the new DWARFDie object.
+ ///
+ /// Extract an attribute value from this DIE only. This call doesn't look
+ /// for the attribute value in any DW_AT_specification or
+ /// DW_AT_abstract_origin referenced DIEs.
+ ///
+ /// \param Attr the attribute to extract.
+ /// \returns a valid DWARFDie instance if the attribute exists, or an invalid
+ /// DWARFDie object if it doesn't.
+ DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const;
+ DWARFDie getAttributeValueAsReferencedDie(const DWARFFormValue &V) const;
+
+ /// Extract the range base attribute from this DIE as absolute section offset.
+ ///
+ /// This is a utility function that checks for either the DW_AT_rnglists_base
+ /// or DW_AT_GNU_ranges_base attribute.
+ ///
+ /// \returns anm optional absolute section offset value for the attribute.
+ Optional<uint64_t> getRangesBaseAttribute() const;
+
+ /// Get the DW_AT_high_pc attribute value as an address.
+ ///
+ /// In DWARF version 4 and later the high PC can be encoded as an offset from
+ /// the DW_AT_low_pc. This function takes care of extracting the value as an
+ /// address or offset and adds it to the low PC if needed and returns the
+ /// value as an optional in case the DIE doesn't have a DW_AT_high_pc
+ /// attribute.
+ ///
+ /// \param LowPC the low PC that might be needed to calculate the high PC.
+ /// \returns an optional address value for the attribute.
+ Optional<uint64_t> getHighPC(uint64_t LowPC) const;
+
+ /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
+ /// Returns true if both attributes are present.
+ bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC,
+ uint64_t &SectionIndex) const;
+
+ /// Get the address ranges for this DIE.
+ ///
+ /// Get the hi/low PC range if both attributes are available or exrtracts the
+ /// non-contiguous address ranges from the DW_AT_ranges attribute.
+ ///
+ /// Extracts the range information from this DIE only. This call doesn't look
+ /// for the range in any DW_AT_specification or DW_AT_abstract_origin DIEs.
+ ///
+ /// \returns a address range vector that might be empty if no address range
+ /// information is available.
+ Expected<DWARFAddressRangesVector> getAddressRanges() const;
+
+ /// Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any
+ /// of its children.
+ ///
+ /// Get the hi/low PC range if both attributes are available or exrtracts the
+ /// non-contiguous address ranges from the DW_AT_ranges attribute for this DIE
+ /// and all children.
+ ///
+ /// \param Ranges the addres range vector to fill in.
+ void collectChildrenAddressRanges(DWARFAddressRangesVector &Ranges) const;
+
+ bool addressRangeContainsAddress(const uint64_t Address) const;
+
+ /// If a DIE represents a subprogram (or inlined subroutine), returns its
+ /// mangled name (or short name, if mangled is missing). This name may be
+ /// fetched from specification or abstract origin for this subprogram.
+ /// Returns null if no name is found.
+ const char *getSubroutineName(DINameKind Kind) const;
+
+ /// Return the DIE name resolving DW_AT_sepcification or DW_AT_abstract_origin
+ /// references if necessary. Returns null if no name is found.
+ const char *getName(DINameKind Kind) const;
+
+ /// Returns the declaration line (start line) for a DIE, assuming it specifies
+ /// a subprogram. This may be fetched from specification or abstract origin
+ /// for this subprogram by resolving DW_AT_sepcification or
+ /// DW_AT_abstract_origin references if necessary.
+ uint64_t getDeclLine() const;
+
+ /// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column
+ /// from DIE (or zeroes if they are missing). This function looks for
+ /// DW_AT_call attributes in this DIE only, it will not resolve the attribute
+ /// values in any DW_AT_specification or DW_AT_abstract_origin DIEs.
+ /// \param CallFile filled in with non-zero if successful, zero if there is no
+ /// DW_AT_call_file attribute in this DIE.
+ /// \param CallLine filled in with non-zero if successful, zero if there is no
+ /// DW_AT_call_line attribute in this DIE.
+ /// \param CallColumn filled in with non-zero if successful, zero if there is
+ /// no DW_AT_call_column attribute in this DIE.
+ /// \param CallDiscriminator filled in with non-zero if successful, zero if
+ /// there is no DW_AT_GNU_discriminator attribute in this DIE.
+ void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
+ uint32_t &CallColumn, uint32_t &CallDiscriminator) const;
+
+ class attribute_iterator;
+
+ /// Get an iterator range to all attributes in the current DIE only.
+ ///
+ /// \returns an iterator range for the attributes of the current DIE.
+ iterator_range<attribute_iterator> attributes() const;
+
+ class iterator;
+
+ iterator begin() const;
+ iterator end() const;
+
+ std::reverse_iterator<iterator> rbegin() const;
+ std::reverse_iterator<iterator> rend() const;
+
+ iterator_range<iterator> children() const;
+};
+
+class DWARFDie::attribute_iterator
+ : public iterator_facade_base<attribute_iterator, std::forward_iterator_tag,
+ const DWARFAttribute> {
+ /// The DWARF DIE we are extracting attributes from.
+ DWARFDie Die;
+ /// The value vended to clients via the operator*() or operator->().
+ DWARFAttribute AttrValue;
+ /// The attribute index within the abbreviation declaration in Die.
+ uint32_t Index;
+
+ friend bool operator==(const attribute_iterator &LHS,
+ const attribute_iterator &RHS);
+
+ /// Update the attribute index and attempt to read the attribute value. If the
+ /// attribute is able to be read, update AttrValue and the Index member
+ /// variable. If the attribute value is not able to be read, an appropriate
+ /// error will be set if the Err member variable is non-NULL and the iterator
+ /// will be set to the end value so iteration stops.
+ void updateForIndex(const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I);
+
+public:
+ attribute_iterator() = delete;
+ 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; }
+};
+
+inline bool operator==(const DWARFDie::attribute_iterator &LHS,
+ const DWARFDie::attribute_iterator &RHS) {
+ return LHS.Index == RHS.Index;
+}
+
+inline bool operator!=(const DWARFDie::attribute_iterator &LHS,
+ const DWARFDie::attribute_iterator &RHS) {
+ return !(LHS == RHS);
+}
+
+inline bool operator==(const DWARFDie &LHS, const DWARFDie &RHS) {
+ return LHS.getDebugInfoEntry() == RHS.getDebugInfoEntry() &&
+ LHS.getDwarfUnit() == RHS.getDwarfUnit();
+}
+
+inline bool operator!=(const DWARFDie &LHS, const DWARFDie &RHS) {
+ return !(LHS == RHS);
+}
+
+inline bool operator<(const DWARFDie &LHS, const DWARFDie &RHS) {
+ return LHS.getOffset() < RHS.getOffset();
+}
+
+class DWARFDie::iterator
+ : public iterator_facade_base<iterator, std::bidirectional_iterator_tag,
+ const DWARFDie> {
+ DWARFDie Die;
+
+ friend std::reverse_iterator<llvm::DWARFDie::iterator>;
+ friend bool operator==(const DWARFDie::iterator &LHS,
+ const DWARFDie::iterator &RHS);
+
+public:
+ iterator() = default;
+
+ explicit iterator(DWARFDie D) : Die(D) {}
+
+ iterator &operator++() {
+ Die = Die.getSibling();
+ return *this;
+ }
+
+ iterator &operator--() {
+ Die = Die.getPreviousSibling();
+ return *this;
+ }
+
+ const DWARFDie &operator*() const { return Die; }
+};
+
+inline bool operator==(const DWARFDie::iterator &LHS,
+ const DWARFDie::iterator &RHS) {
+ return LHS.Die == RHS.Die;
+}
+
+inline bool operator!=(const DWARFDie::iterator &LHS,
+ const DWARFDie::iterator &RHS) {
+ return !(LHS == RHS);
+}
+
+// These inline functions must follow the DWARFDie::iterator definition above
+// as they use functions from that class.
+inline DWARFDie::iterator DWARFDie::begin() const {
+ return iterator(getFirstChild());
+}
+
+inline DWARFDie::iterator DWARFDie::end() const {
+ return iterator(getLastChild());
+}
+
+inline iterator_range<DWARFDie::iterator> DWARFDie::children() const {
+ return make_range(begin(), end());
+}
+
+} // end namespace llvm
+
+namespace std {
+
+template <>
+class reverse_iterator<llvm::DWARFDie::iterator>
+ : public llvm::iterator_facade_base<
+ reverse_iterator<llvm::DWARFDie::iterator>,
+ bidirectional_iterator_tag, const llvm::DWARFDie> {
+
+private:
+ llvm::DWARFDie Die;
+ bool AtEnd;
+
+public:
+ reverse_iterator(llvm::DWARFDie::iterator It)
+ : Die(It.Die), AtEnd(!It.Die.getPreviousSibling()) {
+ if (!AtEnd)
+ Die = Die.getPreviousSibling();
+ }
+
+ llvm::DWARFDie::iterator base() const {
+ return llvm::DWARFDie::iterator(AtEnd ? Die : Die.getSibling());
+ }
+
+ reverse_iterator<llvm::DWARFDie::iterator> &operator++() {
+ assert(!AtEnd && "Incrementing rend");
+ llvm::DWARFDie D = Die.getPreviousSibling();
+ if (D)
+ Die = D;
+ else
+ AtEnd = true;
+ return *this;
+ }
+
+ reverse_iterator<llvm::DWARFDie::iterator> &operator--() {
+ if (AtEnd) {
+ AtEnd = false;
+ return *this;
+ }
+ Die = Die.getSibling();
+ assert(!Die.isNULL() && "Decrementing rbegin");
+ return *this;
+ }
+
+ const llvm::DWARFDie &operator*() const {
+ assert(Die.isValid());
+ return Die;
+ }
+
+ // FIXME: We should be able to specify the equals operator as a friend, but
+ // that causes the compiler to think the operator overload is ambiguous
+ // with the friend declaration and the actual definition as candidates.
+ bool equals(const reverse_iterator<llvm::DWARFDie::iterator> &RHS) const {
+ return Die == RHS.Die && AtEnd == RHS.AtEnd;
+ }
+};
+
+} // namespace std
+
+namespace llvm {
+
+inline bool operator==(const std::reverse_iterator<DWARFDie::iterator> &LHS,
+ const std::reverse_iterator<DWARFDie::iterator> &RHS) {
+ return LHS.equals(RHS);
+}
+
+inline bool operator!=(const std::reverse_iterator<DWARFDie::iterator> &LHS,
+ const std::reverse_iterator<DWARFDie::iterator> &RHS) {
+ return !(LHS == RHS);
+}
+
+inline std::reverse_iterator<DWARFDie::iterator> DWARFDie::rbegin() const {
+ return llvm::make_reverse_iterator(end());
+}
+
+inline std::reverse_iterator<DWARFDie::iterator> DWARFDie::rend() const {
+ return llvm::make_reverse_iterator(begin());
+}
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFDIE_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFExpression.h
new file mode 100644
index 000000000..456d9df95
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFExpression.h
@@ -0,0 +1,159 @@
+//===--- DWARFExpression.h - DWARF Expression handling ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFEXPRESSION_H
+#define LLVM_DEBUGINFO_DWARFEXPRESSION_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/DataExtractor.h"
+
+namespace llvm {
+class DWARFUnit;
+class MCRegisterInfo;
+class raw_ostream;
+
+class DWARFExpression {
+public:
+ class iterator;
+
+ /// This class represents an Operation in the Expression. Each operation can
+ /// have up to 2 oprerands.
+ ///
+ /// An Operation can be in Error state (check with isError()). This
+ /// means that it couldn't be decoded successfully and if it is the
+ /// case, all others fields contain undefined values.
+ class Operation {
+ public:
+ /// Size and signedness of expression operations' operands.
+ enum Encoding : uint8_t {
+ Size1 = 0,
+ Size2 = 1,
+ Size4 = 2,
+ Size8 = 3,
+ SizeLEB = 4,
+ SizeAddr = 5,
+ SizeRefAddr = 6,
+ SizeBlock = 7, ///< Preceding operand contains block size
+ BaseTypeRef = 8,
+ SignBit = 0x80,
+ SignedSize1 = SignBit | Size1,
+ SignedSize2 = SignBit | Size2,
+ SignedSize4 = SignBit | Size4,
+ SignedSize8 = SignBit | Size8,
+ SignedSizeLEB = SignBit | SizeLEB,
+ SizeNA = 0xFF ///< Unused operands get this encoding.
+ };
+
+ enum DwarfVersion : uint8_t {
+ DwarfNA, ///< Serves as a marker for unused entries
+ Dwarf2 = 2,
+ Dwarf3,
+ Dwarf4,
+ Dwarf5
+ };
+
+ /// Description of the encoding of one expression Op.
+ struct Description {
+ DwarfVersion Version; ///< Dwarf version where the Op was introduced.
+ Encoding Op[2]; ///< Encoding for Op operands, or SizeNA.
+
+ Description(DwarfVersion Version = DwarfNA, Encoding Op1 = SizeNA,
+ Encoding Op2 = SizeNA)
+ : Version(Version) {
+ Op[0] = Op1;
+ Op[1] = Op2;
+ }
+ };
+
+ private:
+ friend class DWARFExpression::iterator;
+ uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>.
+ Description Desc;
+ bool Error;
+ uint64_t EndOffset;
+ uint64_t Operands[2];
+ uint64_t OperandEndOffsets[2];
+
+ public:
+ Description &getDescription() { return Desc; }
+ uint8_t getCode() { return Opcode; }
+ uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; }
+ uint64_t getOperandEndOffset(unsigned Idx) { return OperandEndOffsets[Idx]; }
+ uint64_t getEndOffset() { return EndOffset; }
+ bool extract(DataExtractor Data, uint16_t Version, uint8_t AddressSize,
+ uint64_t Offset);
+ bool isError() { return Error; }
+ bool print(raw_ostream &OS, const DWARFExpression *Expr,
+ const MCRegisterInfo *RegInfo, DWARFUnit *U, bool isEH);
+ bool verify(DWARFUnit *U);
+ };
+
+ /// An iterator to go through the expression operations.
+ class iterator
+ : public iterator_facade_base<iterator, std::forward_iterator_tag,
+ Operation> {
+ friend class DWARFExpression;
+ const DWARFExpression *Expr;
+ uint64_t Offset;
+ Operation Op;
+ iterator(const DWARFExpression *Expr, uint64_t Offset)
+ : Expr(Expr), Offset(Offset) {
+ Op.Error =
+ Offset >= Expr->Data.getData().size() ||
+ !Op.extract(Expr->Data, Expr->Version, Expr->AddressSize, Offset);
+ }
+
+ public:
+ class Operation &operator++() {
+ Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset;
+ Op.Error =
+ Offset >= Expr->Data.getData().size() ||
+ !Op.extract(Expr->Data, Expr->Version, Expr->AddressSize, Offset);
+ return Op;
+ }
+
+ class Operation &operator*() {
+ return Op;
+ }
+
+ // Comparison operators are provided out of line.
+ friend bool operator==(const iterator &, const iterator &);
+ };
+
+ DWARFExpression(DataExtractor Data, uint16_t Version, uint8_t AddressSize)
+ : Data(Data), Version(Version), AddressSize(AddressSize) {
+ assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2);
+ }
+
+ iterator begin() const { return iterator(this, 0); }
+ iterator end() const { return iterator(this, Data.getData().size()); }
+
+ void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, DWARFUnit *U,
+ bool IsEH = false) const;
+
+ bool verify(DWARFUnit *U);
+
+private:
+ DataExtractor Data;
+ uint16_t Version;
+ uint8_t AddressSize;
+};
+
+inline bool operator==(const DWARFExpression::iterator &LHS,
+ const DWARFExpression::iterator &RHS) {
+ return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset;
+}
+
+inline bool operator!=(const DWARFExpression::iterator &LHS,
+ const DWARFExpression::iterator &RHS) {
+ return !(LHS == RHS);
+}
+}
+#endif
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
new file mode 100644
index 000000000..6fec6fcb6
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
@@ -0,0 +1,321 @@
+//===- DWARFFormValue.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFFORMVALUE_H
+#define LLVM_DEBUGINFO_DWARFFORMVALUE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include <cstdint>
+
+namespace llvm {
+
+class DWARFContext;
+class DWARFUnit;
+class raw_ostream;
+
+class DWARFFormValue {
+public:
+ enum FormClass {
+ FC_Unknown,
+ FC_Address,
+ FC_Block,
+ FC_Constant,
+ FC_String,
+ FC_Flag,
+ FC_Reference,
+ FC_Indirect,
+ FC_SectionOffset,
+ FC_Exprloc
+ };
+
+private:
+ struct ValueType {
+ ValueType() { uval = 0; }
+ ValueType(int64_t V) : sval(V) {}
+ ValueType(uint64_t V) : uval(V) {}
+ ValueType(const char *V) : cstr(V) {}
+
+ union {
+ uint64_t uval;
+ int64_t sval;
+ const char *cstr;
+ };
+ const uint8_t *data = nullptr;
+ uint64_t SectionIndex; /// Section index for reference forms.
+ };
+
+ 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.
+
+ DWARFFormValue(dwarf::Form F, ValueType V) : Form(F), Value(V) {}
+
+public:
+ DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F) {}
+
+ static DWARFFormValue createFromSValue(dwarf::Form F, int64_t V);
+ static DWARFFormValue createFromUValue(dwarf::Form F, uint64_t V);
+ static DWARFFormValue createFromPValue(dwarf::Form F, const char *V);
+ static DWARFFormValue createFromBlockValue(dwarf::Form F,
+ ArrayRef<uint8_t> D);
+ static DWARFFormValue createFromUnit(dwarf::Form F, const DWARFUnit *Unit,
+ uint64_t *OffsetPtr);
+
+ dwarf::Form getForm() const { return Form; }
+ uint64_t getRawUValue() const { return Value.uval; }
+
+ bool isFormClass(FormClass FC) const;
+ const DWARFUnit *getUnit() const { return U; }
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const;
+ void dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts,
+ object::SectionedAddress SA) const;
+ static void dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS,
+ DIDumpOptions DumpOpts, uint64_t SectionIndex);
+
+ /// Extracts a value in \p Data at offset \p *OffsetPtr. The information
+ /// in \p FormParams is needed to interpret some forms. The optional
+ /// \p Context and \p Unit allows extracting information if the form refers
+ /// to other sections (e.g., .debug_str).
+ bool extractValue(const DWARFDataExtractor &Data, uint64_t *OffsetPtr,
+ dwarf::FormParams FormParams,
+ const DWARFContext *Context = nullptr,
+ const DWARFUnit *Unit = nullptr);
+
+ bool extractValue(const DWARFDataExtractor &Data, uint64_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;
+ }
+
+ /// getAsFoo functions below return the extracted value as Foo if only
+ /// DWARFFormValue has form class is suitable for representing Foo.
+ Optional<uint64_t> getAsReference() const;
+ struct UnitOffset {
+ DWARFUnit *Unit;
+ uint64_t Offset;
+ };
+ Optional<UnitOffset> getAsRelativeReference() const;
+ Optional<uint64_t> getAsUnsignedConstant() const;
+ Optional<int64_t> getAsSignedConstant() const;
+ Optional<const char *> getAsCString() const;
+ Optional<uint64_t> getAsAddress() const;
+ Optional<object::SectionedAddress> getAsSectionedAddress() const;
+ Optional<uint64_t> getAsSectionOffset() const;
+ Optional<ArrayRef<uint8_t>> getAsBlock() const;
+ Optional<uint64_t> getAsCStringOffset() const;
+ Optional<uint64_t> getAsReferenceUVal() const;
+
+ /// Skip a form's value in \p DebugInfoData at the offset specified by
+ /// \p OffsetPtr.
+ ///
+ /// Skips the bytes for the current form and updates the offset.
+ ///
+ /// \param DebugInfoData The data where we want to skip the value.
+ /// \param OffsetPtr A reference to the offset that will be updated.
+ /// \param Params DWARF parameters to help interpret forms.
+ /// \returns true on success, false if the form was not skipped.
+ bool skipValue(DataExtractor DebugInfoData, uint64_t *OffsetPtr,
+ const dwarf::FormParams Params) const {
+ return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, Params);
+ }
+
+ /// Skip a form's value in \p DebugInfoData at the offset specified by
+ /// \p OffsetPtr.
+ ///
+ /// Skips the bytes for the specified form and updates the offset.
+ ///
+ /// \param Form The DW_FORM enumeration that indicates the form to skip.
+ /// \param DebugInfoData The data where we want to skip the value.
+ /// \param OffsetPtr A reference to the offset that will be updated.
+ /// \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,
+ uint64_t *OffsetPtr,
+ const dwarf::FormParams FormParams);
+
+private:
+ void dumpString(raw_ostream &OS) const;
+};
+
+namespace dwarf {
+
+/// Take an optional DWARFFormValue and try to extract a string value from it.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and was a string.
+inline Optional<const char *> toString(const Optional<DWARFFormValue> &V) {
+ if (V)
+ return V->getAsCString();
+ return None;
+}
+
+/// Take an optional DWARFFormValue and try to extract a string value from it.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and was a string.
+inline StringRef toStringRef(const Optional<DWARFFormValue> &V,
+ StringRef Default = {}) {
+ if (V)
+ if (auto S = V->getAsCString())
+ return *S;
+ return Default;
+}
+
+/// Take an optional DWARFFormValue and extract a string value from it.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \param Default the default value to return in case of failure.
+/// \returns the string value or Default if the V doesn't have a value or the
+/// form value's encoding wasn't a string.
+inline const char *toString(const Optional<DWARFFormValue> &V,
+ const char *Default) {
+ return toString(V).getValueOr(Default);
+}
+
+/// Take an optional DWARFFormValue and try to extract an unsigned constant.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and has a unsigned constant form.
+inline Optional<uint64_t> toUnsigned(const Optional<DWARFFormValue> &V) {
+ if (V)
+ return V->getAsUnsignedConstant();
+ return None;
+}
+
+/// Take an optional DWARFFormValue and extract a unsigned constant.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \param Default the default value to return in case of failure.
+/// \returns the extracted unsigned value or Default if the V doesn't have a
+/// value or the form value's encoding wasn't an unsigned constant form.
+inline uint64_t toUnsigned(const Optional<DWARFFormValue> &V,
+ uint64_t Default) {
+ return toUnsigned(V).getValueOr(Default);
+}
+
+/// Take an optional DWARFFormValue and try to extract an reference.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and has a reference form.
+inline Optional<uint64_t> toReference(const Optional<DWARFFormValue> &V) {
+ if (V)
+ return V->getAsReference();
+ return None;
+}
+
+/// Take an optional DWARFFormValue and extract a reference.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \param Default the default value to return in case of failure.
+/// \returns the extracted reference value or Default if the V doesn't have a
+/// value or the form value's encoding wasn't a reference form.
+inline uint64_t toReference(const Optional<DWARFFormValue> &V,
+ uint64_t Default) {
+ return toReference(V).getValueOr(Default);
+}
+
+/// Take an optional DWARFFormValue and try to extract an signed constant.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and has a signed constant form.
+inline Optional<int64_t> toSigned(const Optional<DWARFFormValue> &V) {
+ if (V)
+ return V->getAsSignedConstant();
+ return None;
+}
+
+/// Take an optional DWARFFormValue and extract a signed integer.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \param Default the default value to return in case of failure.
+/// \returns the extracted signed integer value or Default if the V doesn't
+/// have a value or the form value's encoding wasn't a signed integer form.
+inline int64_t toSigned(const Optional<DWARFFormValue> &V, int64_t Default) {
+ return toSigned(V).getValueOr(Default);
+}
+
+/// Take an optional DWARFFormValue and try to extract an address.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and has a address form.
+inline Optional<uint64_t> toAddress(const Optional<DWARFFormValue> &V) {
+ if (V)
+ return V->getAsAddress();
+ return None;
+}
+
+inline Optional<object::SectionedAddress>
+toSectionedAddress(const Optional<DWARFFormValue> &V) {
+ if (V)
+ return V->getAsSectionedAddress();
+ return None;
+}
+
+/// Take an optional DWARFFormValue and extract a address.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \param Default the default value to return in case of failure.
+/// \returns the extracted address value or Default if the V doesn't have a
+/// value or the form value's encoding wasn't an address form.
+inline uint64_t toAddress(const Optional<DWARFFormValue> &V, uint64_t Default) {
+ return toAddress(V).getValueOr(Default);
+}
+
+/// Take an optional DWARFFormValue and try to extract an section offset.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and has a section offset form.
+inline Optional<uint64_t> toSectionOffset(const Optional<DWARFFormValue> &V) {
+ if (V)
+ return V->getAsSectionOffset();
+ return None;
+}
+
+/// Take an optional DWARFFormValue and extract a section offset.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \param Default the default value to return in case of failure.
+/// \returns the extracted section offset value or Default if the V doesn't
+/// have a value or the form value's encoding wasn't a section offset form.
+inline uint64_t toSectionOffset(const Optional<DWARFFormValue> &V,
+ uint64_t Default) {
+ return toSectionOffset(V).getValueOr(Default);
+}
+
+/// Take an optional DWARFFormValue and try to extract block data.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and has a block form.
+inline Optional<ArrayRef<uint8_t>> toBlock(const Optional<DWARFFormValue> &V) {
+ if (V)
+ return V->getAsBlock();
+ return None;
+}
+
+} // end namespace dwarf
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFFORMVALUE_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h
new file mode 100644
index 000000000..38cd42ddb
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h
@@ -0,0 +1,82 @@
+//===- DWARFGdbIndex.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFGDBINDEX_H
+#define LLVM_DEBUGINFO_DWARF_DWARFGDBINDEX_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataExtractor.h"
+#include <cstdint>
+#include <utility>
+
+namespace llvm {
+
+class raw_ostream;
+
+class DWARFGdbIndex {
+ uint32_t Version;
+
+ uint32_t CuListOffset;
+ uint32_t TuListOffset;
+ uint32_t AddressAreaOffset;
+ uint32_t SymbolTableOffset;
+ uint32_t ConstantPoolOffset;
+
+ struct CompUnitEntry {
+ uint64_t Offset; /// Offset of a CU in the .debug_info section.
+ uint64_t Length; /// Length of that CU.
+ };
+ SmallVector<CompUnitEntry, 0> CuList;
+
+ struct TypeUnitEntry {
+ uint64_t Offset;
+ uint64_t TypeOffset;
+ uint64_t TypeSignature;
+ };
+ SmallVector<TypeUnitEntry, 0> TuList;
+
+ struct AddressEntry {
+ uint64_t LowAddress; /// The low address.
+ uint64_t HighAddress; /// The high address.
+ uint32_t CuIndex; /// The CU index.
+ };
+ SmallVector<AddressEntry, 0> AddressArea;
+
+ struct SymTableEntry {
+ uint32_t NameOffset; /// Offset of the symbol's name in the constant pool.
+ uint32_t VecOffset; /// Offset of the CU vector in the constant pool.
+ };
+ SmallVector<SymTableEntry, 0> SymbolTable;
+
+ /// Each value is CU index + attributes.
+ SmallVector<std::pair<uint32_t, SmallVector<uint32_t, 0>>, 0>
+ ConstantPoolVectors;
+
+ StringRef ConstantPoolStrings;
+ uint32_t StringPoolOffset;
+
+ void dumpCUList(raw_ostream &OS) const;
+ void dumpTUList(raw_ostream &OS) const;
+ void dumpAddressArea(raw_ostream &OS) const;
+ void dumpSymbolTable(raw_ostream &OS) const;
+ void dumpConstantPool(raw_ostream &OS) const;
+
+ bool parseImpl(DataExtractor Data);
+
+public:
+ void dump(raw_ostream &OS);
+ void parse(DataExtractor Data);
+
+ bool HasContent = false;
+ bool HasError = false;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFGDBINDEX_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFListTable.h
new file mode 100644
index 000000000..496fdb247
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFListTable.h
@@ -0,0 +1,290 @@
+//===- DWARFListTable.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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/Errc.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.
+ uint64_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:
+ const ListEntries &getEntries() const { return Entries; }
+ bool empty() const { return Entries.empty(); }
+ void clear() { Entries.clear(); }
+ Error extract(DWARFDataExtractor Data, uint64_t HeaderOffset, uint64_t End,
+ uint64_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.
+ uint64_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<uint64_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.
+ uint64_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();
+ }
+ uint64_t getHeaderOffset() const { return HeaderOffset; }
+ uint8_t getAddrSize() const { return HeaderData.AddrSize; }
+ uint64_t getLength() const { return HeaderData.Length; }
+ uint16_t getVersion() const { return HeaderData.Version; }
+ StringRef getSectionName() const { return SectionName; }
+ StringRef getListTypeString() const { return ListTypeString; }
+ dwarf::DwarfFormat getFormat() const { return Format; }
+
+ /// Return the size of the table header including the length but not including
+ /// the offsets.
+ static uint8_t getHeaderSize(dwarf::DwarfFormat Format) {
+ switch (Format) {
+ case dwarf::DwarfFormat::DWARF32:
+ return 12;
+ case dwarf::DwarfFormat::DWARF64:
+ return 20;
+ }
+ llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64");
+ }
+
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
+ Optional<uint64_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, uint64_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).
+ uint64_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<uint64_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, uint64_t *OffsetPtr) {
+ return Header.extract(Data, OffsetPtr);
+ }
+ /// Extract an entire table, including all list entries.
+ Error extract(DWARFDataExtractor Data, uint64_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, uint64_t Offset);
+
+ uint64_t getHeaderOffset() const { return Header.getHeaderOffset(); }
+ uint8_t getAddrSize() const { return Header.getAddrSize(); }
+ dwarf::DwarfFormat getFormat() const { return Header.getFormat(); }
+
+ void dump(raw_ostream &OS,
+ llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
+ LookupPooledAddress,
+ DIDumpOptions DumpOpts = {}) const;
+
+ /// Return the contents of the offset entry designated by a given index.
+ Optional<uint64_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 {
+ return DWARFListTableHeader::getHeaderSize(getFormat());
+ }
+
+ uint64_t length() { return Header.length(); }
+};
+
+template <typename DWARFListType>
+Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data,
+ uint64_t *OffsetPtr) {
+ clear();
+ if (Error E = extractHeaderAndOffsets(Data, OffsetPtr))
+ return E;
+
+ Data.setAddressSize(Header.getAddrSize());
+ uint64_t End = getHeaderOffset() + Header.length();
+ while (*OffsetPtr < End) {
+ DWARFListType CurrentList;
+ uint64_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,
+ uint64_t HeaderOffset, uint64_t End,
+ uint64_t *OffsetPtr,
+ StringRef SectionName,
+ StringRef ListTypeString) {
+ if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End)
+ return createStringError(errc::invalid_argument,
+ "invalid %s list offset 0x%" PRIx64,
+ 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 createStringError(errc::illegal_byte_sequence,
+ "no end of list marker detected at end of %s table "
+ "starting at offset 0x%" PRIx64,
+ SectionName.data(), HeaderOffset);
+}
+
+template <typename DWARFListType>
+void DWARFListTableBase<DWARFListType>::dump(
+ raw_ostream &OS,
+ llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
+ LookupPooledAddress,
+ 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, LookupPooledAddress);
+}
+
+template <typename DWARFListType>
+Expected<DWARFListType>
+DWARFListTableBase<DWARFListType>::findList(DWARFDataExtractor Data,
+ uint64_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;
+ uint64_t End = getHeaderOffset() + Header.length();
+ uint64_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/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFObject.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFObject.h
new file mode 100644
index 000000000..88fe3f434
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFObject.h
@@ -0,0 +1,85 @@
+//===- DWARFObject.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===-----------------------------------------------------------------------===/
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFOBJECT_H
+#define LLVM_DEBUGINFO_DWARF_DWARFOBJECT_H
+
+#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/Object/ObjectFile.h"
+
+namespace llvm {
+// This is responsible for low level access to the object file. It
+// knows how to find the required sections and compute relocated
+// values.
+// The default implementations of the get<Section> methods return dummy values.
+// This is to allow clients that only need some of those to implement just the
+// ones they need. We can't use unreachable for as many cases because the parser
+// implementation is eager and will call some of these methods even if the
+// result is not used.
+class DWARFObject {
+ DWARFSection Dummy;
+
+public:
+ virtual ~DWARFObject() = default;
+ virtual StringRef getFileName() const { llvm_unreachable("unimplemented"); }
+ virtual const object::ObjectFile *getFile() const { return nullptr; }
+ virtual ArrayRef<SectionName> getSectionNames() const { return {}; }
+ virtual bool isLittleEndian() const = 0;
+ virtual uint8_t getAddressSize() const { llvm_unreachable("unimplemented"); }
+ virtual void
+ forEachInfoSections(function_ref<void(const DWARFSection &)> F) const {}
+ virtual void
+ forEachTypesSections(function_ref<void(const DWARFSection &)> F) const {}
+ virtual StringRef getAbbrevSection() const { return ""; }
+ virtual const DWARFSection &getLocSection() const { return Dummy; }
+ virtual const DWARFSection &getLoclistsSection() const { return Dummy; }
+ virtual StringRef getArangesSection() const { return ""; }
+ virtual const DWARFSection &getFrameSection() const { return Dummy; }
+ virtual const DWARFSection &getEHFrameSection() const { return Dummy; }
+ virtual const DWARFSection &getLineSection() const { return Dummy; }
+ virtual StringRef getLineStrSection() const { return ""; }
+ virtual StringRef getStrSection() const { return ""; }
+ virtual const DWARFSection &getRangesSection() const { return Dummy; }
+ virtual const DWARFSection &getRnglistsSection() const { return Dummy; }
+ virtual StringRef getMacinfoSection() const { return ""; }
+ virtual const DWARFSection &getPubnamesSection() const { return Dummy; }
+ virtual const DWARFSection &getPubtypesSection() const { return Dummy; }
+ virtual const DWARFSection &getGnuPubnamesSection() const { return Dummy; }
+ virtual const DWARFSection &getGnuPubtypesSection() const { return Dummy; }
+ virtual const DWARFSection &getStrOffsetsSection() const { return Dummy; }
+ virtual void
+ forEachInfoDWOSections(function_ref<void(const DWARFSection &)> F) const {}
+ virtual void
+ forEachTypesDWOSections(function_ref<void(const DWARFSection &)> F) const {}
+ virtual StringRef getAbbrevDWOSection() const { return ""; }
+ virtual const DWARFSection &getLineDWOSection() const { return Dummy; }
+ virtual const DWARFSection &getLocDWOSection() const { return Dummy; }
+ virtual StringRef getStrDWOSection() const { return ""; }
+ virtual const DWARFSection &getStrOffsetsDWOSection() const {
+ return Dummy;
+ }
+ virtual const DWARFSection &getRangesDWOSection() 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 &getNamesSection() const { return Dummy; }
+ virtual const DWARFSection &getAppleObjCSection() const { return Dummy; }
+ virtual StringRef getCUIndexSection() const { return ""; }
+ virtual StringRef getGdbIndexSection() const { return ""; }
+ virtual StringRef getTUIndexSection() const { return ""; }
+ virtual Optional<RelocAddrEntry> find(const DWARFSection &Sec,
+ uint64_t Pos) const = 0;
+};
+
+} // namespace llvm
+#endif
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
new file mode 100644
index 000000000..3add71194
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
@@ -0,0 +1,38 @@
+//===- DWARFRelocMap.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFRELOCMAP_H
+#define LLVM_DEBUGINFO_DWARF_DWARFRELOCMAP_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Object/RelocationResolver.h"
+#include <cstdint>
+
+namespace llvm {
+
+/// RelocAddrEntry contains relocated value and section index.
+/// Section index is -1LL if relocation points to absolute symbol.
+struct RelocAddrEntry {
+ uint64_t SectionIndex;
+ object::RelocationRef Reloc;
+ uint64_t SymbolValue;
+ Optional<object::RelocationRef> Reloc2;
+ uint64_t SymbolValue2;
+ object::RelocationResolver Resolver;
+};
+
+/// In place of applying the relocations to the data we've read from disk we use
+/// a separate mapping table to the side and checking that at locations in the
+/// dwarf where we expect relocated values. This adds a bit of complexity to the
+/// dwarf parsing/extraction at the benefit of not allocating memory for the
+/// entire size of the debug info sections.
+using RelocAddrMap = DenseMap<uint64_t, RelocAddrEntry>;
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFRELOCMAP_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFSection.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFSection.h
new file mode 100644
index 000000000..054524d36
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFSection.h
@@ -0,0 +1,27 @@
+//===- DWARFSection.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFSECTION_H
+#define LLVM_DEBUGINFO_DWARF_DWARFSECTION_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+struct DWARFSection {
+ StringRef Data;
+};
+
+struct SectionName {
+ StringRef Name;
+ bool IsNameUnique;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFSECTION_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
new file mode 100644
index 000000000..c95bdcbd8
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
@@ -0,0 +1,46 @@
+//===- DWARFTypeUnit.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFTYPEUNIT_H
+#define LLVM_DEBUGINFO_DWARF_DWARFTYPEUNIT_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+#include "llvm/Support/DataExtractor.h"
+#include <cstdint>
+
+namespace llvm {
+
+class DWARFContext;
+class DWARFDebugAbbrev;
+struct DWARFSection;
+class raw_ostream;
+
+class DWARFTypeUnit : public DWARFUnit {
+public:
+ DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA,
+ const DWARFSection *RS, const DWARFSection *LocSection,
+ StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
+ const DWARFSection &LS, bool LE, bool IsDWO,
+ const DWARFUnitVector &UnitVector)
+ : DWARFUnit(Context, Section, Header, DA, RS, LocSection, SS, SOS, AOS,
+ LS, LE, IsDWO, UnitVector) {}
+
+ uint64_t getTypeHash() const { return getHeader().getTypeHash(); }
+ uint64_t getTypeOffset() const { return getHeader().getTypeOffset(); }
+
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override;
+ // Enable LLVM-style RTTI.
+ static bool classof(const DWARFUnit *U) { return U->isTypeUnit(); }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFTYPEUNIT_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFUnit.h
new file mode 100644
index 000000000..51de114a3
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -0,0 +1,527 @@
+//===- DWARFUnit.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
+#define LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#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"
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+#include "llvm/Support/DataExtractor.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+class DWARFAbbreviationDeclarationSet;
+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.
+ uint64_t Offset = 0;
+ // Version, address size, and DWARF format.
+ dwarf::FormParams FormParams;
+ uint64_t Length = 0;
+ uint64_t AbbrOffset = 0;
+
+ // For DWO units only.
+ const DWARFUnitIndex::Entry *IndexEntry = nullptr;
+
+ // For type units only.
+ uint64_t TypeHash = 0;
+ uint64_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,
+ uint64_t *offset_ptr, DWARFSectionKind Kind = DW_SECT_INFO,
+ const DWARFUnitIndex *Index = nullptr,
+ const DWARFUnitIndex::Entry *Entry = nullptr);
+ uint64_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();
+ }
+ uint64_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; }
+ uint64_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; }
+ uint8_t getUnitLengthFieldByteSize() const {
+ return dwarf::getUnitLengthFieldByteSize(FormParams.Format);
+ }
+ uint64_t getNextUnitOffset() const {
+ return Offset + Length + getUnitLengthFieldByteSize();
+ }
+};
+
+const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
+ DWARFSectionKind Kind);
+
+/// Describe a collection of units. Intended to hold all units either from
+/// .debug_info and .debug_types, or from .debug_info.dwo and .debug_types.dwo.
+class DWARFUnitVector final : public SmallVector<std::unique_ptr<DWARFUnit>, 1> {
+ std::function<std::unique_ptr<DWARFUnit>(uint64_t, DWARFSectionKind,
+ const DWARFSection *,
+ const DWARFUnitIndex::Entry *)>
+ Parser;
+ int NumInfoUnits = -1;
+
+public:
+ using UnitVector = SmallVectorImpl<std::unique_ptr<DWARFUnit>>;
+ using iterator = typename UnitVector::iterator;
+ using iterator_range = llvm::iterator_range<typename UnitVector::iterator>;
+
+ DWARFUnit *getUnitForOffset(uint64_t Offset) const;
+ DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E);
+
+ /// Read units from a .debug_info or .debug_types section. Calls made
+ /// before finishedInfoUnits() are assumed to be for .debug_info sections,
+ /// calls after finishedInfoUnits() are for .debug_types sections. Caller
+ /// must not mix calls to addUnitsForSection and addUnitsForDWOSection.
+ void addUnitsForSection(DWARFContext &C, const DWARFSection &Section,
+ DWARFSectionKind SectionKind);
+ /// Read units from a .debug_info.dwo or .debug_types.dwo section. Calls
+ /// made before finishedInfoUnits() are assumed to be for .debug_info.dwo
+ /// sections, calls after finishedInfoUnits() are for .debug_types.dwo
+ /// sections. Caller must not mix calls to addUnitsForSection and
+ /// addUnitsForDWOSection.
+ void addUnitsForDWOSection(DWARFContext &C, const DWARFSection &DWOSection,
+ DWARFSectionKind SectionKind, bool Lazy = false);
+
+ /// Add an existing DWARFUnit to this UnitVector. This is used by the DWARF
+ /// verifier to process unit separately.
+ DWARFUnit *addUnit(std::unique_ptr<DWARFUnit> Unit);
+
+ /// Returns number of all units held by this instance.
+ unsigned getNumUnits() const { return size(); }
+ /// Returns number of units from all .debug_info[.dwo] sections.
+ unsigned getNumInfoUnits() const {
+ return NumInfoUnits == -1 ? size() : NumInfoUnits;
+ }
+ /// Returns number of units from all .debug_types[.dwo] sections.
+ unsigned getNumTypesUnits() const { return size() - NumInfoUnits; }
+ /// Indicate that parsing .debug_info[.dwo] is done, and remaining units
+ /// will be from .debug_types[.dwo].
+ void finishedInfoUnits() { NumInfoUnits = size(); }
+
+private:
+ void addUnitsImpl(DWARFContext &Context, const DWARFObject &Obj,
+ const DWARFSection &Section, const DWARFDebugAbbrev *DA,
+ const DWARFSection *RS, const DWARFSection *LocSection,
+ StringRef SS, const DWARFSection &SOS,
+ const DWARFSection *AOS, const DWARFSection &LS, bool LE,
+ bool IsDWO, bool Lazy, DWARFSectionKind SectionKind);
+};
+
+/// Represents base address of the CU.
+/// 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.
+ dwarf::FormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32};
+
+ StrOffsetsContributionDescriptor(uint64_t Base, uint64_t Size,
+ uint8_t Version, dwarf::DwarfFormat Format)
+ : Base(Base), Size(Size), FormParams({Version, 0, Format}) {}
+ StrOffsetsContributionDescriptor() = default;
+
+ uint8_t getVersion() const { return FormParams.Version; }
+ dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
+ uint8_t getDwarfOffsetByteSize() const {
+ return FormParams.getDwarfOffsetByteSize();
+ }
+ /// Determine whether a contribution to the string offsets table is
+ /// consistent with the relevant section size and that its length is
+ /// a multiple of the size of one of its entries.
+ Expected<StrOffsetsContributionDescriptor>
+ validateContributionSize(DWARFDataExtractor &DA);
+};
+
+class DWARFUnit {
+ DWARFContext &Context;
+ /// Section containing this DWARFUnit.
+ const DWARFSection &InfoSection;
+
+ DWARFUnitHeader Header;
+ const DWARFDebugAbbrev *Abbrev;
+ const DWARFSection *RangeSection;
+ uint64_t RangeSectionBase;
+ /// We either keep track of the location list section or its data, depending
+ /// on whether we are handling a split DWARF section or not.
+ union {
+ const DWARFSection *LocSection;
+ StringRef LocSectionData;
+ };
+ const DWARFSection &LineSection;
+ StringRef StringSection;
+ const DWARFSection &StringOffsetSection;
+ const DWARFSection *AddrOffsetSection;
+ uint32_t AddrOffsetSectionBase = 0;
+ bool isLittleEndian;
+ bool IsDWO;
+ const DWARFUnitVector &UnitVector;
+
+ /// Start, length, and DWARF format of the unit's contribution to the string
+ /// offsets table (DWARF v5).
+ Optional<StrOffsetsContributionDescriptor> StringOffsetsTableContribution;
+
+ /// A table of range lists (DWARF v5 and later).
+ Optional<DWARFDebugRnglistTable> RngListTable;
+
+ mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
+ llvm::Optional<object::SectionedAddress> BaseAddr;
+ /// The compile unit debug information entry items.
+ std::vector<DWARFDebugInfoEntry> DieArray;
+
+ /// 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;
+
+ uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) {
+ auto First = DieArray.data();
+ assert(Die >= First && Die < First + DieArray.size());
+ return Die - First;
+ }
+
+protected:
+ const DWARFUnitHeader &getHeader() const { return Header; }
+
+ /// 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
+ /// DIE's DW_AT_str_offsets_base attribute.
+ Expected<Optional<StrOffsetsContributionDescriptor>>
+ determineStringOffsetsTableContribution(DWARFDataExtractor &DA);
+
+ /// Find the unit's contribution to the string offsets table and determine its
+ /// length and form. The given offset is expected to be 0 in a dwo file or,
+ /// in a dwp file, the start of the unit's contribution to the string offsets
+ /// table section (as determined by the index table).
+ Expected<Optional<StrOffsetsContributionDescriptor>>
+ determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA);
+
+public:
+ DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA,
+ const DWARFSection *RS, const DWARFSection *LocSection,
+ StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
+ const DWARFSection &LS, bool LE, bool IsDWO,
+ const DWARFUnitVector &UnitVector);
+
+ virtual ~DWARFUnit();
+
+ bool isDWOUnit() const { return IsDWO; }
+ DWARFContext& getContext() const { return Context; }
+ const DWARFSection &getInfoSection() const { return InfoSection; }
+ const DWARFSection *getLocSection() const { return LocSection; }
+ StringRef getLocSectionData() const { return LocSectionData; }
+ uint64_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();
+ }
+ uint64_t getLength() const { return Header.getLength(); }
+ uint8_t getUnitType() const { return Header.getUnitType(); }
+ bool isTypeUnit() const { return Header.isTypeUnit(); }
+ uint64_t getNextUnitOffset() const { return Header.getNextUnitOffset(); }
+ const DWARFSection &getLineSection() const { return LineSection; }
+ StringRef getStringSection() const { return StringSection; }
+ const DWARFSection &getStringOffsetSection() const {
+ return StringOffsetSection;
+ }
+
+ void setAddrOffsetSection(const DWARFSection *AOS, uint32_t Base) {
+ AddrOffsetSection = AOS;
+ AddrOffsetSectionBase = Base;
+ }
+
+ /// Recursively update address to Die map.
+ void updateAddressDieMap(DWARFDie Die);
+
+ void setRangesSection(const DWARFSection *RS, uint64_t Base) {
+ RangeSection = RS;
+ RangeSectionBase = Base;
+ }
+
+ Optional<object::SectionedAddress>
+ getAddrOffsetSectionItem(uint32_t Index) const;
+ Optional<uint64_t> getStringOffsetSectionItem(uint32_t Index) const;
+
+ DWARFDataExtractor getDebugInfoExtractor() const;
+
+ DataExtractor getStringExtractor() const {
+ return DataExtractor(StringSection, false, 0);
+ }
+
+ /// 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(uint64_t RangeListOffset,
+ DWARFDebugRangeList &RangeList) const;
+ void clear();
+
+ const Optional<StrOffsetsContributionDescriptor> &
+ getStringOffsetsTableContribution() const {
+ return StringOffsetsTableContribution;
+ }
+
+ uint8_t getDwarfStringOffsetsByteSize() const {
+ assert(StringOffsetsTableContribution);
+ return StringOffsetsTableContribution->getDwarfOffsetByteSize();
+ }
+
+ uint64_t getStringOffsetsBase() const {
+ assert(StringOffsetsTableContribution);
+ return StringOffsetsTableContribution->Base;
+ }
+
+ const DWARFAbbreviationDeclarationSet *getAbbreviations() const;
+
+ static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) {
+ switch (UnitType) {
+ case dwarf::DW_UT_compile:
+ return Tag == dwarf::DW_TAG_compile_unit;
+ case dwarf::DW_UT_type:
+ return Tag == dwarf::DW_TAG_type_unit;
+ case dwarf::DW_UT_partial:
+ return Tag == dwarf::DW_TAG_partial_unit;
+ case dwarf::DW_UT_skeleton:
+ return Tag == dwarf::DW_TAG_skeleton_unit;
+ case dwarf::DW_UT_split_compile:
+ case dwarf::DW_UT_split_type:
+ return dwarf::isUnitType(Tag);
+ }
+ return false;
+ }
+
+ /// 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
+ /// DWARF5 is defined as one of the following six types.
+ static uint32_t getDWARF5HeaderSize(uint8_t UnitType) {
+ switch (UnitType) {
+ case dwarf::DW_UT_compile:
+ case dwarf::DW_UT_partial:
+ return 12;
+ case dwarf::DW_UT_skeleton:
+ case dwarf::DW_UT_split_compile:
+ return 20;
+ case dwarf::DW_UT_type:
+ case dwarf::DW_UT_split_type:
+ return 24;
+ }
+ llvm_unreachable("Invalid UnitType.");
+ }
+
+ llvm::Optional<object::SectionedAddress> getBaseAddress();
+
+ DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
+ extractDIEsIfNeeded(ExtractUnitDIEOnly);
+ if (DieArray.empty())
+ return DWARFDie();
+ return DWARFDie(this, &DieArray[0]);
+ }
+
+ DWARFDie getNonSkeletonUnitDIE(bool ExtractUnitDIEOnly = true) {
+ parseDWO();
+ if (DWO)
+ return DWO->getUnitDIE(ExtractUnitDIEOnly);
+ return getUnitDIE(ExtractUnitDIEOnly);
+ }
+
+ const char *getCompilationDir();
+ 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(uint64_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<uint64_t> getRnglistOffset(uint32_t Index) {
+ if (RngListTable)
+ return RngListTable->getOffsetEntry(Index);
+ return None;
+ }
+
+ Expected<DWARFAddressRangesVector> collectAddressRanges();
+
+ /// Returns subprogram DIE with address range encompassing the provided
+ /// address. The pointer is alive as long as parsed compile unit DIEs are not
+ /// cleared.
+ DWARFDie getSubroutineForAddress(uint64_t Address);
+
+ /// getInlinedChainForAddress - fetches inlined chain for a given address.
+ /// Returns empty chain if there is no subprogram containing address. The
+ /// chain is valid as long as parsed compile unit DIEs are not cleared.
+ void getInlinedChainForAddress(uint64_t Address,
+ SmallVectorImpl<DWARFDie> &InlinedChain);
+
+ /// Return the DWARFUnitVector containing this unit.
+ const DWARFUnitVector &getUnitVector() const { return UnitVector; }
+
+ /// Returns the number of DIEs in the unit. Parses the unit
+ /// if necessary.
+ unsigned getNumDIEs() {
+ extractDIEsIfNeeded(false);
+ return DieArray.size();
+ }
+
+ /// 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
+ /// method on a DIE that isn't accessible by following
+ /// children/sibling links starting from this unit's getUnitDIE().
+ uint32_t getDIEIndex(const DWARFDie &D) {
+ return getDIEIndex(D.getDebugInfoEntry());
+ }
+
+ /// Return the DIE object at the given index.
+ DWARFDie getDIEAtIndex(unsigned Index) {
+ assert(Index < DieArray.size());
+ return DWARFDie(this, &DieArray[Index]);
+ }
+
+ 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);
+
+ /// 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.
+ DWARFDie getDIEForOffset(uint64_t Offset) {
+ extractDIEsIfNeeded(false);
+ assert(!DieArray.empty());
+ auto It =
+ llvm::partition_point(DieArray, [=](const DWARFDebugInfoEntry &DIE) {
+ return DIE.getOffset() < Offset;
+ });
+ if (It != DieArray.end() && It->getOffset() == Offset)
+ return DWARFDie(this, &*It);
+ return DWARFDie();
+ }
+
+ uint32_t getLineTableOffset() const {
+ if (auto IndexEntry = Header.getIndexEntry())
+ if (const auto *Contrib = IndexEntry->getOffset(DW_SECT_LINE))
+ return Contrib->Offset;
+ return 0;
+ }
+
+ die_iterator_range dies() {
+ extractDIEsIfNeeded(false);
+ return die_iterator_range(DieArray.begin(), DieArray.end());
+ }
+
+ virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
+
+ Error tryExtractDIEsIfNeeded(bool CUDieOnly);
+
+private:
+ /// Size in bytes of the .debug_info data associated with this compile unit.
+ size_t getDebugInfoSize() const {
+ return Header.getLength() + Header.getUnitLengthFieldByteSize() -
+ getHeaderSize();
+ }
+
+ /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
+ /// hasn't already been done
+ void extractDIEsIfNeeded(bool CUDieOnly);
+
+ /// extractDIEsToVector - Appends all parsed DIEs to a vector.
+ void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
+ std::vector<DWARFDebugInfoEntry> &DIEs) const;
+
+ /// clearDIEs - Clear parsed DIEs to keep memory usage low.
+ void clearDIEs(bool KeepCUDie);
+
+ /// parseDWO - Parses .dwo file for current compile unit. Returns true if
+ /// it was actually constructed.
+ bool parseDWO();
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
new file mode 100644
index 000000000..684103aac
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
@@ -0,0 +1,105 @@
+//===- DWARFUnitIndex.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFUNITINDEX_H
+#define LLVM_DEBUGINFO_DWARF_DWARFUNITINDEX_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataExtractor.h"
+#include <cstdint>
+#include <memory>
+
+namespace llvm {
+
+class raw_ostream;
+
+enum DWARFSectionKind {
+ DW_SECT_INFO = 1,
+ DW_SECT_TYPES,
+ DW_SECT_ABBREV,
+ DW_SECT_LINE,
+ DW_SECT_LOC,
+ DW_SECT_STR_OFFSETS,
+ DW_SECT_MACINFO,
+ DW_SECT_MACRO,
+};
+
+class DWARFUnitIndex {
+ struct Header {
+ uint32_t Version;
+ uint32_t NumColumns;
+ uint32_t NumUnits;
+ uint32_t NumBuckets = 0;
+
+ bool parse(DataExtractor IndexData, uint64_t *OffsetPtr);
+ void dump(raw_ostream &OS) const;
+ };
+
+public:
+ class Entry {
+ public:
+ struct SectionContribution {
+ uint32_t Offset;
+ uint32_t Length;
+ };
+
+ private:
+ const DWARFUnitIndex *Index;
+ uint64_t Signature;
+ std::unique_ptr<SectionContribution[]> Contributions;
+ friend class DWARFUnitIndex;
+
+ public:
+ const SectionContribution *getOffset(DWARFSectionKind Sec) const;
+ const SectionContribution *getOffset() const;
+
+ const SectionContribution *getOffsets() const {
+ return Contributions.get();
+ }
+
+ uint64_t getSignature() const { return Signature; }
+ };
+
+private:
+ struct Header Header;
+
+ DWARFSectionKind InfoColumnKind;
+ int InfoColumn = -1;
+ std::unique_ptr<DWARFSectionKind[]> ColumnKinds;
+ std::unique_ptr<Entry[]> Rows;
+ mutable std::vector<Entry *> OffsetLookup;
+
+ static StringRef getColumnHeader(DWARFSectionKind DS);
+
+ bool parseImpl(DataExtractor IndexData);
+
+public:
+ DWARFUnitIndex(DWARFSectionKind InfoColumnKind)
+ : InfoColumnKind(InfoColumnKind) {}
+
+ explicit operator bool() const { return Header.NumBuckets; }
+
+ bool parse(DataExtractor IndexData);
+ void dump(raw_ostream &OS) const;
+
+ const Entry *getFromOffset(uint32_t Offset) const;
+ const Entry *getFromHash(uint64_t Offset) const;
+
+ ArrayRef<DWARFSectionKind> getColumnKinds() const {
+ return makeArrayRef(ColumnKinds.get(), Header.NumColumns);
+ }
+
+ ArrayRef<Entry> getRows() const {
+ return makeArrayRef(Rows.get(), Header.NumBuckets);
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFUNITINDEX_H
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
new file mode 100644
index 000000000..a4a3a11d4
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
@@ -0,0 +1,336 @@
+//===- DWARFVerifier.h ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
+#define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
+
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+
+#include <cstdint>
+#include <map>
+#include <set>
+
+namespace llvm {
+class raw_ostream;
+struct DWARFAttribute;
+class DWARFContext;
+class DWARFDie;
+class DWARFUnit;
+class DWARFCompileUnit;
+class DWARFDataExtractor;
+class DWARFDebugAbbrev;
+class DataExtractor;
+struct DWARFSection;
+
+/// A class that verifies DWARF debug information given a DWARF Context.
+class DWARFVerifier {
+public:
+ /// A class that keeps the address range information for a single DIE.
+ struct DieRangeInfo {
+ DWARFDie Die;
+
+ /// Sorted DWARFAddressRanges.
+ std::vector<DWARFAddressRange> Ranges;
+
+ /// Sorted DWARFAddressRangeInfo.
+ std::set<DieRangeInfo> Children;
+
+ DieRangeInfo() = default;
+ DieRangeInfo(DWARFDie Die) : Die(Die) {}
+
+ /// Used for unit testing.
+ DieRangeInfo(std::vector<DWARFAddressRange> Ranges)
+ : Ranges(std::move(Ranges)) {}
+
+ typedef std::vector<DWARFAddressRange>::const_iterator
+ address_range_iterator;
+ typedef std::set<DieRangeInfo>::const_iterator die_range_info_iterator;
+
+ /// Inserts the address range. If the range overlaps with an existing
+ /// range, the range is *not* added and an iterator to the overlapping
+ /// range is returned.
+ ///
+ /// This is used for finding overlapping ranges within the same DIE.
+ address_range_iterator insert(const DWARFAddressRange &R);
+
+ /// Finds an address range in the sorted vector of ranges.
+ address_range_iterator findRange(const DWARFAddressRange &R) const {
+ auto Begin = Ranges.begin();
+ auto End = Ranges.end();
+ auto Iter = std::upper_bound(Begin, End, R);
+ if (Iter != Begin)
+ --Iter;
+ return Iter;
+ }
+
+ /// Inserts the address range info. If any of its ranges overlaps with a
+ /// range in an existing range info, the range info is *not* added and an
+ /// iterator to the overlapping range info.
+ ///
+ /// This is used for finding overlapping children of the same DIE.
+ die_range_info_iterator insert(const DieRangeInfo &RI);
+
+ /// Return true if ranges in this object contains all ranges within RHS.
+ bool contains(const DieRangeInfo &RHS) const;
+
+ /// Return true if any range in this object intersects with any range in
+ /// RHS.
+ bool intersects(const DieRangeInfo &RHS) const;
+ };
+
+private:
+ raw_ostream &OS;
+ DWARFContext &DCtx;
+ DIDumpOptions DumpOpts;
+ /// A map that tracks all references (converted absolute references) so we
+ /// can verify each reference points to a valid DIE and not an offset that
+ /// lies between to valid DIEs.
+ std::map<uint64_t, std::set<uint64_t>> ReferenceToDIEOffsets;
+ uint32_t NumDebugLineErrors = 0;
+ // Used to relax some checks that do not currently work portably
+ bool IsObjectFile;
+ bool IsMachOObject;
+
+ raw_ostream &error() const;
+ raw_ostream &warn() const;
+ raw_ostream &note() const;
+ raw_ostream &dump(const DWARFDie &Die, unsigned indent = 0) const;
+
+ /// Verifies the abbreviations section.
+ ///
+ /// This function currently checks that:
+ /// --No abbreviation declaration has more than one attributes with the same
+ /// name.
+ ///
+ /// \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 occurred during verification.
+ unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev);
+
+ /// Verifies the header of a unit in a .debug_info or .debug_types section.
+ ///
+ /// This function currently checks for:
+ /// - Unit is in 32-bit DWARF format. The function can be modified to
+ /// support 64-bit format.
+ /// - The DWARF version is valid
+ /// - The unit type is valid (if unit is in version >=5)
+ /// - The unit doesn't extend beyond the containing section
+ /// - The address size is valid
+ /// - The offset in the .debug_abbrev section is valid
+ ///
+ /// \param DebugInfoData The section data
+ /// \param Offset A reference to the offset start of the unit. The offset will
+ /// be updated to point to the next unit in the section
+ /// \param UnitIndex The index of the unit to be verified
+ /// \param UnitType A reference to the type of the unit
+ /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is
+ /// in 64-bit format.
+ ///
+ /// \returns true if the header is verified successfully, false otherwise.
+ bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
+ uint64_t *Offset, unsigned UnitIndex, uint8_t &UnitType,
+ bool &isUnitDWARF64);
+
+ /// Verifies the header of a unit in a .debug_info or .debug_types section.
+ ///
+ /// This function currently verifies:
+ /// - The debug info attributes.
+ /// - The debug info form=s.
+ /// - The presence of a root DIE.
+ /// - That the root DIE is a unit DIE.
+ /// - If a unit type is provided, that the unit DIE matches the unit type.
+ /// - The DIE ranges.
+ /// - That call site entries are only nested within subprograms with a
+ /// DW_AT_call attribute.
+ ///
+ /// \param Unit The DWARF Unit to verify.
+ ///
+ /// \returns The number of errors that occurred during verification.
+ unsigned verifyUnitContents(DWARFUnit &Unit);
+
+ /// Verifies the unit headers and contents in a .debug_info or .debug_types
+ /// section.
+ ///
+ /// \param S The DWARF Section to verify.
+ /// \param SectionKind The object-file section kind that S comes from.
+ ///
+ /// \returns The number of errors that occurred during verification.
+ unsigned verifyUnitSection(const DWARFSection &S,
+ DWARFSectionKind SectionKind);
+
+ /// Verifies that a call site entry is nested within a subprogram with a
+ /// DW_AT_call attribute.
+ ///
+ /// \returns Number of errors that occurred during verification.
+ unsigned verifyDebugInfoCallSite(const DWARFDie &Die);
+
+ /// Verify that all Die ranges are valid.
+ ///
+ /// This function currently checks for:
+ /// - cases in which lowPC >= highPC
+ ///
+ /// \returns Number of errors that occurred during verification.
+ unsigned verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI);
+
+ /// Verifies the attribute's DWARF attribute and its value.
+ ///
+ /// This function currently checks for:
+ /// - DW_AT_ranges values is a valid .debug_ranges offset
+ /// - DW_AT_stmt_list is a valid .debug_line offset
+ ///
+ /// \param Die The DWARF DIE that owns the attribute value
+ /// \param AttrValue The DWARF attribute value to check
+ ///
+ /// \returns NumErrors The number of errors occurred during verification of
+ /// attributes' values in a unit
+ unsigned verifyDebugInfoAttribute(const DWARFDie &Die,
+ DWARFAttribute &AttrValue);
+
+ /// Verifies the attribute's DWARF form.
+ ///
+ /// This function currently checks for:
+ /// - All DW_FORM_ref values that are CU relative have valid CU offsets
+ /// - All DW_FORM_ref_addr values have valid section offsets
+ /// - All DW_FORM_strp values have valid .debug_str offsets
+ ///
+ /// \param Die The DWARF DIE that owns the attribute value
+ /// \param AttrValue The DWARF attribute value to check
+ ///
+ /// \returns NumErrors The number of errors occurred during verification of
+ /// attributes' forms in a unit
+ unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue);
+
+ /// Verifies the all valid references that were found when iterating through
+ /// all of the DIE attributes.
+ ///
+ /// This function will verify that all references point to DIEs whose DIE
+ /// offset matches. This helps to ensure if a DWARF link phase moved things
+ /// around, that it doesn't create invalid references by failing to relocate
+ /// CU relative and absolute references.
+ ///
+ /// \returns NumErrors The number of errors occurred during verification of
+ /// references for the .debug_info and .debug_types sections
+ unsigned verifyDebugInfoReferences();
+
+ /// 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();
+
+ /// Verify that all of the rows in the line table are valid.
+ ///
+ /// This function currently checks for:
+ /// - addresses within a sequence that decrease in value
+ /// - invalid file indexes
+ void verifyDebugLineRows();
+
+ /// Verify that an Apple-style accelerator table is valid.
+ ///
+ /// This function currently checks that:
+ /// - The fixed part of the header fits in the section
+ /// - The size of the section is as large as what the header describes
+ /// - There is at least one atom
+ /// - The form for each atom is valid
+ /// - The tag for each DIE in the table is valid
+ /// - The buckets have a valid index, or they are empty
+ /// - Each hashdata offset is valid
+ /// - Each DIE is valid
+ ///
+ /// \param AccelSection pointer to the section containing the acceleration table
+ /// \param StrData pointer to the string section
+ /// \param SectionName the name of the table we're verifying
+ ///
+ /// \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,
+ DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE());
+
+ /// Verify the information in any of the following sections, if available:
+ /// .debug_abbrev, debug_abbrev.dwo
+ ///
+ /// Any errors are reported to the stream that was this object was
+ /// constructed with.
+ ///
+ /// \returns true if .debug_abbrev and .debug_abbrev.dwo verify successfully,
+ /// false otherwise.
+ bool handleDebugAbbrev();
+
+ /// Verify the information in the .debug_info and .debug_types sections.
+ ///
+ /// Any errors are reported to the stream that this object was
+ /// constructed with.
+ ///
+ /// \returns true if all sections verify successfully, false otherwise.
+ bool handleDebugInfo();
+
+ /// Verify the information in the .debug_line section.
+ ///
+ /// Any errors are reported to the stream that was this object was
+ /// constructed with.
+ ///
+ /// \returns true if the .debug_line verifies successfully, false otherwise.
+ bool handleDebugLine();
+
+ /// Verify the information in accelerator tables, if they exist.
+ ///
+ /// Any errors are reported to the stream that was this object was
+ /// constructed with.
+ ///
+ /// \returns true if the existing Apple-style accelerator tables verify
+ /// successfully, false otherwise.
+ bool handleAccelTables();
+};
+
+static inline bool operator<(const DWARFVerifier::DieRangeInfo &LHS,
+ const DWARFVerifier::DieRangeInfo &RHS) {
+ return std::tie(LHS.Ranges, LHS.Die) < std::tie(RHS.Ranges, RHS.Die);
+}
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H