This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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!  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]