From c689142becccac9fa3b1f9833243048a50396ffe Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Fri, 13 Dec 2002 16:40:25 +0000 Subject: [PATCH] 2002-12-13 Andrew Cagney * frame.h (frame_id_unwind): Declare. (struct frame_info): Add fields id_unwind, id_unwind_cache_p and id_unwind_cache. (frame_id_unwind_ftype): Declare. * frame.c (frame_id_unwind): New function. (set_unwind_by_pc): Add unwind_id parameter. Initialized. (create_new_frame, get_prev_frame): Pass id_unwind to set_unwind_by_pc. (frame_saved_regs_id_unwind): New function. (frame_saved_regs_id_unwind): New function. * dummy-frame.c (dummy_frame_id_unwind): New function. (struct dummy_frame): Add field id. (generic_push_dummy_frame): Initialize `id'. * dummy-frame.h (dummy_frame_id_unwind): Declare. --- gdb/ChangeLog | 17 +++++++++++ gdb/dummy-frame.c | 16 +++++++++++ gdb/dummy-frame.h | 6 ++++ gdb/frame.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- gdb/frame.h | 16 +++++++++++ 5 files changed, 137 insertions(+), 3 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f789563..bd4af6a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,22 @@ 2002-12-13 Andrew Cagney + * frame.h (frame_id_unwind): Declare. + (struct frame_info): Add fields id_unwind, id_unwind_cache_p and + id_unwind_cache. + (frame_id_unwind_ftype): Declare. + * frame.c (frame_id_unwind): New function. + (set_unwind_by_pc): Add unwind_id parameter. Initialized. + (create_new_frame, get_prev_frame): Pass id_unwind to + set_unwind_by_pc. + (frame_saved_regs_id_unwind): New function. + (frame_saved_regs_id_unwind): New function. + * dummy-frame.c (dummy_frame_id_unwind): New function. + (struct dummy_frame): Add field id. + (generic_push_dummy_frame): Initialize `id'. + * dummy-frame.h (dummy_frame_id_unwind): Declare. + +2002-12-13 Andrew Cagney + * infcmd.c (run_stack_dummy): Create a frame ID directly and then pass that to set_momentary_breakpoint. Move comments to where they belong. diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c index deed9c3..fab10c0 100644 --- a/gdb/dummy-frame.c +++ b/gdb/dummy-frame.c @@ -43,6 +43,7 @@ struct dummy_frame CORE_ADDR fp; CORE_ADDR sp; CORE_ADDR top; + struct frame_id id; struct regcache *regcache; /* Address range of the call dummy code. Look for PC in the range @@ -232,6 +233,7 @@ generic_push_dummy_frame (void) dummy_frame->sp = read_sp (); dummy_frame->top = 0; dummy_frame->fp = fp; + dummy_frame->id = get_frame_id (get_current_frame ()); regcache_cpy (dummy_frame->regcache, current_regcache); dummy_frame->next = dummy_frame_stack; dummy_frame_stack = dummy_frame; @@ -342,3 +344,17 @@ dummy_frame_pc_unwind (struct frame_info *frame, return dummy->pc; } + +struct frame_id +dummy_frame_id_unwind (struct frame_info *frame, + void **cache) +{ + struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache); + /* Oops! In a dummy-frame but can't find the stack dummy. Pretend + that the frame doesn't unwind. Should this function instead + return a has-no-caller indication? */ + if (dummy == NULL) + return null_frame_id; + return dummy->id; +} + diff --git a/gdb/dummy-frame.h b/gdb/dummy-frame.h index 7f3aee8..cfa2709 100644 --- a/gdb/dummy-frame.h +++ b/gdb/dummy-frame.h @@ -60,6 +60,12 @@ extern void dummy_frame_register_unwind (struct frame_info *frame, extern CORE_ADDR dummy_frame_pc_unwind (struct frame_info *frame, void **unwind_cache); +/* Assuming that FRAME is a dummy, return the ID of the calling frame + (the frame that the dummy has the saved state of). */ + +extern struct frame_id dummy_frame_id_unwind (struct frame_info *frame, + void **unwind_cache); + /* Does the PC fall in a dummy frame? This function is used by "frame.c" when creating a new `struct diff --git a/gdb/frame.c b/gdb/frame.c index 29ebfbe..b23d517 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -133,6 +133,19 @@ frame_pc_unwind (struct frame_info *frame) return frame->pc_unwind_cache; } +struct frame_id +frame_id_unwind (struct frame_info *frame) +{ + if (!frame->id_unwind_cache_p) + { + frame->id_unwind_cache = + frame->id_unwind (frame, &frame->unwind_cache); + frame->id_unwind_cache_p = 1; + } + return frame->id_unwind_cache; +} + + void frame_register_unwind (struct frame_info *frame, int regnum, int *optimizedp, enum lval_type *lvalp, @@ -632,6 +645,68 @@ frame_saved_regs_pc_unwind (struct frame_info *frame, void **cache) return FRAME_SAVED_PC (frame); } +static struct frame_id +frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache) +{ + int fromleaf; + struct frame_id id; + + if (next_frame->next == NULL) + /* 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 (next_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. */ + id.base = get_frame_base (next_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. */ + id.base = FRAME_CHAIN (next_frame); + + /* FIXME: cagney/2002-06-08: There should be two tests here. + The first would check for a valid frame chain based on a user + selectable policy. The default being ``stop at main'' (as + implemented by generic_func_frame_chain_valid()). Other + policies would be available - stop at NULL, .... The second + test, if provided by the target architecture, would check for + more exotic cases - most target architectures wouldn't bother + with this second case. */ + if (!FRAME_CHAIN_VALID (id.base, next_frame)) + return null_frame_id; + } + if (id.base == 0) + return null_frame_id; + + /* FIXME: cagney/2002-06-08: This should probably return the frame's + function and not the PC (a.k.a. resume address). */ + id.pc = frame_pc_unwind (next_frame); + return id; +} + /* Function: get_saved_register Find register number REGNUM relative to FRAME and put its (raw, target format) contents in *RAW_BUFFER. @@ -736,7 +811,8 @@ deprecated_generic_get_saved_register (char *raw_buffer, int *optimized, static void set_unwind_by_pc (CORE_ADDR pc, CORE_ADDR fp, frame_register_unwind_ftype **unwind_register, - frame_pc_unwind_ftype **unwind_pc) + frame_pc_unwind_ftype **unwind_pc, + frame_id_unwind_ftype **unwind_id) { if (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES) { @@ -746,6 +822,7 @@ set_unwind_by_pc (CORE_ADDR pc, CORE_ADDR fp, return vaguely correct values.. */ *unwind_register = frame_saved_regs_register_unwind; *unwind_pc = frame_saved_regs_pc_unwind; + *unwind_id = frame_saved_regs_id_unwind; } else if (DEPRECATED_PC_IN_CALL_DUMMY_P () ? DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0) @@ -753,11 +830,13 @@ set_unwind_by_pc (CORE_ADDR pc, CORE_ADDR fp, { *unwind_register = dummy_frame_register_unwind; *unwind_pc = dummy_frame_pc_unwind; + *unwind_id = dummy_frame_id_unwind; } else { *unwind_register = frame_saved_regs_register_unwind; *unwind_pc = frame_saved_regs_pc_unwind; + *unwind_id = frame_saved_regs_id_unwind; } } @@ -809,7 +888,7 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) /* Select/initialize an unwind function. */ set_unwind_by_pc (fi->pc, fi->frame, &fi->register_unwind, - &fi->pc_unwind); + &fi->pc_unwind, &fi->id_unwind); return fi; } @@ -1064,7 +1143,7 @@ get_prev_frame (struct frame_info *next_frame) check things like the debug info at that point (dwarf2cfi?) and use that to decide how the frame should be unwound. */ set_unwind_by_pc (prev->pc, prev->frame, &prev->register_unwind, - &prev->pc_unwind); + &prev->pc_unwind, &prev->id_unwind); /* NOTE: cagney/2002-11-18: The code segments, found in create_new_frame and get_prev_frame(), that initializes the diff --git a/gdb/frame.h b/gdb/frame.h index 5a45502..0fd305e 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -298,6 +298,10 @@ extern const char *frame_map_regnum_to_name (int regnum); extern CORE_ADDR frame_pc_unwind (struct frame_info *frame); +/* Unwind the frame ID. Return an ID that uniquely identifies the + caller's frame. */ +extern struct frame_id frame_id_unwind (struct frame_info *frame); + /* Return the location (and possibly value) of REGNUM for the previous (older, up) frame. All parameters except VALUEP can be assumed to @@ -328,6 +332,12 @@ typedef void (frame_register_unwind_ftype) (struct frame_info *frame, typedef CORE_ADDR (frame_pc_unwind_ftype) (struct frame_info *frame, void **unwind_cache); +/* Same as for registers above, but return the ID of the frame that + called this one. */ + +typedef struct frame_info (frame_id_unwind_ftype) (struct frame_info *frame, + void **unwind_cache); + /* Describe the saved registers of a frame. */ #if defined (EXTRA_FRAME_INFO) || defined (FRAME_FIND_SAVED_REGS) @@ -424,6 +434,12 @@ struct frame_info int pc_unwind_cache_p; CORE_ADDR pc_unwind_cache; + /* See description above. The previous frame's resume address. + Save the previous PC in a local cache. */ + frame_id_unwind_ftype *id_unwind; + int id_unwind_cache_p; + struct frame_id id_unwind_cache; + /* 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 */ -- 2.7.4