Index: gdb/gdbarch.c =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.c,v retrieving revision 1.427 diff -u -p -r1.427 gdbarch.c --- gdb/gdbarch.c 16 May 2008 00:27:23 -0000 1.427 +++ gdb/gdbarch.c 23 May 2008 15:13:39 -0000 @@ -52,7 +52,12 @@ /* Static function declarations */ static void alloc_gdbarch_data (struct gdbarch *); - +static struct value * +default_prev_register_from_epilogue (struct gdbarch *gdbarch, + struct frame_info *this_frame, + void **this_prologue_cache, + int regnum, + CORE_ADDR pc); /* Non-zero if we want to trace architecture code. */ #ifndef GDBARCH_DEBUG @@ -237,6 +242,7 @@ struct gdbarch gdbarch_target_signal_from_host_ftype *target_signal_from_host; gdbarch_target_signal_to_host_ftype *target_signal_to_host; gdbarch_record_special_symbol_ftype *record_special_symbol; + gdbarch_prev_register_from_epilogue_ftype *prev_register_from_epilogue; }; @@ -366,6 +372,7 @@ struct gdbarch startup_gdbarch = default_target_signal_from_host, /* target_signal_from_host */ default_target_signal_to_host, /* target_signal_to_host */ 0, /* record_special_symbol */ + default_prev_register_from_epilogue, /* prev_register_from_epilogue */ /* startup_gdbarch() */ }; @@ -449,6 +456,7 @@ gdbarch_alloc (const struct gdbarch_info gdbarch->displaced_step_location = NULL; gdbarch->target_signal_from_host = default_target_signal_from_host; gdbarch->target_signal_to_host = default_target_signal_to_host; + gdbarch->prev_register_from_epilogue = default_prev_register_from_epilogue; /* gdbarch_alloc() */ return gdbarch; @@ -617,6 +625,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of target_signal_from_host, invalid_p == 0 */ /* Skip verify of target_signal_to_host, invalid_p == 0 */ /* Skip verify of record_special_symbol, has predicate */ + /* Skip verify of prev_register_from_epilogue, invalid_p == 0 */ buf = ui_file_xstrdup (log, &dummy); make_cleanup (xfree, buf); if (strlen (buf) > 0) @@ -889,6 +898,9 @@ gdbarch_dump (struct gdbarch *gdbarch, s "gdbarch_dump: pointer_to_address = <0x%lx>\n", (long) gdbarch->pointer_to_address); fprintf_unfiltered (file, + "gdbarch_dump: prev_register_from_epilogue = <0x%lx>\n", + (long) gdbarch->prev_register_from_epilogue); + fprintf_unfiltered (file, "gdbarch_dump: gdbarch_print_float_info_p() = %d\n", gdbarch_print_float_info_p (gdbarch)); fprintf_unfiltered (file, @@ -3190,6 +3202,23 @@ set_gdbarch_record_special_symbol (struc gdbarch->record_special_symbol = record_special_symbol; } +struct value * +gdbarch_prev_register_from_epilogue (struct gdbarch *gdbarch, struct frame_info *this_frame, void **this_prologue_cache, int regnum, CORE_ADDR pc) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->prev_register_from_epilogue != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_prev_register_from_epilogue called\n"); + return gdbarch->prev_register_from_epilogue (gdbarch, this_frame, this_prologue_cache, regnum, pc); +} + +void +set_gdbarch_prev_register_from_epilogue (struct gdbarch *gdbarch, + gdbarch_prev_register_from_epilogue_ftype prev_register_from_epilogue) +{ + gdbarch->prev_register_from_epilogue = prev_register_from_epilogue; +} + /* Keep a registry of per-architecture data-pointers required by GDB modules. */ @@ -3600,6 +3629,16 @@ deprecated_current_gdbarch_select_hack ( reinit_frame_cache (); } +static struct value * +default_prev_register_from_epilogue (struct gdbarch *gdbarch, + struct frame_info *this_frame, + void **this_prologue_cache, + int regnum, + CORE_ADDR pc) +{ + return NULL; +} + extern void _initialize_gdbarch (void); void Index: gdb/gdbarch.h =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.h,v retrieving revision 1.382 diff -u -p -r1.382 gdbarch.h --- gdb/gdbarch.h 16 May 2008 00:27:23 -0000 1.382 +++ gdb/gdbarch.h 23 May 2008 15:13:39 -0000 @@ -798,6 +798,12 @@ typedef void (gdbarch_record_special_sym extern void gdbarch_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile, asymbol *sym); extern void set_gdbarch_record_special_symbol (struct gdbarch *gdbarch, gdbarch_record_special_symbol_ftype *record_special_symbol); +/* Create architecture dependent sentinel_frame. */ + +typedef struct value * (gdbarch_prev_register_from_epilogue_ftype) (struct gdbarch *gdbarch, struct frame_info *this_frame, void **this_prologue_cache, int regnum, CORE_ADDR pc); +extern struct value * gdbarch_prev_register_from_epilogue (struct gdbarch *gdbarch, struct frame_info *this_frame, void **this_prologue_cache, int regnum, CORE_ADDR pc); +extern void set_gdbarch_prev_register_from_epilogue (struct gdbarch *gdbarch, gdbarch_prev_register_from_epilogue_ftype *prev_register_from_epilogue); + extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch); Index: gdb/gdbarch.sh =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.sh,v retrieving revision 1.468 diff -u -p -r1.468 gdbarch.sh --- gdb/gdbarch.sh 16 May 2008 00:27:23 -0000 1.468 +++ gdb/gdbarch.sh 23 May 2008 15:13:39 -0000 @@ -703,6 +703,10 @@ m:int:target_signal_to_host:enum target_ # Record architecture-specific information from the symbol table. M:void:record_special_symbol:struct objfile *objfile, asymbol *sym:objfile, sym + +# Create architecture dependent sentinel_frame. +m:struct value *:prev_register_from_epilogue:struct frame_info *this_frame, void **this_prologue_cache, int regnum, CORE_ADDR pc:this_frame, this_prologue_cache, regnum, pc::default_prev_register_from_epilogue::0 + EOF } @@ -1133,7 +1137,12 @@ cat <regcache, I386_ESP_REGNUM, + value_contents_raw (value)); + esp = value_as_address (value); + esp -= 4; + store_unsigned_integer (value_contents_raw (value), 4, esp); + return 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, value_contents_raw (value)); + + return value; +} static struct gdbarch * i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) @@ -2587,6 +2648,7 @@ i386_gdbarch_init (struct gdbarch_info i set_gdbarch_return_value (gdbarch, i386_return_value); set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue); + set_gdbarch_in_function_epilogue_p (gdbarch, i386_in_function_epilogue_p); /* Stack grows downward. */ set_gdbarch_inner_than (gdbarch, core_addr_lessthan); @@ -2625,6 +2687,8 @@ i386_gdbarch_init (struct gdbarch_info i frame_unwind_append_unwinder (gdbarch, &i386_sigtramp_frame_unwind); frame_unwind_append_unwinder (gdbarch, &i386_frame_unwind); + set_gdbarch_prev_register_from_epilogue (gdbarch, + i386_prev_register_from_epilogue); /* If we have a register mapping, enable the generic core file support, unless it has already been enabled. */ Index: gdb/sentinel-frame.c =================================================================== RCS file: /cvs/src/src/gdb/sentinel-frame.c,v retrieving revision 1.18 diff -u -p -r1.18 sentinel-frame.c --- gdb/sentinel-frame.c 30 Apr 2008 21:16:45 -0000 1.18 +++ gdb/sentinel-frame.c 23 May 2008 15:13:40 -0000 @@ -49,8 +49,25 @@ sentinel_frame_prev_register (struct fra { struct gdbarch *gdbarch = get_frame_arch (this_frame); struct frame_unwind_cache *cache = *this_prologue_cache; - struct value *value; + struct value *value = NULL; + if (regnum != gdbarch_pc_regnum (gdbarch)) + { + struct value *value_pc; + CORE_ADDR pc; + value_pc = sentinel_frame_prev_register (this_frame, + this_prologue_cache, + gdbarch_pc_regnum (gdbarch)); + pc = value_as_address (value_pc); + if (gdbarch_in_function_epilogue_p (gdbarch, pc)) + value = gdbarch_prev_register_from_epilogue (gdbarch, + this_frame, + this_prologue_cache, + regnum, + pc); + if (value) + return value; + } /* Return the actual value. */ value = allocate_value (register_type (gdbarch, regnum)); VALUE_LVAL (value) = lval_register; @@ -84,3 +101,4 @@ const struct frame_unwind sentinel_frame }; const struct frame_unwind *const sentinel_frame_unwind = &sentinel_frame_unwinder; +