summaryrefslogtreecommitdiff
path: root/lib/DebugInfo/DWARFDebugLine.cpp
diff options
context:
space:
mode:
authorAlexey Samsonov <samsonov@google.com>2012-08-07 11:46:57 +0000
committerAlexey Samsonov <samsonov@google.com>2012-08-07 11:46:57 +0000
commit351f83be64057380877615153fe5dc50308ab017 (patch)
tree64f4a82adea27798422027ccf6f6fa6ad5a35b10 /lib/DebugInfo/DWARFDebugLine.cpp
parentb6fdd022b7414f916ba7b08560a0f55e14863326 (diff)
downloadllvm-351f83be64057380877615153fe5dc50308ab017.tar.gz
llvm-351f83be64057380877615153fe5dc50308ab017.tar.bz2
llvm-351f83be64057380877615153fe5dc50308ab017.tar.xz
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
Diffstat (limited to 'lib/DebugInfo/DWARFDebugLine.cpp')
-rw-r--r--lib/DebugInfo/DWARFDebugLine.cpp117
1 files changed, 78 insertions, 39 deletions
diff --git a/lib/DebugInfo/DWARFDebugLine.cpp b/lib/DebugInfo/DWARFDebugLine.cpp
index 117fa31aa8..d99575d800 100644
--- a/lib/DebugInfo/DWARFDebugLine.cpp
+++ b/lib/DebugInfo/DWARFDebugLine.cpp
@@ -95,14 +95,46 @@ void DWARFDebugLine::LineTable::dump(raw_ostream &OS) const {
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::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).
+ }
+}
+
DWARFDebugLine::DumpingState::~DumpingState() {}
-void DWARFDebugLine::DumpingState::finalize(uint32_t offset) {
+void DWARFDebugLine::DumpingState::finalize() {
LineTable::dump(OS);
}
@@ -180,8 +212,9 @@ DWARFDebugLine::parsePrologue(DataExtractor debug_line_data,
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",
prologue_offset, end_prologue_offset, *offset_ptr);
+ return false;
}
- return end_prologue_offset;
+ return true;
}
bool
@@ -430,47 +463,53 @@ DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
}
}
- 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;
}