aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
blob: 3cc7dc657395c4f6c67b461aec813adc3fe7521d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
//===-- 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_