+/* Return a structure containing various interesting information
+ about the frame that called THIS_FRAME. Returns NULL
+ if there is no such frame. */
+
+struct frame_info *
+get_prev_frame (struct frame_info *this_frame)
+{
+ struct frame_info *prev_frame;
+
+ /* Return the inner-most frame, when the caller passes in NULL. */
+ /* NOTE: cagney/2002-11-09: Not sure how this would happen. The
+ caller should have previously obtained a valid frame using
+ get_selected_frame() and then called this code - only possibility
+ I can think of is code behaving badly.
+
+ NOTE: cagney/2003-01-10: Talk about code behaving badly. Check
+ block_innermost_frame(). It does the sequence: frame = NULL;
+ while (1) { frame = get_prev_frame (frame); .... }. Ulgh! Why
+ it couldn't be written better, I don't know.
+
+ NOTE: cagney/2003-01-11: I suspect what is happening is
+ block_innermost_frame() is, when the target has no state
+ (registers, memory, ...), still calling this function. The
+ assumption being that this function will return NULL indicating
+ that a frame isn't possible, rather than checking that the target
+ has state and then calling get_current_frame() and
+ get_prev_frame(). This is a guess mind. */
+ if (this_frame == NULL)
+ {
+ /* NOTE: cagney/2002-11-09: There was a code segment here that
+ would error out when CURRENT_FRAME was NULL. The comment
+ that went with it made the claim ...
+
+ ``This screws value_of_variable, which just wants a nice
+ clean NULL return from block_innermost_frame if there are no
+ frames. I don't think I've ever seen this message happen
+ otherwise. And returning NULL here is a perfectly legitimate
+ thing to do.''
+
+ Per the above, this code shouldn't even be called with a NULL
+ THIS_FRAME. */
+ return current_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 (this_frame != NULL);
+
+ if (this_frame->level >= 0
+ && !backtrace_below_main
+ && inside_main_func (get_frame_pc (this_frame)))
+ /* Don't unwind past main(), bug always unwind the sentinel frame.
+ Note, this is done _before_ the frame has been marked as
+ previously unwound. That way if the user later decides to
+ allow unwinds past main(), that just happens. */
+ {
+ if (frame_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "Outermost frame - inside main func.\n");
+ return NULL;
+ }
+
+ /* Only try to do the unwind once. */
+ if (this_frame->prev_p)
+ return this_frame->prev;
+ this_frame->prev_p = 1;
+
+#if 0
+ /* If we're inside the entry file, it isn't valid. Don't apply this
+ test to a dummy frame - dummy frame PC's typically land in the
+ entry file. Don't apply this test to the sentinel frame.
+ Sentinel frames should always be allowed to unwind. */
+ /* NOTE: drow/2002-12-25: should there be a way to disable this
+ check? It assumes a single small entry file, and the way some
+ debug readers (e.g. dbxread) figure out which object is the
+ entry file is somewhat hokey. */
+ /* NOTE: cagney/2003-01-10: If there is a way of disabling this test
+ then it should probably be moved to before the ->prev_p test,
+ above. */
+ /* NOTE: vinschen/2003-04-01: Disabled. It turns out that the call to
+ inside_entry_file destroys a meaningful backtrace under some
+ conditions. E. g. the backtrace tests in the asm-source testcase
+ are broken for some targets. In this test the functions are all
+ implemented as part of one file and the testcase is not necessarily
+ linked with a start file (depending on the target). What happens is,
+ that the first frame is printed normaly and following frames are
+ treated as being inside the enttry file then. This way, only the
+ #0 frame is printed in the backtrace output. */
+ if (this_frame->type != DUMMY_FRAME && this_frame->level >= 0
+ && inside_entry_file (get_frame_pc (this_frame)))
+ {
+ if (frame_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "Outermost frame - inside entry file\n");
+ return NULL;
+ }
+#endif
+
+ /* If we're already inside the entry function for the main objfile,
+ then it isn't valid. Don't apply this test to a dummy frame -
+ dummy frame PC's typically land in the entry func. Don't apply
+ this test to the sentinel frame. Sentinel frames should always
+ be allowed to unwind. */
+ /* NOTE: cagney/2003-02-25: Don't enable until someone has found
+ hard evidence that this is needed. */
+ if (0
+ && this_frame->type != DUMMY_FRAME && this_frame->level >= 0
+ && inside_entry_func (get_frame_pc (this_frame)))
+ {
+ if (frame_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "Outermost frame - inside entry func\n");
+ return NULL;
+ }
+
+ /* If any of the old frame initialization methods are around, use
+ the legacy get_prev_frame method. */
+ if (legacy_frame_p (current_gdbarch))
+ {
+ prev_frame = legacy_get_prev_frame (this_frame);
+ if (frame_debug && prev_frame == NULL)
+ fprintf_unfiltered (gdb_stdlog,
+ "Outermost frame - legacy_get_prev_frame NULL.\n");
+ return prev_frame;
+ }
+
+ /* Check that this frame's ID was valid. If it wasn't, don't try to
+ unwind to the prev frame. Be careful to not apply this test to
+ the sentinel frame. */
+ if (this_frame->level >= 0 && !frame_id_p (get_frame_id (this_frame)))
+ {
+ if (frame_debug)
+ fprintf_filtered (gdb_stdlog,
+ "Outermost frame - this ID is NULL\n");
+ return NULL;
+ }
+
+ /* Check that this frame's ID isn't inner to (younger, below, next)
+ the next frame. This happens when frame unwind goes backwards.
+ Since the sentinel frame isn't valid, don't apply this if this
+ frame is entier the inner-most or sentinel frame. */
+ if (this_frame->level > 0
+ && frame_id_inner (get_frame_id (this_frame),
+ get_frame_id (this_frame->next)))
+ error ("This frame inner-to next frame (corrupt stack?)");
+
+ /* Check that this and the next frame are different. If they are
+ not, there is most likely a stack cycle. As with the inner-than
+ test, avoid the inner-most and sentinel frames. */
+ /* FIXME: cagney/2003-03-17: Can't yet enable this this check. The
+ frame_id_eq() method doesn't yet use function addresses when
+ comparing frame IDs. */
+ if (0
+ && this_frame->level > 0
+ && frame_id_eq (get_frame_id (this_frame),
+ get_frame_id (this_frame->next)))
+ error ("This frame identical to next frame (corrupt stack?)");
+
+ /* 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
+ definition, recursive). Try to prevent it.
+
+ There is no reason to worry about memory leaks, should the
+ remainder of the function fail. The allocated memory will be
+ quickly reclaimed when the frame cache is flushed, and the `we've
+ been here before' check above will stop repeated memory
+ allocation calls. */
+ prev_frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
+ prev_frame->level = this_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
+ DEPRECATED_FRAME_CHAIN()) assume THIS_FRAME's data structures
+ have already been initialized (using
+ DEPRECATED_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 THIS_FRAME's frame ID. */
+
+ if (frame_pc_unwind (this_frame) == 0)
+ {
+ /* The allocated PREV_FRAME will be reclaimed when the frame
+ obstack is next purged. */
+ if (frame_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "Outermost frame - unwound PC zero\n");
+ return NULL;
+ }
+
+ /* Set the unwind functions based on that identified PC. */
+ prev_frame->unwind = frame_unwind_find_by_pc (current_gdbarch,
+ frame_pc_unwind (this_frame));
+
+ /* FIXME: cagney/2003-04-02: Rather than storing the frame's type in
+ the frame, the unwinder's type should be returned directly.
+ Unfortunatly, legacy code, called by legacy_get_prev_frame,
+ explicitly set the frames type using the method
+ deprecated_set_frame_type(). */
+ gdb_assert (prev_frame->unwind->type != UNKNOWN_FRAME);
+ prev_frame->type = prev_frame->unwind->type;
+
+ /* Can the frame's type and unwinder be computed on demand? That
+ would make a frame's creation really really lite! */
+
+ /* The prev's frame's ID is computed by demand in get_frame_id(). */
+
+ /* The unwound frame ID is validate at the start of this function,
+ as part of the logic to decide if that frame should be further
+ unwound, and not here while the prev frame is being created.
+ Doing this makes it possible for the user to examine a frame that
+ has an invalid frame ID.
+
+ The very old VAX frame_args_address_correct() method noted: [...]
+ For the sake of argument, suppose that the stack is somewhat
+ trashed (which is one reason that "info frame" exists). So,
+ return 0 (indicating we don't know the address of the arglist) if
+ we don't know what frame this frame calls. */
+
+ /* Link it in. */
+ this_frame->prev = prev_frame;
+ prev_frame->next = this_frame;
+
+ return prev_frame;
+}
+