"----------------\n";
for (uint32_t i = 0; i < FileNames.size(); ++i) {
const FileNameEntry& fileEntry = FileNames[i];
- OS << format("file_names[%3u] %4u ", i+1, fileEntry.DirIdx)
- << format("0x%8.8x 0x%8.8x ", fileEntry.ModTime, fileEntry.Length)
+ OS << format("file_names[%3u] %4" PRIu64 " ", i+1, fileEntry.DirIdx)
+ << format("0x%8.8" PRIx64 " 0x%8.8" PRIx64 " ",
+ fileEntry.ModTime, fileEntry.Length)
<< fileEntry.Name << '\n';
}
}
}
void DWARFDebugLine::Row::dump(raw_ostream &OS) const {
- OS << format("0x%16.16llx %6u %6u", Address, Line, Column)
+ OS << format("0x%16.16" PRIx64 " %6u %6u", Address, Line, Column)
<< format(" %6u %3u ", File, Isa)
<< (IsStmt ? " is_stmt" : "")
<< (BasicBlock ? " basic_block" : "")
}
}
+DWARFDebugLine::State::~State() {}
+
void DWARFDebugLine::State::appendRowToMatrix(uint32_t offset) {
+ if (Sequence::Empty) {
+ // Record the beginning of instruction sequence.
+ Sequence::Empty = false;
+ Sequence::LowPC = Address;
+ Sequence::FirstRowIndex = row;
+ }
++row; // Increase the row number.
LineTable::appendRow(*this);
+ if (EndSequence) {
+ // Record the end of instruction sequence.
+ Sequence::HighPC = Address;
+ Sequence::LastRowIndex = row;
+ if (Sequence::isValid())
+ LineTable::appendSequence(*this);
+ Sequence::reset();
+ }
Row::postAppend();
}
-void DWARFDebugLine::parse(const DataExtractor debug_line_data) {
- LineTableMap.clear();
- uint32_t offset = 0;
- State state;
- while (debug_line_data.isValidOffset(offset)) {
- const uint32_t debug_line_offset = offset;
-
- if (parseStatementTable(debug_line_data, &offset, state)) {
- // Make sure we don't don't loop infinitely
- if (offset <= debug_line_offset)
- break;
-
- LineTableMap[debug_line_offset] = state;
- state.reset();
- }
- else
- ++offset; // Try next byte in line table
+void DWARFDebugLine::State::finalize() {
+ row = DoneParsingLineTable;
+ if (!Sequence::Empty) {
+ fprintf(stderr, "warning: last sequence in debug line table is not"
+ "terminated!\n");
+ }
+ // Sort all sequences so that address lookup will work faster.
+ if (!Sequences.empty()) {
+ std::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC);
+ // Note: actually, instruction address ranges of sequences should not
+ // overlap (in shared objects and executables). If they do, the address
+ // lookup would still work, though, but result would be ambiguous.
+ // We don't report warning in this case. For example,
+ // sometimes .so compiled from multiple object files contains a few
+ // rudimentary sequences for address ranges [0x0, 0xsomething).
}
}
-void DWARFDebugLine::DumpingState::finalize(uint32_t offset) {
- LineTable::dump(OS);
-}
-
-void DWARFDebugLine::dump(const DataExtractor debug_line_data, raw_ostream &OS){
- uint32_t offset = 0;
- DumpingState state(OS);
- while (debug_line_data.isValidOffset(offset)) {
- const uint32_t debug_line_offset = offset;
-
- if (parseStatementTable(debug_line_data, &offset, state)) {
- // Make sure we don't don't loop infinitely
- if (offset <= debug_line_offset)
- break;
+DWARFDebugLine::DumpingState::~DumpingState() {}
- state.reset();
- }
- else
- ++offset; // Try next byte in line table
- }
+void DWARFDebugLine::DumpingState::finalize() {
+ LineTable::dump(OS);
}
const DWARFDebugLine::LineTable *
return 0;
}
+const DWARFDebugLine::LineTable *
+DWARFDebugLine::getOrParseLineTable(DataExtractor debug_line_data,
+ uint32_t offset) {
+ std::pair<LineTableIter, bool> pos =
+ LineTableMap.insert(LineTableMapTy::value_type(offset, LineTable()));
+ if (pos.second) {
+ // Parse and cache the line table for at this offset.
+ State state;
+ if (!parseStatementTable(debug_line_data, &offset, state))
+ return 0;
+ pos.first->second = state;
+ }
+ return &pos.first->second;
+}
+
bool
DWARFDebugLine::parsePrologue(DataExtractor debug_line_data,
uint32_t *offset_ptr, Prologue *prologue) {
if (*offset_ptr != end_prologue_offset) {
fprintf(stderr, "warning: parsing line table prologue at 0x%8.8x should"
- " have ended at 0x%8.8x but it ended ad 0x%8.8x\n",
+ " have ended at 0x%8.8x but it ended ad 0x%8.8x\n",
prologue_offset, end_prologue_offset, *offset_ptr);
+ return false;
}
- return end_prologue_offset;
+ return true;
}
bool
const uint32_t end_offset = debug_line_offset + prologue->TotalLength +
sizeof(prologue->TotalLength);
+ state.reset();
+
while (*offset_ptr < end_offset) {
uint8_t opcode = debug_line_data.getU8(offset_ptr);
// of such opcodes because they are specified in the prologue
// as a multiple of LEB128 operands for each opcode.
{
- assert(opcode - 1 < prologue->StandardOpcodeLengths.size());
+ assert(opcode - 1U < prologue->StandardOpcodeLengths.size());
uint8_t opcode_length = prologue->StandardOpcodeLengths[opcode - 1];
for (uint8_t i=0; i<opcode_length; ++i)
debug_line_data.getULEB128(offset_ptr);
// field in the header, plus the value of the line_range field,
// minus 1 (line base + line range - 1). If the desired line
// increment is greater than the maximum line increment, a standard
- // opcode must be used instead of a special opcode. The “address
- // advance” is calculated by dividing the desired address increment
+ // opcode must be used instead of a special opcode. The "address
+ // advance" is calculated by dividing the desired address increment
// by the minimum_instruction_length field from the header. The
// special opcode is then calculated using the following formula:
//
}
}
- state.finalize(*offset_ptr);
+ state.finalize();
return end_offset;
}
-static bool findMatchingAddress(const DWARFDebugLine::Row& row1,
- const DWARFDebugLine::Row& row2) {
- return row1.Address < row2.Address;
-}
-
uint32_t
-DWARFDebugLine::LineTable::lookupAddress(uint64_t address,
- uint64_t cu_high_pc) const {
- uint32_t index = UINT32_MAX;
- if (!Rows.empty()) {
- // Use the lower_bound algorithm to perform a binary search since we know
- // that our line table data is ordered by address.
- DWARFDebugLine::Row row;
- row.Address = address;
- typedef std::vector<Row>::const_iterator iterator;
- iterator begin_pos = Rows.begin();
- iterator end_pos = Rows.end();
- iterator pos = std::lower_bound(begin_pos, end_pos, row,
- findMatchingAddress);
- if (pos == end_pos) {
- if (address < cu_high_pc)
- return Rows.size()-1;
- } else {
- // Rely on fact that we are using a std::vector and we can do
- // pointer arithmetic to find the row index (which will be one less
- // that what we found since it will find the first position after
- // the current address) since std::vector iterators are just
- // pointers to the container type.
- index = pos - begin_pos;
- if (pos->Address > address) {
- if (index > 0)
- --index;
- else
- index = UINT32_MAX;
- }
- }
+DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const {
+ uint32_t unknown_index = UINT32_MAX;
+ if (Sequences.empty())
+ return unknown_index;
+ // First, find an instruction sequence containing the given address.
+ DWARFDebugLine::Sequence sequence;
+ sequence.LowPC = address;
+ SequenceIter first_seq = Sequences.begin();
+ SequenceIter last_seq = Sequences.end();
+ SequenceIter seq_pos = std::lower_bound(first_seq, last_seq, sequence,
+ DWARFDebugLine::Sequence::orderByLowPC);
+ DWARFDebugLine::Sequence found_seq;
+ if (seq_pos == last_seq) {
+ found_seq = Sequences.back();
+ } else if (seq_pos->LowPC == address) {
+ found_seq = *seq_pos;
+ } else {
+ if (seq_pos == first_seq)
+ return unknown_index;
+ found_seq = *(seq_pos - 1);
+ }
+ if (!found_seq.containsPC(address))
+ return unknown_index;
+ // Search for instruction address in the rows describing the sequence.
+ // Rows are stored in a vector, so we may use arithmetical operations with
+ // iterators.
+ DWARFDebugLine::Row row;
+ row.Address = address;
+ RowIter first_row = Rows.begin() + found_seq.FirstRowIndex;
+ RowIter last_row = Rows.begin() + found_seq.LastRowIndex;
+ RowIter row_pos = std::lower_bound(first_row, last_row, row,
+ DWARFDebugLine::Row::orderByAddress);
+ if (row_pos == last_row) {
+ return found_seq.LastRowIndex - 1;
+ }
+ uint32_t index = found_seq.FirstRowIndex + (row_pos - first_row);
+ if (row_pos->Address > address) {
+ if (row_pos == first_row)
+ return unknown_index;
+ else
+ index--;
}
- return index; // Failed to find address.
+ return index;
}