Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Andrew Cagney <ac131313@redhat.com>
To: Kevin Buettner <kevinb@redhat.com>, gdb-patches@sources.redhat.com
Subject: Re: [patch/rfc/rfa*] Only compare against dummy frame tos when saved
Date: Thu, 26 Sep 2002 09:35:00 -0000	[thread overview]
Message-ID: <3D933757.1000906@redhat.com> (raw)
In-Reply-To: <1020919172106.ZM21484@localhost.localdomain>

[-- Attachment #1: Type: text/plain, Size: 4615 bytes --]

> 
> I think this change will be okay for ia64 so long as the following
> FIXME comment in ia64-tdep.c is fixed:
> 
>   /* FIXME: This doesn't belong here!  Instead, SAVE_DUMMY_FRAME_TOS needs
>      to be defined to call generic_save_dummy_frame_tos().  But at the
>      time of this writing, SAVE_DUMMY_FRAME_TOS wasn't gdbarch'd, so
>      I chose to put this call here instead of using the old mechanisms. 
>      Once SAVE_DUMMY_FRAME_TOS is gdbarch'd, all we need to do is add the
>      line
> 
> 	set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
> 
>      to ia64_gdbarch_init() and remove the line below. */
> 
> At the moment, ia64 depends upon ->top being set, but your change will
> disable the appropriate test because ia64-tdep.c doesn't (correctly) set
> the SAVE_DUMMY_FRAME_TOS method.
> 
> I'll try to find a moment or two to give it a try...

No need.  I skipped ``plan b'' and went straight onto ``plan c''.

The attached revised patch modifies generic_find_dummy_frame() so that, 
as before, it only tests TOP when it was set.  However, this time it 
uses the value of TOP instead of find_dummy_frame_p().  I think this is 
more robust since, as with the ia64, it allows an architecture to 
explicitly set TOS (rather than rely on hand_function_call() to set it).

I should note that, per the rs6000, this change is likely to flush out 
some latent architecture bugs and, as a consequence, cause regressions 
:-(  Sigh!

There is going to be a trade off here .... :-/

Andrew



The original description was:

> 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 



[-- Attachment #2: diffs --]
[-- Type: text/plain, Size: 2826 bytes --]

2002-09-25  Andrew Cagney  <ac131313@redhat.com>

	* blockframe.c (generic_find_dummy_frame): Rewrite.  Only test
	against TOP when TOP was explictly set.
	(generic_push_dummy_frame): Set TOP to zero.

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	26 Sep 2002 16:19:30 -0000
@@ -1151,8 +1151,8 @@
 
 /* Function: find_dummy_frame(pc, fp, sp)
 
-   Search the stack of dummy frames for one matching the given PC, FP
-   and SP.  Unlike PC_IN_CALL_DUMMY, this function doesn't need to
+   Search the stack of dummy frames for one matching the given PC and
+   FP/SP.  Unlike PC_IN_CALL_DUMMY, this function doesn't need to
    adjust for DECR_PC_AFTER_BREAK.  This is because it is only legal
    to call this function after the PC has been adjusted.  */
 
@@ -1163,12 +1163,37 @@
 
   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 */
+    {
+      /* Does the PC fall within the dummy frame's breakpoint
+         instruction.  If not, discard this one.  */
+      if (!(pc >= dummyframe->call_lo && pc < dummyframe->call_hi))
+	continue;
+      /* Does the FP match?  */
+      if (dummyframe->top != 0)
+	{
+	  /* If the target architecture explicitly saved the
+	     top-of-stack before the inferior function call, assume
+	     that that same architecture will always pass in an FP
+	     (frame base) value that eactly matches that saved TOS.
+	     Don't check the saved SP and SP as they can lead to false
+	     hits.  */
+	  if (fp != dummyframe->top)
+	    continue;
+	}
+      else
+	{
+	  /* An older target that hasn't explicitly or implicitly
+             saved the dummy frame's top-of-stack.  Try matching the
+             FP against the saved SP and FP.  NOTE: If you're trying
+             to fix a problem with GDB not correctly finding a dummy
+             frame, check the comments that go with FRAME_ALIGN() and
+             SAVE_DUMMY_FRAME_TOS().  */
+	  if (fp != dummyframe->fp && fp != dummyframe->sp)
+	    continue;
+	}
+      /* The FP matches this dummy frame.  */
       return dummyframe->regcache;
+    }
 
   return 0;
 }
@@ -1265,7 +1290,7 @@
 
   dummy_frame->pc = read_pc ();
   dummy_frame->sp = read_sp ();
-  dummy_frame->top = dummy_frame->sp;
+  dummy_frame->top = 0;
   dummy_frame->fp = fp;
   regcache_cpy (dummy_frame->regcache, current_regcache);
   dummy_frame->next = dummy_frame_stack;

      reply	other threads:[~2002-09-26 16:35 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-09-17 17:55 Andrew Cagney
2002-09-19 10:21 ` Kevin Buettner
2002-09-26  9:35   ` Andrew Cagney [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3D933757.1000906@redhat.com \
    --to=ac131313@redhat.com \
    --cc=gdb-patches@sources.redhat.com \
    --cc=kevinb@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox