//===-- 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 #include #include 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 StandardOpcodeLengths; std::vector IncludeDirectories; std::vector 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& 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 RowVector; typedef RowVector::const_iterator RowIter; typedef std::vector 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 LineTableMapTy; typedef LineTableMapTy::iterator LineTableIter; typedef LineTableMapTy::const_iterator LineTableConstIter; const RelocAddrMap *RelocMap; LineTableMapTy LineTableMap; }; } #endif