diff options
author | Andrew Cagney <cagney@redhat.com> | 2003-01-10 15:22:39 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2003-01-10 15:22:39 +0000 |
commit | 38c4f67e850d9f0e4ce517beb1d9fe18ffeca1d5 (patch) | |
tree | 70a9b761f4dd631ae59a7a23c74b1e9589f5fb06 | |
parent | 812e900cfcaad5c1a17d6728e204cbf34d4eb557 (diff) | |
download | gdb-38c4f67e850d9f0e4ce517beb1d9fe18ffeca1d5.zip gdb-38c4f67e850d9f0e4ce517beb1d9fe18ffeca1d5.tar.gz gdb-38c4f67e850d9f0e4ce517beb1d9fe18ffeca1d5.tar.bz2 |
2003-01-10 Andrew Cagney <ac131313@redhat.com>
* sentinel-frame.c (sentinel_frame_register_unwind): Correctly set
LVALP and ADDRP.
* frame.c: Include "ui-out.h".
* frame.c (frame_type_from_pc): New function.
(create_new_frame): Use.
(set_unwind_by_pc): Drop unused frame parameter.
(deprecated_get_prev_frame): Rename old get_prev_frame.
(get_prev_frame): Rewrite. Unwind the PC first. Use
frame_id_unwind.
* 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.
-rw-r--r-- | gdb/ChangeLog | 57 | ||||
-rw-r--r-- | gdb/Makefile.in | 9 | ||||
-rw-r--r-- | gdb/dummy-frame.c | 46 | ||||
-rw-r--r-- | gdb/dummy-frame.h | 11 | ||||
-rw-r--r-- | gdb/frame.c | 403 | ||||
-rw-r--r-- | gdb/frame.h | 20 |
6 files changed, 368 insertions, 178 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 11ca878..ec82762 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,60 @@ +2003-01-10 Andrew Cagney <ac131313@redhat.com> + + * sentinel-frame.c (sentinel_frame_register_unwind): Correctly set + LVALP and ADDRP. + + * frame.c: Include "ui-out.h". + +2003-01-09 Andrew Cagney <ac131313@redhat.com> + + * frame.c (frame_type_from_pc): New function. + (create_new_frame): Use. + (set_unwind_by_pc): Drop unused frame parameter. + (deprecated_get_prev_frame): Rename old get_prev_frame. + (get_prev_frame): Rewrite. Unwind the PC first. Use + frame_id_unwind. + +2003-01-09 Andrew Cagney <ac131313@redhat.com> + + * 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. + 2003-01-09 Daniel Jacobowitz <drow@mvista.com> * lin-lwp.c (child_wait): Ignore exit statuses for processes other diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 057405f..84f1d74 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -521,7 +521,8 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ 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_utils_h = remote-utils.h $(target_h) 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 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \ 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 @@ fork-child.o: fork-child.c $(defs_h) $(gdb_string_h) $(frame_h) \ 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) $(ui_out_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-lang.o: scm-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \ 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) \ diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c index fab10c0..a1abc29 100644 --- a/gdb/dummy-frame.c +++ b/gdb/dummy-frame.c @@ -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 @@ struct dummy_frame 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 @@ static struct dummy_frame *dummy_frame_stack = NULL; 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 @@ find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp) 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 @@ cached_find_dummy_frame (struct frame_info *frame, void **cache) 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 @@ generic_pc_in_call_dummy (CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR fp) 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 @@ deprecated_read_register_dummy (CORE_ADDR pc, CORE_ADDR fp, int regno) 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 @@ generic_push_dummy_frame (void) 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 @@ generic_pop_current_frame (void (*popper) (struct frame_info * frame)) 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 @@ generic_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs, 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 @@ dummy_frame_register_unwind (struct frame_info *frame, void **cache, 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 @@ dummy_frame_pc_unwind (struct frame_info *frame, } -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; } diff --git a/gdb/dummy-frame.h b/gdb/dummy-frame.h index cfa2709..7743c8e 100644 --- a/gdb/dummy-frame.h +++ b/gdb/dummy-frame.h @@ -24,6 +24,8 @@ struct frame_info; struct regcache; +struct frame_id; +struct frame_unwind_cache; /* GENERIC DUMMY FRAMES @@ -46,7 +48,7 @@ struct regcache; 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 @@ extern void dummy_frame_register_unwind (struct frame_info *frame, 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? diff --git a/gdb/frame.c b/gdb/frame.c index acc163e..79d0ee6 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -31,9 +31,11 @@ #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" +#include "ui-out.h" /* Return a frame uniq ID that can be used to, later, re-find the frame. */ @@ -138,8 +140,7 @@ 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 (frame, &frame->unwind_cache, &frame->id_unwind_cache); frame->id_unwind_cache_p = 1; } return frame->id_unwind_cache; @@ -161,29 +162,11 @@ frame_register_unwind (struct frame_info *frame, int regnum, 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 +212,11 @@ frame_register (struct frame_info *frame, int regnum, 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 +306,9 @@ generic_unwind_get_saved_register (char *raw_buffer, 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 +398,21 @@ frame_map_regnum_to_name (int regnum) 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; @@ -479,15 +447,33 @@ get_frame_saved_regs (struct frame_info *fi) /* Return the innermost (currently executing) stack frame. */ +static int +unwind_to_current_frame (struct ui_out *ui_out, void *args) +{ + current_frame = get_prev_frame (args); + return 0; +} + struct frame_info * get_current_frame (void) { + if (!target_has_stack) + error ("No stack."); + if (!target_has_registers) + error ("No registers."); + if (!target_has_memory) + error ("No memory."); if (current_frame == NULL) { - if (target_has_stack) - current_frame = create_new_frame (read_fp (), read_pc ()); - else - error ("No stack."); + struct frame_info *sentinel_frame = + create_sentinel_frame (current_regcache); + if (catch_exceptions (uiout, unwind_to_current_frame, sentinel_frame, + NULL, RETURN_MASK_ERROR) < 0) + { + /* Oops! Fake a current frame? Is this useful? It has a PC + of zero, for instance. */ + current_frame = sentinel_frame; + } } return current_frame; } @@ -555,8 +541,14 @@ select_frame (struct frame_info *fi) 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 +593,22 @@ frame_saved_regs_register_unwind (struct frame_info *frame, void **cache, #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 +638,18 @@ 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) +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 +667,7 @@ frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache) /* 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 +685,24 @@ frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache) 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 @@ -807,7 +807,7 @@ deprecated_generic_get_saved_register (char *raw_buffer, int *optimized, demand, initialize the ->context object. */ static void -set_unwind_by_pc (CORE_ADDR pc, CORE_ADDR fp, +set_unwind_by_pc (CORE_ADDR pc, frame_register_unwind_ftype **unwind_register, frame_pc_unwind_ftype **unwind_pc, frame_id_unwind_ftype **unwind_id) @@ -838,6 +838,29 @@ set_unwind_by_pc (CORE_ADDR pc, CORE_ADDR fp, } } +/* Determine the frame's type based on its PC. */ + +static enum frame_type +frame_type_from_pc (CORE_ADDR pc) +{ + /* FIXME: cagney/2002-11-24: Can't yet directly call + pc_in_dummy_frame() as some architectures don't set + PC_IN_CALL_DUMMY() to generic_pc_in_call_dummy() (remember the + latter is implemented by simply calling pc_in_dummy_frame). */ + if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES + && DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0)) + return DUMMY_FRAME; + else + { + char *name; + find_pc_partial_function (pc, &name, NULL, NULL); + if (PC_IN_SIGTRAMP (pc, name)) + return SIGTRAMP_FRAME; + else + return NORMAL_FRAME; + } +} + /* Create an arbitrary (i.e. address specified by user) or innermost frame. Always returns a non-NULL value. */ @@ -851,37 +874,15 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) fi->frame = addr; fi->pc = pc; - /* 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 - when it encounters a SIGTRAMP_FRAME or DUMMY_FRAME. This stops - get_prev_frame() overriding the frame's type when the INIT code - has previously set it. This is really somewhat bogus. The - initialization, as seen in create_new_frame(), should occur - before the INIT function has been called. */ - if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES - && (DEPRECATED_PC_IN_CALL_DUMMY_P () - ? DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0) - : pc_in_dummy_frame (pc))) - /* NOTE: cagney/2002-11-11: Does this even occure? */ - type = DUMMY_FRAME; - else - { - char *name; - find_pc_partial_function (pc, &name, NULL, NULL); - if (PC_IN_SIGTRAMP (fi->pc, name)) - type = SIGTRAMP_FRAME; - else - type = NORMAL_FRAME; - } - fi->type = type; + fi->next = create_sentinel_frame (current_regcache); + fi->type = frame_type_from_pc (pc); if (INIT_EXTRA_FRAME_INFO_P ()) INIT_EXTRA_FRAME_INFO (0, fi); /* Select/initialize an unwind function. */ - set_unwind_by_pc (fi->pc, fi->frame, &fi->register_unwind, - &fi->pc_unwind, &fi->id_unwind); + set_unwind_by_pc (fi->pc, &fi->register_unwind, &fi->pc_unwind, + &fi->id_unwind); return fi; } @@ -892,7 +893,12 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) 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. */ @@ -923,39 +929,16 @@ reinit_frame_cache (void) } } -/* Return a structure containing various interesting information - about the frame that called NEXT_FRAME. Returns NULL - if there is no such frame. */ +/* Create the previous frame using the original INIT_EXTRA_INFO + method. */ -struct frame_info * -get_prev_frame (struct frame_info *next_frame) +static struct frame_info * +deprecated_get_prev_frame (struct frame_info *next_frame) { CORE_ADDR address = 0; struct frame_info *prev; int fromleaf; - /* Return the inner-most frame, when the caller passes in NULL. */ - /* NOTE: cagney/2002-11-09: Not sure how this would happen. The - caller should have previously obtained a valid frame using - get_selected_frame() and then called this code - only possibility - I can think of is code behaving badly. */ - if (next_frame == NULL) - { - /* NOTE: cagney/2002-11-09: There was a code segment here that - would error out when CURRENT_FRAME was NULL. The comment - that went with it made the claim ... - - ``This screws value_of_variable, which just wants a nice - clean NULL return from block_innermost_frame if there are no - frames. I don't think I've ever seen this message happen - otherwise. And returning NULL here is a perfectly legitimate - thing to do.'' - - Per the above, this code shouldn't even be called with a NULL - NEXT_FRAME. */ - return current_frame; - } - /* Only try to do the unwind once. */ if (next_frame->prev_p) return next_frame->prev; @@ -1124,8 +1107,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, - &prev->pc_unwind, &prev->id_unwind); + set_unwind_by_pc (prev->pc, &prev->register_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 @@ -1163,6 +1146,136 @@ get_prev_frame (struct frame_info *next_frame) return prev; } +/* Return a structure containing various interesting information + about the frame that called NEXT_FRAME. Returns NULL + if there is no such frame. */ + +struct frame_info * +get_prev_frame (struct frame_info *next_frame) +{ + struct frame_info *prev_frame; + + /* Return the inner-most frame, when the caller passes in NULL. */ + /* NOTE: cagney/2002-11-09: Not sure how this would happen. The + caller should have previously obtained a valid frame using + get_selected_frame() and then called this code - only possibility + I can think of is code behaving badly. + + NOTE: cagney/2003-01-10: Talk about code behaving badly. Check + block_innermost_frame(). It does the sequence: frame = NULL; + while (1) { frame = get_prev_frame (frame); .... }. Ulgh! Why + it couldn't be written better, I don't know. */ + if (next_frame == NULL) + { + /* NOTE: cagney/2002-11-09: There was a code segment here that + would error out when CURRENT_FRAME was NULL. The comment + that went with it made the claim ... + + ``This screws value_of_variable, which just wants a nice + clean NULL return from block_innermost_frame if there are no + frames. I don't think I've ever seen this message happen + otherwise. And returning NULL here is a perfectly legitimate + thing to do.'' + + Per the above, this code shouldn't even be called with a NULL + NEXT_FRAME. */ + return current_frame; + } + + if ((DEPRECATED_INIT_FRAME_PC_P () + || DEPRECATED_INIT_FRAME_PC_FIRST_P ()) + && next_frame->level >= 0) + /* Don't try to unwind the sentinal frame using the old code. */ + return deprecated_get_prev_frame (next_frame); + + /* There is always a frame. If this assertion fails, suspect that + something should be calling get_selected_frame() or + get_current_frame(). */ + gdb_assert (next_frame != NULL); + + /* Only try to do the unwind once. */ + if (next_frame->prev_p) + return next_frame->prev; + next_frame->prev_p = 1; + + if (next_frame->level >= 0 + /* && !backtrace_below_main */ + && inside_main_func (next_frame->pc)) + /* Don't unwind past main(), always unwind the sentinel frame. */ + return 0; + + /* Allocate the new frame but do not wire it in. Some (bad) code in + INIT_EXTRA_FRAME_INFO tries to look along frame->next to pull + some fancy tricks (of course such code is, by definition, + recursive). Try to prevent it. */ + prev_frame = FRAME_OBSTACK_ZALLOC (struct frame_info); + prev_frame->level = next_frame->level + 1; + + /* Try to unwind the PC. If that doesn't work, assume we've reached + the oldest frame and simply return. Is there a better sentinal + value? The unwound PC value is then used to initialize the new + previous frame's type. + + Note that the pc-unwind is intentionally performed before the + frame chain. This is ok since, for old targets, both + frame_pc_unwind (nee, FRAME_SAVED_PC) and FRAME_CHAIN()) assume + NEXT_FRAME's data structures have already been initialized (using + INIT_EXTRA_FRAME_INFO) and hence the call order doesn't matter. + + By unwinding the PC first, it becomes possible to, in the case of + a dummy frame, avoid also unwinding the frame ID. This is + because (well ignoring the PPC) a dummy frame can be located + using NEXT_FRAME's frame ID. */ + + prev_frame->pc = frame_pc_unwind (next_frame); + if (prev_frame->pc == 0) + /* The allocated PREV_FRAME will be reclaimed when the frame + obstack is next purged. */ + return NULL; + prev_frame->type = frame_type_from_pc (prev_frame->pc); + + /* Set the unwind functions based on that identified PC. */ + set_unwind_by_pc (prev_frame->pc, &prev_frame->register_unwind, + &prev_frame->pc_unwind, &prev_frame->id_unwind); + + /* Now figure out how to initialize this new frame. Perhaphs one + day, this will too, be selected by set_unwind_by_pc(). */ + if (prev_frame->type != DUMMY_FRAME) + { + /* A dummy frame doesn't need to unwind the frame ID because the + frame ID comes from the previous frame. The other frames do + though. True? */ +#if 0 + /* Oops, the frame doesn't chain. Treat this as the last frame. */ + prev_frame->id = frame_id_unwind (next_frame); + if (!frame_id_p (prev_frame->id)) + return NULL; +#else + /* FIXME: cagney/2002-12-18: Instead of this hack, should just + save the frame ID directly. */ + struct frame_id id = frame_id_unwind (next_frame); + if (!frame_id_p (id)) + return NULL; + prev_frame->frame = id.base; +#endif + } + + /* Link it in. */ + next_frame->prev = prev_frame; + prev_frame->next = next_frame; + + /* NOTE: cagney/2002-12-18: Eventually this call will go away. + Instead of initializing extra info, all frames will use the + frame_cache (passed to the unwind functions) to store extra frame + info. */ + if (INIT_EXTRA_FRAME_INFO_P ()) + /* NOTE: This code doesn't bother trying to sort out frameless + functions. That is left to the target. */ + INIT_EXTRA_FRAME_INFO (0, prev_frame); + + return prev_frame; +} + CORE_ADDR get_frame_pc (struct frame_info *frame) { diff --git a/gdb/frame.h b/gdb/frame.h index fbe6275..98dace6 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -29,6 +29,9 @@ struct symtab_and_line; 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 @@ enum frame_type 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 @@ extern struct frame_id frame_id_unwind (struct frame_info *frame); 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 @@ typedef void (frame_register_unwind_ftype) (struct frame_info *frame, 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 @@ struct frame_info /* 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 @@ enum print_what 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. */ |