Index: include/llvm/DebugInfo/DWARF/DWARFDebugLine.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -203,6 +203,9 @@ typedef SequenceVector::const_iterator SequenceIter; RowVector Rows; SequenceVector Sequences; + + private: + uint32_t findRowInSeq(const DWARFDebugLine::Sequence &seq, uint64_t address) const; }; const LineTable *getLineTable(uint32_t offset) const; Index: lib/DebugInfo/DWARF/DWARFDebugLine.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -522,8 +522,33 @@ return end_offset; } +static uint32_t unknown_index = UINT32_MAX; +uint32_t DWARFDebugLine::LineTable::findRowInSeq( + const DWARFDebugLine::Sequence &seq, uint64_t address) const +{ + // 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() + seq.FirstRowIndex; + RowIter last_row = Rows.begin() + seq.LastRowIndex; + LineTable::RowIter row_pos = std::lower_bound(first_row, last_row, row, + DWARFDebugLine::Row::orderByAddress); + if (row_pos == last_row) { + return seq.LastRowIndex - 1; + } + uint32_t index = seq.FirstRowIndex + (row_pos - first_row); + if (row_pos->Address > address) { + if (row_pos == first_row) + return unknown_index; + else + index--; + } + return index; +} + uint32_t 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. @@ -545,26 +570,7 @@ } 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; + return findRowInSeq(found_seq,address); } bool DWARFDebugLine::LineTable::lookupAddressRange( @@ -594,42 +600,22 @@ while (seq_pos != last_seq && seq_pos->LowPC < end_addr) { DWARFDebugLine::Sequence cur_seq = *seq_pos; - uint32_t first_row_index; - uint32_t last_row_index; - if (seq_pos == start_pos) { - // For the first sequence, we need to find which row in the sequence is the - // first in our range. 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() + cur_seq.FirstRowIndex; - RowIter last_row = Rows.begin() + cur_seq.LastRowIndex; - RowIter row_pos = std::upper_bound(first_row, last_row, row, - DWARFDebugLine::Row::orderByAddress); - // The 'row_pos' iterator references the first row that is greater than - // our start address. Unless that's the first row, we want to start at - // the row before that. - first_row_index = cur_seq.FirstRowIndex + (row_pos - first_row); - if (row_pos != first_row) - --first_row_index; - } else + uint32_t first_row_index = unknown_index; + uint32_t last_row_index = unknown_index; + // For the first sequence, we need to find which row in the sequence is the + // first in our range. + if (seq_pos == start_pos) + first_row_index = findRowInSeq(cur_seq, address); + if (first_row_index == unknown_index) first_row_index = cur_seq.FirstRowIndex; // For the last sequence in our range, we need to figure out the last row in // range. For all other sequences we can go to the end of the sequence. - if (cur_seq.HighPC > end_addr) { - DWARFDebugLine::Row row; - row.Address = end_addr; - RowIter first_row = Rows.begin() + cur_seq.FirstRowIndex; - RowIter last_row = Rows.begin() + cur_seq.LastRowIndex; - RowIter row_pos = std::upper_bound(first_row, last_row, row, - DWARFDebugLine::Row::orderByAddress); - // The 'row_pos' iterator references the first row that is greater than - // our end address. The row before that is the last row we want. - last_row_index = cur_seq.FirstRowIndex + (row_pos - first_row) - 1; - } else - // Contrary to what you might expect, DWARFDebugLine::SequenceLastRowIndex - // isn't a valid index within the current sequence. It's that plus one. + if (cur_seq.HighPC > end_addr) + last_row_index = findRowInSeq(cur_seq, end_addr-1); + // Contrary to what you might expect, DWARFDebugLine::SequenceLastRowIndex + // isn't a valid index within the current sequence. It's that plus one. + if (last_row_index == unknown_index) last_row_index = cur_seq.LastRowIndex - 1; for (uint32_t i = first_row_index; i <= last_row_index; ++i) { Index: test/DebugInfo/debuglineinfo-macho.test =================================================================== --- test/DebugInfo/debuglineinfo-macho.test +++ test/DebugInfo/debuglineinfo-macho.test @@ -3,3 +3,39 @@ RUN: llvm-dwarfdump %p/Inputs/test-multiple-macho.o | FileCheck %s CHECK-NOT: error: failed to compute relocation: X86_64_RELOC_UNSIGNED + +# Check that relocations get applied correctly +RUN: llvm-rtdyld -printobjline %p/Inputs/test-simple-macho.o \ +RUN: | FileCheck %s -check-prefix TEST_SIMPLE +RUN: llvm-rtdyld -printline %p/Inputs/test-simple-macho.o \ +RUN: | FileCheck %s -check-prefix TEST_SIMPLE +RUN: llvm-rtdyld -printobjline %p/Inputs/test-multiple-macho.o \ +RUN: | FileCheck %s -check-prefix TEST_MULTIPLE +RUN: llvm-rtdyld -printline %p/Inputs/test-multiple-macho.o \ +RUN: | FileCheck %s -check-prefix TEST_MULTIPLE + +TEST_SIMPLE: Function: _foo, Size = 11 +TEST_SIMPLE-NEXT: Line info @ 0: simple.c, line:1 +TEST_SIMPLE-NEXT: Line info @ 7: simple.c, line:2 +TEST_SIMPLE-NEXT: Line info @ 11: simple.c, line:2 + +TEST_MULTIPLE: Function: _bar, Size = 48 +TEST_MULTIPLE-NEXT: Line info @ 0: multiple.c, line:5 +TEST_MULTIPLE-NEXT: Line info @ 7: multiple.c, line:6 +TEST_MULTIPLE-NEXT: Line info @ 16: multiple.c, line:9 +TEST_MULTIPLE-NEXT: Line info @ 21: multiple.c, line:9 +TEST_MULTIPLE-NEXT: Line info @ 26: multiple.c, line:7 +TEST_MULTIPLE-NEXT: Line info @ 33: multiple.c, line:10 +TEST_MULTIPLE-NOT: Line info @ 48: multiple.c, line:12 +TEST_MULTIPLE-NEXT: Function: _foo, Size = 16 +TEST_MULTIPLE-NEXT: Line info @ 0: multiple.c, line:1 +TEST_MULTIPLE-NEXT: Line info @ 7: multiple.c, line:2 +TEST_MULTIPLE-NOT: Line info @ 16: multiple.c, line:5 +TEST_MULTIPLE-NEXT: Function: _fubar, Size = 46 +TEST_MULTIPLE-NEXT: Line info @ 0: multiple.c, line:12 +TEST_MULTIPLE-NEXT: Line info @ 7: multiple.c, line:13 +TEST_MULTIPLE-NEXT: Line info @ 12: multiple.c, line:17 +TEST_MULTIPLE-NEXT: Line info @ 25: multiple.c, line:15 +TEST_MULTIPLE-NEXT: Line info @ 34: multiple.c, line:19 +TEST_MULTIPLE-NEXT: Line info @ 41: multiple.c, line:21 +TEST_MULTIPLE-NEXT: Line info @ 46: multiple.c, line:21