#include "value.h" /* for read_register */
#include "target.h" /* for target_has_stack */
#include "inferior.h" /* for read_pc */
+#include "annotate.h"
/* Is ADDR inside the startup file? Note that if your machine
has a way to detect the bottom of the stack, there is no need
FRAME
get_current_frame ()
{
- /* We assume its address is kept in a general register;
- param.h says which register. */
-
+ if (current_frame == NULL)
+ {
+ if (target_has_stack)
+ current_frame = create_new_frame (read_fp (), read_pc ());
+ else
+ error ("No stack.");
+ }
return current_frame;
}
current_frame = frame;
}
+/* Create an arbitrary (i.e. address specified by user) or innermost frame.
+ Always returns a non-NULL value. */
+
FRAME
create_new_frame (addr, pc)
FRAME_ADDR addr;
obstack_init (&frame_cache_obstack);
current_frame = (struct frame_info *) 0; /* Invalidate cache */
+ select_frame ((FRAME) 0, -1);
+ annotate_frames_invalid ();
}
/* Flush the frame cache, and start a new one if necessary. */
+
void
reinit_frame_cache ()
{
flush_cached_frames ();
- if (target_has_stack)
+#if 0
+ /* The inferior_pid test is wrong if there is a corefile. But I don't
+ think this code is needed at all, now that get_current_frame will
+ create the frame if it is needed. */
+ if (inferior_pid != 0)
{
set_current_frame (create_new_frame (read_fp (), read_pc ()));
select_frame (get_current_frame (), 0);
set_current_frame (0);
select_frame ((FRAME) 0, -1);
}
+#endif
}
/* Return a structure containing various interesting information
if (!next_frame)
{
+#if 0
+ /* 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. */
if (!current_frame)
{
error ("You haven't set up a process's stack to examine.");
}
+#endif
return current_frame;
}
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 INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC.
+ Replace INIT_EXTRA_FRAME_INFO and 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 FRAME_CHAIN_VALID called *before*
+ INIT_EXTRA_FRAME_INFO (there is no good way to get information
+ deduced in 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 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. */
+ kingdon@cygnus.com, 13Apr93, 31Jan94. */
#ifdef INIT_FRAME_PC_FIRST
INIT_FRAME_PC_FIRST (fromleaf, prev);
#endif
/* This entry is in the frame queue now, which is good since
- FRAME_SAVED_PC may use that queue to figure out it's value
+ 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. */
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 FRAME_CHAIN or thereabouts, but it seems like there is no reason
+ this can't be an architecture-independent check. */
+ if (next_frame != NULL)
+ {
+ if (prev->frame == next_frame->frame
+ && prev->pc == next_frame->pc)
+ {
+ next_frame->prev = NULL;
+ obstack_free (&frame_cache_obstack, prev);
+ return NULL;
+ }
+ }
+
find_pc_partial_function (prev->pc, &name,
(CORE_ADDR *)NULL,(CORE_ADDR *)NULL);
if (IN_SIGTRAMP (prev->pc, name))
fi = get_frame_info (frame);
pc = fi->pc;
- if (fi->next != 0)
- /* We are not in the innermost frame. We need to subtract one to
- get the correct block, in case the call instruction was the
- last instruction of the block. If there are any machines on
- which the saved pc does not point to after the call insn, we
- probably want to make fi->pc point after the call insn anyway. */
+ if (fi->next != 0 && fi->next->signal_handler_caller == 0)
+ /* We are not in the innermost frame and we were not interrupted
+ by a signal. We need to subtract one to get the correct block,
+ in case the call instruction was the last instruction of the block.
+ If there are any machines on which the saved pc does not point to
+ after the call insn, we probably want to make fi->pc point after
+ the call insn anyway. */
--pc;
return block_for_pc (pc);
}
{
/* Need to read the symbols to get a good value for the end address. */
if (endaddr != NULL && !pst->readin)
- PSYMTAB_TO_SYMTAB (pst);
+ {
+ /* Need to get the terminal in case symbol-reading produces
+ output. */
+ target_terminal_ours_for_output ();
+ PSYMTAB_TO_SYMTAB (pst);
+ }
if (pst->readin)
{
/* See if we're in a transfer table for Sun shared libs. */
- if (msymbol -> type == mst_text)
+ if (msymbol -> type == mst_text || msymbol -> type == mst_file_text)
cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol);
else
/* It is a transfer table for Sun shared libraries. */
}
}
+/* Return the full FRAME which corresponds to the given FRAME_ADDR
+ or NULL if no FRAME on the chain corresponds to FRAME_ADDR. */
+
+FRAME
+find_frame_addr_in_frame_chain (frame_addr)
+ FRAME_ADDR frame_addr;
+{
+ FRAME frame = NULL;
+
+ if (frame_addr == (CORE_ADDR)0)
+ return NULL;
+
+ while (1)
+ {
+ frame = get_prev_frame (frame);
+ if (frame == NULL)
+ return NULL;
+
+ if (FRAME_FP (frame) == frame_addr)
+ return frame;
+ }
+}
+
#ifdef SIGCONTEXT_PC_OFFSET
/* Get saved user PC for sigtramp from sigcontext for BSD style sigtramp. */