xref: /freebsd/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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