llvm.org GIT mirror llvm / 23125c5
[DWARF] Fix a bug in line info handling This fixes a bug in the line info handling in the dwarf code, based on a problem I when implementing RelocVisitor support for MachO. Since addr+size will give the first address past the end of the function, we need to back up one line table entry. Fix this by looking up the end_addr-1, which is the last address in the range. Note that this also removes a duplicate output from the llvm-rtdyld line table dump. The relevant line is the end_sequence one in the line table and has an offset of the first address part the end of the range and hence should not be included. Also factor out the common functionality into a separate function. This comes up on MachO much more than on ELF, since MachO doesn't store the symbol size separately, hence making said situation always occur. Differential Revision: http://reviews.llvm.org/D9925 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238699 91177308-0d34-0410-b5e6-96231b3b80d8 Keno Fischer 4 years ago
4 changed file(s) with 88 addition(s) and 72 deletion(s). Raw diff Collapse all Expand all
170170 struct LineTable {
171171 LineTable();
172172
173 // Represents an invalid row
174 const uint32_t UnknownRowIndex = UINT32_MAX;
175
173176 void appendRow(const DWARFDebugLine::Row &R) {
174177 Rows.push_back(R);
175178 }
178181 }
179182
180183 // Returns the index of the row with file/line info for a given address,
181 // or -1 if there is no such row.
184 // or UnknownRowIndex if there is no such row.
182185 uint32_t lookupAddress(uint64_t address) const;
183186
184187 bool lookupAddressRange(uint64_t address, uint64_t size,
210213 typedef SequenceVector::const_iterator SequenceIter;
211214 RowVector Rows;
212215 SequenceVector Sequences;
216
217 private:
218 uint32_t findRowInSeq(const DWARFDebugLine::Sequence &seq,
219 uint64_t address) const;
213220 };
214221
215222 const LineTable *getLineTable(uint32_t offset) const;
530530 return end_offset;
531531 }
532532
533 uint32_t
534 DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &seq,
535 uint64_t address) const {
536 if (!seq.containsPC(address))
537 return UnknownRowIndex;
538 // Search for instruction address in the rows describing the sequence.
539 // Rows are stored in a vector, so we may use arithmetical operations with
540 // iterators.
541 DWARFDebugLine::Row row;
542 row.Address = address;
543 RowIter first_row = Rows.begin() + seq.FirstRowIndex;
544 RowIter last_row = Rows.begin() + seq.LastRowIndex;
545 LineTable::RowIter row_pos = std::lower_bound(
546 first_row, last_row, row, DWARFDebugLine::Row::orderByAddress);
547 if (row_pos == last_row) {
548 return seq.LastRowIndex - 1;
549 }
550 uint32_t index = seq.FirstRowIndex + (row_pos - first_row);
551 if (row_pos->Address > address) {
552 if (row_pos == first_row)
553 return UnknownRowIndex;
554 else
555 index--;
556 }
557 return index;
558 }
559
533560 uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const {
534 uint32_t unknown_index = UINT32_MAX;
535561 if (Sequences.empty())
536 return unknown_index;
562 return UnknownRowIndex;
537563 // First, find an instruction sequence containing the given address.
538564 DWARFDebugLine::Sequence sequence;
539565 sequence.LowPC = address;
548574 found_seq = *seq_pos;
549575 } else {
550576 if (seq_pos == first_seq)
551 return unknown_index;
577 return UnknownRowIndex;
552578 found_seq = *(seq_pos - 1);
553579 }
554 if (!found_seq.containsPC(address))
555 return unknown_index;
556 // Search for instruction address in the rows describing the sequence.
557 // Rows are stored in a vector, so we may use arithmetical operations with
558 // iterators.
559 DWARFDebugLine::Row row;
560 row.Address = address;
561 RowIter first_row = Rows.begin() + found_seq.FirstRowIndex;
562 RowIter last_row = Rows.begin() + found_seq.LastRowIndex;
563 RowIter row_pos = std::lower_bound(first_row, last_row, row,
564 DWARFDebugLine::Row::orderByAddress);
565 if (row_pos == last_row) {
566 return found_seq.LastRowIndex - 1;
567 }
568 uint32_t index = found_seq.FirstRowIndex + (row_pos - first_row);
569 if (row_pos->Address > address) {
570 if (row_pos == first_row)
571 return unknown_index;
572 else
573 index--;
574 }
575 return index;
580 return findRowInSeq(found_seq, address);
576581 }
577582
578583 bool DWARFDebugLine::LineTable::lookupAddressRange(
601606 // index we just calculated
602607
603608 while (seq_pos != last_seq && seq_pos->LowPC < end_addr) {
604 DWARFDebugLine::Sequence cur_seq = *seq_pos;
605 uint32_t first_row_index;
606 uint32_t last_row_index;
607 if (seq_pos == start_pos) {
608 // For the first sequence, we need to find which row in the sequence is the
609 // first in our range. Rows are stored in a vector, so we may use
610 // arithmetical operations with iterators.
611 DWARFDebugLine::Row row;
612 row.Address = address;
613 RowIter first_row = Rows.begin() + cur_seq.FirstRowIndex;
614 RowIter last_row = Rows.begin() + cur_seq.LastRowIndex;
615 RowIter row_pos = std::upper_bound(first_row, last_row, row,
616 DWARFDebugLine::Row::orderByAddress);
617 // The 'row_pos' iterator references the first row that is greater than
618 // our start address. Unless that's the first row, we want to start at
619 // the row before that.
620 first_row_index = cur_seq.FirstRowIndex + (row_pos - first_row);
621 if (row_pos != first_row)
622 --first_row_index;
623 } else
624 first_row_index = cur_seq.FirstRowIndex;
625
626 // For the last sequence in our range, we need to figure out the last row in
627 // range. For all other sequences we can go to the end of the sequence.
628 if (cur_seq.HighPC > end_addr) {
629 DWARFDebugLine::Row row;
630 row.Address = end_addr;
631 RowIter first_row = Rows.begin() + cur_seq.FirstRowIndex;
632 RowIter last_row = Rows.begin() + cur_seq.LastRowIndex;
633 RowIter row_pos = std::upper_bound(first_row, last_row, row,
634 DWARFDebugLine::Row::orderByAddress);
635 // The 'row_pos' iterator references the first row that is greater than
636 // our end address. The row before that is the last row we want.
637 last_row_index = cur_seq.FirstRowIndex + (row_pos - first_row) - 1;
638 } else
639 // Contrary to what you might expect, DWARFDebugLine::SequenceLastRowIndex
640 // isn't a valid index within the current sequence. It's that plus one.
609 const DWARFDebugLine::Sequence &cur_seq = *seq_pos;
610 // For the first sequence, we need to find which row in the sequence is the
611 // first in our range.
612 uint32_t first_row_index = cur_seq.FirstRowIndex;
613 if (seq_pos == start_pos)
614 first_row_index = findRowInSeq(cur_seq, address);
615
616 // Figure out the last row in the range.
617 uint32_t last_row_index = findRowInSeq(cur_seq, end_addr - 1);
618 if (last_row_index == UnknownRowIndex)
641619 last_row_index = cur_seq.LastRowIndex - 1;
620
621 assert(first_row_index != UnknownRowIndex);
622 assert(last_row_index != UnknownRowIndex);
642623
643624 for (uint32_t i = first_row_index; i <= last_row_index; ++i) {
644625 result.push_back(i);
0 # Check that relocations get applied
11 RUN: llvm-dwarfdump %p/Inputs/test-simple-macho.o | FileCheck %s
22 RUN: llvm-dwarfdump %p/Inputs/test-multiple-macho.o | FileCheck %s
3 RUN: llvm-rtdyld -printline %p/Inputs/test-multiple-macho.o | \
4 RUN: FileCheck --check-prefix=SIZE %s
3 RUN: llvm-rtdyld -printline %p/Inputs/test-multiple-macho.o | FileCheck %s
54 RUN: llvm-rtdyld -printobjline %p/Inputs/test-multiple-macho.o | FileCheck %s
65
7 SIZE: Function: _bar, Size = 48
8 SIZE: Function: _foo, Size = 16
9 SIZE: Function: _fubar, Size = 46
6 CHECK-NOT: error: failed to compute relocation: X86_64_RELOC_UNSIGNED
107
11 CHECK-NOT: error: failed to compute relocation: X86_64_RELOC_UNSIGNED
8 # Check that relocations get applied correctly
9 RUN: llvm-rtdyld -printobjline %p/Inputs/test-simple-macho.o \
10 RUN: | FileCheck %s -check-prefix TEST_SIMPLE
11 RUN: llvm-rtdyld -printline %p/Inputs/test-simple-macho.o \
12 RUN: | FileCheck %s -check-prefix TEST_SIMPLE
13 RUN: llvm-rtdyld -printobjline %p/Inputs/test-multiple-macho.o \
14 RUN: | FileCheck %s -check-prefix TEST_MULTIPLE
15 RUN: llvm-rtdyld -printline %p/Inputs/test-multiple-macho.o \
16 RUN: | FileCheck %s -check-prefix TEST_MULTIPLE
17
18 TEST_SIMPLE: Function: _foo, Size = 11
19 TEST_SIMPLE-NEXT: Line info @ 0: simple.c, line:1
20 TEST_SIMPLE-NEXT: Line info @ 7: simple.c, line:2
21 TEST_SIMPLE-NOT: Line info @ 11: simple.c, line:2
22
23 TEST_MULTIPLE: Function: _bar, Size = 48
24 TEST_MULTIPLE-NEXT: Line info @ 0: multiple.c, line:5
25 TEST_MULTIPLE-NEXT: Line info @ 7: multiple.c, line:6
26 TEST_MULTIPLE-NEXT: Line info @ 16: multiple.c, line:9
27 TEST_MULTIPLE-NEXT: Line info @ 21: multiple.c, line:9
28 TEST_MULTIPLE-NEXT: Line info @ 26: multiple.c, line:7
29 TEST_MULTIPLE-NEXT: Line info @ 33: multiple.c, line:10
30 TEST_MULTIPLE-NOT: Line info @ 48: multiple.c, line:12
31 TEST_MULTIPLE-NEXT: Function: _foo, Size = 16
32 TEST_MULTIPLE-NEXT: Line info @ 0: multiple.c, line:1
33 TEST_MULTIPLE-NEXT: Line info @ 7: multiple.c, line:2
34 TEST_MULTIPLE-NOT: Line info @ 16: multiple.c, line:5
35 TEST_MULTIPLE-NEXT: Function: _fubar, Size = 46
36 TEST_MULTIPLE-NEXT: Line info @ 0: multiple.c, line:12
37 TEST_MULTIPLE-NEXT: Line info @ 7: multiple.c, line:13
38 TEST_MULTIPLE-NEXT: Line info @ 12: multiple.c, line:17
39 TEST_MULTIPLE-NEXT: Line info @ 25: multiple.c, line:15
40 TEST_MULTIPLE-NEXT: Line info @ 34: multiple.c, line:19
41 TEST_MULTIPLE-NEXT: Line info @ 41: multiple.c, line:21
42 TEST_MULTIPLE-NOT: Line info @ 46: multiple.c, line:21
1717 TEST_INLINE-NEXT: Function: _Z3foov, Size = 3
1818 TEST_INLINE-NEXT: Line info @ 0: test-inline.cpp, line:28
1919 TEST_INLINE-NEXT: Line info @ 2: test-inline.cpp, line:29
20 TEST_INLINE-NEXT: Line info @ 3: test-inline.cpp, line:29
2120 TEST_INLINE-NEXT: Function: main, Size = 146
2221 TEST_INLINE-NEXT: Line info @ 0: test-inline.cpp, line:39
2322 TEST_INLINE-NEXT: Line info @ 21: test-inline.cpp, line:41
2827 TEST_INLINE-NEXT: Line info @ 95: test-inline.cpp, line:46
2928 TEST_INLINE-NEXT: Line info @ 114: test-inline.cpp, line:48
3029 TEST_INLINE-NEXT: Line info @ 141: test-inline.cpp, line:49
31 TEST_INLINE-NEXT: Line info @ 146: test-inline.cpp, line:49
3230
3331 ; This test checks the case where all code is in a single section.
3432 TEST_PARAMETERS: Function: _Z15test_parametersPfPA2_dR11char_structPPitm, Size = 170
4846 TEST_PARAMETERS-NEXT: Line info @ 95: test-parameters.cpp, line:46
4947 TEST_PARAMETERS-NEXT: Line info @ 114: test-parameters.cpp, line:48
5048 TEST_PARAMETERS-NEXT: Line info @ 141: test-parameters.cpp, line:49
51 TEST_PARAMETERS-NEXT: Line info @ 146: test-parameters.cpp, line:49
5249