diff options
-rw-r--r-- | gdb/ChangeLog | 21 | ||||
-rw-r--r-- | gdb/blockframe.c | 6 | ||||
-rw-r--r-- | gdb/dummy-frame.c | 15 | ||||
-rw-r--r-- | gdb/dummy-frame.h | 6 | ||||
-rw-r--r-- | gdb/frame.c | 51 | ||||
-rw-r--r-- | gdb/frame.h | 26 | ||||
-rw-r--r-- | gdb/stack.c | 2 |
7 files changed, 109 insertions, 18 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 397849b..2fbb8fd 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,24 @@ +2002-11-15 Andrew Cagney <ac131313@redhat.com> + + * frame.c (frame_pc_unwind): New function. + (frame_saved_regs_pc_unwind): New function. + (frame_register_unwind): Pass unwind_cache instead of + register_unwind_cache. + (set_unwind_by_pc): Add unwind_pc parameter, set. + (create_new_frame): Pass frame->pc_unwind to set_unwind_by_pc. + (get_prev_frame): Ditto. + * frame.h (frame_pc_unwind_ftype): Declare. + (struct frame_info): Add pc_unwind, pc_unwind_cache_p and + pc_unwind_cache. Rename register_unwind_cache to unwind_cache. + (frame_pc_unwind): Declare. + * dummy-frame.c (dummy_frame_pc_unwind): New function. + (struct dummy_frame): Add comment mentioning that values are for + previous frame. + * dummy-frame.h (dummy_frame_pc_unwind): Declare. + * blockframe.c (file_frame_chain_valid): Use frame_pc_unwind. + (generic_file_frame_chain_valid): Ditto. + * stack.c (frame_info): Ditto. + 2002-11-15 David Carlton <carlton@math.stanford.edu> * linespec.c (locate_first_half): New function. diff --git a/gdb/blockframe.c b/gdb/blockframe.c index 1a2a568..3e70b2a 100644 --- a/gdb/blockframe.c +++ b/gdb/blockframe.c @@ -49,7 +49,7 @@ int file_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe) { return ((chain) != 0 - && !inside_entry_file (FRAME_SAVED_PC (thisframe))); + && !inside_entry_file (frame_pc_unwind (thisframe))); } /* Use the alternate method of avoiding running up off the end of the @@ -753,12 +753,12 @@ pc_in_call_dummy_at_entry_point (CORE_ADDR pc, CORE_ADDR sp, int generic_file_frame_chain_valid (CORE_ADDR fp, struct frame_info *fi) { - if (PC_IN_CALL_DUMMY (FRAME_SAVED_PC (fi), fp, fp)) + if (PC_IN_CALL_DUMMY (frame_pc_unwind (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))); + && !inside_entry_file (frame_pc_unwind (fi))); } int diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c index ddc4db8..06dacbb 100644 --- a/gdb/dummy-frame.c +++ b/gdb/dummy-frame.c @@ -37,6 +37,8 @@ struct dummy_frame { struct dummy_frame *next; + /* These values belong to the caller (the previous frame, the frame + that this unwinds back to). */ CORE_ADDR pc; CORE_ADDR fp; CORE_ADDR sp; @@ -308,3 +310,16 @@ dummy_frame_register_unwind (struct frame_info *frame, void **cache, } } +CORE_ADDR +dummy_frame_pc_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 0; + return dummy->pc; +} + diff --git a/gdb/dummy-frame.h b/gdb/dummy-frame.h index bd4e199..d85fcfb 100644 --- a/gdb/dummy-frame.h +++ b/gdb/dummy-frame.h @@ -54,6 +54,12 @@ extern void dummy_frame_register_unwind (struct frame_info *frame, int *realnump, void *valuep); +/* Assuming that FRAME is a dummy, return the resume address for the + previous frame. */ + +extern CORE_ADDR dummy_frame_pc_unwind (struct frame_info *frame, + void **unwind_cache); + /* Return the regcache that belongs to the dummy-frame identifed by PC and FP, or NULL if no such frame exists. */ /* FIXME: cagney/2002-11-08: The function only exists because of diff --git a/gdb/frame.c b/gdb/frame.c index bfefc77..6cd1777 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -84,6 +84,17 @@ frame_find_by_id (struct frame_id id) return NULL; } +CORE_ADDR +frame_pc_unwind (struct frame_info *frame) +{ + if (!frame->pc_unwind_cache_p) + { + frame->pc_unwind_cache = frame->pc_unwind (frame, &frame->unwind_cache); + frame->pc_unwind_cache_p = 1; + } + return frame->pc_unwind_cache; +} + void frame_register_unwind (struct frame_info *frame, int regnum, int *optimizedp, enum lval_type *lvalp, @@ -124,7 +135,7 @@ frame_register_unwind (struct frame_info *frame, int regnum, } /* Ask this frame to unwind its register. */ - frame->register_unwind (frame, &frame->register_unwind_cache, regnum, + frame->register_unwind (frame, &frame->unwind_cache, regnum, optimizedp, lvalp, addrp, realnump, bufferp); } @@ -524,6 +535,12 @@ frame_saved_regs_register_unwind (struct frame_info *frame, void **cache, } } +static CORE_ADDR +frame_saved_regs_pc_unwind (struct frame_info *frame, void **cache) +{ + return FRAME_SAVED_PC (frame); +} + /* Function: get_saved_register Find register number REGNUM relative to FRAME and put its (raw, target format) contents in *RAW_BUFFER. @@ -627,18 +644,28 @@ 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) + frame_register_unwind_ftype **unwind_register, + frame_pc_unwind_ftype **unwind_pc) { if (!USE_GENERIC_DUMMY_FRAMES) - /* Still need to set this to something. The ``info frame'' code - calls this function to find out where the saved registers are. - Hopefully this is robust enough to stop any core dumps and - return vaguely correct values.. */ - *unwind = frame_saved_regs_register_unwind; + { + /* Still need to set this to something. The ``info frame'' code + calls this function to find out where the saved registers are. + Hopefully this is robust enough to stop any core dumps and + return vaguely correct values.. */ + *unwind_register = frame_saved_regs_register_unwind; + *unwind_pc = frame_saved_regs_pc_unwind; + } else if (PC_IN_CALL_DUMMY (pc, fp, fp)) - *unwind = dummy_frame_register_unwind; + { + *unwind_register = dummy_frame_register_unwind; + *unwind_pc = dummy_frame_pc_unwind; + } else - *unwind = frame_saved_regs_register_unwind; + { + *unwind_register = frame_saved_regs_register_unwind; + *unwind_pc = frame_saved_regs_pc_unwind; + } } /* Create an arbitrary (i.e. address specified by user) or innermost frame. @@ -666,7 +693,8 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) INIT_EXTRA_FRAME_INFO (0, fi); /* Select/initialize an unwind function. */ - set_unwind_by_pc (fi->pc, fi->frame, &fi->register_unwind); + set_unwind_by_pc (fi->pc, fi->frame, &fi->register_unwind, + &fi->pc_unwind); return fi; } @@ -913,7 +941,8 @@ get_prev_frame (struct frame_info *next_frame) (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. */ - set_unwind_by_pc (prev->pc, prev->frame, &prev->register_unwind); + set_unwind_by_pc (prev->pc, prev->frame, &prev->register_unwind, + &prev->pc_unwind); find_pc_partial_function (prev->pc, &name, (CORE_ADDR *) NULL, (CORE_ADDR *) NULL); diff --git a/gdb/frame.h b/gdb/frame.h index 70d85f1..a371a58 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -139,6 +139,12 @@ extern void frame_read_unsigned_register (struct frame_info *frame, extern int frame_map_name_to_regnum (const char *name, int strlen); extern const char *frame_map_regnum_to_name (int regnum); +/* Unwind the PC. Strictly speaking return the resume address of the + calling frame. For GDB, `pc' is the resume address and not a + specific register. */ + +extern CORE_ADDR frame_pc_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 @@ -163,6 +169,12 @@ typedef void (frame_register_unwind_ftype) (struct frame_info *frame, 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); + /* Describe the saved registers of a frame. */ #if defined (EXTRA_FRAME_INFO) || defined (FRAME_FIND_SAVED_REGS) @@ -252,10 +264,18 @@ struct frame_info related unwind data. */ struct context *context; - /* See description above. Return the register value for the - previous frame. */ + /* Unwind cache shared between the unwind functions - they had + better all agree as to the contents. */ + void *unwind_cache; + + /* See description above. The previous frame's registers. */ frame_register_unwind_ftype *register_unwind; - void *register_unwind_cache; + + /* See description above. The previous frame's resume address. + Save the previous PC in a local cache. */ + frame_pc_unwind_ftype *pc_unwind; + int pc_unwind_cache_p; + CORE_ADDR pc_unwind_cache; /* Pointers to the next (down, inner, younger) and previous (up, outer, older) frame_info's in the frame cache. */ diff --git a/gdb/stack.c b/gdb/stack.c index b9a3033..ba7edd5 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -866,7 +866,7 @@ frame_info (char *addr_exp, int from_tty) puts_filtered ("; "); wrap_here (" "); printf_filtered ("saved %s ", REGISTER_NAME (PC_REGNUM)); - print_address_numeric (FRAME_SAVED_PC (fi), 1, gdb_stdout); + print_address_numeric (frame_pc_unwind (fi), 1, gdb_stdout); printf_filtered ("\n"); { |