|  | //===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H | 
|  | #define LLVM_DEBUGINFO_DWARFDEBUGLINE_H | 
|  |  | 
|  | #include "DWARFRelocMap.h" | 
|  | #include "llvm/Support/DataExtractor.h" | 
|  | #include <map> | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | class raw_ostream; | 
|  |  | 
|  | class DWARFDebugLine { | 
|  | public: | 
|  | DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {} | 
|  | struct FileNameEntry { | 
|  | FileNameEntry() : Name(0), DirIdx(0), ModTime(0), Length(0) {} | 
|  |  | 
|  | const char *Name; | 
|  | uint64_t DirIdx; | 
|  | uint64_t ModTime; | 
|  | uint64_t Length; | 
|  | }; | 
|  |  | 
|  | struct Prologue { | 
|  | Prologue() | 
|  | : TotalLength(0), Version(0), PrologueLength(0), MinInstLength(0), | 
|  | DefaultIsStmt(0), LineBase(0), LineRange(0), OpcodeBase(0) {} | 
|  |  | 
|  | // The size in bytes of the statement information for this compilation unit | 
|  | // (not including the total_length field itself). | 
|  | uint32_t TotalLength; | 
|  | // Version identifier for the statement information format. | 
|  | uint16_t Version; | 
|  | // The number of bytes following the prologue_length field to the beginning | 
|  | // of the first byte of the statement program itself. | 
|  | uint32_t PrologueLength; | 
|  | // 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 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; | 
|  | std::vector<uint8_t> StandardOpcodeLengths; | 
|  | std::vector<const char*> IncludeDirectories; | 
|  | std::vector<FileNameEntry> FileNames; | 
|  |  | 
|  | // Length of the prologue in bytes. | 
|  | uint32_t getLength() const { | 
|  | return PrologueLength + sizeof(TotalLength) + sizeof(Version) + | 
|  | sizeof(PrologueLength); | 
|  | } | 
|  | // Length of the line table data in bytes (not including the prologue). | 
|  | uint32_t getStatementTableLength() const { | 
|  | return TotalLength + sizeof(TotalLength) - getLength(); | 
|  | } | 
|  | int32_t getMaxLineIncrementForSpecialOpcode() const { | 
|  | return LineBase + (int8_t)LineRange - 1; | 
|  | } | 
|  | void dump(raw_ostream &OS) const; | 
|  | void clear() { | 
|  | TotalLength = Version = PrologueLength = 0; | 
|  | MinInstLength = LineBase = LineRange = OpcodeBase = 0; | 
|  | StandardOpcodeLengths.clear(); | 
|  | IncludeDirectories.clear(); | 
|  | FileNames.clear(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | // Standard .debug_line state machine structure. | 
|  | struct Row { | 
|  | Row(bool default_is_stmt = false) { reset(default_is_stmt); } | 
|  | /// Called after a row is appended to the matrix. | 
|  | void postAppend(); | 
|  | void reset(bool default_is_stmt); | 
|  | void dump(raw_ostream &OS) const; | 
|  |  | 
|  | static bool orderByAddress(const Row& LHS, const Row& RHS) { | 
|  | return LHS.Address < RHS.Address; | 
|  | } | 
|  |  | 
|  | // The program-counter value corresponding to a machine instruction | 
|  | // generated by the compiler. | 
|  | uint64_t 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 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 describes instructions at address range [LowPC, HighPC) | 
|  | // and is described by line table rows [FirstRowIndex, LastRowIndex). | 
|  | uint64_t LowPC; | 
|  | uint64_t HighPC; | 
|  | unsigned FirstRowIndex; | 
|  | unsigned LastRowIndex; | 
|  | bool Empty; | 
|  |  | 
|  | Sequence() { reset(); } | 
|  | void reset() { | 
|  | LowPC = 0; | 
|  | HighPC = 0; | 
|  | FirstRowIndex = 0; | 
|  | LastRowIndex = 0; | 
|  | Empty = true; | 
|  | } | 
|  | static bool orderByLowPC(const Sequence& LHS, const Sequence& RHS) { | 
|  | return LHS.LowPC < RHS.LowPC; | 
|  | } | 
|  | bool isValid() const { | 
|  | return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); | 
|  | } | 
|  | bool containsPC(uint64_t pc) const { | 
|  | return (LowPC <= pc && pc < HighPC); | 
|  | } | 
|  | }; | 
|  |  | 
|  | struct LineTable { | 
|  | void appendRow(const DWARFDebugLine::Row &state) { Rows.push_back(state); } | 
|  | void appendSequence(const DWARFDebugLine::Sequence &sequence) { | 
|  | Sequences.push_back(sequence); | 
|  | } | 
|  | void clear() { | 
|  | Prologue.clear(); | 
|  | Rows.clear(); | 
|  | Sequences.clear(); | 
|  | } | 
|  |  | 
|  | // Returns the index of the row with file/line info for a given address, | 
|  | // or -1 if there is no such row. | 
|  | uint32_t lookupAddress(uint64_t address) const; | 
|  |  | 
|  | bool lookupAddressRange(uint64_t address, | 
|  | uint64_t size, | 
|  | std::vector<uint32_t>& result) const; | 
|  |  | 
|  | // Extracts filename by its index in filename table in prologue. | 
|  | // Returns true on success. | 
|  | bool getFileNameByIndex(uint64_t FileIndex, | 
|  | bool NeedsAbsoluteFilePath, | 
|  | std::string &Result) const; | 
|  |  | 
|  | void dump(raw_ostream &OS) const; | 
|  |  | 
|  | struct Prologue Prologue; | 
|  | typedef std::vector<Row> RowVector; | 
|  | typedef RowVector::const_iterator RowIter; | 
|  | typedef std::vector<Sequence> SequenceVector; | 
|  | typedef SequenceVector::const_iterator SequenceIter; | 
|  | RowVector Rows; | 
|  | SequenceVector Sequences; | 
|  | }; | 
|  |  | 
|  | struct State : public Row, public Sequence, public LineTable { | 
|  | // Special row codes. | 
|  | enum { | 
|  | StartParsingLineTable = 0, | 
|  | DoneParsingLineTable = -1 | 
|  | }; | 
|  |  | 
|  | State() : row(StartParsingLineTable) {} | 
|  | virtual ~State(); | 
|  |  | 
|  | virtual void appendRowToMatrix(uint32_t offset); | 
|  | virtual void finalize(); | 
|  | virtual void reset() { | 
|  | Row::reset(Prologue.DefaultIsStmt); | 
|  | Sequence::reset(); | 
|  | } | 
|  |  | 
|  | // The row number that starts at zero for the prologue, and increases for | 
|  | // each row added to the matrix. | 
|  | unsigned row; | 
|  | }; | 
|  |  | 
|  | struct DumpingState : public State { | 
|  | DumpingState(raw_ostream &OS) : OS(OS) {} | 
|  | virtual ~DumpingState(); | 
|  | virtual void finalize(); | 
|  | private: | 
|  | raw_ostream &OS; | 
|  | }; | 
|  |  | 
|  | static bool parsePrologue(DataExtractor debug_line_data, uint32_t *offset_ptr, | 
|  | Prologue *prologue); | 
|  | /// Parse a single line table (prologue and all rows). | 
|  | static bool parseStatementTable(DataExtractor debug_line_data, | 
|  | const RelocAddrMap *RMap, | 
|  | uint32_t *offset_ptr, State &state); | 
|  |  | 
|  | const LineTable *getLineTable(uint32_t offset) const; | 
|  | const LineTable *getOrParseLineTable(DataExtractor debug_line_data, | 
|  | uint32_t offset); | 
|  |  | 
|  | private: | 
|  | typedef std::map<uint32_t, LineTable> LineTableMapTy; | 
|  | typedef LineTableMapTy::iterator LineTableIter; | 
|  | typedef LineTableMapTy::const_iterator LineTableConstIter; | 
|  |  | 
|  | const RelocAddrMap *RelocMap; | 
|  | LineTableMapTy LineTableMap; | 
|  | }; | 
|  |  | 
|  | } | 
|  |  | 
|  | #endif |