From: Andrew Cagney <ac131313@redhat.com>
To: Daniel Jacobowitz <drow@mvista.com>
Cc: gdb-patches@sources.redhat.com
Subject: Re: RFC: Mostly kill FRAME_CHAIN_VALID, add user knob
Date: Thu, 02 Jan 2003 19:34:00 -0000 [thread overview]
Message-ID: <3E149438.3040900@redhat.com> (raw)
In-Reply-To: <20021226191541.GA8483@nevyn.them.org>
[-- Attachment #1: Type: text/plain, Size: 2133 bytes --]
> Pretty gross, neh? Well, file vs. func is merely a question of whether we
> stop at main or not, so I added "set backtrace-below-main" in order to let
> the user choose. Generic vs. not is a question of dummy frames, and the
> generic versions work with non-generic dummy frames, so there's no reason
> for that distinction earlier. It won't harm those three m68k targets (if
> they still work) to use a more comprehensive frame_chain_valid. And the
> five more specific ones up above can be retained, since they are only
> _additional_ checks. I'm not entirely convinced that the Interix one is
> necessary but I left it alone.
>
> So, after this patch we have FRAME_CHAIN_VALID as a predicated function that
> only five architectures define; everything else just uses the new
> frame_chain_valid () function, which is a more general version of
> generic_func_frame_chain_valid.
>
> I'm more confident I got the texinfo right this time :) I tested the patch
> and the new functionality on i386-linux and arm-elf, to make sure I got the
> details of FRAME_CHAIN_VALID_P () right.
>
> I'll look to commit this in January, if no one has any comments. Andrew,
> would you rather this went in frame.c? Since a purpose of that file seems
> to be moving things from blockframe.c to it...
FYI,
Much of this is superseeded by the frame overhaul - in particular the
introduction of frame_id_unwind(). The new code doesn't even call frame
chain valid!
Perhaphs wait for the attached [wip] to be committed and then tweak that
to match your proposed policy (we can then just deprecate
FRAME_CHAIN_VALID_P :-). However, making the change in parallel
wouldn't hurt.
Looking at my WIP, I'll need to tweak the code segment:
+ prev_frame->pc = frame_pc_unwind (next_frame);
+ if (prev_frame->pc == 0)
+ /* The allocated PREV_FRAME will be reclaimed when the frame
+ obstack is next purged. */
+ return NULL;
+ prev_frame->type = frame_type_from_pc (prev_frame->pc);
so that it checks for where the PC resides and abort accordingly.
The attached is WIP since I still need to see it working once :-)
Andrew
[-- Attachment #2: diffs --]
[-- Type: text/plain, Size: 6915 bytes --]
2002-12-18 Andrew Cagney <ac131313@redhat.com>
* frame.c (frame_type_from_pc): New function.
(create_new_frame): Use frame_type_from_pc.
(deprecated_get_prev_frame): New function. Move the old style
previous frame code to here....
(get_prev_frame): ... from here. Re-implement using
deprecated_get_prev_frame, frame_pc_unwind, frame_id_unwind and
frame_type_from_pc
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.47
diff -u -r1.47 frame.c
--- frame.c 13 Dec 2002 23:18:56 -0000 1.47
+++ frame.c 18 Dec 2002 19:07:42 -0000
@@ -846,6 +846,29 @@
}
}
+/* Determine the frame's type based on its PC. */
+
+static enum frame_type
+frame_type_from_pc (CORE_ADDR pc)
+{
+ /* FIXME: cagney/2002-11-24: Can't yet directly call
+ pc_in_dummy_frame() as some architectures don't set
+ PC_IN_CALL_DUMMY() to generic_pc_in_call_dummy() (remember the
+ latter is implemented by simply calling pc_in_dummy_frame). */
+ if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES
+ && DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0))
+ return DUMMY_FRAME;
+ else
+ {
+ char *name;
+ find_pc_partial_function (pc, &name, NULL, NULL);
+ if (PC_IN_SIGTRAMP (pc, name))
+ return SIGTRAMP_FRAME;
+ else
+ return NORMAL_FRAME;
+ }
+}
+
/* Create an arbitrary (i.e. address specified by user) or innermost frame.
Always returns a non-NULL value. */
@@ -864,37 +887,14 @@
fi->frame = addr;
fi->pc = pc;
- /* NOTE: cagney/2002-11-18: The code segments, found in
- create_new_frame and get_prev_frame(), that initializes the
- frames type is subtly different. The latter only updates ->type
- when it encounters a SIGTRAMP_FRAME or DUMMY_FRAME. This stops
- get_prev_frame() overriding the frame's type when the INIT code
- has previously set it. This is really somewhat bogus. The
- initialization, as seen in create_new_frame(), should occur
- before the INIT function has been called. */
- if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES
- && (DEPRECATED_PC_IN_CALL_DUMMY_P ()
- ? DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0)
- : pc_in_dummy_frame (pc)))
- /* NOTE: cagney/2002-11-11: Does this even occure? */
- type = DUMMY_FRAME;
- else
- {
- char *name;
- find_pc_partial_function (pc, &name, NULL, NULL);
- if (PC_IN_SIGTRAMP (fi->pc, name))
- type = SIGTRAMP_FRAME;
- else
- type = NORMAL_FRAME;
- }
- fi->type = type;
+ fi->type = frame_type_from_pc (pc);
if (INIT_EXTRA_FRAME_INFO_P ())
INIT_EXTRA_FRAME_INFO (0, fi);
@@ -936,12 +936,10 @@
}
}
-/* Return a structure containing various interesting information
- about the frame that called NEXT_FRAME. Returns NULL
- if there is no such frame. */
+/* Create the previous frame using the old style methods. */
-struct frame_info *
-get_prev_frame (struct frame_info *next_frame)
+static struct frame_info *
+deprecated_get_prev_frame (struct frame_info *next_frame)
{
CORE_ADDR address = 0;
struct frame_info *prev;
@@ -1185,6 +1183,102 @@
}
return prev;
+}
+
+/* Return a structure containing various interesting information
+ about the frame that called NEXT_FRAME. Returns NULL
+ if there is no such frame. */
+
+struct frame_info *
+get_prev_frame (struct frame_info *next_frame)
+{
+ struct frame_info *prev_frame;
+
+ if (DEPRECATED_INIT_FRAME_PC_P ()
+ || DEPRECATED_INIT_FRAME_PC_FIRST_P ())
+ return deprecated_get_prev_frame (next_frame);
+
+ /* There is always a frame. If this assertion fails, suspect that
+ something should be calling get_selected_frame() or
+ get_current_frame(). */
+ gdb_assert (next_frame != NULL);
+
+ /* Only try to do the unwind once. */
+ if (next_frame->prev_p)
+ return next_frame->prev;
+ next_frame->prev_p = 1;
+
+ /* Allocate the new frame but do not wire it in. Some (bad) code
+ tries to look along frame->next to pull some fancy tricks (of
+ course such code is, by definition, recursive). Try to prevent
+ it. */
+ prev_frame = frame_obstack_alloc (sizeof (struct frame_info));
+ memset (prev_frame, 0, sizeof (struct frame_info));
+ prev_frame->level = next_frame->level + 1;
+
+ /* Try to unwind the PC. If that doesn't work, assume we've reached
+ the oldest frame and simply return. Is there a better sentinal
+ value? The unwound PC value is then used to initialize the new
+ previous frame's type.
+
+ Note that the pc-unwind is intentionally performed before the
+ frame chain. This is ok since, for old targets, both
+ frame_pc_unwind (nee, FRAME_SAVED_PC) and FRAME_CHAIN()) assume
+ NEXT_FRAME's data structures have already been initialized (using
+ INIT_EXTRA_FRAME_INFO) and hence the call order doesn't matter.
+
+ By unwinding the PC first, it becomes possible to, in the case of
+ a dummy frame, avoid also unwinding the frame ID. This is
+ because (well ignoring the PPC) a dummy frame can be located
+ using NEXT_FRAME's frame ID. */
+
+ prev_frame->pc = frame_pc_unwind (next_frame);
+ if (prev_frame->pc == 0)
+ /* The allocated PREV_FRAME will be reclaimed when the frame
+ obstack is next purged. */
+ return NULL;
+ prev_frame->type = frame_type_from_pc (prev_frame->pc);
+
+ /* Set the unwind functions based on that identified PC. */
+ set_unwind_by_pc (prev_frame->pc, &prev_frame->register_unwind,
+ &prev_frame->pc_unwind, &prev_frame->id_unwind);
+
+ /* Now figure out how to initialize this new frame. Perhaphs one
+ day, this will too, be selected by set_unwind_by_pc(). */
+ if (prev_frame->type != DUMMY_FRAME)
+ {
+ /* A dummy frame doesn't need to unwind the frame ID because the
+ frame ID comes from the previous frame. The other frames do
+ though. True? */
+#if 0
+ /* Oops, the frame doesn't chain. Treat this as the last frame. */
+ prev_frame->id = frame_id_unwind (next_frame);
+ if (!frame_id_p (prev_frame->id))
+ return NULL;
+#else
+ /* FIXME: cagney/2002-12-18: Instead of this hack, should just
+ save the frame ID directly. */
+ struct frame_id id = frame_id_unwind (next_frame);
+ if (!frame_id_p (id))
+ return NULL;
+ prev_frame->frame = id.base;
+#endif
+ }
+
+ /* Link it in. */
+ next_frame->prev = prev_frame;
+ prev_frame->next = next_frame;
+
+ /* NOTE: cagney/2002-12-18: Eventually this call will go away.
+ Instead of initializing extra info, all frames will use the
+ frame_cache (passed to the unwind functions) to store extra frame
+ info. */
+ if (INIT_EXTRA_FRAME_INFO_P ())
+ /* NOTE: This code doesn't bother trying to sort out frameless
+ functions. That is left to the target. */
+ INIT_EXTRA_FRAME_INFO (0, prev_frame);
+
+ return prev_frame;
}
CORE_ADDR
next prev parent reply other threads:[~2003-01-02 19:34 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-12-26 12:20 Daniel Jacobowitz
2003-01-02 19:34 ` Andrew Cagney [this message]
2003-01-05 1:42 ` Daniel Jacobowitz
2003-01-05 1:44 ` Daniel Jacobowitz
2003-01-06 23:03 ` Andrew Cagney
2003-01-10 20:10 ` Andrew Cagney
2003-01-10 20:29 ` Andrew Cagney
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=3E149438.3040900@redhat.com \
--to=ac131313@redhat.com \
--cc=drow@mvista.com \
--cc=gdb-patches@sources.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