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]

[patch/rfc/rfa*] Only compare against dummy frame tos when saved


Hello,

The generic code for finding a previously saved dummy frame, given the PC and ``frame'', looks like:

static struct regcache *
generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
{
struct dummy_frame *dummyframe;

for (dummyframe = dummy_frame_stack; dummyframe != NULL;
dummyframe = dummyframe->next)
if ((pc >= dummyframe->call_lo && pc < dummyframe->call_hi)
&& (fp == dummyframe->fp
|| fp == dummyframe->sp
|| fp == dummyframe->top))
/* The frame in question lies between the saved fp and sp, inclusive */
return dummyframe->regcache;

return 0;
}

I think it is trying to handle two cases:

1. Where the FP passed in is the dummy frames true base and should match SP of the previous frame or FP of that frame.

2. Where the FP passed in is the frame base from the next inner most frame (returned by frame_chain()) it should match the saved top-of-stack value (using SAVE_DUMMY_FRAME_TOS()).

If a target is somehow capable of unwinding through the dummy frame back to its base then #1 is used. If, however, it isn't possible to unwind back through a [generic] dummy frame, then targets use #2. Case #2 is easy to spot because the frame_chain code starts with:

if (PC_IN_CALL_DUMMY(frame_saved_pc(frame)...)
return frame->frame;

Unfortunatly, the test is too generous and a problem occures when using #2 while trying to unwind through frameless functions :-(

0: innermost() fp=30 top=40
1: <dummy frame> fp=20 top=30
2: frameless() fp=20 top=20
3: <dummy frame> fp=10 top=20

When trying to unwind 2:frameless(), GDB calls frame_saved_pc()=<dummy frame> and frame_chain()=20. These two values are then used to find saved the dummy frame on the dummy_frame_stack. The above test is so generous, though, that it incorrectly matches the first dummy frame (#1, 20 == 1:fp) instead of (#3 20 == 3:top). This will send GDB into a backtrace loop #0, #1, #2, #1, #2, #1 #2 ....

The attached patch fixes this problem by being more careful about which of the above tests is used and when. the ``fp == dummyframe->top'' test is used IFF top was saved. The other tests IFF top wasn't saved.

This change does, however, have the potential to break break every target that sets save_dummy_frame_tos(). Going through the list of targets (and treating any with a frame_chain() like the above as ok):

cris-tdep.c: ok
ia64-tdep.c: ok
mcore-tdep.c: *** I suspect it doesn't but should
mn10300-tdep.c: *** I suspect it doesn't but should
rs6000-tdep.c: ok
s390-tdep.c: ok
xstormy16-tdep.c: ok (I think).

I think, for the two *** cases, the code can be tweaked to have frame_chain() return frame->frame.

Thoughts? Ok for the targets with maintainers?

I'll need this or something similar to get MIPS generic dummy frames working.

Oh, and I have a plan B: Add an extra gdbarch flag that, when set, enables the more strict tests.

Andrew
Tue Sep 17 16:38:58 2002  Andrew Cagney  <cagney@redhat.com>

	* blockframe.c (generic_find_dummy_frame): Only compare against
 	the dummy frame top when that was saved.

Index: blockframe.c
===================================================================
RCS file: /cvs/src/src/gdb/blockframe.c,v
retrieving revision 1.40
diff -u -r1.40 blockframe.c
--- blockframe.c	17 Sep 2002 20:42:01 -0000	1.40
+++ blockframe.c	17 Sep 2002 23:35:15 -0000
@@ -1164,9 +1164,9 @@
   for (dummyframe = dummy_frame_stack; dummyframe != NULL;
        dummyframe = dummyframe->next)
     if ((pc >= dummyframe->call_lo && pc < dummyframe->call_hi)
-	&& (fp == dummyframe->fp
-	    || fp == dummyframe->sp
-	    || fp == dummyframe->top))
+	&& ((SAVE_DUMMY_FRAME_TOS_P () && fp == dummyframe->top)
+	    || (!SAVE_DUMMY_FRAME_TOS_P () && (fp == dummyframe->fp
+					      || fp == dummyframe->sp))))
       /* The frame in question lies between the saved fp and sp, inclusive */
       return dummyframe->regcache;
 

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