[gdb/symtab] Fix line-table end-of-sequence sorting

Consider test-case gdb.dwarf2/dw2-ranges-base.exp.  It has (ignoring
non-sensical entries that are filtered out by buildsym_compunit::record_line)
a line-table for dw2-ranges-base.c like this:
...
 Line Number Statements:
  [0x0000014e]  Extended opcode 2: set Address to 0x4004ba
  [0x00000159]  Advance Line by 10 to 11
  [0x0000015b]  Copy
  [0x0000015c]  Advance PC by 12 to 0x4004c6
  [0x0000015e]  Extended opcode 1: End of Sequence

  [0x00000161]  Extended opcode 2: set Address to 0x4004ae
  [0x0000016c]  Advance Line by 20 to 21
  [0x0000016e]  Copy
  [0x0000016f]  Advance PC by 12 to 0x4004ba
  [0x00000171]  Extended opcode 1: End of Sequence

  [0x00000174]  Extended opcode 2: set Address to 0x4004a7
  [0x0000017f]  Advance Line by 30 to 31
  [0x00000181]  Copy
  [0x00000182]  Advance PC by 7 to 0x4004ae
  [0x00000184]  Extended opcode 1: End of Sequence
...

If we disable the sorting in buildsym_compunit::end_symtab_with_blockvector,
we have the unsorted line table:
...
INDEX  LINE   ADDRESS            IS-STMT
0      11     0x00000000004004ba Y
1      END    0x00000000004004c6 Y
2      21     0x00000000004004ae Y
3      END    0x00000000004004ba Y
4      31     0x00000000004004a7 Y
5      END    0x00000000004004ae Y
...
It contains 3 sequences, 11/END, 21/END and 31/END.

We want to sort the 3 sequences relative to each other, while sorting on
address, to get:
...
INDEX  LINE   ADDRESS            IS-STMT
0      31     0x00000000004004a7 Y
1      END    0x00000000004004ae Y
2      21     0x00000000004004ae Y
3      END    0x00000000004004ba Y
4      11     0x00000000004004ba Y
5      END    0x00000000004004c6 Y
...

However, if we re-enable the sorting, we have instead:
...
INDEX  LINE   ADDRESS            IS-STMT
0      31     0x00000000004004a7 Y
1      21     0x00000000004004ae Y
2      END    0x00000000004004ae Y
3      11     0x00000000004004ba Y
4      END    0x00000000004004ba Y
5      END    0x00000000004004c6 Y
...

This is a regression since commit 3d92a3e313 "gdb: Don't reorder line table
entries too much when sorting", that introduced sorting on address while
keeping entries with the same address in pre-sort order.

Indeed the entries 1 and 2 are in pre-sort order (they map to entries 2 and 5
in the unsorted line table), but entry 1 does not belong in the sequence
terminated by 2.

Fix this by handling End-Of-Sequence entries in the sorting function, such
that they are sorted before other entries with the same address.

Also, revert the find_pc_sect_line workaround introduced in commit 3d92a3e313,
since that's no longer necessary.

Tested on x86_64-linux.

gdb/ChangeLog:

2020-07-06  Tom de Vries  <tdevries@suse.de>

	* buildsym.c (buildsym_compunit::end_symtab_with_blockvector): Handle
	End-Of-Sequence in lte_is_less_than.
	* symtab.c (find_pc_sect_line): Revert change from commit 3d92a3e313
	"gdb: Don't reorder line table entries too much when sorting".

gdb/testsuite/ChangeLog:

2020-07-06  Tom de Vries  <tdevries@suse.de>

	* gdb.dwarf2/dw2-ranges-base.exp: Test line-table order.
This commit is contained in:
Tom de Vries
2020-07-06 14:28:58 +02:00
parent b5b098c2c9
commit d8cc8af6a1
5 changed files with 30 additions and 6 deletions

View File

@ -1,3 +1,10 @@
2020-07-06 Tom de Vries <tdevries@suse.de>
* buildsym.c (buildsym_compunit::end_symtab_with_blockvector): Handle
End-Of-Sequence in lte_is_less_than.
* symtab.c (find_pc_sect_line): Revert change from commit 3d92a3e313
"gdb: Don't reorder line table entries too much when sorting".
2020-07-06 Tom de Vries <tdevries@suse.de> 2020-07-06 Tom de Vries <tdevries@suse.de>
PR tui/26205 PR tui/26205

View File

@ -943,6 +943,10 @@ buildsym_compunit::end_symtab_with_blockvector (struct block *static_block,
= [] (const linetable_entry &ln1, = [] (const linetable_entry &ln1,
const linetable_entry &ln2) -> bool const linetable_entry &ln2) -> bool
{ {
if (ln1.pc == ln2.pc
&& ((ln1.line == 0) != (ln2.line == 0)))
return ln1.line == 0;
return (ln1.pc < ln2.pc); return (ln1.pc < ln2.pc);
}; };

View File

@ -3236,12 +3236,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
struct linetable_entry *last = item + len; struct linetable_entry *last = item + len;
item = std::upper_bound (first, last, pc, pc_compare); item = std::upper_bound (first, last, pc, pc_compare);
if (item != first) if (item != first)
{ prev = item - 1; /* Found a matching item. */
/* Found a matching item. Skip backwards over any end of
sequence markers. */
for (prev = item - 1; prev->line == 0 && prev != first; prev--)
/* Nothing. */;
}
/* At this point, prev points at the line whose start addr is <= pc, and /* At this point, prev points at the line whose start addr is <= pc, and
item points at the next line. If we ran off the end of the linetable item points at the next line. If we ran off the end of the linetable

View File

@ -1,3 +1,7 @@
2020-07-06 Tom de Vries <tdevries@suse.de>
* gdb.dwarf2/dw2-ranges-base.exp: Test line-table order.
2020-07-03 Pedro Alves <palves@redhat.com> 2020-07-03 Pedro Alves <palves@redhat.com>
* gdb.base/structs2.c (main): Adjust second parem_reg call to * gdb.base/structs2.c (main): Adjust second parem_reg call to

View File

@ -144,12 +144,26 @@ gdb_test "info line frame3" \
# Ensure that the line table correctly tracks the end of sequence markers. # Ensure that the line table correctly tracks the end of sequence markers.
set end_seq_count 0 set end_seq_count 0
set prev -1
set seq_count 0
gdb_test_multiple "maint info line-table gdb.dwarf2/dw2-ranges-base.c" \ gdb_test_multiple "maint info line-table gdb.dwarf2/dw2-ranges-base.c" \
"count END markers in line table" { "count END markers in line table" {
-re "^$decimal\[ \t\]+$decimal\[ \t\]+$hex\(\[ \t\]+Y\)? *\r\n" { -re "^$decimal\[ \t\]+$decimal\[ \t\]+$hex\(\[ \t\]+Y\)? *\r\n" {
if { $prev != -1 } {
gdb_assert "$prev == 1" \
"prev of normal entry at $seq_count is end marker"
}
set prev 0
incr seq_count
exp_continue exp_continue
} }
-re "^$decimal\[ \t\]+END\[ \t\]+$hex\(\[ \t\]+Y\)? *\r\n" { -re "^$decimal\[ \t\]+END\[ \t\]+$hex\(\[ \t\]+Y\)? *\r\n" {
if { $prev != -1 } {
gdb_assert "$prev == 0" \
"prev of end marker at $seq_count is normal entry"
}
set prev 1
incr seq_count
incr end_seq_count incr end_seq_count
exp_continue exp_continue
} }