//===-- 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 SymbolFileDWARF_DWARFDebugLine_h_ #define SymbolFileDWARF_DWARFDebugLine_h_ #include <map> #include <vector> #include <string> #include "lldb/lldb-private.h" #include "DWARFDefines.h" class SymbolFileDWARF; class DWARFDebugInfoEntry; //---------------------------------------------------------------------- // DWARFDebugLine //---------------------------------------------------------------------- class DWARFDebugLine { public: //------------------------------------------------------------------ // FileNameEntry //------------------------------------------------------------------ struct FileNameEntry { FileNameEntry() : name(), dir_idx(0), mod_time(0), length(0) { } std::string name; dw_sleb128_t dir_idx; dw_sleb128_t mod_time; dw_sleb128_t length; }; //------------------------------------------------------------------ // Prologue //------------------------------------------------------------------ struct Prologue { Prologue() : total_length(0), version(0), prologue_length(0), min_inst_length(0), default_is_stmt(0), line_base(0), line_range(0), opcode_base(0), standard_opcode_lengths(), include_directories(), file_names() { } typedef std::shared_ptr<Prologue> shared_ptr; uint32_t total_length; // The size in bytes of the statement information for this compilation unit (not including the total_length field itself). uint16_t version; // Version identifier for the statement information format. uint32_t prologue_length;// The number of bytes following the prologue_length field to the beginning of the first byte of the statement program itself. uint8_t min_inst_length;// 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 default_is_stmt;// The initial value of theis_stmtregister. int8_t line_base; // This parameter affects the meaning of the special opcodes. See below. uint8_t line_range; // This parameter affects the meaning of the special opcodes. See below. uint8_t opcode_base; // The number assigned to the first special opcode. std::vector<uint8_t> standard_opcode_lengths; std::vector<std::string> include_directories; std::vector<FileNameEntry> file_names; // Length of the prologue in bytes uint32_t Length() const { return prologue_length + sizeof(total_length) + sizeof(version) + sizeof(prologue_length); } // Length of the line table data in bytes (not including the prologue) uint32_t StatementTableLength() const { return total_length + sizeof(total_length) - Length(); } int32_t MaxLineIncrementForSpecialOpcode() const { return line_base + (int8_t)line_range - 1; } bool IsValid() const; // void Append(BinaryStreamBuf& buff) const; void Dump (lldb_private::Log *log); void Clear() { total_length = version = prologue_length = min_inst_length = line_base = line_range = opcode_base = 0; line_base = 0; standard_opcode_lengths.clear(); include_directories.clear(); file_names.clear(); } bool GetFile(uint32_t file_idx, std::string& file, std::string& dir) const; }; // Standard .debug_line state machine structure struct Row { typedef std::vector<Row> collection; typedef collection::iterator iterator; typedef collection::const_iterator const_iterator; Row(bool default_is_stmt = false); Row(const Row& rhs) : address(rhs.address), line(rhs.line), column(rhs.column), file(rhs.file), is_stmt(rhs.is_stmt), basic_block(rhs.basic_block), end_sequence(rhs.end_sequence), prologue_end(rhs.prologue_end), epilogue_begin(rhs.epilogue_begin), isa(rhs.isa) {} Row& operator =(const Row& rhs) { if (&rhs == this) return *this; address = rhs.address; line = rhs.line; column = rhs.column; file = rhs.file; is_stmt = rhs.is_stmt; basic_block = rhs.basic_block; end_sequence = rhs.end_sequence; prologue_end = rhs.prologue_end; epilogue_begin = rhs.epilogue_begin; isa = rhs.isa; return *this; } virtual ~Row() {} void PostAppend (); void Reset(bool default_is_stmt); void Dump(lldb_private::Log *log) const; static void Insert(Row::collection& state_coll, const Row& state); static void Dump(lldb_private::Log *log, const Row::collection& state_coll); dw_addr_t address; // The program-counter value corresponding to a machine instruction generated by the compiler. uint32_t line; // 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. uint16_t column; // 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 file; // An unsigned integer indicating the identity of the source file corresponding to a machine instruction. uint8_t is_stmt:1, // A boolean indicating that the current instruction is the beginning of a statement. basic_block:1, // A boolean indicating that the current instruction is the beginning of a basic block. end_sequence:1, // A boolean indicating that the current address is that of the first byte after the end of a sequence of target machine instructions. prologue_end: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. epilogue_begin: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. uint32_t isa; // An unsigned integer whose value encodes the applicable instruction set architecture for the current instruction. }; //------------------------------------------------------------------ // LineTable //------------------------------------------------------------------ struct LineTable { typedef std::shared_ptr<LineTable> shared_ptr; LineTable() : prologue(), rows() { } void AppendRow(const DWARFDebugLine::Row& state); void Clear() { prologue.reset(); rows.clear(); } uint32_t LookupAddress(dw_addr_t address, dw_addr_t cu_high_pc) const; void Dump(lldb_private::Log *log) const; Prologue::shared_ptr prologue; Row::collection rows; }; //------------------------------------------------------------------ // State //------------------------------------------------------------------ struct State : public Row { typedef void (*Callback)(dw_offset_t offset, const State& state, void* userData); // Special row codes used when calling the callback enum { StartParsingLineTable = 0, DoneParsingLineTable = -1 }; State (Prologue::shared_ptr& prologue_sp, lldb_private::Log *log, Callback callback, void* userData); void AppendRowToMatrix (dw_offset_t offset); void Finalize (dw_offset_t offset); void Reset (); Prologue::shared_ptr prologue; lldb_private::Log *log; Callback callback; // Callback function that gets called each time an entry is to be added to the matrix void* callbackUserData; int row; // The row number that starts at zero for the prologue, and increases for each row added to the matrix private: DISALLOW_COPY_AND_ASSIGN (State); }; static bool DumpOpcodes(lldb_private::Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t line_offset = DW_INVALID_OFFSET, uint32_t dump_flags = 0); // If line_offset is invalid, dump everything static bool DumpLineTableRows(lldb_private::Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t line_offset = DW_INVALID_OFFSET); // If line_offset is invalid, dump everything static bool ParseSupportFiles(const lldb::ModuleSP &module_sp, const lldb_private::DataExtractor& debug_line_data, const char *cu_comp_dir, dw_offset_t stmt_list, lldb_private::FileSpecList &support_files); static bool ParsePrologue(const lldb_private::DataExtractor& debug_line_data, lldb::offset_t* offset_ptr, Prologue* prologue); static bool ParseStatementTable(const lldb_private::DataExtractor& debug_line_data, lldb::offset_t* offset_ptr, State::Callback callback, void* userData); static dw_offset_t DumpStatementTable(lldb_private::Log *log, const lldb_private::DataExtractor& debug_line_data, const dw_offset_t line_offset); static dw_offset_t DumpStatementOpcodes(lldb_private::Log *log, const lldb_private::DataExtractor& debug_line_data, const dw_offset_t line_offset, uint32_t flags); static bool ParseStatementTable(const lldb_private::DataExtractor& debug_line_data, lldb::offset_t *offset_ptr, LineTable* line_table); static void Parse(const lldb_private::DataExtractor& debug_line_data, DWARFDebugLine::State::Callback callback, void* userData); // static void AppendLineTableData(const DWARFDebugLine::Prologue* prologue, const DWARFDebugLine::Row::collection& state_coll, const uint32_t addr_size, BinaryStreamBuf &debug_line_data); DWARFDebugLine() : m_lineTableMap() { } void Parse(const lldb_private::DataExtractor& debug_line_data); void ParseIfNeeded(const lldb_private::DataExtractor& debug_line_data); LineTable::shared_ptr GetLineTable(const dw_offset_t offset) const; protected: typedef std::map<dw_offset_t, LineTable::shared_ptr> LineTableMap; typedef LineTableMap::iterator LineTableIter; typedef LineTableMap::const_iterator LineTableConstIter; LineTableMap m_lineTableMap; }; #endif // SymbolFileDWARF_DWARFDebugLine_h_