From 65a7e4d60ff61d720e7b1755937fa7e871ef8e4b Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Tue, 7 Apr 2020 11:30:46 -0400 Subject: [PATCH] gdb: add target_ops::supports_displaced_step A previous patch added some `displaced_step_prepare` and `displaced_step_finish` methods to allow a target_ops to implement displaced stepping. The default implementation is to defer to the gdbarch. However, there is still a `gdbarch_supports_displaced_stepping` check in infrun.c, that decides if we should use displaced stepping or not. So if a target_ops implemented displaced stepping, independently of the gdbarch, displaced stepping wouldn't be used. Add the target_ops::supports_displaced_step method, with a default behavior of checking if the gdbarch supports it (which is in sync with the default implementations of displaced_step_prepare and displaced_step_finish). --- gdb/displaced-stepping.c | 11 ++++++++++- gdb/displaced-stepping.h | 2 ++ gdb/infrun.c | 23 ++++++++++------------- gdb/target-delegates.c | 28 ++++++++++++++++++++++++++++ gdb/target.h | 3 +++ 5 files changed, 53 insertions(+), 14 deletions(-) diff --git a/gdb/displaced-stepping.c b/gdb/displaced-stepping.c index 3fafeb2bf9..19df11e24e 100644 --- a/gdb/displaced-stepping.c +++ b/gdb/displaced-stepping.c @@ -187,8 +187,17 @@ multiple_displaced_buffer_manager::finish (gdbarch *arch, thread_info *thread, return status; } +bool +default_supports_displaced_step (target_ops *target, thread_info *thread) +{ + /* Only check for the presence of `prepare`. `finish` is required by the + gdbarch verification to be provided if `prepare` is. */ + gdbarch *arch = thread->arch (); + return gdbarch_displaced_step_prepare_p (arch); +} + displaced_step_prepare_status - default_displaced_step_prepare (target_ops *target, thread_info *thread) +default_displaced_step_prepare (target_ops *target, thread_info *thread) { gdbarch *arch = thread->arch (); return gdbarch_displaced_step_prepare (arch, thread); diff --git a/gdb/displaced-stepping.h b/gdb/displaced-stepping.h index c46f99f549..515d4b1903 100644 --- a/gdb/displaced-stepping.h +++ b/gdb/displaced-stepping.h @@ -152,6 +152,8 @@ private: std::vector m_buffers; }; +bool default_supports_displaced_step (target_ops *target, thread_info *thread); + displaced_step_prepare_status default_displaced_step_prepare (target_ops *target, thread_info *thread); diff --git a/gdb/infrun.c b/gdb/infrun.c index 90d5b2717e..de09bb0383 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -1603,15 +1603,15 @@ show_can_use_displaced_stepping (struct ui_file *file, int from_tty, "to step over breakpoints is %s.\n"), value); } -/* Return true if the gdbarch implements the required methods to use - displaced stepping. */ +/* Return true if the target behing THREAD supports displaced stepping. */ static bool -gdbarch_supports_displaced_stepping (gdbarch *arch) +target_supports_displaced_stepping (thread_info *thread) { - /* Only check for the presence of `prepare`. `finish` is required by the - gdbarch verification to be provided if `prepare` is provided. */ - return gdbarch_displaced_step_prepare_p (arch); + inferior *inf = thread->inf; + target_ops *target = inf->top_target (); + + return target->supports_displaced_step (thread); } /* Return non-zero if displaced stepping can/should be used to step @@ -1630,11 +1630,8 @@ use_displaced_stepping (thread_info *tp) && !target_is_non_stop_p ()) return false; - gdbarch *gdbarch = get_thread_regcache (tp)->arch (); - - /* If the architecture doesn't implement displaced stepping, don't use - it. */ - if (!gdbarch_supports_displaced_stepping (gdbarch)) + /* If the target doesn't support displaced stepping, don't use it. */ + if (!target_supports_displaced_stepping (tp)) return false; /* If recording, don't use displaced stepping. */ @@ -1702,9 +1699,9 @@ displaced_step_prepare_throw (thread_info *tp) displaced_step_thread_state *thread_disp_step_state = get_displaced_stepping_state (tp); - /* We should never reach this function if the architecture does not + /* We should never reach this function if the target does not support displaced stepping. */ - gdb_assert (gdbarch_supports_displaced_stepping (gdbarch)); + gdb_assert (target_supports_displaced_stepping (tp)); /* Nor if the thread isn't meant to step over a breakpoint. */ gdb_assert (tp->control.trap_expected); diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c index 14206c1375..4586fc7c26 100644 --- a/gdb/target-delegates.c +++ b/gdb/target-delegates.c @@ -171,6 +171,7 @@ struct dummy_target : public target_ops const struct frame_unwind *get_tailcall_unwinder () override; void prepare_to_generate_core () override; void done_generating_core () override; + bool supports_displaced_step (thread_info *arg0) override; displaced_step_prepare_status displaced_step_prepare (thread_info *arg0) override; displaced_step_finish_status displaced_step_finish (thread_info *arg0, gdb_signal arg1) override; }; @@ -342,6 +343,7 @@ struct debug_target : public target_ops const struct frame_unwind *get_tailcall_unwinder () override; void prepare_to_generate_core () override; void done_generating_core () override; + bool supports_displaced_step (thread_info *arg0) override; displaced_step_prepare_status displaced_step_prepare (thread_info *arg0) override; displaced_step_finish_status displaced_step_finish (thread_info *arg0, gdb_signal arg1) override; }; @@ -4367,6 +4369,32 @@ debug_target::done_generating_core () fputs_unfiltered (")\n", gdb_stdlog); } +bool +target_ops::supports_displaced_step (thread_info *arg0) +{ + return this->beneath ()->supports_displaced_step (arg0); +} + +bool +dummy_target::supports_displaced_step (thread_info *arg0) +{ + return default_supports_displaced_step (this, arg0); +} + +bool +debug_target::supports_displaced_step (thread_info *arg0) +{ + bool result; + fprintf_unfiltered (gdb_stdlog, "-> %s->supports_displaced_step (...)\n", this->beneath ()->shortname ()); + result = this->beneath ()->supports_displaced_step (arg0); + fprintf_unfiltered (gdb_stdlog, "<- %s->supports_displaced_step (", this->beneath ()->shortname ()); + target_debug_print_thread_info_p (arg0); + fputs_unfiltered (") = ", gdb_stdlog); + target_debug_print_bool (result); + fputs_unfiltered ("\n", gdb_stdlog); + return result; +} + displaced_step_prepare_status target_ops::displaced_step_prepare (thread_info *arg0) { diff --git a/gdb/target.h b/gdb/target.h index 255c71fef0..f2bb55e4bd 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -1254,6 +1254,9 @@ struct target_ops virtual void done_generating_core () TARGET_DEFAULT_IGNORE (); + virtual bool supports_displaced_step (thread_info *thread) + TARGET_DEFAULT_FUNC (default_supports_displaced_step); + virtual displaced_step_prepare_status displaced_step_prepare (thread_info *thread) TARGET_DEFAULT_FUNC (default_displaced_step_prepare); -- 2.34.1