This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


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

step-over problems with gdb/egcs on alpha



hi -

I've been having problems under OSF1 with stepping over functions in gdb
in programs compiled with egcs.  I'm not entirely sure whether this
is the fault of egcs or gdb, so i'm sending this to both lists.

I've tested this with versions of egcs and gdb out of cvs.
The egcs version string was

  egcs-2.93.19 19990424 (gcc2 ss-980929 experimental)

The gdb tree was checked out from cvs the afternoon of Apr. 28.  (19990422)

This is on an `alphaev56-dec-osf4.0d' host.


Here's a source which shows the problem:

-- x.c --------------------------------------------------
/* compile/link with debugging. */
/*when trying to step over the get_fname call, gdb will step into it instead.*/

void get_fname ()
{
  const char* dir = "foo";
}



int main (int argc, char* argv[])
{
  get_fname ();
}
---------------------------------------------------------


I compile this with:

$ gcc -g -o x x.c

and then run gdb:

$ gdb x
GNU gdb 19990422
Copyright 1998 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 "alphaev56-dec-osf4.0d"...
warning: Target may not support alpha architecture

(gdb) break main
Breakpoint 1 at 0x1200011c4: file x.c, line 13.
(gdb) run
Starting program: /home/snyder/egcstest/x 

Breakpoint 1, main (argc=1, argv=0x11ffff568) at x.c:13
13        get_fname ();
(gdb) n
get_fname () at x.c:5
5       {


Note that when i tried to step _over_ the call to get_fname(),
gdb actually stepped _into_ the function.


What's happening?
By stepping through the gdb code, i found that things go wrong in
wait_for_inferior.  After actually single-stepping into get_fname,
stop_pc is get_fname+8, and we get to the test:

      if (stop_pc == stop_func_start	/* Quick test */
	  || (in_prologue (stop_pc, stop_func_start) &&
	      !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, stop_func_name))
	  || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, stop_func_name)
	  || stop_func_name == 0)

It looks like this is supposed to be true if stop_pc is at the start
of a function.  However, in this case, this test fails because
in_prologue returns false for get_fname+8.

So now we turn to in_prologue.
The algorithm used by in_prologue seems to be `return true for pc if it
is in the pc range of the source line which includes the start of the
function':


  if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
    goto nosyms;		/* Might be in prologue */

  sal = find_pc_line (func_addr, 0);

  if (sal.line == 0)
    goto nosyms;

  /* sal.end is the address of the first instruction past sal.line. */
  if (sal.end > func_addr
      && sal.end <= func_end)	/* Is prologue in function? */
    return pc < sal.end;	/* Yes, is pc in prologue? */


If i trace through this for this case, here is what i see.

get_fname is at 0x120001160.
pc is 0x120001168.
find_pc_partial_function returns
   func_addr  0x120001160
   func_end   0x1200011a0

find_pc_line (0x120001160) returns
   sal.line  4
   sal.pc    0x1200011dc
   sal.end   0x120001168


This then causes in_prologue to return false, because ! (pc < sal.end).

So the problem seems to be that find_pc_line is returning a funny
range.  If i look at the generated assembly code x.s, i see the
following:


...
.text
	.align 5
	.globl get_fname__Fv
	.ent get_fname__Fv
get_fname__Fv:
	.frame $15,32,$26,0
	.mask 0x4008000,-32
	ldgp $29,0($27)
$get_fname__Fv..ng:
$LFB1:
$LM1:
	 #.stabn 68,0,5,$LM1
...
	 #.stabn 68,0,7,$LM4
$L2:
	mov $15,$30
	ldq $26,0($30)
	ldq $15,8($30)
	lda $30,32($30)
	ret $31,($26),1
$LFE1:
	.end get_fname__Fv
 #.stabs "get_fname__Fv:F22",36,0,5,get_fname__Fv
 #.stabs "dir:26=*2",128,0,6,-16
 #.stabn 192,0,0,$LBB2
 #.stabn 224,0,0,$LBE2
	.align 5
	.globl main
	.ent main
main:
	.frame $15,32,$26,0
	.mask 0x4008000,-32
	ldgp $29,0($27)
$main..ng:
$LFB2:
$LM5:
	 #.stabn 68,0,12,$LM5



Note that the first .stabn for a function is associated _not_
with the start of the function, but 8 bytes _past_ the start
of the function (since it comes after the ldgp).

So, when in_prologue tries to get the line range containing
the start of the function, it is actually getting a line range
which came from some other function.

For the time being, i've worked around this with the appended patch
to gdb, which modifies in_prologue so that if the pc range found
by find_pc_line appears to be outside the function in question,
it takes the next line range instead (in pc order).

But i wonder if the real fix isn't to make egcs emit the .stabn
directives _before_ the ldgp instructions.

sss

1999-04-28  scott snyder  <snyder@d0olb.fnal.gov>

	* symtab.c (in_prologue): If the line range found appears to be
	outside the function in question, take the next range instead.
	This can happen with egcs on the alpha.



Index: symtab.c
===================================================================
RCS file: /cvs/gdb/gdb/gdb/symtab.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 symtab.c
--- symtab.c	1999/04/26 18:25:32	1.1.1.2
+++ symtab.c	1999/04/28 23:23:59
@@ -4257,6 +4257,11 @@
 
   sal = find_pc_line (func_addr, 0);
 
+  /* On the alpha with egcs, the last stabn line directive of a function
+     can overlap the beginning of the next function... */
+  if (sal.pc < func_addr || sal.pc >= sal.end)
+    sal = find_pc_line (sal.end, 0);
+
   if (sal.line == 0)
     goto nosyms;
 


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