- 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. */
-
-CORE_ADDR
-sigtramp_saved_pc (struct frame_info *frame)
-{
- CORE_ADDR sigcontext_addr;
- char *buf;
- int ptrbytes = TARGET_PTR_BIT / TARGET_CHAR_BIT;
- int sigcontext_offs = (2 * TARGET_INT_BIT) / TARGET_CHAR_BIT;
-
- buf = alloca (ptrbytes);
- /* Get sigcontext address, it is the third parameter on the stack. */
- if (frame->next)
- sigcontext_addr = read_memory_integer (FRAME_ARGS_ADDRESS (frame->next)
- + FRAME_ARGS_SKIP
- + sigcontext_offs,
- ptrbytes);
- else
- sigcontext_addr = read_memory_integer (read_register (SP_REGNUM)
- + sigcontext_offs,
- ptrbytes);
-
- /* Don't cause a memory_error when accessing sigcontext in case the stack
- layout has changed or the stack is corrupt. */
- target_read_memory (sigcontext_addr + SIGCONTEXT_PC_OFFSET, buf, ptrbytes);
- return extract_unsigned_integer (buf, ptrbytes);
-}
-#endif /* SIGCONTEXT_PC_OFFSET */
-
-
-/* Are we in a call dummy? The code below which allows DECR_PC_AFTER_BREAK
- below is for infrun.c, which may give the macro a pc without that
- subtracted out. */
-
-extern CORE_ADDR text_end;
-
-int
-pc_in_call_dummy_before_text_end (CORE_ADDR pc, CORE_ADDR sp,
- CORE_ADDR frame_address)
-{
- return ((pc) >= text_end - CALL_DUMMY_LENGTH
- && (pc) <= text_end + DECR_PC_AFTER_BREAK);
-}
-
-int
-pc_in_call_dummy_after_text_end (CORE_ADDR pc, CORE_ADDR sp,
- CORE_ADDR frame_address)
-{
- return ((pc) >= text_end
- && (pc) <= text_end + CALL_DUMMY_LENGTH + DECR_PC_AFTER_BREAK);
-}
-
-/* Is the PC in a call dummy? SP and FRAME_ADDRESS are the bottom and
- top of the stack frame which we are checking, where "bottom" and
- "top" refer to some section of memory which contains the code for
- the call dummy. Calls to this macro assume that the contents of
- SP_REGNUM and FP_REGNUM (or the saved values thereof), respectively,
- are the things to pass.
-
- This won't work on the 29k, where SP_REGNUM and FP_REGNUM don't
- have that meaning, but the 29k doesn't use ON_STACK. This could be
- fixed by generalizing this scheme, perhaps by passing in a frame
- and adding a few fields, at least on machines which need them for
- PC_IN_CALL_DUMMY.
-
- Something simpler, like checking for the stack segment, doesn't work,
- since various programs (threads implementations, gcc nested function
- stubs, etc) may either allocate stack frames in another segment, or
- allocate other kinds of code on the stack. */
-
-int
-pc_in_call_dummy_on_stack (CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR frame_address)
-{
- return (INNER_THAN ((sp), (pc))
- && (frame_address != 0)
- && INNER_THAN ((pc), (frame_address)));
-}
-
-int
-pc_in_call_dummy_at_entry_point (CORE_ADDR pc, CORE_ADDR sp,
- CORE_ADDR frame_address)
-{
- return ((pc) >= CALL_DUMMY_ADDRESS ()
- && (pc) <= (CALL_DUMMY_ADDRESS () + DECR_PC_AFTER_BREAK));
-}
-
-
-/*
- * GENERIC DUMMY FRAMES
- *
- * The following code serves to maintain the dummy stack frames for
- * inferior function calls (ie. when gdb calls into the inferior via
- * call_function_by_hand). This code saves the machine state before
- * the call in host memory, so we must maintain an independent stack
- * and keep it consistant etc. I am attempting to make this code
- * generic enough to be used by many targets.
- *
- * The cheapest and most generic way to do CALL_DUMMY on a new target
- * is probably to define CALL_DUMMY to be empty, CALL_DUMMY_LENGTH to
- * zero, and CALL_DUMMY_LOCATION to AT_ENTRY. Then you must remember
- * to define PUSH_RETURN_ADDRESS, because no call instruction will be
- * being executed by the target. Also FRAME_CHAIN_VALID as
- * generic_{file,func}_frame_chain_valid and FIX_CALL_DUMMY as
- * generic_fix_call_dummy. */
-
-/* Dummy frame. This saves the processor state just prior to setting
- up the inferior function call. Older targets save the registers
- on the target stack (but that really slows down function calls). */
-
-struct dummy_frame
-{
- struct dummy_frame *next;
-
- CORE_ADDR pc;
- CORE_ADDR fp;
- CORE_ADDR sp;
- CORE_ADDR top;
- char *registers;
-};
-
-static struct dummy_frame *dummy_frame_stack = NULL;
-
-/* Function: find_dummy_frame(pc, fp, sp)
- Search the stack of dummy frames for one matching the given PC, FP and SP.
- This is the work-horse for pc_in_call_dummy and read_register_dummy */
-
-char *
-generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
-{
- struct dummy_frame *dummyframe;
-
- if (pc != entry_point_address ())
- return 0;
-
- for (dummyframe = dummy_frame_stack; dummyframe != NULL;
- dummyframe = dummyframe->next)
- if (fp == dummyframe->fp
- || fp == dummyframe->sp
- || fp == dummyframe->top)
- /* The frame in question lies between the saved fp and sp, inclusive */
- return dummyframe->registers;
-
- return 0;
-}
-
-/* Function: pc_in_call_dummy (pc, fp)
- Return true if this is a dummy frame created by gdb for an inferior call */
-
-int
-generic_pc_in_call_dummy (CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR fp)
-{
- /* if find_dummy_frame succeeds, then PC is in a call dummy */
- /* Note: SP and not FP is passed on. */
- return (generic_find_dummy_frame (pc, sp) != 0);
-}
-
-/* Function: read_register_dummy
- Find a saved register from before GDB calls a function in the inferior */
-
-CORE_ADDR
-generic_read_register_dummy (CORE_ADDR pc, CORE_ADDR fp, int regno)
-{
- char *dummy_regs = generic_find_dummy_frame (pc, fp);
-
- if (dummy_regs)
- return extract_address (&dummy_regs[REGISTER_BYTE (regno)],
- REGISTER_RAW_SIZE (regno));
- else
- return 0;
-}
-
-/* Save all the registers on the dummy frame stack. Most ports save the
- registers on the target stack. This results in lots of unnecessary memory
- references, which are slow when debugging via a serial line. Instead, we
- save all the registers internally, and never write them to the stack. The
- registers get restored when the called function returns to the entry point,
- where a breakpoint is laying in wait. */
-
-void
-generic_push_dummy_frame (void)
-{
- struct dummy_frame *dummy_frame;
- CORE_ADDR fp = (get_current_frame ())->frame;
-
- /* check to see if there are stale dummy frames,
- perhaps left over from when a longjump took us out of a
- function that was called by the debugger */
-
- dummy_frame = dummy_frame_stack;
- while (dummy_frame)
- if (INNER_THAN (dummy_frame->fp, fp)) /* stale -- destroy! */
- {
- dummy_frame_stack = dummy_frame->next;
- xfree (dummy_frame->registers);
- xfree (dummy_frame);
- dummy_frame = dummy_frame_stack;
- }
- else
- dummy_frame = dummy_frame->next;
-
- dummy_frame = xmalloc (sizeof (struct dummy_frame));
- dummy_frame->registers = xmalloc (REGISTER_BYTES);
-
- dummy_frame->pc = read_pc ();
- dummy_frame->sp = read_sp ();
- dummy_frame->top = dummy_frame->sp;
- dummy_frame->fp = fp;
- read_register_bytes (0, dummy_frame->registers, REGISTER_BYTES);
- dummy_frame->next = dummy_frame_stack;
- dummy_frame_stack = dummy_frame;
-}
-
-void
-generic_save_dummy_frame_tos (CORE_ADDR sp)
-{
- dummy_frame_stack->top = sp;
-}
-
-/* Restore the machine state from either the saved dummy stack or a
- real stack frame. */
-
-void
-generic_pop_current_frame (void (*popper) (struct frame_info * frame))
-{
- struct frame_info *frame = get_current_frame ();
-
- if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
- generic_pop_dummy_frame ();
- else
- (*popper) (frame);
-}
-
-/* Function: pop_dummy_frame
- Restore the machine state from a saved dummy stack frame. */
-
-void
-generic_pop_dummy_frame (void)
-{
- struct dummy_frame *dummy_frame = dummy_frame_stack;
-
- /* FIXME: what if the first frame isn't the right one, eg..
- because one call-by-hand function has done a longjmp into another one? */
-
- if (!dummy_frame)
- error ("Can't pop dummy frame!");
- dummy_frame_stack = dummy_frame->next;
- write_register_bytes (0, dummy_frame->registers, REGISTER_BYTES);
- flush_cached_frames ();
-
- xfree (dummy_frame->registers);
- xfree (dummy_frame);
-}
-
-/* Function: frame_chain_valid
- Returns true for a user frame or a call_function_by_hand dummy frame,
- and false for the CRT0 start-up frame. Purpose is to terminate backtrace */
-
-int
-generic_file_frame_chain_valid (CORE_ADDR fp, struct frame_info *fi)
-{
- if (PC_IN_CALL_DUMMY (FRAME_SAVED_PC (fi), fp, fp))
- return 1; /* don't prune CALL_DUMMY frames */
- else /* fall back to default algorithm (see frame.h) */
- return (fp != 0
- && (INNER_THAN (fi->frame, fp) || fi->frame == fp)
- && !inside_entry_file (FRAME_SAVED_PC (fi)));
-}
-
-int
-generic_func_frame_chain_valid (CORE_ADDR fp, struct frame_info *fi)
-{
- if (PC_IN_CALL_DUMMY ((fi)->pc, fp, fp))
- return 1; /* don't prune CALL_DUMMY frames */
- else /* fall back to default algorithm (see frame.h) */
- return (fp != 0
- && (INNER_THAN (fi->frame, fp) || fi->frame == fp)
- && !inside_main_func ((fi)->pc)
- && !inside_entry_func ((fi)->pc));
-}
-
-/* Function: fix_call_dummy
- Stub function. Generic dummy frames typically do not need to fix
- the frame being created */
-
-void
-generic_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
- struct value **args, struct type *type, int gcc_p)
-{
- return;
-}
-
-/* Function: get_saved_register
- Find register number REGNUM relative to FRAME and put its (raw,
- target format) contents in *RAW_BUFFER.
-
- Set *OPTIMIZED if the variable was optimized out (and thus can't be
- fetched). Note that this is never set to anything other than zero
- in this implementation.
-
- Set *LVAL to lval_memory, lval_register, or not_lval, depending on
- whether the value was fetched from memory, from a register, or in a
- strange and non-modifiable way (e.g. a frame pointer which was
- calculated rather than fetched). We will use not_lval for values
- fetched from generic dummy frames.
-
- Set *ADDRP to the address, either in memory or as a REGISTER_BYTE
- offset into the registers array. If the value is stored in a dummy
- frame, set *ADDRP to zero.
-
- To use this implementation, define a function called
- "get_saved_register" in your target code, which simply passes all
- of its arguments to this function.
-
- The argument RAW_BUFFER must point to aligned memory. */
-
-void
-generic_get_saved_register (char *raw_buffer, int *optimized, CORE_ADDR *addrp,
- struct frame_info *frame, int regnum,
- enum lval_type *lval)
-{
- if (!target_has_registers)
- error ("No registers.");
-
- /* Normal systems don't optimize out things with register numbers. */
- if (optimized != NULL)
- *optimized = 0;
-
- if (addrp) /* default assumption: not found in memory */
- *addrp = 0;
-
- /* Note: since the current frame's registers could only have been
- saved by frames INTERIOR TO the current frame, we skip examining
- the current frame itself: otherwise, we would be getting the
- previous frame's registers which were saved by the current frame. */
-
- while (frame && ((frame = frame->next) != NULL))
- {
- if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
- {
- if (lval) /* found it in a CALL_DUMMY frame */
- *lval = not_lval;
- if (raw_buffer)
- memcpy (raw_buffer,
- generic_find_dummy_frame (frame->pc, frame->frame) +
- REGISTER_BYTE (regnum),
- REGISTER_RAW_SIZE (regnum));
- return;
- }
-
- FRAME_INIT_SAVED_REGS (frame);
- if (frame->saved_regs != NULL
- && frame->saved_regs[regnum] != 0)
- {
- if (lval) /* found it saved on the stack */
- *lval = lval_memory;
- if (regnum == SP_REGNUM)
- {
- if (raw_buffer) /* SP register treated specially */
- store_address (raw_buffer, REGISTER_RAW_SIZE (regnum),
- frame->saved_regs[regnum]);
- }
- else
- {
- if (addrp) /* any other register */
- *addrp = frame->saved_regs[regnum];
- if (raw_buffer)
- read_memory (frame->saved_regs[regnum], raw_buffer,
- REGISTER_RAW_SIZE (regnum));
- }
- return;
- }