This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[rfc] Remove some empty lines from the linetable
- From: Daniel Jacobowitz <drow at false dot org>
- To: gdb-patches at sourceware dot org
- Date: Mon, 1 Oct 2007 11:47:57 -0400
- Subject: [rfc] Remove some empty lines from the linetable
I would really appreciate comments on this patch. I tried to debug an
optimized MIPS/Linux kernel this morning, and "list" was pointing to
truly outlandish lines. The problem was a header file containing some
line information... for a line which had been completely optimized
away.
Before sorting, the line table looked like so:
line 58 at 0x80336f5c
line 0 at 0x80336f60
line 58 at 0x80336f70
line 0 at 0x80336f78
line 58 at 0x803376a0
line 0 at 0x803376ac
line 58 at 0x80337d84
line 0 at 0x80337d84
line 58 at 0x80337df8
line 0 at 0x80337e00
line 58 at 0x80337ec8
line 0 at 0x80337ec8
Nice and regular. This line, from an inlined function, occurs several
times in the function but expands to no code. I'm not sure precisely
why but it has to do with some implementation quirk of GCC.
We sort line tables by PC for lookup. This is necessary, but awkward,
since the tables are not really sortable. When two lines are at the same
PC, we sort the lower line number first. This handles a related case:
.text
line 1
... code ...
.section directive to a different section
line 2
... code ...
GAS inserts an end-of-sequence marker at the end of the .debug_line
block for .text, so that we do not think some other random data
belongs to line 1. If .text is immediately followed by the other
section after linking, we will have an end-of-sequence marker followed
by line 2 at the same PC. And we want to list this as line 2.
Unfortunately this is exactly the wrong thing to do in my example
above. After sorting we get:
line 58 at 0x80336f5c
line 0 at 0x80336f60
line 58 at 0x80336f70
line 0 at 0x80336f78
line 58 at 0x803376a0
line 0 at 0x803376ac
line 0 at 0x80337d84
line 58 at 0x80337d84
line 58 at 0x80337df8
line 0 at 0x80337e00
line 0 at 0x80337ec8
line 58 at 0x80337ec8
There's another source file which contains, among other things:
line 0 at 0x80337d84
line 955 at 0x80337d84
This is the end of code from the other source file, followed by an
empty line from an inlined function, followed by more code at the
calling function. But the strange line table we produce leaves us
with wrong results if we search for 0x80337d88 in the included
file. It should find a zero line and say that it is not present in
this file. Instead, it finds line 58. So a wide range of code is
mis-attributed to the include file.
In the kernel I was working on the size of the misattributed "line"
was about 1MB :-(
I thought about sorting groups of consecutive lines instead of
individual lines. That's tricky and a wasteful of memory, though, if
this simpler solution works: just delete such troublesome cases in
record_line.
If this is too unpleasant or unclear, I think I could push it back
into the DWARF reader. It would require a private version of
record_line.
Anyone have comments on this? I haven't regression-tested the patch
yet, but it helps enough to let me get back to what I was doing.
--
Daniel Jacobowitz
CodeSourcery
2007-10-01 Daniel Jacobowitz <dan@codesourcery.com>
* buildsym.c (record_line): Remove empty lines followed by
end-of-sequence markers.
Index: buildsym.c
===================================================================
RCS file: /cvs/src/src/gdb/buildsym.c,v
retrieving revision 1.50
diff -u -p -r1.50 buildsym.c
--- buildsym.c 23 Aug 2007 18:08:26 -0000 1.50
+++ buildsym.c 1 Oct 2007 15:35:58 -0000
@@ -752,9 +752,34 @@ record_line (struct subfile *subfile, in
* sizeof (struct linetable_entry))));
}
+ pc = gdbarch_addr_bits_remove (current_gdbarch, pc);
+
+ /* Normally, we treat lines as unsorted. But the end of sequence
+ marker is special. We sort line markers at the same PC by line
+ number, so end of sequence markers (which have line == 0) appear
+ first. This is right if the marker ends the previous function,
+ and there is no padding before the next function. But it is
+ wrong if the previous line was empty and we are now marking a
+ switch to a different subfile. We must leave the end of sequence
+ marker at the end of this group of lines, not sort the empty line
+ to after the marker. The easiest way to accomplish this is to
+ delete any empty lines from our table, if they are followed by
+ end of sequence markers. All we lose is the ability to set
+ breakpoints at some lines which contain no instructions
+ anyway. */
+ if (line == 0 && subfile->line_vector->nitems > 0)
+ {
+ e = subfile->line_vector->item + subfile->line_vector->nitems - 1;
+ while (subfile->line_vector->nitems > 0 && e->pc == pc)
+ {
+ e--;
+ subfile->line_vector->nitems--;
+ }
+ }
+
e = subfile->line_vector->item + subfile->line_vector->nitems++;
e->line = line;
- e->pc = gdbarch_addr_bits_remove (current_gdbarch, pc);
+ e->pc = pc;
}
/* Needed in order to sort line tables from IBM xcoff files. Sigh! */