/* Definitions for dealing with stack frames, for GDB, the GNU debugger.
Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996,
- 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GDB.
#define FRAME_H 1
struct symtab_and_line;
+struct frame_unwind;
+struct block;
+
+/* A legacy unwinder to prop up architectures using the old style
+ saved regs array. */
+extern const struct frame_unwind *legacy_saved_regs_unwind;
/* The frame object. */
/* The frame object's ID. This provides a per-frame unique identifier
that can be used to relocate a `struct frame_info' after a target
- resume or a frame cache destruct (assuming the target hasn't
- unwound the stack past that frame - a problem handled elsewhere). */
+ resume or a frame cache destruct. It of course assumes that the
+ inferior hasn't unwound the stack past that frame. */
struct frame_id
{
CORE_ADDR pc;
};
+/* Methods for constructing and comparing Frame IDs.
+
+ NOTE: Given frameless functions A and B, where A calls B (and hence
+ B is inner-to A). The relationships: !eq(A,B); !eq(B,A);
+ !inner(A,B); !inner(B,A); all hold. This is because, while B is
+ inner to A, B is not strictly inner to A (being frameless, they
+ have the same .base value). */
+
+/* For convenience. All fields are zero. */
+extern const struct frame_id null_frame_id;
+
+/* Construct a frame ID. The second parameter isn't yet well defined.
+ It might be the containing function, or the resume PC (see comment
+ above in `struct frame_id')? A func/pc of zero indicates a
+ wildcard (i.e., do not use func in frame ID comparisons). */
+extern struct frame_id frame_id_build (CORE_ADDR base,
+ CORE_ADDR func_or_pc);
+
+/* Returns non-zero when L is a valid frame (a valid frame has a
+ non-zero .base). */
+extern int frame_id_p (struct frame_id l);
+
+/* Returns non-zero when L and R identify the same frame, or, if
+ either L or R have a zero .func, then the same frame base. */
+extern int frame_id_eq (struct frame_id l, struct frame_id r);
+
+/* Returns non-zero when L is strictly inner-than R (they have
+ different frame .bases). Neither L, nor R can be `null'. See note
+ above about frameless functions. */
+extern int frame_id_inner (struct frame_id l, struct frame_id r);
+
+
/* For every stopped thread, GDB tracks two frames: current and
selected. Current frame is the inner most frame of the selected
thread. Selected frame is the one being examined by the the GDB
extern CORE_ADDR get_frame_base (struct frame_info *);
/* Return the per-frame unique identifer. Can be used to relocate a
- frame after a frame cache flush (and other similar operations). */
-extern void get_frame_id (struct frame_info *fi, struct frame_id *id);
+ frame after a frame cache flush (and other similar operations). If
+ FI is NULL, return the null_frame_id. */
+extern struct frame_id get_frame_id (struct frame_info *fi);
/* The frame's level: 0 for innermost, 1 for its caller, ...; or -1
for an invalid frame). */
PC_IN_SIGTRAMP() indicates a SIGTRAMP_FRAME and
DEPRECATED_PC_IN_CALL_DUMMY() indicates a DUMMY_FRAME. I suspect
the real problem here is that get_prev_frame() only sets
- initialized after INIT_EXTRA_FRAME_INFO as been called.
+ initialized after DEPRECATED_INIT_EXTRA_FRAME_INFO as been called.
Consequently, some targets found that the frame's type was wrong
and tried to fix it. The correct fix is to modify get_prev_frame()
so that it initializes the frame's type before calling any other
/* NOTE: cagney/2002-09-13: Return void as one day these functions may
be changed to return an indication that the read succeeded. */
+extern void frame_unwind_register (struct frame_info *frame,
+ int regnum, void *buf);
+
extern void frame_unwind_signed_register (struct frame_info *frame,
int regnum, LONGEST *val);
/* NOTE: cagney/2002-09-13: Return void as one day these functions may
be changed to return an indication that the read succeeded. */
+extern void frame_read_register (struct frame_info *frame, int regnum,
+ void *buf);
+
extern void frame_read_signed_register (struct frame_info *frame,
int regnum, LONGEST *val);
/* Map between a frame register number and its name. A frame register
space is a superset of the cooked register space --- it also
- includes builtin registers. */
+ includes builtin registers. If NAMELEN is negative, use the NAME's
+ length when doing the comparison. */
-extern int frame_map_name_to_regnum (const char *name, int strlen);
+extern int frame_map_name_to_regnum (const char *name, int namelen);
extern const char *frame_map_regnum_to_name (int regnum);
/* Unwind the PC. Strictly speaking return the resume address of the
extern CORE_ADDR frame_pc_unwind (struct frame_info *frame);
-\f
-/* Return the location (and possibly value) of REGNUM for the previous
- (older, up) frame. All parameters except VALUEP can be assumed to
- be non NULL. When VALUEP is NULL, just the location of the
- register should be returned.
-
- UNWIND_CACHE is provided as mechanism for implementing a per-frame
- local cache. It's initial value being NULL. Memory for that cache
- should be allocated using frame_obstack_alloc().
-
- Register window architectures (eg SPARC) should note that REGNUM
- identifies the register for the previous frame. For instance, a
- request for the value of "o1" for the previous frame would be found
- in the register "i1" in this FRAME. */
-
-typedef void (frame_register_unwind_ftype) (struct frame_info *frame,
- void **unwind_cache,
- int regnum,
- int *optimized,
- enum lval_type *lvalp,
- CORE_ADDR *addrp,
- int *realnump,
- void *valuep);
-
-/* Same as for registers above, but return the address at which the
- calling frame would resume. */
-
-typedef CORE_ADDR (frame_pc_unwind_ftype) (struct frame_info *frame,
- void **unwind_cache);
+/* Discard the specified frame. Restoring the registers to the state
+ of the caller. */
+extern void frame_pop (struct frame_info *frame);
/* Describe the saved registers of a frame. */
special, the address here is the sp for the previous frame, not
the address where the sp was saved. */
/* Allocated by frame_saved_regs_zalloc () which is called /
- initialized by FRAME_INIT_SAVED_REGS(). */
+ initialized by DEPRECATED_FRAME_INIT_SAVED_REGS(). */
CORE_ADDR *saved_regs; /*NUM_REGS + NUM_PSEUDO_REGS*/
#ifdef EXTRA_FRAME_INFO
/* Anything extra for this structure that may have been defined
in the machine dependent files. */
- /* Allocated by frame_obstack_alloc () which is called /
- initialized by INIT_EXTRA_FRAME_INFO */
+ /* Allocated by frame_extra_info_zalloc () which is called /
+ initialized by DEPRECATED_INIT_EXTRA_FRAME_INFO */
struct frame_extra_info *extra_info;
/* If dwarf2 unwind frame informations is used, this structure holds all
related unwind data. */
struct context *context;
- /* Unwind cache shared between the unwind functions - they had
- better all agree as to the contents. */
- void *unwind_cache;
+ /* Prologue cache shared between the unwind functions. See
+ "frame-unwind.h" for more information. */
+ void *prologue_cache;
- /* See description above. The previous frame's registers. */
- frame_register_unwind_ftype *register_unwind;
+ /* The frame's unwinder. */
+ const struct frame_unwind *unwind;
- /* See description above. The previous frame's resume address.
- Save the previous PC in a local cache. */
- frame_pc_unwind_ftype *pc_unwind;
+ /* Cached copy of the previous frame's resume address. */
int pc_unwind_cache_p;
CORE_ADDR pc_unwind_cache;
+ /* This frame's ID. Note that the frame's ID, base and PC contain
+ redundant information. */
+ struct frame_id id;
+
/* Pointers to the next (down, inner, younger) and previous (up,
outer, older) frame_info's in the frame cache. */
struct frame_info *next; /* down, inner, younger */
#define SIZEOF_FRAME_SAVED_REGS \
(sizeof (CORE_ADDR) * (NUM_REGS+NUM_PSEUDO_REGS))
-extern void *frame_obstack_alloc (unsigned long size);
-extern void frame_saved_regs_zalloc (struct frame_info *);
+/* Allocate zero initialized memory from the frame cache obstack.
+ Appendices to the frame info (such as the unwind cache) should
+ allocate memory using this method. */
-/* Define a default FRAME_CHAIN_VALID, in the form that is suitable for most
- targets. If FRAME_CHAIN_VALID returns zero it means that the given frame
- is the outermost one and has no caller.
+extern void *frame_obstack_zalloc (unsigned long size);
+#define FRAME_OBSTACK_ZALLOC(TYPE) ((TYPE *) frame_obstack_zalloc (sizeof (TYPE)))
- XXXX - both default and alternate frame_chain_valid functions are
- deprecated. New code should use dummy frames and one of the
- generic functions. */
+/* If FRAME_CHAIN_VALID returns zero it means that the given frame
+ is the outermost one and has no caller. */
-extern int file_frame_chain_valid (CORE_ADDR, struct frame_info *);
-extern int func_frame_chain_valid (CORE_ADDR, struct frame_info *);
-extern int nonnull_frame_chain_valid (CORE_ADDR, struct frame_info *);
-extern int generic_file_frame_chain_valid (CORE_ADDR, struct frame_info *);
-extern int generic_func_frame_chain_valid (CORE_ADDR, struct frame_info *);
-extern void generic_save_dummy_frame_tos (CORE_ADDR sp);
+extern int frame_chain_valid (CORE_ADDR, struct frame_info *);
+extern void generic_save_dummy_frame_tos (CORE_ADDR sp);
#ifdef FRAME_FIND_SAVED_REGS
/* XXX - deprecated */
-#define FRAME_INIT_SAVED_REGS(FI) get_frame_saved_regs (FI, NULL)
-extern void get_frame_saved_regs (struct frame_info *,
- struct frame_saved_regs *);
+#define DEPRECATED_FRAME_INIT_SAVED_REGS(FI) deprecated_get_frame_saved_regs (FI, NULL)
+extern void deprecated_get_frame_saved_regs (struct frame_info *,
+ struct frame_saved_regs *);
#endif
extern struct block *get_frame_block (struct frame_info *,
extern CORE_ADDR get_pc_function_start (CORE_ADDR);
-extern struct block *block_for_pc (CORE_ADDR);
-
-extern struct block *block_for_pc_sect (CORE_ADDR, asection *);
-
extern int frameless_look_for_prologue (struct frame_info *);
extern void print_frame_args (struct symbol *, struct frame_info *,
extern void print_stack_frame (struct frame_info *, int, int);
-extern void print_only_stack_frame (struct frame_info *, int, int);
-
extern void show_stack_frame (struct frame_info *);
extern void print_frame_info (struct frame_info *, int, int, int);
/* NOTE: cagney/2002-06-26: Targets should no longer use this
function. Instead, the contents of a dummy frames registers can be
obtained by applying: frame_register_unwind to the dummy frame; or
- get_saved_register to the next outer frame. */
+ frame_register_unwind() to the next outer frame. */
extern char *deprecated_generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp);
int nargs, struct value **args,
struct type *type, int gcc_p);
+void generic_unwind_get_saved_register (char *raw_buffer,
+ int *optimizedp,
+ CORE_ADDR *addrp,
+ struct frame_info *frame,
+ int regnum,
+ enum lval_type *lvalp);
+
/* The function generic_get_saved_register() has been made obsolete.
- GET_SAVED_REGISTER now defaults to the recursive equivalent -
- generic_unwind_get_saved_register() - so there is no need to even
- set GET_SAVED_REGISTER. Architectures that need to override the
- register unwind mechanism should modify frame->unwind(). */
+ DEPRECATED_GET_SAVED_REGISTER now defaults to the recursive
+ equivalent - generic_unwind_get_saved_register() - so there is no
+ need to even set DEPRECATED_GET_SAVED_REGISTER. Architectures that
+ need to override the register unwind mechanism should modify
+ frame->unwind(). */
extern void deprecated_generic_get_saved_register (char *, int *, CORE_ADDR *,
struct frame_info *, int,
enum lval_type *);
extern void generic_save_call_dummy_addr (CORE_ADDR lo, CORE_ADDR hi);
-extern void get_saved_register (char *raw_buffer, int *optimized,
- CORE_ADDR * addrp,
- struct frame_info *frame,
- int regnum, enum lval_type *lval);
+/* FIXME: cagney/2003-02-02: Should be deprecated or replaced with a
+ function called frame_read_register_p(). This slightly weird (and
+ older) variant of frame_read_register() returns zero (indicating
+ the register is unavailable) if either: the register isn't cached;
+ or the register has been optimized out. Problem is, neither check
+ is exactly correct. A register can't be optimized out (it may not
+ have been saved as part of a function call); The fact that a
+ register isn't in the register cache doesn't mean that the register
+ isn't available (it could have been fetched from memory). */
extern int frame_register_read (struct frame_info *frame, int regnum,
void *buf);
extern struct frame_info *deprecated_selected_frame;
-/* NOTE: cagney/2002-11-28:
-
- These functions are used to explicitly create and set the inner
- most (current) frame vis:
-
- set_current_frame (create_new_frame (read_fp(), stop_pc)));
-
- Such code should be removed. Instead that task can be left to
- get_current_frame() which will update things on-demand.
-
- The only vague exception is found in "infcmd.c" (and a few
- architectures specific files) as part of the code implementing the
- command ``(gdb) frame FRAME PC''. There, the frame should be
- created/selected in a single shot. */
-
-extern void set_current_frame (struct frame_info *);
-extern struct frame_info *create_new_frame (CORE_ADDR, CORE_ADDR);
+/* Create a frame using the specified BASE and PC. */
+
+extern struct frame_info *create_new_frame (CORE_ADDR base, CORE_ADDR pc);
+
+
+/* Create/access the frame's `extra info'. The extra info is used by
+ older code to store information such as the analyzed prologue. The
+ zalloc() should only be called by the INIT_EXTRA_INFO method. */
+
+extern struct frame_extra_info *frame_extra_info_zalloc (struct frame_info *fi,
+ long size);
+extern struct frame_extra_info *get_frame_extra_info (struct frame_info *fi);
+
+/* Create/access the frame's `saved_regs'. The saved regs are used by
+ older code to store the address of each register (except for
+ SP_REGNUM where the value of the register in the previous frame is
+ stored). */
+extern CORE_ADDR *frame_saved_regs_zalloc (struct frame_info *);
+extern CORE_ADDR *get_frame_saved_regs (struct frame_info *);
+
+/* FIXME: cagney/2002-12-06: Has the PC in the current frame changed?
+ "infrun.c", Thanks to DECR_PC_AFTER_BREAK, can change the PC after
+ the initial frame create. This puts things back in sync. */
+extern void deprecated_update_frame_pc_hack (struct frame_info *frame,
+ CORE_ADDR pc);
+
+/* FIXME: cagney/2002-12-18: Has the frame's base changed? Or to be
+ more exact, whas that initial guess at the frame's base as returned
+ by read_fp() wrong. If it was, fix it. This shouldn't be
+ necessary since the code should be getting the frame's base correct
+ from the outset. */
+extern void deprecated_update_frame_base_hack (struct frame_info *frame,
+ CORE_ADDR base);
+
+/* FIXME: cagney/2003-01-04: Explicitly set the frame's saved_regs
+ and/or extra_info. Target code is allocating a fake frame and than
+ initializing that to get around the problem of, when creating the
+ inner most frame, there is no where to cache information such as
+ the prologue analysis. This is fixed by the new unwind mechanism -
+ even the inner most frame has somewhere to store things like the
+ prolog analysis (or at least will once the frame overhaul is
+ finished). */
+extern void deprecated_set_frame_saved_regs_hack (struct frame_info *frame,
+ CORE_ADDR *saved_regs);
+extern void deprecated_set_frame_extra_info_hack (struct frame_info *frame,
+ struct frame_extra_info *extra_info);
+
+/* FIXME: cagney/2003-01-04: Allocate a frame from the heap (rather
+ than the frame obstack). Targets do this as a way of saving the
+ prologue analysis from the inner most frame before that frame has
+ been created. By always creating a frame, this problem goes away. */
+extern struct frame_info *deprecated_frame_xmalloc (void);
+
+/* FIXME: cagney/2003-01-05: Allocate a frame, along with the
+ saved_regs and extra_info. Set up cleanups for all three. Same as
+ for deprecated_frame_xmalloc, targets are calling this when
+ creating a scratch `struct frame_info'. The frame overhaul makes
+ this unnecessary since all frame queries are parameterized with a
+ common cache parameter and a frame. */
+extern struct frame_info *deprecated_frame_xmalloc_with_cleanup (long sizeof_saved_regs,
+ long sizeof_extra_info);
+
+/* FIXME: cagney/2003-01-07: These are just nasty. Code shouldn't be
+ doing this. I suspect it dates back to the days when every field
+ of an allocated structure was explicitly initialized. */
+extern void deprecated_set_frame_next_hack (struct frame_info *fi,
+ struct frame_info *next);
+extern void deprecated_set_frame_prev_hack (struct frame_info *fi,
+ struct frame_info *prev);
+
+/* FIXME: cagney/2003-01-07: Instead of the dwarf2cfi having its own
+ dedicated `struct frame_info . context' field, the code should use
+ the per frame `unwind_cache' that is passed to the
+ frame_pc_unwind(), frame_register_unwind() and frame_id_unwind()
+ methods.
+
+ See "dummy-frame.c" for an example of how a cfi-frame object can be
+ implemented using this. */
+extern struct context *deprecated_get_frame_context (struct frame_info *fi);
+extern void deprecated_set_frame_context (struct frame_info *fi,
+ struct context *context);
+
+/* Return non-zero if the architecture is relying on legacy frame
+ code. */
+extern int legacy_frame_p (struct gdbarch *gdbarch);
#endif /* !defined (FRAME_H) */