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
next 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