From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30294 invoked by alias); 21 Feb 2002 20:50:27 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 30146 invoked from network); 21 Feb 2002 20:50:20 -0000 Received: from unknown (HELO zwingli.cygnus.com) (208.245.165.35) by sources.redhat.com with SMTP; 21 Feb 2002 20:50:20 -0000 Received: by zwingli.cygnus.com (Postfix, from userid 442) id 98D1A5E9E9; Thu, 21 Feb 2002 15:50:19 -0500 (EST) To: fnf@redhat.com Cc: gdb-patches@sources.redhat.com Subject: Re: [RFC] Gdb line table implementation tweak References: <200202130028.g1D0StM11730@fred.ninemoons.com> From: Jim Blandy Date: Thu, 21 Feb 2002 12:50:00 -0000 In-Reply-To: <200202130028.g1D0StM11730@fred.ninemoons.com> Message-ID: User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.1 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2002-02/txt/msg00604.txt.bz2 Holey moley! This patch is approved, sir. Fred Fish 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 > > 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 > > 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 : 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
, 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 : 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
, 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 : push %ebp > 0x8048611 : mov %esp,%ebp > 0x8048613 : mov 0x8(%ebp),%eax > line 13 at 0x8048616 0x8048616 : pop %ebp > 0x8048617 : ret > line 0 at 0x8048618 > line 16 at 0x8048618 0x8048618
: push %ebp > 0x8048619 : mov %esp,%ebp > 0x804861b : sub $0x8,%esp > > line 18 at 0x804861e 0x804861e : sub $0xc,%esp > 0x8048621 : push $0x5 > 0x8048623 : call 0x8048634 > 0x8048628 : add $0x10,%esp > > line 19 at 0x804862b 0x804862b : mov $0x0,%eax > 0x8048630 : leave > 0x8048631 : ret > > line 0 at 0x8048632 0x8048632 : mov %esi,%esi > 0x8048634 : push %ebp > 0x8048635 : mov %esp,%ebp > 0x8048637 : sub $0x8,%esp > 0x804863a : sub $0x8,%esp > 0x804863d : pushl 0x8(%ebp) > 0x8048640 : push $0x804872b > 0x8048645 : call 0x80484cc > 0x804864a : add $0x10,%esp > 0x804864d : leave > 0x804864e : ret > 0x804864f : 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 : push %ebp > 0x8048681 : mov %esp,%ebp > 0x8048683 : sub $0x8,%esp > 0x8048686 : mov %ebp,%esp > 0x8048688 : pop %ebp > 0x8048689 : ret > 0x804868a : 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 > + > + * 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 > > * 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;