1226584Sdim//===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===//
2226584Sdim//
3226584Sdim//                     The LLVM Compiler Infrastructure
4226584Sdim//
5226584Sdim// This file is distributed under the University of Illinois Open Source
6226584Sdim// License. See LICENSE.TXT for details.
7226584Sdim//
8226584Sdim//===----------------------------------------------------------------------===//
9226584Sdim
10226584Sdim#ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H
11226584Sdim#define LLVM_DEBUGINFO_DWARFDEBUGLINE_H
12226584Sdim
13249423Sdim#include "DWARFRelocMap.h"
14226584Sdim#include "llvm/Support/DataExtractor.h"
15226584Sdim#include <map>
16243830Sdim#include <string>
17226584Sdim#include <vector>
18226584Sdim
19226584Sdimnamespace llvm {
20226584Sdim
21226584Sdimclass raw_ostream;
22226584Sdim
23226584Sdimclass DWARFDebugLine {
24226584Sdimpublic:
25249423Sdim  DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {}
26226584Sdim  struct FileNameEntry {
27239462Sdim    FileNameEntry() : Name(0), DirIdx(0), ModTime(0), Length(0) {}
28226584Sdim
29239462Sdim    const char *Name;
30226584Sdim    uint64_t DirIdx;
31226584Sdim    uint64_t ModTime;
32226584Sdim    uint64_t Length;
33226584Sdim  };
34226584Sdim
35226584Sdim  struct Prologue {
36226584Sdim    Prologue()
37226584Sdim      : TotalLength(0), Version(0), PrologueLength(0), MinInstLength(0),
38226584Sdim        DefaultIsStmt(0), LineBase(0), LineRange(0), OpcodeBase(0) {}
39226584Sdim
40226584Sdim    // The size in bytes of the statement information for this compilation unit
41226584Sdim    // (not including the total_length field itself).
42226584Sdim    uint32_t TotalLength;
43226584Sdim    // Version identifier for the statement information format.
44226584Sdim    uint16_t Version;
45226584Sdim    // The number of bytes following the prologue_length field to the beginning
46226584Sdim    // of the first byte of the statement program itself.
47226584Sdim    uint32_t PrologueLength;
48226584Sdim    // The size in bytes of the smallest target machine instruction. Statement
49226584Sdim    // program opcodes that alter the address register first multiply their
50226584Sdim    // operands by this value.
51226584Sdim    uint8_t MinInstLength;
52226584Sdim    // The initial value of theis_stmtregister.
53226584Sdim    uint8_t DefaultIsStmt;
54226584Sdim    // This parameter affects the meaning of the special opcodes. See below.
55226584Sdim    int8_t LineBase;
56226584Sdim    // This parameter affects the meaning of the special opcodes. See below.
57226584Sdim    uint8_t LineRange;
58226584Sdim    // The number assigned to the first special opcode.
59226584Sdim    uint8_t OpcodeBase;
60226584Sdim    std::vector<uint8_t> StandardOpcodeLengths;
61239462Sdim    std::vector<const char*> IncludeDirectories;
62226584Sdim    std::vector<FileNameEntry> FileNames;
63226584Sdim
64226584Sdim    // Length of the prologue in bytes.
65226584Sdim    uint32_t getLength() const {
66226584Sdim      return PrologueLength + sizeof(TotalLength) + sizeof(Version) +
67226584Sdim             sizeof(PrologueLength);
68226584Sdim    }
69226584Sdim    // Length of the line table data in bytes (not including the prologue).
70226584Sdim    uint32_t getStatementTableLength() const {
71226584Sdim      return TotalLength + sizeof(TotalLength) - getLength();
72226584Sdim    }
73226584Sdim    int32_t getMaxLineIncrementForSpecialOpcode() const {
74226584Sdim      return LineBase + (int8_t)LineRange - 1;
75226584Sdim    }
76226584Sdim    void dump(raw_ostream &OS) const;
77226584Sdim    void clear() {
78226584Sdim      TotalLength = Version = PrologueLength = 0;
79226584Sdim      MinInstLength = LineBase = LineRange = OpcodeBase = 0;
80226584Sdim      StandardOpcodeLengths.clear();
81226584Sdim      IncludeDirectories.clear();
82226584Sdim      FileNames.clear();
83226584Sdim    }
84226584Sdim  };
85226584Sdim
86226584Sdim  // Standard .debug_line state machine structure.
87226584Sdim  struct Row {
88226584Sdim    Row(bool default_is_stmt = false) { reset(default_is_stmt); }
89226584Sdim    /// Called after a row is appended to the matrix.
90226584Sdim    void postAppend();
91226584Sdim    void reset(bool default_is_stmt);
92226584Sdim    void dump(raw_ostream &OS) const;
93226584Sdim
94239462Sdim    static bool orderByAddress(const Row& LHS, const Row& RHS) {
95239462Sdim      return LHS.Address < RHS.Address;
96239462Sdim    }
97239462Sdim
98226584Sdim    // The program-counter value corresponding to a machine instruction
99226584Sdim    // generated by the compiler.
100226584Sdim    uint64_t Address;
101226584Sdim    // An unsigned integer indicating a source line number. Lines are numbered
102226584Sdim    // beginning at 1. The compiler may emit the value 0 in cases where an
103226584Sdim    // instruction cannot be attributed to any source line.
104226584Sdim    uint32_t Line;
105226584Sdim    // An unsigned integer indicating a column number within a source line.
106226584Sdim    // Columns are numbered beginning at 1. The value 0 is reserved to indicate
107226584Sdim    // that a statement begins at the 'left edge' of the line.
108226584Sdim    uint16_t Column;
109226584Sdim    // An unsigned integer indicating the identity of the source file
110226584Sdim    // corresponding to a machine instruction.
111226584Sdim    uint16_t File;
112226584Sdim    // An unsigned integer whose value encodes the applicable instruction set
113226584Sdim    // architecture for the current instruction.
114226584Sdim    uint8_t Isa;
115226584Sdim    // A boolean indicating that the current instruction is the beginning of a
116226584Sdim    // statement.
117226584Sdim    uint8_t IsStmt:1,
118226584Sdim            // A boolean indicating that the current instruction is the
119226584Sdim            // beginning of a basic block.
120226584Sdim            BasicBlock:1,
121226584Sdim            // A boolean indicating that the current address is that of the
122226584Sdim            // first byte after the end of a sequence of target machine
123226584Sdim            // instructions.
124226584Sdim            EndSequence:1,
125226584Sdim            // A boolean indicating that the current address is one (of possibly
126226584Sdim            // many) where execution should be suspended for an entry breakpoint
127226584Sdim            // of a function.
128226584Sdim            PrologueEnd:1,
129226584Sdim            // A boolean indicating that the current address is one (of possibly
130226584Sdim            // many) where execution should be suspended for an exit breakpoint
131226584Sdim            // of a function.
132226584Sdim            EpilogueBegin:1;
133226584Sdim  };
134226584Sdim
135239462Sdim  // Represents a series of contiguous machine instructions. Line table for each
136239462Sdim  // compilation unit may consist of multiple sequences, which are not
137239462Sdim  // guaranteed to be in the order of ascending instruction address.
138239462Sdim  struct Sequence {
139239462Sdim    // Sequence describes instructions at address range [LowPC, HighPC)
140239462Sdim    // and is described by line table rows [FirstRowIndex, LastRowIndex).
141239462Sdim    uint64_t LowPC;
142239462Sdim    uint64_t HighPC;
143239462Sdim    unsigned FirstRowIndex;
144239462Sdim    unsigned LastRowIndex;
145239462Sdim    bool Empty;
146239462Sdim
147239462Sdim    Sequence() { reset(); }
148239462Sdim    void reset() {
149239462Sdim      LowPC = 0;
150239462Sdim      HighPC = 0;
151239462Sdim      FirstRowIndex = 0;
152239462Sdim      LastRowIndex = 0;
153239462Sdim      Empty = true;
154239462Sdim    }
155239462Sdim    static bool orderByLowPC(const Sequence& LHS, const Sequence& RHS) {
156239462Sdim      return LHS.LowPC < RHS.LowPC;
157239462Sdim    }
158239462Sdim    bool isValid() const {
159239462Sdim      return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex);
160239462Sdim    }
161239462Sdim    bool containsPC(uint64_t pc) const {
162239462Sdim      return (LowPC <= pc && pc < HighPC);
163239462Sdim    }
164239462Sdim  };
165239462Sdim
166226584Sdim  struct LineTable {
167226584Sdim    void appendRow(const DWARFDebugLine::Row &state) { Rows.push_back(state); }
168239462Sdim    void appendSequence(const DWARFDebugLine::Sequence &sequence) {
169239462Sdim      Sequences.push_back(sequence);
170239462Sdim    }
171226584Sdim    void clear() {
172226584Sdim      Prologue.clear();
173226584Sdim      Rows.clear();
174239462Sdim      Sequences.clear();
175226584Sdim    }
176226584Sdim
177239462Sdim    // Returns the index of the row with file/line info for a given address,
178239462Sdim    // or -1 if there is no such row.
179239462Sdim    uint32_t lookupAddress(uint64_t address) const;
180243830Sdim
181249423Sdim    bool lookupAddressRange(uint64_t address,
182249423Sdim                            uint64_t size,
183249423Sdim                            std::vector<uint32_t>& result) const;
184249423Sdim
185243830Sdim    // Extracts filename by its index in filename table in prologue.
186243830Sdim    // Returns true on success.
187243830Sdim    bool getFileNameByIndex(uint64_t FileIndex,
188243830Sdim                            bool NeedsAbsoluteFilePath,
189243830Sdim                            std::string &Result) const;
190243830Sdim
191226584Sdim    void dump(raw_ostream &OS) const;
192226584Sdim
193226584Sdim    struct Prologue Prologue;
194239462Sdim    typedef std::vector<Row> RowVector;
195239462Sdim    typedef RowVector::const_iterator RowIter;
196239462Sdim    typedef std::vector<Sequence> SequenceVector;
197239462Sdim    typedef SequenceVector::const_iterator SequenceIter;
198239462Sdim    RowVector Rows;
199239462Sdim    SequenceVector Sequences;
200226584Sdim  };
201226584Sdim
202239462Sdim  struct State : public Row, public Sequence, public LineTable {
203226584Sdim    // Special row codes.
204226584Sdim    enum {
205226584Sdim      StartParsingLineTable = 0,
206226584Sdim      DoneParsingLineTable = -1
207226584Sdim    };
208226584Sdim
209226584Sdim    State() : row(StartParsingLineTable) {}
210226584Sdim    virtual ~State();
211226584Sdim
212226584Sdim    virtual void appendRowToMatrix(uint32_t offset);
213239462Sdim    virtual void finalize();
214239462Sdim    virtual void reset() {
215239462Sdim      Row::reset(Prologue.DefaultIsStmt);
216239462Sdim      Sequence::reset();
217239462Sdim    }
218226584Sdim
219226584Sdim    // The row number that starts at zero for the prologue, and increases for
220226584Sdim    // each row added to the matrix.
221226584Sdim    unsigned row;
222226584Sdim  };
223226584Sdim
224226584Sdim  struct DumpingState : public State {
225226584Sdim    DumpingState(raw_ostream &OS) : OS(OS) {}
226226584Sdim    virtual ~DumpingState();
227239462Sdim    virtual void finalize();
228226584Sdim  private:
229226584Sdim    raw_ostream &OS;
230226584Sdim  };
231226584Sdim
232226584Sdim  static bool parsePrologue(DataExtractor debug_line_data, uint32_t *offset_ptr,
233226584Sdim                            Prologue *prologue);
234226584Sdim  /// Parse a single line table (prologue and all rows).
235226584Sdim  static bool parseStatementTable(DataExtractor debug_line_data,
236249423Sdim                                  const RelocAddrMap *RMap,
237226584Sdim                                  uint32_t *offset_ptr, State &state);
238226584Sdim
239226584Sdim  const LineTable *getLineTable(uint32_t offset) const;
240226584Sdim  const LineTable *getOrParseLineTable(DataExtractor debug_line_data,
241226584Sdim                                       uint32_t offset);
242226584Sdim
243226584Sdimprivate:
244226584Sdim  typedef std::map<uint32_t, LineTable> LineTableMapTy;
245226584Sdim  typedef LineTableMapTy::iterator LineTableIter;
246226584Sdim  typedef LineTableMapTy::const_iterator LineTableConstIter;
247226584Sdim
248249423Sdim  const RelocAddrMap *RelocMap;
249226584Sdim  LineTableMapTy LineTableMap;
250226584Sdim};
251226584Sdim
252226584Sdim}
253226584Sdim
254226584Sdim#endif
255