From a94dd1fda23661238cac626d1adc7a11c55364b3 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Mon, 27 Jan 2003 21:41:41 +0000 Subject: [PATCH] 2003-01-27 Andrew Cagney * sentinel-frame.h, sentinel-frame.c: New files. * Makefile.in (frame.o): Update dependencies. (SFILES): Add sentinel-frame.c. (sentinel_frame_h): Define. (COMMON_OBS): Add sentinel-frame.o. (sentinel-frame.o): Specify dependencies. * frame.c: Include "sentinel-frame.h". (frame_register_unwind): Rewrite assuming that there is always a a ->next frame. (frame_register, generic_unwind_get_saved_register): Ditto. (frame_read_unsigned_register, frame_read_signed_register): Ditto. (create_sentinel_frame, unwind_to_current_frame): New functions. (get_current_frame): Rewrite using create_sentinel_frame and unwind_to_current_frame. When possible, always create a frame. (create_new_frame): Set next to the sentinel frame. (get_next_frame): Rewrite. Don't go below the level 0 frame. (deprecated_update_frame_pc_hack): Update the next frame's PC and ID cache when necessary. (frame_saved_regs_id_unwind): Use frame_relative_level. (deprecated_generic_get_saved_register): Use frame_relative_level, get_frame_saved_regs, get_frame_pc, get_frame_base and get_next_frame. (frame_saved_regs_register_unwind): Use get_frame_saved_regs and frame_register. --- gdb/ChangeLog | 27 +++++ gdb/Makefile.in | 14 ++- gdb/frame.c | 263 ++++++++++++++++++++++--------------------- gdb/sentinel-frame.c | 113 +++++++++++++++++++ gdb/sentinel-frame.h | 41 +++++++ 5 files changed, 327 insertions(+), 131 deletions(-) create mode 100644 gdb/sentinel-frame.c create mode 100644 gdb/sentinel-frame.h diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 24424a1276..216b34f147 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,30 @@ +2003-01-27 Andrew Cagney + + * sentinel-frame.h, sentinel-frame.c: New files. + * Makefile.in (frame.o): Update dependencies. + (SFILES): Add sentinel-frame.c. + (sentinel_frame_h): Define. + (COMMON_OBS): Add sentinel-frame.o. + (sentinel-frame.o): Specify dependencies. + * frame.c: Include "sentinel-frame.h". + (frame_register_unwind): Rewrite assuming that there is always a a + ->next frame. + (frame_register, generic_unwind_get_saved_register): Ditto. + (frame_read_unsigned_register, frame_read_signed_register): Ditto. + (create_sentinel_frame, unwind_to_current_frame): New functions. + (get_current_frame): Rewrite using create_sentinel_frame and + unwind_to_current_frame. When possible, always create a frame. + (create_new_frame): Set next to the sentinel frame. + (get_next_frame): Rewrite. Don't go below the level 0 frame. + (deprecated_update_frame_pc_hack): Update the next frame's PC and + ID cache when necessary. + (frame_saved_regs_id_unwind): Use frame_relative_level. + (deprecated_generic_get_saved_register): Use frame_relative_level, + get_frame_saved_regs, get_frame_pc, get_frame_base and + get_next_frame. + (frame_saved_regs_register_unwind): Use get_frame_saved_regs and + frame_register. + 2003-01-27 Daniel Jacobowitz * gdb_indent.sh: Add -T bfd and -T asection to the indent arguments. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 229c66bdc7..63a6496a79 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -528,7 +528,9 @@ 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 \ @@ -686,6 +688,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 @@ -832,7 +835,9 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \ varobj.o wrapper.o \ jv-lang.o jv-valprint.o jv-typeprint.o \ m2-lang.o p-lang.o p-typeprint.o p-valprint.o \ - scm-exp.o scm-lang.o scm-valprint.o complaints.o typeprint.o \ + scm-exp.o scm-lang.o scm-valprint.o \ + sentinel-frame.o \ + complaints.o typeprint.o \ c-typeprint.o f-typeprint.o m2-typeprint.o \ c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \ nlmread.o serial.o mdebugread.o top.o utils.o \ @@ -1692,7 +1697,8 @@ 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) $(frame_unwind_h) $(command_h) $(gdbcmd_h) + $(language_h) $(frame_unwind_h) $(command_h) $(gdbcmd_h) \ + $(sentinel_frame_h) frame-unwind.o: frame-unwind.c $(defs_h) $(frame_h) $(frame_unwind_h) \ $(gdb_assert_h) $(dummy_frame_h) $(legacy_frame_h) frv-tdep.o: frv-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \ @@ -2125,6 +2131,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) $(frame_unwind_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/frame.c b/gdb/frame.c index d252d8a7df..a0cfc6fedd 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -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" @@ -179,29 +180,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->unwind->reg (frame, &frame->unwind_cache, regnum, @@ -247,25 +230,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 @@ -317,17 +286,17 @@ frame_read_unsigned_register (struct frame_info *frame, int regnum, tests like ``if get_next_frame() == NULL'' and instead just rely on recursive frame calls (like the below code) when manipulating a frame chain. */ - gdb_assert (frame != NULL); - frame_unwind_unsigned_register (get_next_frame (frame), regnum, val); + gdb_assert (frame != NULL && frame->next != NULL); + frame_unwind_unsigned_register (frame->next, regnum, val); } void frame_read_signed_register (struct frame_info *frame, int regnum, LONGEST *val) { - /* See note in frame_read_unsigned_register(). */ - gdb_assert (frame != NULL); - frame_unwind_signed_register (get_next_frame (frame), regnum, val); + /* See note above in frame_read_unsigned_register(). */ + gdb_assert (frame != NULL && frame->next != NULL); + frame_unwind_signed_register (frame->next, regnum, val); } static void @@ -355,25 +324,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 @@ -463,6 +416,32 @@ frame_map_regnum_to_name (int regnum) return builtin_reg_map_regnum_to_name (regnum); } +/* Create a sentinel frame. */ + +struct frame_info * +create_sentinel_frame (struct regcache *regcache) +{ + struct frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info); + frame->type = NORMAL_FRAME; + frame->level = -1; + /* Explicitly initialize the sentinel frame's cache. Provide it + with the underlying regcache. In the future additional + information, such as the frame's thread will be added. */ + frame->unwind_cache = sentinel_frame_cache (regcache); + /* For the moment there is only one sentinel frame implementation. */ + frame->unwind = sentinel_frame_unwind; + /* Link this frame back to itself. The frame is self referential + (the unwound PC is the same as the pc), so make it so. */ + frame->next = frame; + /* Always unwind the PC as part of creating this frame. This + ensures that the frame's PC points at something valid. */ + /* FIXME: cagney/2003-01-10: Problem here. Unwinding a sentinel + frame's PC may require information such as the frame's thread's + stop reason. Is it possible to get to that? */ + frame->pc = frame_pc_unwind (frame); + return frame; +} + /* Info about the innermost stack frame (contents of FP register) */ static struct frame_info *current_frame; @@ -495,17 +474,43 @@ get_frame_saved_regs (struct frame_info *fi) return fi->saved_regs; } -/* Return the innermost (currently executing) stack frame. */ +/* Return the innermost (currently executing) stack frame. This is + split into two functions. The function unwind_to_current_frame() + is wrapped in catch exceptions so that, even when the unwind of the + sentinel frame fails, the function still returns a stack frame. */ + +static int +unwind_to_current_frame (struct ui_out *ui_out, void *args) +{ + struct frame_info *frame = get_prev_frame (args); + /* A sentinel frame can fail to unwind, eg, because it's PC value + lands in somewhere like start. */ + if (frame == NULL) + return 1; + current_frame = frame; + 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; } @@ -593,11 +598,11 @@ frame_saved_regs_register_unwind (struct frame_info *frame, void **cache, gdb_assert (FRAME_INIT_SAVED_REGS_P ()); /* Load the saved_regs register cache. */ - if (frame->saved_regs == NULL) + if (get_frame_saved_regs (frame) == NULL) FRAME_INIT_SAVED_REGS (frame); - if (frame->saved_regs != NULL - && frame->saved_regs[regnum] != 0) + if (get_frame_saved_regs (frame) != NULL + && get_frame_saved_regs (frame)[regnum] != 0) { if (regnum == SP_REGNUM) { @@ -608,7 +613,7 @@ frame_saved_regs_register_unwind (struct frame_info *frame, void **cache, *realnump = -1; if (bufferp != NULL) store_address (bufferp, REGISTER_RAW_SIZE (regnum), - frame->saved_regs[regnum]); + get_frame_saved_regs (frame)[regnum]); } else { @@ -616,7 +621,7 @@ frame_saved_regs_register_unwind (struct frame_info *frame, void **cache, a local copy of its value. */ *optimizedp = 0; *lvalp = lval_memory; - *addrp = frame->saved_regs[regnum]; + *addrp = get_frame_saved_regs (frame)[regnum]; *realnump = -1; if (bufferp != NULL) { @@ -635,13 +640,13 @@ frame_saved_regs_register_unwind (struct frame_info *frame, void **cache, { regs[regnum] = frame_obstack_zalloc (REGISTER_RAW_SIZE (regnum)); - read_memory (frame->saved_regs[regnum], regs[regnum], + read_memory (get_frame_saved_regs (frame)[regnum], regs[regnum], REGISTER_RAW_SIZE (regnum)); } memcpy (bufferp, regs[regnum], REGISTER_RAW_SIZE (regnum)); #else /* Read the value in from memory. */ - read_memory (frame->saved_regs[regnum], bufferp, + read_memory (get_frame_saved_regs (frame)[regnum], bufferp, REGISTER_RAW_SIZE (regnum)); #endif } @@ -650,21 +655,11 @@ frame_saved_regs_register_unwind (struct frame_info *frame, void **cache, } /* No luck, assume this and the next frame have the same register - value. If a value is needed, pass the request on down the chain; - otherwise just return an indication that the value is in the same - register as the next frame. */ - if (bufferp == NULL) - { - *optimizedp = 0; - *lvalp = lval_register; - *addrp = 0; - *realnump = regnum; - } - else - { - frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp, - realnump, bufferp); - } + value. Pass the request down the frame chain to the next frame. + Hopefully that will find the register's location, either in a + register or in memory. */ + frame_register (frame, regnum, optimizedp, lvalp, addrp, realnump, + bufferp); } static CORE_ADDR @@ -684,7 +679,7 @@ frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache, /* Start out by assuming it's NULL. */ (*id) = null_frame_id; - if (next_frame->next == NULL) + if (frame_relative_level (next_frame) <= 0) /* 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 @@ -797,44 +792,50 @@ deprecated_generic_get_saved_register (char *raw_buffer, int *optimized, the current frame itself: otherwise, we would be getting the previous frame's registers which were saved by the current frame. */ - while (frame && ((frame = frame->next) != NULL)) + if (frame != NULL) { - if (get_frame_type (frame) == DUMMY_FRAME) + for (frame = get_next_frame (frame); + frame_relative_level (frame) >= 0; + frame = get_next_frame (frame)) { - if (lval) /* found it in a CALL_DUMMY frame */ - *lval = not_lval; - if (raw_buffer) - /* FIXME: cagney/2002-06-26: This should be via the - gdbarch_register_read() method so that it, on the fly, - constructs either a raw or pseudo register from the raw - register cache. */ - regcache_raw_read (generic_find_dummy_frame (frame->pc, - frame->frame), - regnum, raw_buffer); - return; - } - - FRAME_INIT_SAVED_REGS (frame); - if (frame->saved_regs != NULL - && frame->saved_regs[regnum] != 0) - { - if (lval) /* found it saved on the stack */ - *lval = lval_memory; - if (regnum == SP_REGNUM) + if (get_frame_type (frame) == DUMMY_FRAME) { - if (raw_buffer) /* SP register treated specially */ - store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), - frame->saved_regs[regnum]); + if (lval) /* found it in a CALL_DUMMY frame */ + *lval = not_lval; + if (raw_buffer) + /* FIXME: cagney/2002-06-26: This should be via the + gdbarch_register_read() method so that it, on the + fly, constructs either a raw or pseudo register + from the raw register cache. */ + regcache_raw_read + (generic_find_dummy_frame (get_frame_pc (frame), + get_frame_base (frame)), + regnum, raw_buffer); + return; } - else + + FRAME_INIT_SAVED_REGS (frame); + if (get_frame_saved_regs (frame) != NULL + && get_frame_saved_regs (frame)[regnum] != 0) { - if (addrp) /* any other register */ - *addrp = frame->saved_regs[regnum]; - if (raw_buffer) - read_memory (frame->saved_regs[regnum], raw_buffer, - REGISTER_RAW_SIZE (regnum)); + if (lval) /* found it saved on the stack */ + *lval = lval_memory; + if (regnum == SP_REGNUM) + { + if (raw_buffer) /* SP register treated specially */ + store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), + get_frame_saved_regs (frame)[regnum]); + } + else + { + if (addrp) /* any other register */ + *addrp = get_frame_saved_regs (frame)[regnum]; + if (raw_buffer) + read_memory (get_frame_saved_regs (frame)[regnum], raw_buffer, + REGISTER_RAW_SIZE (regnum)); + } + return; } - return; } } @@ -884,6 +885,7 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) fi->frame = addr; fi->pc = pc; + fi->next = create_sentinel_frame (current_regcache); fi->type = frame_type_from_pc (pc); if (INIT_EXTRA_FRAME_INFO_P ()) @@ -896,12 +898,16 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) } /* Return the frame that FRAME calls (NULL if FRAME is the innermost - frame). */ + frame). Be careful to not fall off the bottom of the frame chain + and onto the sentinel frame. */ struct frame_info * get_next_frame (struct frame_info *frame) { - return frame->next; + if (frame->level > 0) + return frame->next; + else + return NULL; } /* Flush the entire frame cache. */ @@ -1415,6 +1421,7 @@ void deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc) { /* See comment in "frame.h". */ + gdb_assert (frame->next != NULL); frame->pc = pc; } diff --git a/gdb/sentinel-frame.c b/gdb/sentinel-frame.c new file mode 100644 index 0000000000..fe11d8a6f4 --- /dev/null +++ b/gdb/sentinel-frame.c @@ -0,0 +1,113 @@ +/* Code dealing with register stack frames, for GDB, the GNU debugger. + + Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, + 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software + Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +#include "defs.h" +#include "regcache.h" +#include "sentinel-frame.h" +#include "inferior.h" +#include "frame-unwind.h" + +struct frame_unwind_cache +{ + struct regcache *regcache; +}; + +void * +sentinel_frame_cache (struct regcache *regcache) +{ + struct frame_unwind_cache *cache = + FRAME_OBSTACK_ZALLOC (struct frame_unwind_cache); + cache->regcache = regcache; + return cache; +} + +/* Here the register value is taken direct from the register cache. */ + +void +sentinel_frame_register_unwind (struct frame_info *frame, + void **unwind_cache, + int regnum, int *optimized, + enum lval_type *lvalp, CORE_ADDR *addrp, + int *realnum, void *bufferp) +{ + struct frame_unwind_cache *cache = *unwind_cache; + /* Describe the register's location. A reg-frame maps all registers + onto the corresponding hardware register. */ + *optimized = 0; + *lvalp = lval_register; + *addrp = REGISTER_BYTE (regnum); + *realnum = regnum; + + /* If needed, find and return the value of the register. */ + if (bufferp != NULL) + { + /* Return the actual value. */ + /* Use the regcache_cooked_read() method so that it, on the fly, + constructs either a raw or pseudo register from the raw + register cache. */ + regcache_cooked_read (cache->regcache, regnum, bufferp); + } +} + +CORE_ADDR +sentinel_frame_pc_unwind (struct frame_info *frame, + void **cache) +{ + /* FIXME: cagney/2003-01-08: This should be using a per-architecture + method that doesn't suffer from DECR_PC_AFTER_BREAK problems. + Such a method would take unwind_cache, regcache and stop reason + parameters. */ + return read_pc (); +} + +void +sentinel_frame_id_unwind (struct frame_info *frame, + void **cache, + struct frame_id *id) +{ + /* FIXME: cagney/2003-01-08: This should be using a per-architecture + method that doesn't suffer from DECR_PC_AFTER_BREAK problems. + Such a method would take unwind_cache, regcache and stop reason + parameters. */ + id->base = read_fp (); + id->pc = read_pc (); +} + +static void +sentinel_frame_pop (struct frame_info *frame, + void **cache, + struct regcache *regcache) +{ + internal_error (__FILE__, __LINE__, "Function sentinal_frame_pop called"); +} + +const struct frame_unwind sentinel_frame_unwinder = +{ + sentinel_frame_pop, + sentinel_frame_pc_unwind, + sentinel_frame_id_unwind, + sentinel_frame_register_unwind +}; + +const struct frame_unwind *const sentinel_frame_unwind = &sentinel_frame_unwinder; diff --git a/gdb/sentinel-frame.h b/gdb/sentinel-frame.h new file mode 100644 index 0000000000..9b69f42154 --- /dev/null +++ b/gdb/sentinel-frame.h @@ -0,0 +1,41 @@ +/* Code dealing with register stack frames, for GDB, the GNU debugger. + + Copyright 2003 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if !defined (SENTINEL_FRAME_H) +#define SENTINEL_FRAME_H 1 + +struct frame_unwind; +struct regcache; + +/* Implement the sentinel frame. The sentinel frame terminates the + inner most end of the frame chain. If unwound, it returns the + information need to construct an inner-most frame. */ + +/* Pump prime the sentinel frame's cache. Since this needs the + REGCACHE provide that here. */ + +extern void *sentinel_frame_cache (struct regcache *regcache); + +/* At present there is only one type of sentinel frame. */ + +extern const struct frame_unwind *const sentinel_frame_unwind; + +#endif /* !defined (SENTINEL_FRAME_H) */ -- 2.34.1