This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [PATCH RFA] symtab.c: Handle functions with multiple #line directives
- To: Kevin Buettner <kevinb at cygnus dot com>
- Subject: Re: [PATCH RFA] symtab.c: Handle functions with multiple #line directives
- From: Elena Zannoni <ezannoni at cygnus dot com>
- Date: Mon, 26 Mar 2001 14:54:51 -0500 (EST)
- Cc: gdb-patches at sources dot redhat dot com
- References: <1010313073600.ZM15069@ocotillo.lan>
OK, approved. I tested this on solaris, w/ no regressions.
Elena
Kevin Buettner writes:
> The patch (way) below fixes a bug in find_pc_sect_line() which is most
> evident when debugging a function which switches between two (or more)
> source files multiple times via #line directives in the source. In
> order to trigger the bug, it is critical that there be at least two
> such transitions in a given function.
>
> Now for some background...
>
> Perl's xsubpp script is used to transform a source (.xs) file
> containing a mix of C code and other statements into pure C code. In
> the resulting C source code, #line directives are used to indicate
> where the original C code from the .xs file was. It is common for
> there to be several transitions back and forth between
> xsubpp-generated code and the code that appeared in the .xs file.
> Here is a small snippet of code taken from the generated "perl.c" from
> another project that I occasionally work on:
>
> XS(XS_Vile__Window_window_count)
> {
> dXSARGS;
> dXSI32;
> if (items != 0)
> Perl_croak(aTHX_ "Usage: %s()", GvNAME(CvGV(cv)));
> {
> #line 4370 "perl.xs"
> int count;
> WINDOW *wp;
>
> #line 3616 "perl.c"
> int RETVAL;
> dXSTARG;
> #line 4374 "perl.xs"
> count = 0;
> for_each_visible_window(wp)
> count++;
> RETVAL = count;
>
> #line 3625 "perl.c"
> XSprePUSH; PUSHi((IV)RETVAL);
> }
> XSRETURN(1);
> }
>
> Again, the thing to notice here is that the xsubpp tool intermixes code
> that it has generated with code taken from the .xs file. It marks each
> transition with a #line directive. When debugging this code, the
> programmer should be able to step from one line to the next. However,
> at the moment, GDB is not very accomodating:
>
> Breakpoint 1, XS_Vile__Window_window_count (cv=0x82014f8) at perl.c:3606
> 3606 dXSARGS;
> (gdb) n
> 3607 dXSI32;
> (gdb) n
> 3608 if (items != 0)
> (gdb) n
> 3617 dXSTARG;
> (gdb) n
> 3625 XSprePUSH; PUSHi((IV)RETVAL);
> (gdb) n
> 3627 XSRETURN(1);
>
> Note that GDB simply skipped over all the following statements:
>
> count = 0;
> for_each_visible_window(wp)
> count++;
> RETVAL = count;
>
> When we debug the same function with the above mentioned symtab.c
> patch, we see the following (correct) behavior:
>
> Breakpoint 1, XS_Vile__Window_window_count (cv=0x82014f8) at perl.c:3606
> 3606 dXSARGS;
> (gdb) n
> 3607 dXSI32;
> (gdb)
> 3608 if (items != 0)
> (gdb)
> 3617 dXSTARG;
> (gdb)
> 4374 count = 0;
> (gdb)
> 4375 for_each_visible_window(wp)
> (gdb)
> 4376 count++;
> (gdb)
> 4375 for_each_visible_window(wp)
> (gdb)
> 4376 count++;
> (gdb)
> 4375 for_each_visible_window(wp)
> (gdb)
> 4377 RETVAL = count;
> (gdb)
> 3625 XSprePUSH; PUSHi((IV)RETVAL);
> (gdb)
> 3627 XSRETURN(1);
>
> I have constructed a new test which I am proposing be added to the
> GDB testsuite to test for this bug. The proposal is at:
>
> http://sources.redhat.com/ml/gdb-patches/2001-03/msg00185.html
>
> This test causes 12 new FAILs when run against a current GDB and
> no fails when patched with the patch below.
>
> I have tested the patch below on i386-unknown-freebsd4.2 and
> i686-pc-linux-gnu and see no regressions. Also, as shown above,
> it certainly produces better results when debugging real code.
>
> Okay to commit?
>
> * symtab.c (find_pc_sect_line): Revise method used for finding
> the ending pc.
>
> Index: symtab.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/symtab.c,v
> retrieving revision 1.32
> diff -u -p -r1.32 symtab.c
> --- symtab.c 2001/03/06 08:21:17 1.32
> +++ symtab.c 2001/03/10 08:22:11
> @@ -1759,11 +1759,18 @@ find_pc_sect_line (CORE_ADDR pc, struct
> {
> best = prev;
> best_symtab = s;
> - /* If another line is in the linetable, and its PC is closer
> - than the best_end we currently have, take it as best_end. */
> - if (i < len && (best_end == 0 || best_end > item->pc))
> - best_end = item->pc;
> +
> + /* Discard BEST_END if it's before the PC of the current BEST. */
> + if (best_end <= best->pc)
> + best_end = 0;
> }
> +
> + /* If another line (denoted by ITEM) is in the linetable and its
> + PC is after BEST's PC, but before the current BEST_END, then
> + use ITEM's PC as the new best_end. */
> + if (best && i < len && item->pc > best->pc
> + && (best_end == 0 || best_end > item->pc))
> + best_end = item->pc;
> }
>
> if (!best_symtab)
>