Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: "Maciej W. Rozycki" <macro@mips.com>
To: gdb-patches@sourceware.org
Cc: Nigel Stephens <nigel@mips.com>,
	     "Maciej W. Rozycki" <macro@linux-mips.org>
Subject: Do not unwind frames past NULL PC
Date: Fri, 22 Feb 2008 17:21:00 -0000	[thread overview]
Message-ID: <Pine.LNX.4.61.0802221457040.21569@perivale.mips.com> (raw)

Hello,

 Some architectures, like MIPS, specify in the ABI that the value of the 
return address in a frame (or in other words the value of the PC the frame 
would have been called from) being zero denotes the outermost frame.  At 
the moment GDB does not seem to have a way to terminate frame unwinding in 
an architecture-specific way (or to that matter any that would not imply 
an error condition) in get_prev_frame_1(), which is where such a check 
would be needed.

 However even for these architectures which may not necessarily specify in 
the relevant ABI that a NULL PC is the terminating value it seems rather 
unlikely for a function to have been called in a way which would make its 
return address to be zero and yet it having a genuine caller with an 
associated frame.  Therefore I propose the following check to be 
introduced to get_prev_frame_1().  It removes the confusing bogus frame at 
the bottom of a backtrace like below:

(gdb) bt
#0  main (argc=1, argv=0x8114fdd0, envp=0x801065a8)
    at gdb/testsuite/gdb.base/run.c:59
#1  0x801003a3 in __wrap_main ()
#2  0x801000a4 in _start ()
    at sdemdi/crt0.S:93
#3  0x00000000 in ?? ()
(gdb)

 If my assumption is in fact wrong for some other architecture, then 
please let me know.  Otherwise this change has been tested using the 
mipsisa32-sde-elf target, with the mips-sim-sde32/-EB/-mips32r2 and 
mips-sim-sde32/-EL/-mips32r2 boards with no regressions.

2008-02-22  Maciej W. Rozycki  <macro@mips.com>

	* frame.c (get_prev_frame_1): Stop unwinding if the PC of zero
	has been reached.

 OK to apply?

  Maciej

gdb-get_prev_frame.diff
Index: binutils-quilt/ChangeLog-gdb-get_prev_frame
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/ChangeLog-gdb-get_prev_frame	2008-02-22 16:38:40.000000000 +0000
@@ -0,0 +1,4 @@
+2008-02-22  Maciej W. Rozycki  <macro@mips.com>
+
+	* frame.c (get_prev_frame_1): Stop unwinding if the PC of zero
+	has been reached.
Index: binutils-quilt/src/gdb/frame.c
===================================================================
--- binutils-quilt.orig/src/gdb/frame.c	2008-02-22 14:52:45.000000000 +0000
+++ binutils-quilt/src/gdb/frame.c	2008-02-22 16:38:40.000000000 +0000
@@ -1122,13 +1122,18 @@
 static struct frame_info *
 get_prev_frame_1 (struct frame_info *this_frame)
 {
+  enum frame_type this_frame_type;
   struct frame_info *prev_frame;
   struct frame_id this_id;
   struct gdbarch *gdbarch;
+  int pc_regnum;
 
   gdb_assert (this_frame != NULL);
   gdbarch = get_frame_arch (this_frame);
 
+  pc_regnum = gdbarch_pc_regnum (gdbarch);
+  this_frame_type = get_frame_type (this_frame);
+
   if (frame_debug)
     {
       fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame_1 (this_frame=");
@@ -1219,19 +1224,17 @@
      method set the same lval and location information as
      frame_register_unwind.  */
   if (this_frame->level > 0
-      && gdbarch_pc_regnum (gdbarch) >= 0
-      && get_frame_type (this_frame) == NORMAL_FRAME
+      && pc_regnum >= 0
+      && this_frame_type == NORMAL_FRAME
       && get_frame_type (this_frame->next) == NORMAL_FRAME)
     {
       int optimized, realnum, nrealnum;
       enum lval_type lval, nlval;
       CORE_ADDR addr, naddr;
 
-      frame_register_unwind_location (this_frame,
-				      gdbarch_pc_regnum (gdbarch),
+      frame_register_unwind_location (this_frame, pc_regnum,
 				      &optimized, &lval, &addr, &realnum);
-      frame_register_unwind_location (get_next_frame (this_frame),
-				      gdbarch_pc_regnum (gdbarch),
+      frame_register_unwind_location (get_next_frame (this_frame), pc_regnum,
 				      &optimized, &nlval, &naddr, &nrealnum);
 
       if ((lval == lval_memory && lval == nlval && addr == naddr)
@@ -1250,6 +1253,23 @@
 	}
     }
 
+  /* Check for the unwound PC being zero, which means this is
+     the outermost frame.  */
+  if (pc_regnum >= 0
+      && this_frame_type == NORMAL_FRAME
+      && frame_pc_unwind (this_frame) == 0)
+    {
+      if (frame_debug)
+	{
+	  fprintf_unfiltered (gdb_stdlog, "-> ");
+	  fprint_frame (gdb_stdlog, NULL);
+	  fprintf_unfiltered (gdb_stdlog, " // NULL saved PC }\n");
+	}
+
+      this_frame->prev = NULL;
+      return NULL;
+    }
+
   /* Allocate the new frame but do not wire it in to the frame chain.
      Some (bad) code in INIT_FRAME_EXTRA_INFO tries to look along
      frame->next to pull some fancy tricks (of course such code is, by


             reply	other threads:[~2008-02-22 17:12 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-22 17:21 Maciej W. Rozycki [this message]
2008-02-22 18:31 ` Daniel Jacobowitz
2008-02-22 19:50   ` Maciej W. Rozycki
2008-02-25 19:19     ` Maciej W. Rozycki

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=Pine.LNX.4.61.0802221457040.21569@perivale.mips.com \
    --to=macro@mips.com \
    --cc=gdb-patches@sourceware.org \
    --cc=macro@linux-mips.org \
    --cc=nigel@mips.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