10b57cec5SDimitry Andric //===- DWARFDebugLine.h -----------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 9fe6060f1SDimitry Andric #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGLINE_H 10fe6060f1SDimitry Andric #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGLINE_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 1381ad6265SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 140b57cec5SDimitry Andric #include "llvm/DebugInfo/DIContext.h" 150b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 1681ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 170b57cec5SDimitry Andric #include "llvm/Support/MD5.h" 188bcb0991SDimitry Andric #include "llvm/Support/Path.h" 190b57cec5SDimitry Andric #include <cstdint> 200b57cec5SDimitry Andric #include <map> 210b57cec5SDimitry Andric #include <string> 220b57cec5SDimitry Andric #include <vector> 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace llvm { 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric class raw_ostream; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric class DWARFDebugLine { 290b57cec5SDimitry Andric public: 300b57cec5SDimitry Andric struct FileNameEntry { 310b57cec5SDimitry Andric FileNameEntry() = default; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric DWARFFormValue Name; 340b57cec5SDimitry Andric uint64_t DirIdx = 0; 350b57cec5SDimitry Andric uint64_t ModTime = 0; 360b57cec5SDimitry Andric uint64_t Length = 0; 370b57cec5SDimitry Andric MD5::MD5Result Checksum; 380b57cec5SDimitry Andric DWARFFormValue Source; 390b57cec5SDimitry Andric }; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric /// Tracks which optional content types are present in a DWARF file name 420b57cec5SDimitry Andric /// entry format. 430b57cec5SDimitry Andric struct ContentTypeTracker { 440b57cec5SDimitry Andric ContentTypeTracker() = default; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric /// Whether filename entries provide a modification timestamp. 470b57cec5SDimitry Andric bool HasModTime = false; 480b57cec5SDimitry Andric /// Whether filename entries provide a file size. 490b57cec5SDimitry Andric bool HasLength = false; 500b57cec5SDimitry Andric /// For v5, whether filename entries provide an MD5 checksum. 510b57cec5SDimitry Andric bool HasMD5 = false; 520b57cec5SDimitry Andric /// For v5, whether filename entries provide source text. 530b57cec5SDimitry Andric bool HasSource = false; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric /// Update tracked content types with \p ContentType. 560b57cec5SDimitry Andric void trackContentType(dwarf::LineNumberEntryFormat ContentType); 570b57cec5SDimitry Andric }; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric struct Prologue { 600b57cec5SDimitry Andric Prologue(); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric /// The size in bytes of the statement information for this compilation unit 630b57cec5SDimitry Andric /// (not including the total_length field itself). 640b57cec5SDimitry Andric uint64_t TotalLength; 650b57cec5SDimitry Andric /// Version, address size (starting in v5), and DWARF32/64 format; these 660b57cec5SDimitry Andric /// parameters affect interpretation of forms (used in the directory and 670b57cec5SDimitry Andric /// file tables starting with v5). 680b57cec5SDimitry Andric dwarf::FormParams FormParams; 690b57cec5SDimitry Andric /// The number of bytes following the prologue_length field to the beginning 700b57cec5SDimitry Andric /// of the first byte of the statement program itself. 710b57cec5SDimitry Andric uint64_t PrologueLength; 720b57cec5SDimitry Andric /// In v5, size in bytes of a segment selector. 730b57cec5SDimitry Andric uint8_t SegSelectorSize; 740b57cec5SDimitry Andric /// The size in bytes of the smallest target machine instruction. Statement 750b57cec5SDimitry Andric /// program opcodes that alter the address register first multiply their 760b57cec5SDimitry Andric /// operands by this value. 770b57cec5SDimitry Andric uint8_t MinInstLength; 780b57cec5SDimitry Andric /// The maximum number of individual operations that may be encoded in an 790b57cec5SDimitry Andric /// instruction. 800b57cec5SDimitry Andric uint8_t MaxOpsPerInst; 810b57cec5SDimitry Andric /// The initial value of theis_stmtregister. 820b57cec5SDimitry Andric uint8_t DefaultIsStmt; 830b57cec5SDimitry Andric /// This parameter affects the meaning of the special opcodes. See below. 840b57cec5SDimitry Andric int8_t LineBase; 850b57cec5SDimitry Andric /// This parameter affects the meaning of the special opcodes. See below. 860b57cec5SDimitry Andric uint8_t LineRange; 870b57cec5SDimitry Andric /// The number assigned to the first special opcode. 880b57cec5SDimitry Andric uint8_t OpcodeBase; 890b57cec5SDimitry Andric /// This tracks which optional file format content types are present. 900b57cec5SDimitry Andric ContentTypeTracker ContentTypes; 910b57cec5SDimitry Andric std::vector<uint8_t> StandardOpcodeLengths; 920b57cec5SDimitry Andric std::vector<DWARFFormValue> IncludeDirectories; 930b57cec5SDimitry Andric std::vector<FileNameEntry> FileNames; 940b57cec5SDimitry Andric getFormParamsPrologue950b57cec5SDimitry Andric const dwarf::FormParams getFormParams() const { return FormParams; } getVersionPrologue960b57cec5SDimitry Andric uint16_t getVersion() const { return FormParams.Version; } getAddressSizePrologue970b57cec5SDimitry Andric uint8_t getAddressSize() const { return FormParams.AddrSize; } isDWARF64Prologue980b57cec5SDimitry Andric bool isDWARF64() const { return FormParams.Format == dwarf::DWARF64; } 990b57cec5SDimitry Andric sizeofTotalLengthPrologue1000b57cec5SDimitry Andric uint32_t sizeofTotalLength() const { return isDWARF64() ? 12 : 4; } 1010b57cec5SDimitry Andric sizeofPrologueLengthPrologue1020b57cec5SDimitry Andric uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric bool totalLengthIsValid() const; 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric /// Length of the prologue in bytes. 1075ffd83dbSDimitry Andric uint64_t getLength() const; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric /// Get DWARF-version aware access to the file name entry at the provided 1100b57cec5SDimitry Andric /// index. 1110b57cec5SDimitry Andric const llvm::DWARFDebugLine::FileNameEntry & 1120b57cec5SDimitry Andric getFileNameEntry(uint64_t Index) const; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric bool hasFileAtIndex(uint64_t FileIndex) const; 1150b57cec5SDimitry Andric 116bdd1243dSDimitry Andric std::optional<uint64_t> getLastValidFileIndex() const; 117e8d8bef9SDimitry Andric 1188bcb0991SDimitry Andric bool 1198bcb0991SDimitry Andric getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, 1200b57cec5SDimitry Andric DILineInfoSpecifier::FileLineInfoKind Kind, 1218bcb0991SDimitry Andric std::string &Result, 1228bcb0991SDimitry Andric sys::path::Style Style = sys::path::Style::native) const; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric void clear(); 1250b57cec5SDimitry Andric void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; 1265ffd83dbSDimitry Andric Error parse(DWARFDataExtractor Data, uint64_t *OffsetPtr, 1275ffd83dbSDimitry Andric function_ref<void(Error)> RecoverableErrorHandler, 1280b57cec5SDimitry Andric const DWARFContext &Ctx, const DWARFUnit *U = nullptr); 1290b57cec5SDimitry Andric }; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric /// Standard .debug_line state machine structure. 1320b57cec5SDimitry Andric struct Row { 1330b57cec5SDimitry Andric explicit Row(bool DefaultIsStmt = false); 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric /// Called after a row is appended to the matrix. 1360b57cec5SDimitry Andric void postAppend(); 1370b57cec5SDimitry Andric void reset(bool DefaultIsStmt); 1380b57cec5SDimitry Andric void dump(raw_ostream &OS) const; 1390b57cec5SDimitry Andric 1405ffd83dbSDimitry Andric static void dumpTableHeader(raw_ostream &OS, unsigned Indent); 1410b57cec5SDimitry Andric orderByAddressRow1420b57cec5SDimitry Andric static bool orderByAddress(const Row &LHS, const Row &RHS) { 1430b57cec5SDimitry Andric return std::tie(LHS.Address.SectionIndex, LHS.Address.Address) < 1440b57cec5SDimitry Andric std::tie(RHS.Address.SectionIndex, RHS.Address.Address); 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric /// The program-counter value corresponding to a machine instruction 1480b57cec5SDimitry Andric /// generated by the compiler and section index pointing to the section 1490b57cec5SDimitry Andric /// containg this PC. If relocation information is present then section 1500b57cec5SDimitry Andric /// index is the index of the section which contains above address. 1510b57cec5SDimitry Andric /// Otherwise this is object::SectionedAddress::Undef value. 1520b57cec5SDimitry Andric object::SectionedAddress Address; 1530b57cec5SDimitry Andric /// An unsigned integer indicating a source line number. Lines are numbered 1540b57cec5SDimitry Andric /// beginning at 1. The compiler may emit the value 0 in cases where an 1550b57cec5SDimitry Andric /// instruction cannot be attributed to any source line. 1560b57cec5SDimitry Andric uint32_t Line; 1570b57cec5SDimitry Andric /// An unsigned integer indicating a column number within a source line. 1580b57cec5SDimitry Andric /// Columns are numbered beginning at 1. The value 0 is reserved to indicate 1590b57cec5SDimitry Andric /// that a statement begins at the 'left edge' of the line. 1600b57cec5SDimitry Andric uint16_t Column; 1610b57cec5SDimitry Andric /// An unsigned integer indicating the identity of the source file 1620b57cec5SDimitry Andric /// corresponding to a machine instruction. 1630b57cec5SDimitry Andric uint16_t File; 1640b57cec5SDimitry Andric /// An unsigned integer representing the DWARF path discriminator value 1650b57cec5SDimitry Andric /// for this location. 1660b57cec5SDimitry Andric uint32_t Discriminator; 1670b57cec5SDimitry Andric /// An unsigned integer whose value encodes the applicable instruction set 1680b57cec5SDimitry Andric /// architecture for the current instruction. 1690b57cec5SDimitry Andric uint8_t Isa; 170*06c3fb27SDimitry Andric /// An unsigned integer representing the index of an operation within a 171*06c3fb27SDimitry Andric /// VLIW instruction. The index of the first operation is 0. 172*06c3fb27SDimitry Andric /// For non-VLIW architectures, this register will always be 0. 173*06c3fb27SDimitry Andric uint8_t OpIndex; 1740b57cec5SDimitry Andric /// A boolean indicating that the current instruction is the beginning of a 1750b57cec5SDimitry Andric /// statement. 1760b57cec5SDimitry Andric uint8_t IsStmt : 1, 1770b57cec5SDimitry Andric /// A boolean indicating that the current instruction is the 1780b57cec5SDimitry Andric /// beginning of a basic block. 1790b57cec5SDimitry Andric BasicBlock : 1, 1800b57cec5SDimitry Andric /// A boolean indicating that the current address is that of the 1810b57cec5SDimitry Andric /// first byte after the end of a sequence of target machine 1820b57cec5SDimitry Andric /// instructions. 1830b57cec5SDimitry Andric EndSequence : 1, 1840b57cec5SDimitry Andric /// A boolean indicating that the current address is one (of possibly 1850b57cec5SDimitry Andric /// many) where execution should be suspended for an entry breakpoint 1860b57cec5SDimitry Andric /// of a function. 1870b57cec5SDimitry Andric PrologueEnd : 1, 1880b57cec5SDimitry Andric /// A boolean indicating that the current address is one (of possibly 1890b57cec5SDimitry Andric /// many) where execution should be suspended for an exit breakpoint 1900b57cec5SDimitry Andric /// of a function. 1910b57cec5SDimitry Andric EpilogueBegin : 1; 1920b57cec5SDimitry Andric }; 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric /// Represents a series of contiguous machine instructions. Line table for 1950b57cec5SDimitry Andric /// each compilation unit may consist of multiple sequences, which are not 1960b57cec5SDimitry Andric /// guaranteed to be in the order of ascending instruction address. 1970b57cec5SDimitry Andric struct Sequence { 1980b57cec5SDimitry Andric Sequence(); 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric /// Sequence describes instructions at address range [LowPC, HighPC) 2010b57cec5SDimitry Andric /// and is described by line table rows [FirstRowIndex, LastRowIndex). 2020b57cec5SDimitry Andric uint64_t LowPC; 2030b57cec5SDimitry Andric uint64_t HighPC; 2040b57cec5SDimitry Andric /// If relocation information is present then this is the index of the 2050b57cec5SDimitry Andric /// section which contains above addresses. Otherwise this is 2060b57cec5SDimitry Andric /// object::SectionedAddress::Undef value. 2070b57cec5SDimitry Andric uint64_t SectionIndex; 2080b57cec5SDimitry Andric unsigned FirstRowIndex; 2090b57cec5SDimitry Andric unsigned LastRowIndex; 2100b57cec5SDimitry Andric bool Empty; 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric void reset(); 2130b57cec5SDimitry Andric orderByHighPCSequence2140b57cec5SDimitry Andric static bool orderByHighPC(const Sequence &LHS, const Sequence &RHS) { 2150b57cec5SDimitry Andric return std::tie(LHS.SectionIndex, LHS.HighPC) < 2160b57cec5SDimitry Andric std::tie(RHS.SectionIndex, RHS.HighPC); 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric isValidSequence2190b57cec5SDimitry Andric bool isValid() const { 2200b57cec5SDimitry Andric return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric containsPCSequence2230b57cec5SDimitry Andric bool containsPC(object::SectionedAddress PC) const { 2240b57cec5SDimitry Andric return SectionIndex == PC.SectionIndex && 2250b57cec5SDimitry Andric (LowPC <= PC.Address && PC.Address < HighPC); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric }; 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric struct LineTable { 2300b57cec5SDimitry Andric LineTable(); 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric /// Represents an invalid row 2330b57cec5SDimitry Andric const uint32_t UnknownRowIndex = UINT32_MAX; 2340b57cec5SDimitry Andric appendRowLineTable2350b57cec5SDimitry Andric void appendRow(const DWARFDebugLine::Row &R) { Rows.push_back(R); } 2360b57cec5SDimitry Andric appendSequenceLineTable2370b57cec5SDimitry Andric void appendSequence(const DWARFDebugLine::Sequence &S) { 2380b57cec5SDimitry Andric Sequences.push_back(S); 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric /// Returns the index of the row with file/line info for a given address, 2420b57cec5SDimitry Andric /// or UnknownRowIndex if there is no such row. 2430b57cec5SDimitry Andric uint32_t lookupAddress(object::SectionedAddress Address) const; 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric bool lookupAddressRange(object::SectionedAddress Address, uint64_t Size, 2460b57cec5SDimitry Andric std::vector<uint32_t> &Result) const; 2470b57cec5SDimitry Andric hasFileAtIndexLineTable2480b57cec5SDimitry Andric bool hasFileAtIndex(uint64_t FileIndex) const { 2490b57cec5SDimitry Andric return Prologue.hasFileAtIndex(FileIndex); 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric getLastValidFileIndexLineTable252bdd1243dSDimitry Andric std::optional<uint64_t> getLastValidFileIndex() const { 253e8d8bef9SDimitry Andric return Prologue.getLastValidFileIndex(); 254e8d8bef9SDimitry Andric } 255e8d8bef9SDimitry Andric 2560b57cec5SDimitry Andric /// Extracts filename by its index in filename table in prologue. 2570b57cec5SDimitry Andric /// In Dwarf 4, the files are 1-indexed and the current compilation file 2580b57cec5SDimitry Andric /// name is not represented in the list. In DWARF v5, the files are 2590b57cec5SDimitry Andric /// 0-indexed and the primary source file has the index 0. 2600b57cec5SDimitry Andric /// Returns true on success. getFileNameByIndexLineTable2610b57cec5SDimitry Andric bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, 2620b57cec5SDimitry Andric DILineInfoSpecifier::FileLineInfoKind Kind, 2630b57cec5SDimitry Andric std::string &Result) const { 2640b57cec5SDimitry Andric return Prologue.getFileNameByIndex(FileIndex, CompDir, Kind, Result); 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric /// Fills the Result argument with the file and line information 2680b57cec5SDimitry Andric /// corresponding to Address. Returns true on success. 2690b57cec5SDimitry Andric bool getFileLineInfoForAddress(object::SectionedAddress Address, 2700b57cec5SDimitry Andric const char *CompDir, 2710b57cec5SDimitry Andric DILineInfoSpecifier::FileLineInfoKind Kind, 2720b57cec5SDimitry Andric DILineInfo &Result) const; 2730b57cec5SDimitry Andric 274bdd1243dSDimitry Andric /// Extracts directory name by its Entry in include directories table 275bdd1243dSDimitry Andric /// in prologue. Returns true on success. 276bdd1243dSDimitry Andric bool getDirectoryForEntry(const FileNameEntry &Entry, 277bdd1243dSDimitry Andric std::string &Directory) const; 278bdd1243dSDimitry Andric 2790b57cec5SDimitry Andric void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; 2800b57cec5SDimitry Andric void clear(); 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric /// Parse prologue and all rows. 283480093f4SDimitry Andric Error parse(DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, 2840b57cec5SDimitry Andric const DWARFContext &Ctx, const DWARFUnit *U, 2855ffd83dbSDimitry Andric function_ref<void(Error)> RecoverableErrorHandler, 2865ffd83dbSDimitry Andric raw_ostream *OS = nullptr, bool Verbose = false); 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric using RowVector = std::vector<Row>; 2890b57cec5SDimitry Andric using RowIter = RowVector::const_iterator; 2900b57cec5SDimitry Andric using SequenceVector = std::vector<Sequence>; 2910b57cec5SDimitry Andric using SequenceIter = SequenceVector::const_iterator; 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric struct Prologue Prologue; 2940b57cec5SDimitry Andric RowVector Rows; 2950b57cec5SDimitry Andric SequenceVector Sequences; 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric private: 2980b57cec5SDimitry Andric uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq, 2990b57cec5SDimitry Andric object::SectionedAddress Address) const; 300bdd1243dSDimitry Andric std::optional<StringRef> 3010b57cec5SDimitry Andric getSourceByIndex(uint64_t FileIndex, 3020b57cec5SDimitry Andric DILineInfoSpecifier::FileLineInfoKind Kind) const; 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric uint32_t lookupAddressImpl(object::SectionedAddress Address) const; 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric bool lookupAddressRangeImpl(object::SectionedAddress Address, uint64_t Size, 3070b57cec5SDimitry Andric std::vector<uint32_t> &Result) const; 3080b57cec5SDimitry Andric }; 3090b57cec5SDimitry Andric 3108bcb0991SDimitry Andric const LineTable *getLineTable(uint64_t Offset) const; 311480093f4SDimitry Andric Expected<const LineTable *> 312480093f4SDimitry Andric getOrParseLineTable(DWARFDataExtractor &DebugLineData, uint64_t Offset, 3130b57cec5SDimitry Andric const DWARFContext &Ctx, const DWARFUnit *U, 3145ffd83dbSDimitry Andric function_ref<void(Error)> RecoverableErrorHandler); 31581ad6265SDimitry Andric void clearLineTable(uint64_t Offset); 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric /// Helper to allow for parsing of an entire .debug_line section in sequence. 3180b57cec5SDimitry Andric class SectionParser { 3190b57cec5SDimitry Andric public: 3200b57cec5SDimitry Andric using LineToUnitMap = std::map<uint64_t, DWARFUnit *>; 3210b57cec5SDimitry Andric 322e8d8bef9SDimitry Andric SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, 323e8d8bef9SDimitry Andric DWARFUnitVector::iterator_range Units); 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric /// Get the next line table from the section. Report any issues via the 3265ffd83dbSDimitry Andric /// handlers. 3270b57cec5SDimitry Andric /// 3285ffd83dbSDimitry Andric /// \param RecoverableErrorHandler - any issues that don't prevent further 3295ffd83dbSDimitry Andric /// parsing of the table will be reported through this handler. 3305ffd83dbSDimitry Andric /// \param UnrecoverableErrorHandler - any issues that prevent further 3315ffd83dbSDimitry Andric /// parsing of the table will be reported through this handler. 3320b57cec5SDimitry Andric /// \param OS - if not null, the parser will print information about the 3330b57cec5SDimitry Andric /// table as it parses it. 3345ffd83dbSDimitry Andric /// \param Verbose - if true, the parser will print verbose information when 3355ffd83dbSDimitry Andric /// printing to the output. 3365ffd83dbSDimitry Andric LineTable parseNext(function_ref<void(Error)> RecoverableErrorHandler, 3375ffd83dbSDimitry Andric function_ref<void(Error)> UnrecoverableErrorHandler, 3385ffd83dbSDimitry Andric raw_ostream *OS = nullptr, bool Verbose = false); 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric /// Skip the current line table and go to the following line table (if 3410b57cec5SDimitry Andric /// present) immediately. 3420b57cec5SDimitry Andric /// 3435ffd83dbSDimitry Andric /// \param RecoverableErrorHandler - report any recoverable prologue 3445ffd83dbSDimitry Andric /// parsing issues via this handler. 3455ffd83dbSDimitry Andric /// \param UnrecoverableErrorHandler - report any unrecoverable prologue 3465ffd83dbSDimitry Andric /// parsing issues via this handler. 3475ffd83dbSDimitry Andric void skip(function_ref<void(Error)> RecoverableErrorHandler, 3485ffd83dbSDimitry Andric function_ref<void(Error)> UnrecoverableErrorHandler); 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric /// Indicates if the parser has parsed as much as possible. 3510b57cec5SDimitry Andric /// 3520b57cec5SDimitry Andric /// \note Certain problems with the line table structure might mean that 3530b57cec5SDimitry Andric /// parsing stops before the end of the section is reached. done()3540b57cec5SDimitry Andric bool done() const { return Done; } 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric /// Get the offset the parser has reached. getOffset()3578bcb0991SDimitry Andric uint64_t getOffset() const { return Offset; } 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric private: 3608bcb0991SDimitry Andric DWARFUnit *prepareToParse(uint64_t Offset); 3618bcb0991SDimitry Andric void moveToNextTable(uint64_t OldOffset, const Prologue &P); 362*06c3fb27SDimitry Andric bool hasValidVersion(uint64_t Offset); 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric LineToUnitMap LineToUnit; 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric DWARFDataExtractor &DebugLineData; 3670b57cec5SDimitry Andric const DWARFContext &Context; 3688bcb0991SDimitry Andric uint64_t Offset = 0; 3690b57cec5SDimitry Andric bool Done = false; 3700b57cec5SDimitry Andric }; 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric private: 3730b57cec5SDimitry Andric struct ParsingState { 3745ffd83dbSDimitry Andric ParsingState(struct LineTable *LT, uint64_t TableOffset, 3755ffd83dbSDimitry Andric function_ref<void(Error)> ErrorHandler); 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric void resetRowAndSequence(); 3780b57cec5SDimitry Andric void appendRowToMatrix(); 3790b57cec5SDimitry Andric 380*06c3fb27SDimitry Andric struct AddrOpIndexDelta { 381*06c3fb27SDimitry Andric uint64_t AddrOffset; 382*06c3fb27SDimitry Andric int16_t OpIndexDelta; 383*06c3fb27SDimitry Andric }; 3845ffd83dbSDimitry Andric 385*06c3fb27SDimitry Andric /// Advance the address and op-index by the \p OperationAdvance value. 386*06c3fb27SDimitry Andric /// \returns the amount advanced by. 387*06c3fb27SDimitry Andric AddrOpIndexDelta advanceAddrOpIndex(uint64_t OperationAdvance, 388*06c3fb27SDimitry Andric uint8_t Opcode, uint64_t OpcodeOffset); 389*06c3fb27SDimitry Andric 390*06c3fb27SDimitry Andric struct OpcodeAdvanceResults { 3915ffd83dbSDimitry Andric uint64_t AddrDelta; 392*06c3fb27SDimitry Andric int16_t OpIndexDelta; 3935ffd83dbSDimitry Andric uint8_t AdjustedOpcode; 3945ffd83dbSDimitry Andric }; 3955ffd83dbSDimitry Andric 396*06c3fb27SDimitry Andric /// Advance the address and op-index as required by the specified \p Opcode. 3975ffd83dbSDimitry Andric /// \returns the amount advanced by and the calculated adjusted opcode. 398*06c3fb27SDimitry Andric OpcodeAdvanceResults advanceForOpcode(uint8_t Opcode, 3995ffd83dbSDimitry Andric uint64_t OpcodeOffset); 4005ffd83dbSDimitry Andric 401*06c3fb27SDimitry Andric struct SpecialOpcodeDelta { 4025ffd83dbSDimitry Andric uint64_t Address; 4035ffd83dbSDimitry Andric int32_t Line; 404*06c3fb27SDimitry Andric int16_t OpIndex; 4055ffd83dbSDimitry Andric }; 4065ffd83dbSDimitry Andric 407*06c3fb27SDimitry Andric /// Advance the line, address and op-index as required by the specified 408*06c3fb27SDimitry Andric /// special \p Opcode. \returns the address, op-index and line delta. 409*06c3fb27SDimitry Andric SpecialOpcodeDelta handleSpecialOpcode(uint8_t Opcode, 410*06c3fb27SDimitry Andric uint64_t OpcodeOffset); 4115ffd83dbSDimitry Andric 4120b57cec5SDimitry Andric /// Line table we're currently parsing. 4130b57cec5SDimitry Andric struct LineTable *LineTable; 4140b57cec5SDimitry Andric struct Row Row; 4150b57cec5SDimitry Andric struct Sequence Sequence; 4165ffd83dbSDimitry Andric 4175ffd83dbSDimitry Andric private: 4185ffd83dbSDimitry Andric uint64_t LineTableOffset; 4195ffd83dbSDimitry Andric 4205ffd83dbSDimitry Andric bool ReportAdvanceAddrProblem = true; 4215ffd83dbSDimitry Andric bool ReportBadLineRange = true; 4225ffd83dbSDimitry Andric function_ref<void(Error)> ErrorHandler; 4230b57cec5SDimitry Andric }; 4240b57cec5SDimitry Andric 4258bcb0991SDimitry Andric using LineTableMapTy = std::map<uint64_t, LineTable>; 4260b57cec5SDimitry Andric using LineTableIter = LineTableMapTy::iterator; 4270b57cec5SDimitry Andric using LineTableConstIter = LineTableMapTy::const_iterator; 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric LineTableMapTy LineTableMap; 4300b57cec5SDimitry Andric }; 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric } // end namespace llvm 4330b57cec5SDimitry Andric 434fe6060f1SDimitry Andric #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGLINE_H 435