- /* Find the prev's frame's ID. */
- if (prev->type == DUMMY_FRAME
- && gdbarch_unwind_dummy_id_p (current_gdbarch))
- {
- /* When unwinding a normal frame, the stack structure is
- determined by analyzing the frame's function's code (be
- it using brute force prologue analysis, or the dwarf2
- CFI). In the case of a dummy frame, that simply isn't
- possible. The The PC is either the program entry point,
- or some random address on the stack. Trying to use that
- PC to apply standard frame ID unwind techniques is just
- asking for trouble. */
- /* Use an architecture specific method to extract the prev's
- dummy ID from the next frame. Note that this method uses
- frame_register_unwind to obtain the register values
- needed to determine the dummy frame's ID. */
- prev->this_id.value = gdbarch_unwind_dummy_id (current_gdbarch,
- this_frame);
- }
- else
- {
- /* We're unwinding a sentinel frame, the PC of which is
- pointing at a stack dummy. Fake up the dummy frame's ID
- using the same sequence as is found a traditional
- unwinder. Once all architectures supply the
- unwind_dummy_id method, this code can go away. */
- prev->this_id.value = frame_id_build (deprecated_read_fp (),
- read_pc ());
- }
-
- /* Check that the unwound ID is valid. */
- if (!frame_id_p (prev->this_id.value))
- {
- if (frame_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "-> ");
- fprint_frame (gdb_stdlog, NULL);
- fprintf_unfiltered (gdb_stdlog,
- " // unwound legacy ID invalid }\n");
- }
- return NULL;
- }
-
- /* Check that the new frame isn't inner to (younger, below,
- next) the old frame. If that happens the frame unwind is
- going backwards. */
- /* FIXME: cagney/2003-02-25: Ignore the sentinel frame since
- that doesn't have a valid frame ID. Should instead set the
- sentinel frame's frame ID to a `sentinel'. Leave it until
- after the switch to storing the frame ID, instead of the
- frame base, in the frame object. */
-
- /* Link it in. */
- this_frame->prev = prev;
-
- /* FIXME: cagney/2002-01-19: This call will go away. Instead of
- initializing extra info, all frames will use the frame_cache
- (passed to the unwind functions) to store additional frame
- info. Unfortunately legacy targets can't use
- legacy_get_prev_frame() to unwind the sentinel frame and,
- consequently, are forced to take this code path and rely on
- the below call to DEPRECATED_INIT_EXTRA_FRAME_INFO to
- initialize the inner-most frame. */
- if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ())
- {
- DEPRECATED_INIT_EXTRA_FRAME_INFO (0, prev);
- }
-
- if (prev->type == NORMAL_FRAME)
- prev->this_id.value.code_addr
- = get_pc_function_start (prev->this_id.value.code_addr);
-
- if (frame_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "-> ");
- fprint_frame (gdb_stdlog, prev);
- fprintf_unfiltered (gdb_stdlog, " } // legacy innermost frame\n");
- }
- return prev;
- }
-
- /* This code only works on normal frames. A sentinel frame, where
- the level is -1, should never reach this code. */
- gdb_assert (this_frame->level >= 0);
-
- /* On some machines it is possible to call a function without
- setting up a stack frame for it. On these machines, we
- define this macro to take two args; a frameinfo pointer
- identifying a frame and a variable to set or clear if it is
- or isn't leafless. */
-
- /* Still don't want to worry about this except on the innermost
- frame. This macro will set FROMLEAF if THIS_FRAME is a frameless
- function invocation. */
- if (this_frame->level == 0)
- /* FIXME: 2002-11-09: Frameless functions can occure anywhere in
- the frame chain, not just the inner most frame! The generic,
- per-architecture, frame code should handle this and the below
- should simply be removed. */
- fromleaf = FRAMELESS_FUNCTION_INVOCATION (this_frame);
- else
- fromleaf = 0;
-
- if (fromleaf)
- /* A frameless inner-most frame. The `FP' (which isn't an
- architecture frame-pointer register!) of the caller is the same
- as the callee. */
- /* FIXME: 2002-11-09: There isn't any reason to special case this
- edge condition. Instead the per-architecture code should hande
- it locally. */
- /* FIXME: cagney/2003-06-16: This returns the inner most stack
- address for the previous frame, that, however, is wrong. It
- should be the inner most stack address for the previous to
- previous frame. This is because it is the previous to previous
- frame's innermost stack address that is constant through out
- the lifetime of the previous frame (trust me :-). */
- address = get_frame_base (this_frame);
- else
- {
- /* Two macros defined in tm.h specify the machine-dependent
- actions to be performed here.
-
- First, get the frame's chain-pointer.
-
- If that is zero, the frame is the outermost frame or a leaf
- called by the outermost frame. This means that if start
- calls main without a frame, we'll return 0 (which is fine
- anyway).
-
- Nope; there's a problem. This also returns when the current
- routine is a leaf of main. This is unacceptable. We move
- this to after the ffi test; I'd rather have backtraces from
- start go curfluy than have an abort called from main not show
- main. */
- if (DEPRECATED_FRAME_CHAIN_P ())
- address = DEPRECATED_FRAME_CHAIN (this_frame);
- else
- {
- /* Someone is part way through coverting an old architecture
- to the new frame code. Implement FRAME_CHAIN the way the
- new frame will. */
- /* Find PREV frame's unwinder. */
- prev->unwind = frame_unwind_find_by_frame (this_frame->next);
- /* FIXME: cagney/2003-04-02: Rather than storing the frame's
- type in the frame, the unwinder's type should be returned
- directly. Unfortunately, legacy code, called by
- legacy_get_prev_frame, explicitly set the frames type
- using the method deprecated_set_frame_type(). */
- prev->type = prev->unwind->type;
- /* Find PREV frame's ID. */
- prev->unwind->this_id (this_frame,
- &prev->prologue_cache,
- &prev->this_id.value);
- prev->this_id.p = 1;
- address = prev->this_id.value.stack_addr;
- }
-
- if (!legacy_frame_chain_valid (address, this_frame))
- {
- if (frame_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "-> ");
- fprint_frame (gdb_stdlog, NULL);
- fprintf_unfiltered (gdb_stdlog,
- " // legacy frame chain invalid }\n");
- }
- return NULL;
- }
- }
- if (address == 0)
- {
- if (frame_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "-> ");
- fprint_frame (gdb_stdlog, NULL);
- fprintf_unfiltered (gdb_stdlog,
- " // legacy frame chain NULL }\n");
- }
- return NULL;
- }
-
- /* Link in the already allocated prev frame. */
- this_frame->prev = prev;
- deprecated_update_frame_base_hack (prev, address);
-
- /* This change should not be needed, FIXME! We should determine
- whether any targets *need* DEPRECATED_INIT_FRAME_PC to happen
- after DEPRECATED_INIT_EXTRA_FRAME_INFO and come up with a simple
- way to express what goes on here.
-
- DEPRECATED_INIT_EXTRA_FRAME_INFO is called from two places:
- create_new_frame (where the PC is already set up) and here (where
- it isn't). DEPRECATED_INIT_FRAME_PC is only called from here,
- always after DEPRECATED_INIT_EXTRA_FRAME_INFO.
-
- The catch is the MIPS, where DEPRECATED_INIT_EXTRA_FRAME_INFO
- requires the PC value (which hasn't been set yet). Some other
- machines appear to require DEPRECATED_INIT_EXTRA_FRAME_INFO
- before they can do DEPRECATED_INIT_FRAME_PC. Phoo.
-
- We shouldn't need DEPRECATED_INIT_FRAME_PC_FIRST to add more
- complication to an already overcomplicated part of GDB.
- gnu@cygnus.com, 15Sep92.
-
- Assuming that some machines need DEPRECATED_INIT_FRAME_PC after
- DEPRECATED_INIT_EXTRA_FRAME_INFO, one possible scheme:
-
- SETUP_INNERMOST_FRAME(): Default version is just create_new_frame
- (deprecated_read_fp ()), read_pc ()). Machines with extra frame
- info would do that (or the local equivalent) and then set the
- extra fields.
-
- SETUP_ARBITRARY_FRAME(argc, argv): Only change here is that
- create_new_frame would no longer init extra frame info;
- SETUP_ARBITRARY_FRAME would have to do that.
-
- INIT_PREV_FRAME(fromleaf, prev) Replace
- DEPRECATED_INIT_EXTRA_FRAME_INFO and DEPRECATED_INIT_FRAME_PC.
- This should also return a flag saying whether to keep the new
- frame, or whether to discard it, because on some machines (e.g.
- mips) it is really awkward to have DEPRECATED_FRAME_CHAIN_VALID
- called BEFORE DEPRECATED_INIT_EXTRA_FRAME_INFO (there is no good
- way to get information deduced in DEPRECATED_FRAME_CHAIN_VALID
- into the extra fields of the new frame). std_frame_pc(fromleaf,
- prev)
-
- This is the default setting for INIT_PREV_FRAME. It just does
- what the default DEPRECATED_INIT_FRAME_PC does. Some machines
- will call it from INIT_PREV_FRAME (either at the beginning, the
- end, or in the middle). Some machines won't use it.
-
- kingdon@cygnus.com, 13Apr93, 31Jan94, 14Dec94. */
-
- /* NOTE: cagney/2002-11-09: Just ignore the above! There is no
- reason for things to be this complicated.
-
- The trick is to assume that there is always a frame. Instead of
- special casing the inner-most frame, create fake frame
- (containing the hardware registers) that is inner to the
- user-visible inner-most frame (...) and then unwind from that.
- That way architecture code can use use the standard
- frame_XX_unwind() functions and not differentiate between the
- inner most and any other case.
-
- Since there is always a frame to unwind from, there is always
- somewhere (THIS_FRAME) to store all the info needed to construct
- a new (previous) frame without having to first create it. This
- means that the convolution below - needing to carefully order a
- frame's initialization - isn't needed.
-
- The irony here though, is that DEPRECATED_FRAME_CHAIN(), at least
- for a more up-to-date architecture, always calls
- FRAME_SAVED_PC(), and FRAME_SAVED_PC() computes the PC but
- without first needing the frame! Instead of the convolution
- below, we could have simply called FRAME_SAVED_PC() and been done
- with it! Note that FRAME_SAVED_PC() is being superseed by
- frame_pc_unwind() and that function does have somewhere to cache
- that PC value. */
-
- if (DEPRECATED_INIT_FRAME_PC_FIRST_P ())
- deprecated_update_frame_pc_hack (prev,
- DEPRECATED_INIT_FRAME_PC_FIRST (fromleaf,
- prev));
-
- if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ())
- DEPRECATED_INIT_EXTRA_FRAME_INFO (fromleaf, prev);
-
- /* This entry is in the frame queue now, which is good since
- FRAME_SAVED_PC may use that queue to figure out its value (see
- tm-sparc.h). We want the pc saved in the inferior frame. */
- if (DEPRECATED_INIT_FRAME_PC_P ())
- deprecated_update_frame_pc_hack (prev,
- DEPRECATED_INIT_FRAME_PC (fromleaf,
- prev));
-
- /* If ->frame and ->pc are unchanged, we are in the process of
- getting ourselves into an infinite backtrace. Some architectures
- check this in DEPRECATED_FRAME_CHAIN or thereabouts, but it seems
- like there is no reason this can't be an architecture-independent
- check. */
- if (get_frame_base (prev) == get_frame_base (this_frame)
- && get_frame_pc (prev) == get_frame_pc (this_frame))
- {
- this_frame->prev = NULL;
- obstack_free (&frame_cache_obstack, prev);
- if (frame_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "-> ");
- fprint_frame (gdb_stdlog, NULL);
- fprintf_unfiltered (gdb_stdlog,
- " // legacy this.id == prev.id }\n");
- }
- return NULL;
- }
-
- /* Initialize the code used to unwind the frame PREV based on the PC
- (and probably other architectural information). The PC lets you
- check things like the debug info at that point (dwarf2cfi?) and
- use that to decide how the frame should be unwound.
-
- If there isn't a FRAME_CHAIN, the code above will have already
- done this. */
- if (prev->unwind == NULL)
- prev->unwind = frame_unwind_find_by_frame (prev->next);
-
- /* If the unwinder provides a frame type, use it. Otherwize
- continue on to that heuristic mess. */
- if (prev->unwind->type != UNKNOWN_FRAME)
- {
- prev->type = prev->unwind->type;
- if (prev->type == NORMAL_FRAME)
- /* FIXME: cagney/2003-06-16: would get_frame_pc() be better? */
- prev->this_id.value.code_addr
- = get_pc_function_start (prev->this_id.value.code_addr);
- if (frame_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "-> ");
- fprint_frame (gdb_stdlog, prev);
- fprintf_unfiltered (gdb_stdlog, " } // legacy with unwound type\n");
- }
- return prev;
- }
-
- /* 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 (get_frame_pc (prev), 0, 0)
- : pc_in_dummy_frame (get_frame_pc (prev))))
- prev->type = DUMMY_FRAME;
- else
- {
- /* FIXME: cagney/2002-11-10: This should be moved to before the
- INIT code above so that the INIT code knows what the frame's
- type is (in fact, for a [generic] dummy-frame, the type can
- be set and then the entire initialization can be skipped.
- Unforunatly, its the INIT code that sets the PC (Hmm, catch
- 22). */
- char *name;
- find_pc_partial_function (get_frame_pc (prev), &name, NULL, NULL);
- if (PC_IN_SIGTRAMP (get_frame_pc (prev), name))
- prev->type = SIGTRAMP_FRAME;
- /* FIXME: cagney/2002-11-11: Leave prev->type alone. Some
- architectures are forcing the frame's type in INIT so we
- don't want to override it here. Remember, NORMAL_FRAME == 0,
- so it all works (just :-/). Once this initialization is
- moved to the start of this function, all this nastness will
- go away. */
- }