[gdb/symtab] Fix line-table end-of-sequence sorting
authorTom de Vries <tdevries@suse.de>
Mon, 6 Jul 2020 12:28:58 +0000 (14:28 +0200)
committerTom de Vries <tdevries@suse.de>
Mon, 6 Jul 2020 12:28:58 +0000 (14:28 +0200)
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.

gdb/ChangeLog
gdb/buildsym.c
gdb/symtab.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp

index b802641c9d2777cce13c4d81d5dbcfa033dbdcfc..a07dd38291f0e5b9b1d2377ac5a5c219df75951e 100644 (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>
 
        PR tui/26205
index 0c4c3007eaf231d284a03631e426a719b3107a07..bd0ca49140106b8c2d7abf67ea112e7283cae4bb 100644 (file)
@@ -943,6 +943,10 @@ buildsym_compunit::end_symtab_with_blockvector (struct block *static_block,
            = [] (const linetable_entry &ln1,
                  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);
              };
 
index 19f078e36a386d8a0354b4de01cf6711e487ba19..f96ad9554d9ea31b2bdcad6f5aa7bba88cf5d3fd 100644 (file)
@@ -3236,12 +3236,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
       struct linetable_entry *last = item + len;
       item = std::upper_bound (first, last, pc, pc_compare);
       if (item != first)
-       {
-         /* Found a matching item.  Skip backwards over any end of
-            sequence markers.  */
-         for (prev = item - 1; prev->line == 0 && prev != first; prev--)
-           /* Nothing.  */;
-       }
+       prev = item - 1;                /* Found a matching item.  */
 
       /* 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
index 983c4315bfb543c069c773296799ce84df63d343..f75ba7d9cf787b1283dc2092a005f7a5937afc8f 100644 (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>
 
        * gdb.base/structs2.c (main): Adjust second parem_reg call to
index 92f8f6cecbed908721244dbd769b3c5f715668ef..39281a8857f61baabd5851bdb2be417b0aaa2f6b 100644 (file)
@@ -144,12 +144,26 @@ gdb_test "info line frame3" \
 
 # Ensure that the line table correctly tracks the end of sequence markers.
 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" \
     "count END markers in line table" {
        -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
        }
        -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
            exp_continue
        }