From e02bc4cc30e0425abebd623e4decd1bf37b9e3da Mon Sep 17 00:00:00 2001 From: David Smith Date: Fri, 6 Apr 2001 17:53:39 +0000 Subject: [PATCH] 2001-04-06 David Smith * arch-utils.c (default_prepare_to_proceed) (generic_prepare_to_proceed): Added new functions. * arch-utils.h: New function declarations for default_prepare_to_proceed() and generic_prepare_to_proceed(). * gdbarch.sh: Added PREPARE_TO_PROCEED. * gdbarch.c: Regenerated. * gdbarch.h: Regenerated. * inferior.h: Added get_last_target_status() declaration. * infrun.c (get_last_target_status): Added new function. (handle_inferior_event): Saves last pid and waitstatus, which will get returned by get_last_target_status(). * hppa-tdep.c (prepare_to_proceed): Added comment stating that prepare_to_proceed() is potentially redundant since default_prepare_to_proceed() has been added. * linux-thread.c (prepare_to_proceed): Ditto. * lin-lwp.c (prepare_to_proceed): Ditto. * m3-nat.c (prepare_to_proceed): Ditto. --- gdb/ChangeLog | 21 ++++++++++++++++++ gdb/arch-utils.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ gdb/arch-utils.h | 5 +++++ gdb/gdbarch.c | 35 +++++++++++++++++++++++++++++ gdb/gdbarch.h | 14 ++++++++++++ gdb/gdbarch.sh | 1 + gdb/hppa-tdep.c | 5 ++++- gdb/inferior.h | 2 ++ gdb/infrun.c | 22 +++++++++++++++++++ gdb/lin-lwp.c | 6 ++++- gdb/linux-thread.c | 5 ++++- gdb/m3-nat.c | 2 ++ 12 files changed, 170 insertions(+), 3 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6ee409d79b..f521bdc9dc 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,24 @@ +2001-04-06 David Smith + + * arch-utils.c (default_prepare_to_proceed) + (generic_prepare_to_proceed): Added new functions. + * arch-utils.h: New function declarations for + default_prepare_to_proceed() and generic_prepare_to_proceed(). + * gdbarch.sh: Added PREPARE_TO_PROCEED. + * gdbarch.c: Regenerated. + * gdbarch.h: Regenerated. + * inferior.h: Added get_last_target_status() declaration. + * infrun.c (get_last_target_status): Added new function. + (handle_inferior_event): Saves last pid and waitstatus, which will + get returned by get_last_target_status(). + + * hppa-tdep.c (prepare_to_proceed): Added comment stating that + prepare_to_proceed() is potentially redundant since + default_prepare_to_proceed() has been added. + * linux-thread.c (prepare_to_proceed): Ditto. + * lin-lwp.c (prepare_to_proceed): Ditto. + * m3-nat.c (prepare_to_proceed): Ditto. + 2001-04-05 Andrew Cagney Obsolete powerpcle-*-cygwin* and powerpcle-*-solaris* platforms diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 004d3aeb10..10f0fc503a 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -239,6 +239,61 @@ default_frame_address (struct frame_info *fi) return fi->frame; } +/* Default prepare_to_procced(). */ +int +default_prepare_to_proceed (int select_it) +{ + return 0; +} + +/* Generic prepare_to_proceed(). This one should be suitable for most + targets that support threads. */ +int +generic_prepare_to_proceed (int select_it) +{ + int wait_pid; + struct target_waitstatus wait_status; + + /* Get the last target status returned by target_wait(). */ + get_last_target_status (&wait_pid, &wait_status); + + /* Make sure we were stopped at a breakpoint. */ + if (wait_status.kind != TARGET_WAITKIND_STOPPED + || wait_status.value.sig != TARGET_SIGNAL_TRAP) + { + return 0; + } + + if (wait_pid != -1 && inferior_pid != wait_pid) + { + /* Switched over from WAIT_PID. */ + CORE_ADDR wait_pc = read_pc_pid (wait_pid); + + /* Avoid switching where it wouldn't do any good, i.e. if both + threads are at the same breakpoint. */ + if (wait_pc != read_pc () && breakpoint_here_p (wait_pc)) + { + if (select_it) + { + /* User hasn't deleted the breakpoint. Switch back to + WAIT_PID and return non-zero. */ + inferior_pid = wait_pid; + + /* FIXME: This stuff came from switch_to_thread() in + thread.c (which should probably be a public function). */ + flush_cached_frames (); + registers_changed (); + stop_pc = wait_pc; + select_frame (get_current_frame (), 0); + } + + return 1; + } + } + return 0; + +} + /* Functions to manipulate the endianness of the target. */ #ifdef TARGET_BYTE_ORDER_SELECTABLE diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h index bdd72fca0c..d468da6a58 100644 --- a/gdb/arch-utils.h +++ b/gdb/arch-utils.h @@ -105,5 +105,10 @@ extern int no_op_reg_to_regnum (int reg); extern CORE_ADDR default_frame_address (struct frame_info *); +/* Default prepare_to_procced. */ + +extern int default_prepare_to_proceed (int select_it); + +extern int generic_prepare_to_proceed (int select_it); #endif diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 5735315c2f..d84e41deb5 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -226,6 +226,7 @@ struct gdbarch gdbarch_memory_insert_breakpoint_ftype *memory_insert_breakpoint; gdbarch_memory_remove_breakpoint_ftype *memory_remove_breakpoint; CORE_ADDR decr_pc_after_break; + gdbarch_prepare_to_proceed_ftype *prepare_to_proceed; CORE_ADDR function_start_offset; gdbarch_remote_translate_xfer_address_ftype *remote_translate_xfer_address; CORE_ADDR frame_args_skip; @@ -380,6 +381,7 @@ struct gdbarch startup_gdbarch = 0, 0, 0, + 0, /* startup_gdbarch() */ }; @@ -457,6 +459,7 @@ gdbarch_alloc (const struct gdbarch_info *info, gdbarch->memory_insert_breakpoint = default_memory_insert_breakpoint; gdbarch->memory_remove_breakpoint = default_memory_remove_breakpoint; gdbarch->decr_pc_after_break = -1; + gdbarch->prepare_to_proceed = default_prepare_to_proceed; gdbarch->function_start_offset = -1; gdbarch->remote_translate_xfer_address = generic_remote_translate_xfer_address; gdbarch->frame_args_skip = -1; @@ -710,6 +713,7 @@ verify_gdbarch (struct gdbarch *gdbarch) && (gdbarch->decr_pc_after_break == -1)) internal_error (__FILE__, __LINE__, "gdbarch: verify_gdbarch: decr_pc_after_break invalid"); + /* Skip verify of prepare_to_proceed, invalid_p == 0 */ if ((GDB_MULTI_ARCH >= 2) && (gdbarch->function_start_offset == -1)) internal_error (__FILE__, __LINE__, @@ -1320,6 +1324,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: DECR_PC_AFTER_BREAK # %s\n", XSTRING (DECR_PC_AFTER_BREAK)); #endif +#ifdef PREPARE_TO_PROCEED + fprintf_unfiltered (file, + "gdbarch_dump: %s # %s\n", + "PREPARE_TO_PROCEED(select_it)", + XSTRING (PREPARE_TO_PROCEED (select_it))); +#endif #ifdef FUNCTION_START_OFFSET fprintf_unfiltered (file, "gdbarch_dump: FUNCTION_START_OFFSET # %s\n", @@ -2034,6 +2044,13 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: DECR_PC_AFTER_BREAK = %ld\n", (long) DECR_PC_AFTER_BREAK); #endif +#ifdef PREPARE_TO_PROCEED + if (GDB_MULTI_ARCH) + fprintf_unfiltered (file, + "gdbarch_dump: PREPARE_TO_PROCEED = 0x%08lx\n", + (long) current_gdbarch->prepare_to_proceed + /*PREPARE_TO_PROCEED ()*/); +#endif #ifdef FUNCTION_START_OFFSET fprintf_unfiltered (file, "gdbarch_dump: FUNCTION_START_OFFSET = %ld\n", @@ -3868,6 +3885,24 @@ set_gdbarch_decr_pc_after_break (struct gdbarch *gdbarch, gdbarch->decr_pc_after_break = decr_pc_after_break; } +int +gdbarch_prepare_to_proceed (struct gdbarch *gdbarch, int select_it) +{ + if (gdbarch->prepare_to_proceed == 0) + internal_error (__FILE__, __LINE__, + "gdbarch: gdbarch_prepare_to_proceed invalid"); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_prepare_to_proceed called\n"); + return gdbarch->prepare_to_proceed (select_it); +} + +void +set_gdbarch_prepare_to_proceed (struct gdbarch *gdbarch, + gdbarch_prepare_to_proceed_ftype prepare_to_proceed) +{ + gdbarch->prepare_to_proceed = prepare_to_proceed; +} + CORE_ADDR gdbarch_function_start_offset (struct gdbarch *gdbarch) { diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 34891a43b9..548d5a0e1e 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -1215,6 +1215,20 @@ extern void set_gdbarch_decr_pc_after_break (struct gdbarch *gdbarch, CORE_ADDR #endif #endif +/* Default (function) for non- multi-arch platforms. */ +#if (!GDB_MULTI_ARCH) && !defined (PREPARE_TO_PROCEED) +#define PREPARE_TO_PROCEED(select_it) (default_prepare_to_proceed (select_it)) +#endif + +typedef int (gdbarch_prepare_to_proceed_ftype) (int select_it); +extern int gdbarch_prepare_to_proceed (struct gdbarch *gdbarch, int select_it); +extern void set_gdbarch_prepare_to_proceed (struct gdbarch *gdbarch, gdbarch_prepare_to_proceed_ftype *prepare_to_proceed); +#if GDB_MULTI_ARCH +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (PREPARE_TO_PROCEED) +#define PREPARE_TO_PROCEED(select_it) (gdbarch_prepare_to_proceed (current_gdbarch, select_it)) +#endif +#endif + extern CORE_ADDR gdbarch_function_start_offset (struct gdbarch *gdbarch); extern void set_gdbarch_function_start_offset (struct gdbarch *gdbarch, CORE_ADDR function_start_offset); #if GDB_MULTI_ARCH diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 991ea13241..7517e41c26 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -489,6 +489,7 @@ f:2:BREAKPOINT_FROM_PC:unsigned char *:breakpoint_from_pc:CORE_ADDR *pcptr, int f:2:MEMORY_INSERT_BREAKPOINT:int:memory_insert_breakpoint:CORE_ADDR addr, char *contents_cache:addr, contents_cache::0:default_memory_insert_breakpoint::0 f:2:MEMORY_REMOVE_BREAKPOINT:int:memory_remove_breakpoint:CORE_ADDR addr, char *contents_cache:addr, contents_cache::0:default_memory_remove_breakpoint::0 v:2:DECR_PC_AFTER_BREAK:CORE_ADDR:decr_pc_after_break::::0:-1 +f::PREPARE_TO_PROCEED:int:prepare_to_proceed:int select_it:select_it::0:default_prepare_to_proceed::0 v:2:FUNCTION_START_OFFSET:CORE_ADDR:function_start_offset::::0:-1 # f:2:REMOTE_TRANSLATE_XFER_ADDRESS:void:remote_translate_xfer_address:CORE_ADDR gdb_addr, int gdb_len, CORE_ADDR *rem_addr, int *rem_len:gdb_addr, gdb_len, rem_addr, rem_len:::generic_remote_translate_xfer_address::0 diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 3a879088cd..855fcb344c 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -4591,7 +4591,10 @@ unwind_command (char *exp, int from_tty) For these reasons, we have to violate information hiding and call "breakpoint_here_p". If core gdb thinks there is a bpt here, that's what counts, as core gdb is the one which is - putting the BPT instruction in and taking it out. */ + putting the BPT instruction in and taking it out. + + Note that this implementation is potentially redundant now that + default_prepare_to_proceed() has been added. */ int hppa_prepare_to_proceed (void) { diff --git a/gdb/inferior.h b/gdb/inferior.h index d944deb218..b41e941a4d 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -261,6 +261,8 @@ extern int signal_print_update (int, int); extern int signal_pass_update (int, int); +extern void get_last_target_status(int *pid, struct target_waitstatus *status); + /* From infcmd.c */ extern void tty_command (char *, int); diff --git a/gdb/infrun.c b/gdb/infrun.c index 7c9a38c5ec..028fe0994a 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -406,6 +406,12 @@ static struct breakpoint *through_sigtramp_breakpoint = NULL; currently be running in a syscall. */ static int number_of_threads_in_syscalls; +/* This is a cached copy of the pid/waitstatus of the last event + returned by target_wait()/target_wait_hook(). This information is + returned by get_last_target_status(). */ +static int target_last_wait_pid = -1; +static struct target_waitstatus target_last_waitstatus; + /* This is used to remember when a fork, vfork or exec event was caught by a catchpoint, and thus the event is to be followed at the next resume of the inferior, and not @@ -1407,6 +1413,18 @@ check_for_old_step_resume_breakpoint (void) warning ("GDB bug: infrun.c (wait_for_inferior): dropping old step_resume breakpoint"); } +/* Return the cached copy of the last pid/waitstatus returned by + target_wait()/target_wait_hook(). The data is actually cached by + handle_inferior_event(), which gets called immediately after + target_wait()/target_wait_hook(). */ + +void +get_last_target_status(int *pid, struct target_waitstatus *status) +{ + *pid = target_last_wait_pid; + *status = target_last_waitstatus; +} + /* Given an execution control state that has been freshly filled in by an event from the inferior, figure out what it means and take appropriate action. */ @@ -1417,6 +1435,10 @@ handle_inferior_event (struct execution_control_state *ecs) CORE_ADDR tmp; int stepped_after_stopped_by_watchpoint; + /* Cache the last pid/waitstatus. */ + target_last_wait_pid = ecs->pid; + target_last_waitstatus = *ecs->wp; + /* Keep this extra brace for now, minimizes diffs. */ { switch (ecs->infwait_state) diff --git a/gdb/lin-lwp.c b/gdb/lin-lwp.c index 42e98de701..ee1b844c48 100644 --- a/gdb/lin-lwp.c +++ b/gdb/lin-lwp.c @@ -283,7 +283,11 @@ save_inferior_pid (void) } -/* Implementation of the PREPARE_TO_PROCEED hook for the Linux LWP layer. */ +/* Implementation of the PREPARE_TO_PROCEED hook for the Linux LWP + layer. + + Note that this implementation is potentially redundant now that + default_prepare_to_proceed() has been added. */ int lin_lwp_prepare_to_proceed (void) diff --git a/gdb/linux-thread.c b/gdb/linux-thread.c index d06e3f6444..8e73eb2fd8 100644 --- a/gdb/linux-thread.c +++ b/gdb/linux-thread.c @@ -1051,7 +1051,10 @@ quit: } /* If we have switched threads from a one that stopped at breakpoint, - return 1 otherwise 0. */ + return 1 otherwise 0. + + Note that this implementation is potentially redundant now that + default_prepare_to_proceed() has been added. */ int linuxthreads_prepare_to_proceed (int step) diff --git a/gdb/m3-nat.c b/gdb/m3-nat.c index 4fcf951d8e..3ff9835d0d 100644 --- a/gdb/m3-nat.c +++ b/gdb/m3-nat.c @@ -1573,6 +1573,8 @@ mach_thread_output_id (int mid) * if SELECT_IT is nonzero, reselect the thread that was active when * we stopped at a breakpoint. * + * Note that this implementation is potentially redundant now that + * default_prepare_to_proceed() has been added. */ mach3_prepare_to_proceed (int select_it) -- 2.34.1