This is the mail archive of the gdb-patches@sources.redhat.com 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]

Re: [RFC] Gdb line table implementation tweak



Holey moley!  This patch is approved, sir.

Fred Fish <fnf@public.ninemoons.com> writes:

> The implementation of gdb's line number table can cause gdb to give
> misleading results when some parts of a program are compiled with
> debugging enabled and other parts are not.  Here is an example:
> 
>   $ cat Makefile
>   CXX =   g++
>   
>   all:    p p.stabs p1.o.stabs
>   
>   p:      p1.o p2.o
>           $(CXX) -o p p1.o p2.o
>   
>   p1.o:   p1.s
>           $(CXX) -c p1.s
>   
>   p2.o:   p2.s
>           $(CXX) -c p2.s
>   
>   p1.s:   p1.cpp
>           $(CXX) -g -S p1.cpp
>   
>   p2.s:   p2.cpp
>           $(CXX) -S p2.cpp
>   
>   p.stabs:        p
>           objdump --stabs p >p.stabs
>   
>   p1.o.stabs:     p1.o
>           objdump --stabs p1.o >p1.o.stabs
>   
>   clean:
>           rm -f p1.o p2.o p1.s p2.s p Makefile~ *.syms *.stabs
>   
>   
>   $ cat p1.cpp
>   #include <stdio.h>
>   
>   class MainClass
>   {
>   public:
>     MainClass() {};
>     ~MainClass() {};
>     virtual void main();
>   };
>   
>   void MainClass::main()
>   {
>   }
>   
>   int main(int argc, char** argv)
>   {
>     extern void subr (int);
>     subr (5);
>   }
>   
>   $ cat p2.cpp
>   #include <stdio.h>
>   
>   void subr (int x)
>   {
>     printf ("x = %d\n", x);
>   }
>   $
> 
> If we run make to build executable 'p', where p1.o is compiled with
> debugging enabled and p2.o is compiled without debugging, gdb gets
> confused about what file subr() is in.  It thinks it is in p1.cpp,
> when it is really in p2.cpp:
> 
>   $make
>   g++ -g -S p1.cpp
>   g++ -c p1.s
>   g++ -S p2.cpp
>   g++ -c p2.s
>   g++ -o p p1.o p2.o
>   objdump --stabs p >p.stabs
>   objdump --stabs p1.o >p1.o.stabs
>   $ /usr/sourceware/bin/gdb p
>   GNU gdb 2002-02-12-cvs
>   Copyright 2002 Free Software Foundation, Inc.
>   GDB is free software, covered by the GNU General Public License, and you are
>   welcome to change it and/or distribute copies of it under certain conditions.
>   Type "show copying" to see the conditions.
>   There is absolutely no warranty for GDB.  Type "show warranty" for details.
>   This GDB was configured as "i686-pc-linux-gnu"...
>   (gdb) br *0x8048634
>   Breakpoint 1 at 0x8048634: file p1.cpp, line 19.
>   (gdb) x/i 0x8048634
>   0x8048634 <subr__Fi>:   push   %ebp
>   (gdb) run
>   Starting program: /cygnus/cases/106539/example5-linux/p
>   
>   Breakpoint 1, 0x08048634 in subr () at p1.cpp:19
>   19      }
>   (gdb) bt
>   #0  0x08048634 in subr () at p1.cpp:19
>   #1  0x400b2306 in __libc_start_main (main=0x8048618 <main>, argc=1, ubp_av=0xbfffeef4, init=0x8048474 <_init>, fini=0x80486f8 <_fini>, rtld_fini=0x4000d2dc <_dl_fini>,
>       stack_end=0xbfffeeec) at ../sysdeps/generic/libc-start.c:129
>   (gdb) quit
>   The program is running.  Exit anyway? (y or n) y
>   $
> 
> Note in the above, setting the breakpoint at the first instruction of
> subr() appears to put it at line 19 in p1.cpp.  When the program is
> run and gdb stops at subr(), which is actually in p2.cpp, it prints it
> wrong again.  And in the backtrace, gdb gets the right function, but
> the wrong file and line number.
> 
> One way to fix this is to slightly change the line table such that it
> allows gdb to know what ranges of PC's represent ranges for which line
> number info is valid and which don't.  An easy way to do that is to
> use an entry with a line number of zero to mark ranges that have no
> valid line number info.
> 
> For example, the line table for p1.cpp is:
> 
>  Line table:
> 
>  line 12 at 0x8048610
>  line 13 at 0x8048616
>  line 16 at 0x8048618
>  line 18 at 0x804861e
>  line 19 at 0x804862b
>  line 9 at 0x8048690
>  line 19 at 0x8048696
>  line 6 at 0x80486bc
>  line 7 at 0x80486cc
> 
> After applying the attached patch, gdb's internal representation of
> the line table for p1.cpp changes to the following:
> 
>  Line table:
> 
>  line 12 at 0x8048610
>  line 13 at 0x8048616
>  line 0 at 0x8048618
>  line 16 at 0x8048618
>  line 18 at 0x804861e
>  line 19 at 0x804862b
>  line 0 at 0x8048632
>  line 9 at 0x8048690
>  line 19 at 0x8048696
>  line 0 at 0x80486bb
>  line 6 at 0x80486bc
>  line 0 at 0x80486ca
>  line 7 at 0x80486cc
>  line 0 at 0x80486f5
> 
> And rerunning gdb on the test case produces:
> 
>   $ /tmp/gdb p
>   GNU gdb 2002-02-12-cvs
>   Copyright 2002 Free Software Foundation, Inc.
>   GDB is free software, covered by the GNU General Public License, and you are
>   welcome to change it and/or distribute copies of it under certain conditions.
>   Type "show copying" to see the conditions.
>   There is absolutely no warranty for GDB.  Type "show warranty" for details.
>   This GDB was configured as "i686-pc-linux-gnu"...
>   (gdb) br *0x8048634
>   Breakpoint 1 at 0x8048634
>   (gdb) x/i 0x8048634
>   0x8048634 <subr__Fi>:   push   %ebp
>   (gdb) run
>   Starting program: /cygnus/cases/106539/example5-linux/p
>   
>   Breakpoint 1, 0x08048634 in subr ()
>   (gdb) bt
>   #0  0x08048634 in subr ()
>   #1  0x400b2306 in __libc_start_main (main=0x8048618 <main>, argc=1, ubp_av=0xbfffe674, init=0x8048474 <_init>, fini=0x80486f8 <_fini>, rtld_fini=0x4000d2dc <_dl_fini>,
>       stack_end=0xbfffe66c) at ../sysdeps/generic/libc-start.c:129
>   (gdb) quit
>   The program is running.  Exit anyway? (y or n) y
>   $
> 
> It might be a little easier to understand how the line table describes
> the entire range of PC's from it's lowest to highest if we match up
> the new line table entries with a disassembly produced by gdb.  Note
> in the following that now gdb knows which parts actually come from
> p1.cpp (a range starting with a nonzero line number) and which parts
> have no valid line info (a range starting with a zero line number):
> 
> 
>  line 12 at 0x8048610	0x8048610 <main__9MainClass>:   push   %ebp
> 			0x8048611 <main__9MainClass+1>: mov    %esp,%ebp
> 			0x8048613 <main__9MainClass+3>: mov    0x8(%ebp),%eax
>  line 13 at 0x8048616	0x8048616 <main__9MainClass+6>: pop    %ebp
> 			0x8048617 <main__9MainClass+7>: ret
>  line 0 at  0x8048618
>  line 16 at 0x8048618	0x8048618 <main>:       push   %ebp
> 			0x8048619 <main+1>:     mov    %esp,%ebp
> 			0x804861b <main+3>:     sub    $0x8,%esp
> 
>  line 18 at 0x804861e	0x804861e <main+6>:     sub    $0xc,%esp
> 			0x8048621 <main+9>:     push   $0x5
> 			0x8048623 <main+11>:    call   0x8048634 <subr__Fi>
> 			0x8048628 <main+16>:    add    $0x10,%esp
> 
>  line 19 at 0x804862b	0x804862b <main+19>:    mov    $0x0,%eax
> 			0x8048630 <main+24>:    leave
> 			0x8048631 <main+25>:    ret
> 
>  line 0 at 0x8048632	0x8048632 <main+26>:    mov    %esi,%esi
> 			0x8048634 <subr__Fi>:   push   %ebp
> 			0x8048635 <subr__Fi+1>: mov    %esp,%ebp
> 			0x8048637 <subr__Fi+3>: sub    $0x8,%esp
> 			0x804863a <subr__Fi+6>: sub    $0x8,%esp
> 			0x804863d <subr__Fi+9>: pushl  0x8(%ebp)
> 			0x8048640 <subr__Fi+12>:        push   $0x804872b
> 			0x8048645 <subr__Fi+17>:        call   0x80484cc <printf>
> 			0x804864a <subr__Fi+22>:        add    $0x10,%esp
> 			0x804864d <subr__Fi+25>:        leave
> 			0x804864e <subr__Fi+26>:        ret
> 			0x804864f <subr__Fi+27>:        nop
> 			0x8048650 <__do_global_ctors_aux>:      push   %ebp
> 			0x8048651 <__do_global_ctors_aux+1>:    mov    %esp,%ebp
> 			0x8048653 <__do_global_ctors_aux+3>:    push   %ebx
> 			0x8048654 <__do_global_ctors_aux+4>:    sub    $0x4,%esp
> 			0x8048657 <__do_global_ctors_aux+7>:    mov    0x804978c,%eax
> 			0x804865c <__do_global_ctors_aux+12>:   mov    $0x804978c,%ebx
> 			0x8048661 <__do_global_ctors_aux+17>:   cmp    $0xffffffff,%eax
> 			0x8048664 <__do_global_ctors_aux+20>:   je     0x804867c <__do_global_ctors_aux+44>
> 			0x8048666 <__do_global_ctors_aux+22>:   lea    0x0(%esi),%esi
> 			0x8048669 <__do_global_ctors_aux+25>:   lea    0x0(%edi,1),%edi
> 			0x8048670 <__do_global_ctors_aux+32>:   sub    $0x4,%ebx
> 			0x8048673 <__do_global_ctors_aux+35>:   call   *%eax
> 			0x8048675 <__do_global_ctors_aux+37>:   mov    (%ebx),%eax
> 			0x8048677 <__do_global_ctors_aux+39>:   cmp    $0xffffffff,%eax
> 			0x804867a <__do_global_ctors_aux+42>:   jne    0x8048670 <__do_global_ctors_aux+32>
> 			0x804867c <__do_global_ctors_aux+44>:   pop    %eax
> 			0x804867d <__do_global_ctors_aux+45>:   pop    %ebx
> 			0x804867e <__do_global_ctors_aux+46>:   pop    %ebp
> 			0x804867f <__do_global_ctors_aux+47>:   ret
> 			0x8048680 <init_dummy>: push   %ebp
> 			0x8048681 <init_dummy+1>:       mov    %esp,%ebp
> 			0x8048683 <init_dummy+3>:       sub    $0x8,%esp
> 			0x8048686 <init_dummy+6>:       mov    %ebp,%esp
> 			0x8048688 <init_dummy+8>:       pop    %ebp
> 			0x8048689 <init_dummy+9>:       ret
> 			0x804868a <init_dummy+10>:      lea    0x0(%esi),%esi
> 
>  line 9 at 0x8048690	0x8048690 <__tf9MainClass>:     push   %ebp
> 			0x8048691 <__tf9MainClass+1>:   mov    %esp,%ebp
> 			0x8048693 <__tf9MainClass+3>:   sub    $0x8,%esp
> 
>  line 19 at 0x8048696	0x8048696 <__tf9MainClass+6>:   cmpl   $0x0,0x80498b8
> 			0x804869d <__tf9MainClass+13>:  jne    0x80486b4 <__tf9MainClass+36>
> 			0x804869f <__tf9MainClass+15>:  sub    $0x8,%esp
> 			0x80486a2 <__tf9MainClass+18>:  push   $0x8048720
> 			0x80486a7 <__tf9MainClass+23>:  push   $0x80498b8
> 			0x80486ac <__tf9MainClass+28>:  call   0x804849c <__rtti_user>
> 			0x80486b1 <__tf9MainClass+33>:  add    $0x10,%esp
> 			0x80486b4 <__tf9MainClass+36>:  mov    $0x80498b8,%eax
> 			0x80486b9 <__tf9MainClass+41>:  leave
> 			0x80486ba <__tf9MainClass+42>:  ret
> 
>  line 0 at 0x80486bb	0x80486bb <__tf9MainClass+43>:  nop
> 
>  line 6 at 0x80486bc	0x80486bc <__9MainClass>:       push   %ebp
> 			0x80486bd <__9MainClass+1>:     mov    %esp,%ebp
> 			0x80486bf <__9MainClass+3>:     mov    0x8(%ebp),%eax
> 			0x80486c2 <__9MainClass+6>:     movl   $0x8049748,(%eax)
> 			0x80486c8 <__9MainClass+12>:    pop    %ebp
> 			0x80486c9 <__9MainClass+13>:    ret
> 
>  line 0 at 0x80486ca	0x80486ca <__9MainClass+14>:    mov    %esi,%esi
> 
>  line 7 at 0x80486cc	0x80486cc <_._9MainClass>:      push   %ebp
> 			0x80486cd <_._9MainClass+1>:    mov    %esp,%ebp
> 			0x80486cf <_._9MainClass+3>:    sub    $0x8,%esp
> 			0x80486d2 <_._9MainClass+6>:    mov    0xc(%ebp),%eax
> 			0x80486d5 <_._9MainClass+9>:    mov    0x8(%ebp),%edx
> 			0x80486d8 <_._9MainClass+12>:   movl   $0x8049748,(%edx)
> 			0x80486de <_._9MainClass+18>:   and    $0x1,%eax
> 			0x80486e1 <_._9MainClass+21>:   test   %al,%al
> 			0x80486e3 <_._9MainClass+23>:   je     0x80486f3 <_._9MainClass+39>
> 			0x80486e5 <_._9MainClass+25>:   sub    $0xc,%esp
> 			0x80486e8 <_._9MainClass+28>:   pushl  0x8(%ebp)
> 			0x80486eb <_._9MainClass+31>:   call   0x80484ec <__builtin_delete>
> 			0x80486f0 <_._9MainClass+36>:   add    $0x10,%esp
> 			0x80486f3 <_._9MainClass+39>:   leave
> 			0x80486f4 <_._9MainClass+40>:   ret
> 
>  line 0 at 0x80486f5	0x80486f5 <_._9MainClass+41>:   lea    0x0(%esi),%esi
> 
> The patch to make this work for stabs is very simple and supplied
> below for discussion purposes.  I presume it would be fairly easy to
> also change the other debug info readers to do the same thing.
> Obviously someday we would like to have gdb take full advantage of
> more expressive formats like DWARF, but for now this patch seems to
> have substantial advantages.
> 
> I did run before and after testing with the gdb testsuite and it
> didn't show any regressions, or improvements for that matter, but that
> is to be expected since we don't actually test for functionality with
> mixed levels of debugging information.
> 
> -Fred
> 
> Index: ChangeLog
> ===================================================================
> RCS file: /cvs/src/src/gdb/ChangeLog,v
> retrieving revision 1.2184
> diff -c -p -r1.2184 ChangeLog
> *** ChangeLog	2002/02/12 00:59:27	1.2184
> --- ChangeLog	2002/02/13 00:22:47
> ***************
> *** 1,3 ****
> --- 1,14 ----
> + 2002-02-11  Fred Fish  <fnf@redhat.com>
> + 
> + 	* dbxread.c (process_one_symbol): When finding an N_FUN symbol
> + 	that marks the end of the range of a function, enter a line number
> + 	entry that has a line number of zero and a PC offset that matches
> + 	the end of the function.  This starts a range of PC's for which no
> + 	line number information is known.
> + 	* symtab.c (find_pc_sect_line): If our best fit is in a range of
> + 	PC's for which no line number info is found (line number is zero)
> + 	then we didn't find any valid line information.
> + 
>   2002-02-11  Richard Earnshaw  <rearnsha@arm.com>
>   
>   	* arm-linux-nat.c: Really include arm-tdep.h.
> Index: dbxread.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/dbxread.c,v
> retrieving revision 1.29
> diff -c -p -r1.29 dbxread.c
> *** dbxread.c	2002/02/04 11:55:34	1.29
> --- dbxread.c	2002/02/13 00:22:50
> *************** process_one_symbol (int type, int desc, 
> *** 2741,2746 ****
> --- 2741,2747 ----
>   	{
>   	  /* This N_FUN marks the end of a function.  This closes off the
>   	     current block.  */
> + 	  record_line (current_subfile, 0, function_start_offset + valu);
>   	  within_function = 0;
>   	  new = pop_context ();
>   
> Index: symtab.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/symtab.c,v
> retrieving revision 1.54
> diff -c -p -r1.54 symtab.c
> *** symtab.c	2002/02/11 03:21:53	1.54
> --- symtab.c	2002/02/13 00:22:54
> *************** find_pc_sect_line (CORE_ADDR pc, struct 
> *** 1823,1828 ****
> --- 1823,1835 ----
>   	  val.end = alt->pc;
>   	}
>       }
> +   else if (best->line == 0)
> +     {
> +       /* If our best fit is in a range of PC's for which no line
> + 	 number info is available (line number is zero) then we didn't
> + 	 find any valid line information. */
> +       val.pc = pc;
> +     }
>     else
>       {
>         val.symtab = best_symtab;


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