Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Daniel Jacobowitz <drow@false.org>
To: gdb-patches@sourceware.org
Cc: Kevin Buettner <kevinb@redhat.com>, Andrew Cagney <cagney@gnu.org>
Subject: RFC: Make PowerPC backtraces more robust
Date: Fri, 23 Sep 2005 19:34:00 -0000	[thread overview]
Message-ID: <20050923193403.GA7146@nevyn.them.org> (raw)

The PowerPC ABI is pretty explicit about the layout of the stack: if there
is a stack frame, the LR gets saved right after the backchain.  Various bits
of handwritten assembly that I've surveyed honor this convention, as does
GCC.  This patch takes advantage of that to handle backtraces in a couple of
cases that would otherwise be impossible.

This patch helps when there's no symbols available (-> frame_func_unwind
returns 0, skip_prologue does nothing), or where GDB can not handle a
prologue (e.g. assembly stubs which have a fast path which does not set up a
stack frame, falling back to a slow path which does).

It adds a simple heuristic: if the prologue analyzer did not find a stack
frame or a saved link register, then take a look at this frame's LR.  If it
points to the same address as the current PC, or if we can see that it
definitively points to somewhere in the current function, then we know that
the unwound LR is wrong, and/or the function really does have a frame.
If neither of those were true, the function would be recursive without a
stack frame.  So in this case, assume the ABI-mandated backchain and saved
LR.  We can't guess at saved registers, but having the stack is a big
improvement over not.

It seems to work very well.  I've regression tested it on powerpc64-linux
and manually checked some improved cases on powerpc-linux.

Comments?  OK?

-- 
Daniel Jacobowitz
CodeSourcery, LLC

2005-09-23  Daniel Jacobowitz  <dan@codesourcery.com>

	* rs6000-tdep.c (rs6000_frame_cache): Handle misdetected frameless
	functions.

Index: rs6000-tdep.c
===================================================================
RCS file: /big/fsf/rsync/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.243
diff -u -p -r1.243 rs6000-tdep.c
--- rs6000-tdep.c	19 Sep 2005 17:38:03 -0000	1.243
+++ rs6000-tdep.c	23 Sep 2005 18:26:39 -0000
@@ -2852,6 +2852,7 @@ rs6000_frame_cache (struct frame_info *n
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   struct rs6000_framedata fdata;
   int wordsize = tdep->wordsize;
+  CORE_ADDR func, pc;
 
   if ((*this_cache) != NULL)
     return (*this_cache);
@@ -2859,35 +2860,56 @@ rs6000_frame_cache (struct frame_info *n
   (*this_cache) = cache;
   cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
 
-  skip_prologue (frame_func_unwind (next_frame), frame_pc_unwind (next_frame),
-		 &fdata);
+  func = frame_func_unwind (next_frame);
+  pc = frame_pc_unwind (next_frame);
+  skip_prologue (func, pc, &fdata);
+
+  /* Figure out the parent's stack pointer.  */
+
+  /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most
+     address of the current frame.  Things might be easier if the
+     ->frame pointed to the outer-most address of the frame.  In
+     the mean time, the address of the prev frame is used as the
+     base address of this frame.  */
+  cache->base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
+
+  /* If the function appears to be frameless, check a couple of likely
+     indicators that we have simply failed to find the frame setup.
+     Two common cases of this are missing symbols (i.e.
+     frame_func_unwind returns the wrong address or 0), and assembly
+     stubs which have a fast exit path but set up a frame on the slow
+     path.
+
+     If the LR appears to return to this function, then presume that
+     we have an ABI compliant frame that we failed to find.  */
+  if (fdata.frameless && fdata.lr_offset == 0)
+    {
+      CORE_ADDR saved_lr;
+      int make_frame = 0;
+
+      func = frame_func_unwind (next_frame);
+      saved_lr = frame_unwind_register_unsigned (next_frame,
+						 tdep->ppc_lr_regnum);
+      if (func == 0 && saved_lr == pc)
+	make_frame = 1;
+      else if (func != 0)
+	{
+	  CORE_ADDR saved_func = get_pc_function_start (saved_lr);
+	  if (func == saved_func)
+	    make_frame = 1;
+	}
 
-  /* If there were any saved registers, figure out parent's stack
-     pointer.  */
-  /* The following is true only if the frame doesn't have a call to
-     alloca(), FIXME.  */
-
-  if (fdata.saved_fpr == 0
-      && fdata.saved_gpr == 0
-      && fdata.saved_vr == 0
-      && fdata.saved_ev == 0
-      && fdata.lr_offset == 0
-      && fdata.cr_offset == 0
-      && fdata.vr_offset == 0
-      && fdata.ev_offset == 0)
-    cache->base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
-  else
-    {
-      /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most
-	 address of the current frame.  Things might be easier if the
-	 ->frame pointed to the outer-most address of the frame.  In
-	 the mean time, the address of the prev frame is used as the
-	 base address of this frame.  */
-      cache->base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
-      if (!fdata.frameless)
-	/* Frameless really means stackless.  */
-	cache->base = read_memory_addr (cache->base, wordsize);
+      if (make_frame)
+	{
+	  fdata.frameless = 0;
+	  fdata.lr_offset = wordsize;
+	}
     }
+
+  if (!fdata.frameless)
+    /* Frameless really means stackless.  */
+    cache->base = read_memory_addr (cache->base, wordsize);
+
   trad_frame_set_value (cache->saved_regs, SP_REGNUM, cache->base);
 
   /* if != -1, fdata.saved_fpr is the smallest number of saved_fpr.


             reply	other threads:[~2005-09-23 19:34 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-09-23 19:34 Daniel Jacobowitz [this message]
2005-09-28 17:10 ` Kevin Buettner
2005-09-29 15:38   ` Daniel Jacobowitz

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=20050923193403.GA7146@nevyn.them.org \
    --to=drow@false.org \
    --cc=cagney@gnu.org \
    --cc=gdb-patches@sourceware.org \
    --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