2003-01-09 Andrew Cagney * dummy-frame.h (dummy_frame_id_unwind): Update. (dummy_frame_pc_unwind): Update. (dummy_frame_register_unwind): Update. * dummy-frame.c: Update. * frame.c (create_new_frame): Set next to a sentinal frame. (create_sentinel_frame): New function. (frame_id_unwind): Update id_unwind call. (frame_saved_regs_register_unwind): Update cache parameter. (frame_saved_regs_pc_unwind): Update cache parameter. (frame_saved_regs_id_unwind): Update cache and id parameters. * frame.h (frame_id_unwind_ftype): Return the frame ID using a reference parameter. (struct frame_unwind_cache): Declare. (frame_id_unwind_ftype, frame_pc_unwind_ftype, frame_register_unwind_ftype): Change the unwind cache_type to `struct frame_unwind_cache'. (struct frame_info): Change type of unwind_cache to `struct frame_unwind_cache'. * frame.c (get_next_frame): Don't go beyond the inner-most frame. (frame_register_unwind): Assume that there is always a next frame. (frame_register): Ditto. (generic_unwind_get_saved_register): Ditto. * frame.h (frame_type): Add SENTINEL_FRAME. * Makefile.in (frame.o): Update dependencies. * frame.h (FRAME_OBSTACK_ZALLOC): Define. * Makefile.in (sentinel-frame.o): Specify dependencies. (sentinel_frame_h): Define. (SFILES): Add sentinel-frame.c. (COMMON_OBS): Add sentinel-frame.o. * sentinel-frame.c: New file. * sentinel-frame.h: New file. Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.311 diff -u -r1.311 Makefile.in --- Makefile.in 9 Jan 2003 18:03:35 -0000 1.311 +++ Makefile.in 10 Jan 2003 02:08:38 -0000 @@ -521,7 +521,8 @@ objfiles.c osabi.c \ p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c printcmd.c \ regcache.c reggroups.c remote.c \ - scm-exp.c scm-lang.c scm-valprint.c serial.c ser-unix.c source.c \ + scm-exp.c scm-lang.c scm-valprint.c sentinel-frame.c \ + serial.c ser-unix.c source.c \ stabsread.c stack.c std-regs.c symfile.c symmisc.c symtab.c \ target.c thread.c top.c tracepoint.c typeprint.c \ tui/tui.c tui/tui.h tui/tuiCommand.c tui/tuiCommand.h \ @@ -678,6 +679,7 @@ remote_h = remote.h scm_lang_h = scm-lang.h $(scm_tags_h) scm_tags_h = scm-tags.h +sentinel_frame_h = sentinel-frame.h ser_unix_h = ser-unix.h serial_h = serial.h sh_tdep_h = sh-tdep.h @@ -831,6 +833,7 @@ ui-file.o \ frame.o doublest.o \ gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o \ + sentinel-frame.o \ reggroups.o OBS = $(COMMON_OBS) $(ANNOTATE_OBS) @@ -1679,7 +1682,7 @@ frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \ $(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(builtin_regs_h) \ $(gdb_obstack_h) $(dummy_frame_h) $(gdbcore_h) $(annotate_h) \ - $(language_h) + $(language_h) $(sentinel_frame_h) frv-tdep.o: frv-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \ $(arch_utils_h) $(regcache_h) gcore.o: gcore.c $(defs_h) $(cli_decode_h) $(inferior_h) $(gdbcore_h) \ @@ -2110,6 +2113,8 @@ scm-valprint.o: scm-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \ $(expression_h) $(parser_defs_h) $(language_h) $(value_h) \ $(scm_lang_h) $(valprint_h) $(gdbcore_h) +sentinel-frame.o: sentinel-frame.c $(defs_h) $(regcache_h) \ + $(sentinel_frame_h) $(inferior_h) ser-e7kpc.o: ser-e7kpc.c $(defs_h) $(serial_h) $(gdb_string_h) ser-go32.o: ser-go32.c $(defs_h) $(gdbcmd_h) $(serial_h) $(gdb_string_h) ser-pipe.o: ser-pipe.c $(defs_h) $(serial_h) $(ser_unix_h) $(gdb_vfork_h) \ Index: dummy-frame.c =================================================================== RCS file: /cvs/src/src/gdb/dummy-frame.c,v retrieving revision 1.7 diff -u -r1.7 dummy-frame.c --- dummy-frame.c 13 Dec 2002 16:40:25 -0000 1.7 +++ dummy-frame.c 10 Jan 2003 02:08:38 -0000 @@ -33,9 +33,9 @@ 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 frame_unwind_cache { - struct dummy_frame *next; + struct frame_unwind_cache *next; /* These values belong to the caller (the previous frame, the frame that this unwinds back to). */ @@ -52,7 +52,7 @@ CORE_ADDR call_hi; }; -static struct dummy_frame *dummy_frame_stack = NULL; +static struct frame_unwind_cache *dummy_frame_stack = NULL; /* Function: find_dummy_frame(pc, fp, sp) @@ -61,10 +61,10 @@ adjust for DECR_PC_AFTER_BREAK. This is because it is only legal to call this function after the PC has been adjusted. */ -static struct dummy_frame * +static struct frame_unwind_cache * find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp) { - struct dummy_frame *dummyframe; + struct frame_unwind_cache *dummyframe; for (dummyframe = dummy_frame_stack; dummyframe != NULL; dummyframe = dummyframe->next) @@ -103,8 +103,9 @@ return NULL; } -struct dummy_frame * -cached_find_dummy_frame (struct frame_info *frame, void **cache) +struct frame_unwind_cache * +cached_find_dummy_frame (struct frame_info *frame, + struct frame_unwind_cache **cache) { if ((*cache) == NULL) (*cache) = find_dummy_frame (get_frame_pc (frame), get_frame_base (frame)); @@ -114,7 +115,7 @@ struct regcache * generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp) { - struct dummy_frame *dummy = find_dummy_frame (pc, fp); + struct frame_unwind_cache *dummy = find_dummy_frame (pc, fp); if (dummy != NULL) return dummy->regcache; else @@ -158,7 +159,7 @@ int pc_in_dummy_frame (CORE_ADDR pc) { - struct dummy_frame *dummyframe; + struct frame_unwind_cache *dummyframe; for (dummyframe = dummy_frame_stack; dummyframe != NULL; dummyframe = dummyframe->next) @@ -207,7 +208,7 @@ void generic_push_dummy_frame (void) { - struct dummy_frame *dummy_frame; + struct frame_unwind_cache *dummy_frame; CORE_ADDR fp = get_frame_base (get_current_frame ()); /* check to see if there are stale dummy frames, @@ -226,7 +227,7 @@ else dummy_frame = dummy_frame->next; - dummy_frame = xmalloc (sizeof (struct dummy_frame)); + dummy_frame = XMALLOC (struct frame_unwind_cache); dummy_frame->regcache = regcache_xmalloc (current_gdbarch); dummy_frame->pc = read_pc (); @@ -275,7 +276,7 @@ void generic_pop_dummy_frame (void) { - struct dummy_frame *dummy_frame = dummy_frame_stack; + struct frame_unwind_cache *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? */ @@ -305,12 +306,13 @@ register value is taken from the local copy of the register buffer. */ void -dummy_frame_register_unwind (struct frame_info *frame, void **cache, +dummy_frame_register_unwind (struct frame_info *frame, + struct frame_unwind_cache **cache, int regnum, int *optimized, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnum, void *bufferp) { - struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache); + struct frame_unwind_cache *dummy = cached_find_dummy_frame (frame, cache); gdb_assert (dummy != NULL); /* Describe the register's location. Generic dummy frames always @@ -333,9 +335,9 @@ CORE_ADDR dummy_frame_pc_unwind (struct frame_info *frame, - void **cache) + struct frame_unwind_cache **cache) { - struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache); + struct frame_unwind_cache *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? */ @@ -345,16 +347,18 @@ } -struct frame_id +void dummy_frame_id_unwind (struct frame_info *frame, - void **cache) + struct frame_unwind_cache **cache, + struct frame_id *id) { - struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache); + struct frame_unwind_cache *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; + *id = null_frame_id; + else + *id = dummy->id; } Index: dummy-frame.h =================================================================== RCS file: /cvs/src/src/gdb/dummy-frame.h,v retrieving revision 1.5 diff -u -r1.5 dummy-frame.h --- dummy-frame.h 13 Dec 2002 16:40:25 -0000 1.5 +++ dummy-frame.h 10 Jan 2003 02:08:38 -0000 @@ -24,6 +24,8 @@ struct frame_info; struct regcache; +struct frame_id; +struct frame_unwind_cache; /* GENERIC DUMMY FRAMES @@ -46,7 +48,7 @@ previous frame. */ extern void dummy_frame_register_unwind (struct frame_info *frame, - void **unwind_cache, + struct frame_unwind_cache **unwind_cache, int regnum, int *optimized, enum lval_type *lvalp, @@ -58,13 +60,14 @@ previous frame. */ extern CORE_ADDR dummy_frame_pc_unwind (struct frame_info *frame, - void **unwind_cache); + struct frame_unwind_cache **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); +extern void dummy_frame_id_unwind (struct frame_info *frame, + struct frame_unwind_cache **unwind_cache, + struct frame_id *id); /* Does the PC fall in a dummy frame? Index: frame.c =================================================================== RCS file: /cvs/src/src/gdb/frame.c,v retrieving revision 1.56 diff -u -r1.56 frame.c --- frame.c 9 Jan 2003 18:53:20 -0000 1.56 +++ frame.c 10 Jan 2003 02:08:38 -0000 @@ -31,6 +31,7 @@ #include "builtin-regs.h" #include "gdb_obstack.h" #include "dummy-frame.h" +#include "sentinel-frame.h" #include "gdbcore.h" #include "annotate.h" #include "language.h" @@ -138,8 +139,7 @@ { if (!frame->id_unwind_cache_p) { - frame->id_unwind_cache = - frame->id_unwind (frame, &frame->unwind_cache); + frame->id_unwind (frame, &frame->unwind_cache, &frame->id_unwind_cache); frame->id_unwind_cache_p = 1; } return frame->id_unwind_cache; @@ -161,29 +161,11 @@ gdb_assert (realnump != NULL); /* gdb_assert (bufferp != NULL); */ - /* NOTE: cagney/2002-04-14: It would be nice if, instead of a - special case, there was always an inner frame dedicated to the - hardware registers. Unfortunatly, there is too much unwind code - around that looks up/down the frame chain while making the - assumption that each frame level is using the same unwind code. */ - - if (frame == NULL) - { - /* We're in the inner-most frame, get the value direct from the - register cache. */ - *optimizedp = 0; - *lvalp = lval_register; - /* ULGH! Code uses the offset into the raw register byte array - as a way of identifying a register. */ - *addrp = REGISTER_BYTE (regnum); - /* Should this code test ``register_cached (regnum) < 0'' and do - something like set realnum to -1 when the register isn't - available? */ - *realnump = regnum; - if (bufferp) - deprecated_read_register_gen (regnum, bufferp); - return; - } + /* NOTE: cagney/2002-11-27: A program trying to unwind a NULL frame + is broken. There is always a frame. If there, for some reason, + isn't, there is some pretty busted code as it should have + detected the problem before calling here. */ + gdb_assert (frame != NULL); /* Ask this frame to unwind its register. */ frame->register_unwind (frame, &frame->unwind_cache, regnum, @@ -229,25 +211,11 @@ return; } - /* Reached the the bottom (youngest, inner most) of the frame chain - (youngest, inner most) frame, go direct to the hardware register - cache (do not pass go, do not try to cache the value, ...). The - unwound value would have been cached in frame->next but that - doesn't exist. This doesn't matter as the hardware register - cache is stopping any unnecessary accesses to the target. */ - - /* NOTE: cagney/2002-04-14: It would be nice if, instead of a - special case, there was always an inner frame dedicated to the - hardware registers. Unfortunatly, there is too much unwind code - around that looks up/down the frame chain while making the - assumption that each frame level is using the same unwind code. */ - - if (frame == NULL) - frame_register_unwind (NULL, regnum, optimizedp, lvalp, addrp, realnump, - bufferp); - else - frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp, - realnump, bufferp); + /* Obtain the register value by unwinding the register from the next + (more inner frame). */ + gdb_assert (frame != NULL && frame->next != NULL); + frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp, + realnump, bufferp); } void @@ -337,25 +305,9 @@ if (addrp == NULL) addrp = &addrx; - /* Reached the the bottom (youngest, inner most) of the frame chain - (youngest, inner most) frame, go direct to the hardware register - cache (do not pass go, do not try to cache the value, ...). The - unwound value would have been cached in frame->next but that - doesn't exist. This doesn't matter as the hardware register - cache is stopping any unnecessary accesses to the target. */ - - /* NOTE: cagney/2002-04-14: It would be nice if, instead of a - special case, there was always an inner frame dedicated to the - hardware registers. Unfortunatly, there is too much unwind code - around that looks up/down the frame chain while making the - assumption that each frame level is using the same unwind code. */ - - if (frame == NULL) - frame_register_unwind (NULL, regnum, optimizedp, lvalp, addrp, &realnumx, - raw_buffer); - else - frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp, - &realnumx, raw_buffer); + gdb_assert (frame != NULL && frame->next != NULL); + frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp, + &realnumx, raw_buffer); } void @@ -445,6 +397,21 @@ return builtin_reg_map_regnum_to_name (regnum); } +/* Create the sentinel frame. */ + +struct frame_info * +create_sentinel_frame (struct regcache *regcache) +{ + struct frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info); + frame->type = SENTINEL_FRAME; + frame->level = -1; + frame->unwind_cache = sentinel_frame_cache (regcache); + frame->pc_unwind = sentinel_frame_pc_unwind; + frame->id_unwind = sentinel_frame_id_unwind; + frame->register_unwind = sentinel_frame_register_unwind; + return frame; +} + /* Info about the innermost stack frame (contents of FP register) */ static struct frame_info *current_frame; @@ -555,8 +522,14 @@ If the value isn't here AND a value is needed, try the next inner most frame. */ +struct frame_unwind_cache +{ + void *regs[1]; +}; + static void -frame_saved_regs_register_unwind (struct frame_info *frame, void **cache, +frame_saved_regs_register_unwind (struct frame_info *frame, + struct frame_unwind_cache **cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *bufferp) @@ -601,22 +574,22 @@ #if 1 /* Save each register value, as it is read in, in a frame based cache. */ - void **regs = (*cache); - if (regs == NULL) + if ((*cache) == NULL) { int sizeof_cache = ((NUM_REGS + NUM_PSEUDO_REGS) * sizeof (void *)); - regs = frame_obstack_zalloc (sizeof_cache); - (*cache) = regs; + (*cache) = frame_obstack_zalloc (sizeof_cache); } - if (regs[regnum] == NULL) + if ((*cache)->regs[regnum] == NULL) { - regs[regnum] + (*cache)->regs[regnum] = frame_obstack_zalloc (REGISTER_RAW_SIZE (regnum)); - read_memory (frame->saved_regs[regnum], regs[regnum], + read_memory (frame->saved_regs[regnum], + (*cache)->regs[regnum], REGISTER_RAW_SIZE (regnum)); } - memcpy (bufferp, regs[regnum], REGISTER_RAW_SIZE (regnum)); + memcpy (bufferp, (*cache)->regs[regnum], + REGISTER_RAW_SIZE (regnum)); #else /* Read the value in from memory. */ read_memory (frame->saved_regs[regnum], bufferp, @@ -646,16 +619,18 @@ } static CORE_ADDR -frame_saved_regs_pc_unwind (struct frame_info *frame, void **cache) +frame_saved_regs_pc_unwind (struct frame_info *frame, + struct frame_unwind_cache **cache) { return FRAME_SAVED_PC (frame); } -static struct frame_id -frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache) +static void +frame_saved_regs_id_unwind (struct frame_info *next_frame, + struct frame_unwind_cache **cache, + struct frame_id *id) { int fromleaf; - struct frame_id id; if (next_frame->next == NULL) /* FIXME: 2002-11-09: Frameless functions can occure anywhere in @@ -673,7 +648,7 @@ /* 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); + id->base = get_frame_base (next_frame); else { /* Two macros defined in tm.h specify the machine-dependent @@ -691,18 +666,24 @@ 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); + id->base = FRAME_CHAIN (next_frame); - if (!frame_chain_valid (id.base, next_frame)) - return null_frame_id; + if (!frame_chain_valid (id->base, next_frame)) + { + *id = null_frame_id; + return; + } + } + if (id->base == 0) + { + *id = null_frame_id; + return; } - 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; + id->pc = frame_pc_unwind (next_frame); + return; } /* Function: get_saved_register @@ -851,6 +832,7 @@ fi->frame = addr; fi->pc = pc; + fi->next = create_sentinel_frame (current_regcache); /* NOTE: cagney/2002-11-18: The code segments, found in create_new_frame and get_prev_frame(), that initializes the frames type is subtly different. The latter only updates ->type @@ -892,7 +874,12 @@ struct frame_info * get_next_frame (struct frame_info *frame) { - return frame->next; + /* Don't fall off the bottom of the frame chain. This code has an + extra magic frame, don't expose that externally. */ + if (frame->level > 0) + return frame->next; + else + return NULL; } /* Flush the entire frame cache. */ Index: frame.h =================================================================== RCS file: /cvs/src/src/gdb/frame.h,v retrieving revision 1.59 diff -u -r1.59 frame.h --- frame.h 9 Jan 2003 18:53:21 -0000 1.59 +++ frame.h 10 Jan 2003 02:08:39 -0000 @@ -29,6 +29,9 @@ struct frame_info; +/* The frame unwind cache object. */ +struct frame_unwind_cache; + /* 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. It of course assumes that the @@ -229,7 +232,10 @@ DUMMY_FRAME, /* In a signal handler, various OSs handle this in various ways. The main thing is that the frame may be far from normal. */ - SIGTRAMP_FRAME + SIGTRAMP_FRAME, + /* The sentinel frame. Marks the inner-most end of the chain of + frames. */ + SENTINEL_FRAME }; extern enum frame_type get_frame_type (struct frame_info *); @@ -318,7 +324,7 @@ in the register "i1" in this FRAME. */ typedef void (frame_register_unwind_ftype) (struct frame_info *frame, - void **unwind_cache, + struct frame_unwind_cache **unwind_cache, int regnum, int *optimized, enum lval_type *lvalp, @@ -330,13 +336,14 @@ calling frame would resume. */ typedef CORE_ADDR (frame_pc_unwind_ftype) (struct frame_info *frame, - void **unwind_cache); + struct frame_unwind_cache **unwind_cache); /* Same as for registers above, but return the ID of the frame that called this one. */ -typedef struct frame_id (frame_id_unwind_ftype) (struct frame_info *frame, - void **unwind_cache); +typedef void (frame_id_unwind_ftype) (struct frame_info *frame, + struct frame_unwind_cache **unwind_cache, + struct frame_id *id); /* Describe the saved registers of a frame. */ @@ -423,7 +430,7 @@ /* Unwind cache shared between the unwind functions - they had better all agree as to the contents. */ - void *unwind_cache; + struct frame_unwind_cache *unwind_cache; /* See description above. The previous frame's registers. */ frame_register_unwind_ftype *register_unwind; @@ -477,6 +484,7 @@ allocate memory using this method. */ extern void *frame_obstack_zalloc (unsigned long size); +#define FRAME_OBSTACK_ZALLOC(TYPE) ((TYPE *) frame_obstack_zalloc (sizeof (TYPE))) /* If FRAME_CHAIN_VALID returns zero it means that the given frame is the outermost one and has no caller. */