mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-28 01:50:48 +00:00
* arch-utils.c (generic_in_function_epilogue_p): New function.
* arch-utils.h (generic_in_function_epilogue_p): Declare extern. * breakpoint.c (watchpoint_check): Add test whether the pc is currently in the epilogue of a function. * gdbarch.c: Autogenerated from gdbarch.sh. * gdbarch.h: Ditto. * gdbarch.sh (function_list): Add `in_function_epilogue_p' definition.
This commit is contained in:
@@ -1,3 +1,13 @@
|
||||
2001-11-06 Corinna Vinschen <vinschen@redhat.com>
|
||||
|
||||
* arch-utils.c (generic_in_function_epilogue_p): New function.
|
||||
* arch-utils.h (generic_in_function_epilogue_p): Declare extern.
|
||||
* breakpoint.c (watchpoint_check): Add test whether the pc is
|
||||
currently in the epilogue of a function.
|
||||
* gdbarch.c: Autogenerated from gdbarch.sh.
|
||||
* gdbarch.h: Ditto.
|
||||
* gdbarch.sh (function_list): Add `in_function_epilogue_p' definition.
|
||||
|
||||
2001-11-05 Jim Blandy <jimb@redhat.com>
|
||||
|
||||
* config/s390/s390.mh (NATDEPFILES): Don't split this across
|
||||
|
||||
@@ -111,6 +111,12 @@ generic_in_solib_call_trampoline (CORE_ADDR pc, char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
generic_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
legacy_register_name (int i)
|
||||
{
|
||||
|
||||
@@ -134,4 +134,6 @@ extern CORE_ADDR generic_skip_trampoline_code (CORE_ADDR pc);
|
||||
|
||||
extern int generic_in_solib_call_trampoline (CORE_ADDR pc, char *name);
|
||||
|
||||
extern int generic_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2308,6 +2308,14 @@ watchpoint_check (PTR p)
|
||||
reinit_frame_cache ();
|
||||
fr = find_frame_addr_in_frame_chain (b->watchpoint_frame);
|
||||
within_current_scope = (fr != NULL);
|
||||
/* in_function_epilogue_p() returns a non-zero value if we're still
|
||||
in the function but the stack frame has already been invalidated.
|
||||
Since we can't rely on the values of local variables after the
|
||||
stack has been destroyed, we are treating the watchpoint in that
|
||||
state as `not changed' without further checking. */
|
||||
if (within_current_scope && fr == get_current_frame ()
|
||||
&& gdbarch_in_function_epilogue_p (current_gdbarch, read_pc ()))
|
||||
return WP_VALUE_NOT_CHANGED;
|
||||
if (within_current_scope)
|
||||
/* If we end up stopping, the current frame will get selected
|
||||
in normal_stop. So this call to select_frame won't affect
|
||||
|
||||
@@ -254,6 +254,7 @@ struct gdbarch
|
||||
gdbarch_print_insn_ftype *print_insn;
|
||||
gdbarch_skip_trampoline_code_ftype *skip_trampoline_code;
|
||||
gdbarch_in_solib_call_trampoline_ftype *in_solib_call_trampoline;
|
||||
gdbarch_in_function_epilogue_p_ftype *in_function_epilogue_p;
|
||||
};
|
||||
|
||||
|
||||
@@ -392,6 +393,7 @@ struct gdbarch startup_gdbarch =
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
/* startup_gdbarch() */
|
||||
};
|
||||
|
||||
@@ -500,6 +502,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
|
||||
current_gdbarch->print_insn = legacy_print_insn;
|
||||
current_gdbarch->skip_trampoline_code = generic_skip_trampoline_code;
|
||||
current_gdbarch->in_solib_call_trampoline = generic_in_solib_call_trampoline;
|
||||
current_gdbarch->in_function_epilogue_p = generic_in_function_epilogue_p;
|
||||
/* gdbarch_alloc() */
|
||||
|
||||
return current_gdbarch;
|
||||
@@ -754,6 +757,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
|
||||
/* Skip verify of print_insn, invalid_p == 0 */
|
||||
/* Skip verify of skip_trampoline_code, invalid_p == 0 */
|
||||
/* Skip verify of in_solib_call_trampoline, invalid_p == 0 */
|
||||
/* Skip verify of in_function_epilogue_p, invalid_p == 0 */
|
||||
buf = ui_file_xstrdup (log, &dummy);
|
||||
make_cleanup (xfree, buf);
|
||||
if (strlen (buf) > 0)
|
||||
@@ -778,6 +782,10 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: GDB_MULTI_ARCH = %d\n",
|
||||
GDB_MULTI_ARCH);
|
||||
if (GDB_MULTI_ARCH)
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: in_function_epilogue_p = 0x%08lx\n",
|
||||
(long) current_gdbarch->in_function_epilogue_p);
|
||||
if (GDB_MULTI_ARCH)
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: register_read = 0x%08lx\n",
|
||||
@@ -4241,6 +4249,24 @@ set_gdbarch_in_solib_call_trampoline (struct gdbarch *gdbarch,
|
||||
gdbarch->in_solib_call_trampoline = in_solib_call_trampoline;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR addr)
|
||||
{
|
||||
if (gdbarch->in_function_epilogue_p == 0)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"gdbarch: gdbarch_in_function_epilogue_p invalid");
|
||||
if (gdbarch_debug >= 2)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_in_function_epilogue_p called\n");
|
||||
return gdbarch->in_function_epilogue_p (gdbarch, addr);
|
||||
}
|
||||
|
||||
void
|
||||
set_gdbarch_in_function_epilogue_p (struct gdbarch *gdbarch,
|
||||
gdbarch_in_function_epilogue_p_ftype in_function_epilogue_p)
|
||||
{
|
||||
gdbarch->in_function_epilogue_p = in_function_epilogue_p;
|
||||
}
|
||||
|
||||
|
||||
/* Keep a registry of per-architecture data-pointers required by GDB
|
||||
modules. */
|
||||
|
||||
@@ -2069,6 +2069,20 @@ extern void set_gdbarch_in_solib_call_trampoline (struct gdbarch *gdbarch, gdbar
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* A target might have problems with watchpoints as soon as the stack
|
||||
frame of the current function has been destroyed. This mostly happens
|
||||
as the first action in a funtion's epilogue. in_function_epilogue_p()
|
||||
is defined to return a non-zero value if either the given addr is one
|
||||
instruction after the stack destroying instruction up to the trailing
|
||||
return instruction or if we can figure out that the stack frame has
|
||||
already been invalidated regardless of the value of addr. Targets
|
||||
which don't suffer from that problem could just let this functionality
|
||||
untouched. */
|
||||
|
||||
typedef int (gdbarch_in_function_epilogue_p_ftype) (struct gdbarch *gdbarch, CORE_ADDR addr);
|
||||
extern int gdbarch_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR addr);
|
||||
extern void set_gdbarch_in_function_epilogue_p (struct gdbarch *gdbarch, gdbarch_in_function_epilogue_p_ftype *in_function_epilogue_p);
|
||||
|
||||
extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch);
|
||||
|
||||
|
||||
|
||||
@@ -546,6 +546,16 @@ f:2:SKIP_TRAMPOLINE_CODE:CORE_ADDR:skip_trampoline_code:CORE_ADDR pc:pc:::generi
|
||||
# trampoline code in the ".plt" section. IN_SOLIB_CALL_TRAMPOLINE evaluates
|
||||
# to nonzero if we are current stopped in one of these.
|
||||
f:2:IN_SOLIB_CALL_TRAMPOLINE:int:in_solib_call_trampoline:CORE_ADDR pc, char *name:pc, name:::generic_in_solib_call_trampoline::0
|
||||
# A target might have problems with watchpoints as soon as the stack
|
||||
# frame of the current function has been destroyed. This mostly happens
|
||||
# as the first action in a funtion's epilogue. in_function_epilogue_p()
|
||||
# is defined to return a non-zero value if either the given addr is one
|
||||
# instruction after the stack destroying instruction up to the trailing
|
||||
# return instruction or if we can figure out that the stack frame has
|
||||
# already been invalidated regardless of the value of addr. Targets
|
||||
# which don't suffer from that problem could just let this functionality
|
||||
# untouched.
|
||||
m:::int:in_function_epilogue_p:CORE_ADDR addr:addr::0:generic_in_function_epilogue_p::0
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user