llvm-6502/lib/DebugInfo/DWARFDebugLine.h
Alexey Samsonov 351f83be64 Fix the representation of debug line table in DebugInfo LLVM library,
and "instruction address -> file/line" lookup.

Instead of plain collection of rows, debug line table for compilation unit is now
treated as the number of row ranges, describing sequences (series of contiguous machine
instructions). The sequences are not always listed in the order of increasing
address, so previously used std::lower_bound() sometimes produced wrong results.
Now the instruction address lookup consists of two stages: finding the correct
sequence, and searching for address in range of rows for this sequence.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161414 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-07 11:46:57 +00:00

239 lines
8.1 KiB
C++

//===-- 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 "llvm/Support/DataExtractor.h"
#include <map>
#include <vector>
namespace llvm {
class raw_ostream;
class DWARFDebugLine {
public:
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;
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,
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;
LineTableMapTy LineTableMap;
};
}
#endif