From patchwork Fri Sep 11 12:13:22 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antoine Tremblay X-Patchwork-Id: 8635 Received: (qmail 1787 invoked by alias); 11 Sep 2015 12:14:33 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 1753 invoked by uid 89); 11 Sep 2015 12:14:32 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.6 required=5.0 tests=AWL, BAYES_40, SPF_PASS autolearn=ham version=3.3.2 X-HELO: usevmg20.ericsson.net Received: from usevmg20.ericsson.net (HELO usevmg20.ericsson.net) (198.24.6.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Fri, 11 Sep 2015 12:14:18 +0000 Received: from EUSAAHC003.ericsson.se (Unknown_Domain [147.117.188.81]) by usevmg20.ericsson.net (Symantec Mail Security) with SMTP id C0.AF.32596.9E662F55; Fri, 11 Sep 2015 07:30:17 +0200 (CEST) Received: from elxa4wqvvz1.dyn.mo.ca.am.ericsson.se (147.117.188.8) by smtps-am.internal.ericsson.com (147.117.188.81) with Microsoft SMTP Server (TLS) id 14.3.248.2; Fri, 11 Sep 2015 08:13:36 -0400 From: Antoine Tremblay To: CC: Antoine Tremblay Subject: [PATCH 6/7] Support conditional breakpoints on targets that can software single step in GDBServer. Date: Fri, 11 Sep 2015 08:13:22 -0400 Message-ID: <1441973603-15247-7-git-send-email-antoine.tremblay@ericsson.com> In-Reply-To: <1441973603-15247-1-git-send-email-antoine.tremblay@ericsson.com> References: <1441973603-15247-1-git-send-email-antoine.tremblay@ericsson.com> MIME-Version: 1.0 X-IsSubscribed: yes First a bit of background : Since this patch https://sourceware.org/ml/gdb-patches/2015-04/msg01110.html conditional breakpoints have been disabled on targets that do not support software single step properly. This was due to the get_next_pcs beeing to simple to be used or broken entirely. This in effect made the get_next_pcs callback implemented on those targets dead code since there is no situation in which a step over will occur as there is also no software breakpoint support on those targets. In fact the only purpose of the code after this change is to populate the function pointer so that can_hardware_single_step can return false since the previous way to know if a target supported hardware single step was to check if a software single step function was implemented. This patch cleans this up a bit so that targets that do support software single step properly can enable conditional breakpoints and that we do not keep dead code. It also makes it clear that if a target can't hardware or software single step memory breakpoints are not supported. To do this, on linux a new low target callback supports_hardware_single_step is implemented and is to return true if the target does support such a feature. This way can_hardware_single_step will use that callback rather than check if the get_next_pcs implementation is present. This enables the bad get_next_pcs functions to be removed and to be able to trust that if get_next_pcs is implemented it means that the target really supports software single step and that we can use it for conditional breakpoints for example. Note that the hardware single step support was enabled as per the current behavior, I did not check if tile for example really has ptrace singlestep support but since the current implementation assumed it had I kept it that way. No regressions, tested on ubuntu 14.04 ARMv7 and x86. Also compilation was tested on aarch64, bfin, cris, crisv32, m32r, mips, nios2, ppc, s390, sparc, tic6x, tile, xtensa gdb/gdbserver/ChangeLog: * linux-aarch64-low.c (aarch64_supports_hardware_single_step): New function. (struct linux_target_ops): New field supports_hardware_single_step. * linux-arm-low.c (arm_supports_hardware_single_step): New function. * linux-bfin-low.c (bfin_supports_hardware_single_step): Likewise. * linux-cris-low.c (cris_get_next_pcs): Remove. * linux-crisv32-low.c (cris_supports_hardware_single_step): New function. * linux-low.c (can_hardware_single_step): Use supports_hardware_single_step. (can_software_single_step): New function. (supports_breakpoints): Add single step support requirement. (linux_resume_one_lwp_throw): Add error if target can't single step. (start_step_over): Likewise. (linux_supports_software_single_step): New function. * linux-m32r-low.c (m32r_supports_hardware_single_step): New function. * linux-mips-low.c (mips_get_next_pcs): Remove. * linux-nios2-low.c (nios2_get_next_pcs): Remove. * linux-ppc-low.c (ppc_supports_hardware_single_step): New function. * linux-s390-low.c (s390_supports_hardware_single_step): Likewise. * linux-sh-low.c (sh_supports_hardware_single_step): Likewise. * linux-sparc-low.c (sparc_get_next_pcs): Remove. * linux-tic6x-low.c (tic6x_supports_hardware_single_step): New function. * linux-tile-low.c (tile_supports_hardware_single_step): Likewise. * linux-x86-low.c (x86_supports_hardware_single_step): Likewise. * linux-xtensa-low.c (xtensa_supports_hardware_single_step): Likewise. * server.c (handle_query): Support conditional breakpoints for software single step. * target.c (target_can_do_software_single_step): New function. * target.h (struct target_ops): New field target_can_do_software_single_step. --- gdb/gdbserver/linux-aarch64-low.c | 9 +++++++ gdb/gdbserver/linux-arm-low.c | 9 +++++++ gdb/gdbserver/linux-bfin-low.c | 28 +++++++++++++++++++++ gdb/gdbserver/linux-cris-low.c | 18 +------------ gdb/gdbserver/linux-crisv32-low.c | 41 +++++++++++++++++------------- gdb/gdbserver/linux-low.c | 53 +++++++++++++++++++++++++++++++-------- gdb/gdbserver/linux-low.h | 3 +++ gdb/gdbserver/linux-m32r-low.c | 28 +++++++++++++++++++++ gdb/gdbserver/linux-mips-low.c | 17 +------------ gdb/gdbserver/linux-nios2-low.c | 14 +---------- gdb/gdbserver/linux-ppc-low.c | 21 ++++++++++++++++ gdb/gdbserver/linux-s390-low.c | 21 ++++++++++++++++ gdb/gdbserver/linux-sh-low.c | 28 +++++++++++++++++++++ gdb/gdbserver/linux-sparc-low.c | 15 +---------- gdb/gdbserver/linux-tic6x-low.c | 28 +++++++++++++++++++++ gdb/gdbserver/linux-tile-low.c | 30 +++++++++++++++++++++- gdb/gdbserver/linux-x86-low.c | 9 +++++++ gdb/gdbserver/linux-xtensa-low.c | 28 +++++++++++++++++++++ gdb/gdbserver/server.c | 8 ++---- gdb/gdbserver/target.c | 7 ++++++ gdb/gdbserver/target.h | 9 +++++++ 21 files changed, 329 insertions(+), 95 deletions(-) diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c index 2956211..567ab98 100644 --- a/gdb/gdbserver/linux-aarch64-low.c +++ b/gdb/gdbserver/linux-aarch64-low.c @@ -571,6 +571,14 @@ aarch64_supports_range_stepping (void) return 1; } +/* Support for hardware single step. */ + +static int +aarch64_supports_hardware_single_step (void) +{ + return 1; +} + struct linux_target_ops the_low_target = { aarch64_arch_setup, @@ -603,6 +611,7 @@ struct linux_target_ops the_low_target = NULL, /* emit_ops */ NULL, /* get_min_fast_tracepoint_insn_len */ aarch64_supports_range_stepping, + aarch64_supports_hardware_single_step, }; void diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c index eb98a36..a9ed91d 100644 --- a/gdb/gdbserver/linux-arm-low.c +++ b/gdb/gdbserver/linux-arm-low.c @@ -1112,6 +1112,14 @@ arm_arch_setup (void) arm_set_byte_order (); } +/* Support for hardware single step. */ + +static int +arm_supports_hardware_single_step (void) +{ + return 0; +} + /* Register sets without using PTRACE_GETREGSET. */ static struct regset_info arm_regsets[] = { @@ -1190,6 +1198,7 @@ struct linux_target_ops the_low_target = { NULL, /* emit_ops */ NULL, /* get_min_fast_tracepoint_insn_len */ NULL, /* supports_range_stepping */ + arm_supports_hardware_single_step, }; void diff --git a/gdb/gdbserver/linux-bfin-low.c b/gdb/gdbserver/linux-bfin-low.c index 3032a34..18b8e43 100644 --- a/gdb/gdbserver/linux-bfin-low.c +++ b/gdb/gdbserver/linux-bfin-low.c @@ -103,6 +103,14 @@ bfin_arch_setup (void) current_process ()->tdesc = tdesc_bfin; } +/* Support for hardware single step. */ + +static int +bfin_supports_hardware_single_step (void) +{ + return 1; +} + static struct usrregs_info bfin_usrregs_info = { bfin_num_regs, @@ -133,6 +141,26 @@ struct linux_target_ops the_low_target = { NULL, /* get_next_pcs */ 2, bfin_breakpoint_at, + NULL, /* supports_z_point_type */ + NULL, /* insert_point */ + NULL, /* remove_point */ + NULL, /* stopped_by_watchpoint */ + NULL, /* stopped_data_address */ + NULL, /* collect_ptrace_register */ + NULL, /* supply_ptrace_register */ + NULL, /* siginfo_fixup */ + NULL, /* new_process */ + NULL, /* new_thread */ + NULL, /* new_fork */ + NULL, /* prepare_to_resume */ + NULL, /* process_qsupported */ + NULL, /* supports_tracepoints */ + NULL, /* get_thread_area */ + NULL, /* install_fast_tracepoint_jump_pad */ + NULL, /* emit_ops */ + NULL, /* get_min_fast_tracepoint_insn_len */ + NULL, /* supports_range_stepping */ + bfin_supports_hardware_single_step, }; diff --git a/gdb/gdbserver/linux-cris-low.c b/gdb/gdbserver/linux-cris-low.c index cd1ae4d..b56827e 100644 --- a/gdb/gdbserver/linux-cris-low.c +++ b/gdb/gdbserver/linux-cris-low.c @@ -104,18 +104,6 @@ cris_breakpoint_at (CORE_ADDR where) return 0; } -/* We only place breakpoints in empty marker functions, and thread locking - is outside of the function. So rather than importing software single-step, - we can just run until exit. */ -static void -cris_get_next_pcs (struct get_next_pcs *next_pcs) -{ - struct regcache *regcache = get_thread_regcache (current_thread, 1); - CORE_ADDR pc; - collect_register_by_name (regcache, "srp", &pc); - VEC_safe_push (CORE_ADDR, next_pcs->result, pc); -} - static void cris_arch_setup (void) { @@ -149,13 +137,9 @@ struct linux_target_ops the_low_target = { cris_get_pc, cris_set_pc, cris_breakpoint_from_pc, - cris_get_next_pcs, + NULL, 0, cris_breakpoint_at, - 0, - 0, - 0, - 0, }; void diff --git a/gdb/gdbserver/linux-crisv32-low.c b/gdb/gdbserver/linux-crisv32-low.c index 05ad85a..4e9ebc1 100644 --- a/gdb/gdbserver/linux-crisv32-low.c +++ b/gdb/gdbserver/linux-crisv32-low.c @@ -100,22 +100,6 @@ cris_breakpoint_at (CORE_ADDR where) return 0; } -/* We only place breakpoints in empty marker functions, and thread locking - is outside of the function. So rather than importing software single-step, - we can just run until exit. */ - -/* FIXME: This function should not be needed, since we have PTRACE_SINGLESTEP - for CRISv32. Without it, td_ta_event_getmsg in thread_db_create_event - will fail when debugging multi-threaded applications. */ -static void -cris_get_next_pcs (struct get_next_pcs *next_pcs) -{ - struct regcache *regcache = get_thread_regcache (current_thread, 1); - CORE_ADDR pc; - collect_register_by_name (regcache, "srp", &pc); - VEC_safe_push (CORE_ADDR, next_pcs->result, pc); -} - static void cris_write_data_breakpoint (struct regcache *regcache, int bp, unsigned long start, unsigned long end) @@ -386,6 +370,14 @@ cris_arch_setup (void) current_process ()->tdesc = tdesc_crisv32; } +/* Support for hardware single step. */ + +static int +cris_supports_hardware_single_step (void) +{ + return 1; +} + static struct regset_info cris_regsets[] = { { PTRACE_GETREGS, PTRACE_SETREGS, 0, cris_num_regs * 4, GENERAL_REGS, cris_fill_gregset, cris_store_gregset }, @@ -428,7 +420,7 @@ struct linux_target_ops the_low_target = { cris_get_pc, cris_set_pc, cris_breakpoint_from_pc, - cris_get_next_pcs, + NULL, 0, cris_breakpoint_at, cris_supports_z_point_type, @@ -436,6 +428,21 @@ struct linux_target_ops the_low_target = { cris_remove_point, cris_stopped_by_watchpoint, cris_stopped_data_address, + NULL, /* collect_ptrace_register */ + NULL, /* supply_ptrace_register */ + NULL, /* siginfo_fixup */ + NULL, /* new_process */ + NULL, /* new_thread */ + NULL, /* new_fork */ + NULL, /* prepare_to_resume */ + NULL, /* process_qsupported */ + NULL, /* supports_tracepoints */ + NULL, /* get_thread_area */ + NULL, /* install_fast_tracepoint_jump_pad */ + NULL, /* emit_ops */ + NULL, /* get_min_fast_tracepoint_insn_len */ + NULL, /* supports_range_stepping */ + cris_supports_hardware_single_step, }; void diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 229df46..f19769d 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -272,22 +272,35 @@ static void complete_ongoing_step_over (void); being stepped. */ ptid_t step_over_bkpt; -/* True if the low target can hardware single-step. Such targets - don't need a GET_NEXT_PCS callback. */ +/* True if the low target can hardware single-step. */ static int can_hardware_single_step (void) { - return (the_low_target.get_next_pcs == NULL); + if (the_low_target.supports_hardware_single_step != NULL) + return the_low_target.supports_hardware_single_step (); + else + return 0; +} + +/* True if the low target can software single-step. Such targets + implement the GET_NEXT_PCS callback. */ + +static int +can_software_single_step (void) +{ + return (the_low_target.get_next_pcs != NULL); } -/* True if the low target supports memory breakpoints. If so, we'll - have a GET_PC implementation. */ +/* True if the low target supports memory breakpoints. If so, we'll have a + GET_PC implementation. We will also need to support hardware or software + single stepping. */ static int supports_breakpoints (void) { - return (the_low_target.get_pc != NULL); + return (the_low_target.get_pc != NULL && + (can_hardware_single_step () || can_software_single_step ())); } /* Returns true if this target can support fast tracepoints. This @@ -4026,10 +4039,16 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp, { step = 1; } - else { - install_software_single_step_breakpoints (lwp); - step = 0; - } + else if (can_software_single_step ()) + { + install_software_single_step_breakpoints (lwp); + step = 0; + } + else + { + internal_error (__FILE__, __LINE__, + "stepping is not implemented on this target"); + } } if (proc->tdesc != NULL && the_low_target.get_pc != NULL) @@ -4439,11 +4458,16 @@ start_step_over (struct lwp_info *lwp) { step = 1; } - else + else if (can_software_single_step ()) { install_software_single_step_breakpoints (lwp); step = 0; } + else + { + internal_error (__FILE__, __LINE__, + "stepping is not implemented on this target"); + } current_thread = saved_thread; @@ -5638,6 +5662,12 @@ linux_supports_hardware_single_step (void) } static int +linux_supports_software_single_step (void) +{ + return can_software_single_step (); +} + +static int linux_stopped_by_watchpoint (void) { struct lwp_info *lwp = get_thread_lwp (current_thread); @@ -7064,6 +7094,7 @@ static struct target_ops linux_target_ops = { linux_mntns_unlink, linux_mntns_readlink, linux_breakpoint_from_pc, + linux_supports_software_single_step, }; static void diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h index 597c36d..b6f8175 100644 --- a/gdb/gdbserver/linux-low.h +++ b/gdb/gdbserver/linux-low.h @@ -240,6 +240,9 @@ struct linux_target_ops /* Returns true if the low target supports range stepping. */ int (*supports_range_stepping) (void); + + /* Returns true if the low target supports hardware single step. */ + int (*supports_hardware_single_step) (void); }; extern struct linux_target_ops the_low_target; diff --git a/gdb/gdbserver/linux-m32r-low.c b/gdb/gdbserver/linux-m32r-low.c index 4712a32..3767f35 100644 --- a/gdb/gdbserver/linux-m32r-low.c +++ b/gdb/gdbserver/linux-m32r-low.c @@ -101,6 +101,14 @@ m32r_arch_setup (void) current_process ()->tdesc = tdesc_m32r; } +/* Support for hardware single step. */ + +static int +m32r_supports_hardware_single_step (void) +{ + return 1; +} + static struct usrregs_info m32r_usrregs_info = { m32r_num_regs, @@ -131,6 +139,26 @@ struct linux_target_ops the_low_target = { NULL, 0, m32r_breakpoint_at, + NULL, /* supports_z_point_type */ + NULL, /* insert_point */ + NULL, /* remove_point */ + NULL, /* stopped_by_watchpoint */ + NULL, /* stopped_data_address */ + NULL, /* collect_ptrace_register */ + NULL, /* supply_ptrace_register */ + NULL, /* siginfo_fixup */ + NULL, /* new_process */ + NULL, /* new_thread */ + NULL, /* new_fork */ + NULL, /* prepare_to_resume */ + NULL, /* process_qsupported */ + NULL, /* supports_tracepoints */ + NULL, /* get_thread_area */ + NULL, /* install_fast_tracepoint_jump_pad */ + NULL, /* emit_ops */ + NULL, /* get_min_fast_tracepoint_insn_len */ + NULL, /* supports_range_stepping */ + m32r_supports_hardware_single_step, }; void diff --git a/gdb/gdbserver/linux-mips-low.c b/gdb/gdbserver/linux-mips-low.c index d462f2c..e752b7e 100644 --- a/gdb/gdbserver/linux-mips-low.c +++ b/gdb/gdbserver/linux-mips-low.c @@ -274,21 +274,6 @@ mips_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) return (const unsigned char *) &mips_breakpoint; } -/* We only place breakpoints in empty marker functions, and thread locking - is outside of the function. So rather than importing software single-step, - we can just run until exit. */ -static void -mips_get_next_pcs (struct get_next_pcs *next_pcs) -{ - CORE_ADDR result; - struct regcache *regcache = get_thread_regcache (current_thread, 1); - union mips_register ra; - collect_register_by_name (regcache, "r31", ra.buf); - result = register_size (regcache->tdesc, 0) == 4 ? ra.reg32 : ra.reg64; - - VEC_safe_push (CORE_ADDR, next_pcs->result, result); -} - static int mips_breakpoint_at (CORE_ADDR where) { @@ -893,7 +878,7 @@ struct linux_target_ops the_low_target = { mips_get_pc, mips_set_pc, mips_breakpoint_from_pc, - mips_get_next_pcs, + NULL, /* get_next_pcs */ 0, mips_breakpoint_at, mips_supports_z_point_type, diff --git a/gdb/gdbserver/linux-nios2-low.c b/gdb/gdbserver/linux-nios2-low.c index a24eb23..cb3addd 100644 --- a/gdb/gdbserver/linux-nios2-low.c +++ b/gdb/gdbserver/linux-nios2-low.c @@ -146,18 +146,6 @@ nios2_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) return (const unsigned char *) &nios2_breakpoint; } -/* Implement the get_next_pcs linux_target_ops method. */ - -static void -nios2_get_next_pcs (struct get_next_pcs *next_pcs) -{ - union nios2_register ra; - struct regcache *regcache = get_thread_regcache (current_thread, 1); - - collect_register_by_name (regcache, "ra", ra.buf); - VEC_safe_push (CORE_ADDR, next_pcs->result, ra.reg32); -} - /* Implement the breakpoint_at linux_target_ops method. */ static int @@ -280,7 +268,7 @@ struct linux_target_ops the_low_target = nios2_get_pc, nios2_set_pc, nios2_breakpoint_from_pc, - nios2_get_next_pcs, + NULL, /* get_next_pcs */ 0, nios2_breakpoint_at, }; diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c index fa87e19..4939cfa 100644 --- a/gdb/gdbserver/linux-ppc-low.c +++ b/gdb/gdbserver/linux-ppc-low.c @@ -641,6 +641,14 @@ ppc_store_evrregset (struct regcache *regcache, const void *buf) supply_register_by_name (regcache, "spefscr", ®set->spefscr); } +/* Support for hardware single step. */ + +static int +ppc_supports_hardware_single_step (void) +{ + return 1; +} + static struct regset_info ppc_regsets[] = { /* List the extra register sets before GENERAL_REGS. That way we will fetch them every time, but still fall back to PTRACE_PEEKUSER for the @@ -701,6 +709,19 @@ struct linux_target_ops the_low_target = { NULL, ppc_collect_ptrace_register, ppc_supply_ptrace_register, + NULL, /* siginfo_fixup */ + NULL, /* new_process */ + NULL, /* new_thread */ + NULL, /* new_fork */ + NULL, /* prepare_to_resume */ + NULL, /* process_qsupported */ + NULL, /* supports_tracepoints */ + NULL, /* get_thread_area */ + NULL, /* install_fast_tracepoint_jump_pad */ + NULL, /* emit_ops */ + NULL, /* get_min_fast_tracepoint_insn_len */ + NULL, /* supports_range_stepping */ + ppc_supports_hardware_single_step, }; void diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c index 44d3f26..794a621 100644 --- a/gdb/gdbserver/linux-s390-low.c +++ b/gdb/gdbserver/linux-s390-low.c @@ -611,6 +611,14 @@ s390_breakpoint_at (CORE_ADDR pc) return memcmp (c, s390_breakpoint, s390_breakpoint_len) == 0; } +/* Support for hardware single step. */ + +static int +s390_supports_hardware_single_step (void) +{ + return 1; +} + static struct usrregs_info s390_usrregs_info = { s390_num_regs, @@ -687,6 +695,19 @@ struct linux_target_ops the_low_target = { NULL, s390_collect_ptrace_register, s390_supply_ptrace_register, + NULL, /* siginfo_fixup */ + NULL, /* new_process */ + NULL, /* new_thread */ + NULL, /* new_fork */ + NULL, /* prepare_to_resume */ + NULL, /* process_qsupported */ + NULL, /* supports_tracepoints */ + NULL, /* get_thread_area */ + NULL, /* install_fast_tracepoint_jump_pad */ + NULL, /* emit_ops */ + NULL, /* get_min_fast_tracepoint_insn_len */ + NULL, /* supports_range_stepping */ + s390_supports_hardware_single_step, }; void diff --git a/gdb/gdbserver/linux-sh-low.c b/gdb/gdbserver/linux-sh-low.c index 5c11fd7..6a210bf 100644 --- a/gdb/gdbserver/linux-sh-low.c +++ b/gdb/gdbserver/linux-sh-low.c @@ -98,6 +98,14 @@ sh_breakpoint_at (CORE_ADDR where) return 0; } +/* Support for hardware single step. */ + +static int +sh_supports_hardware_single_step (void) +{ + return 1; +} + /* Provide only a fill function for the general register set. ps_lgetregs will use this for NPTL support. */ @@ -159,6 +167,26 @@ struct linux_target_ops the_low_target = { NULL, 0, sh_breakpoint_at, + NULL, /* supports_z_point_type */ + NULL, /* insert_point */ + NULL, /* remove_point */ + NULL, /* stopped_by_watchpoint */ + NULL, /* stopped_data_address */ + NULL, /* collect_ptrace_register */ + NULL, /* supply_ptrace_register */ + NULL, /* siginfo_fixup */ + NULL, /* new_process */ + NULL, /* new_thread */ + NULL, /* new_fork */ + NULL, /* prepare_to_resume */ + NULL, /* process_qsupported */ + NULL, /* supports_tracepoints */ + NULL, /* get_thread_area */ + NULL, /* install_fast_tracepoint_jump_pad */ + NULL, /* emit_ops */ + NULL, /* get_min_fast_tracepoint_insn_len */ + NULL, /* supports_range_stepping */ + sh_supports_hardware_single_step, }; void diff --git a/gdb/gdbserver/linux-sparc-low.c b/gdb/gdbserver/linux-sparc-low.c index e804281..25546e3 100644 --- a/gdb/gdbserver/linux-sparc-low.c +++ b/gdb/gdbserver/linux-sparc-low.c @@ -264,19 +264,6 @@ sparc_breakpoint_at (CORE_ADDR where) return 0; } -/* We only place breakpoints in empty marker functions, and thread locking - is outside of the function. So rather than importing software single-step, - we can just run until exit. */ -static void -sparc_get_next_pcs (struct get_next_pcs *next_pcs) -{ - struct regcache *regcache = get_thread_regcache (current_thread, 1); - CORE_ADDR lr; - /* O7 is the equivalent to the 'lr' of other archs. */ - collect_register_by_name (regcache, "o7", &lr); - VEC_safe_push (CORE_ADDR, next_pcs->result, lr); -} - static void sparc_arch_setup (void) { @@ -331,7 +318,7 @@ struct linux_target_ops the_low_target = { /* No sparc_set_pc is needed. */ NULL, sparc_breakpoint_from_pc, - sparc_get_next_pcs, + NULL, 0, sparc_breakpoint_at, NULL, /* supports_z_point_type */ diff --git a/gdb/gdbserver/linux-tic6x-low.c b/gdb/gdbserver/linux-tic6x-low.c index 86b433c..22bffe2 100644 --- a/gdb/gdbserver/linux-tic6x-low.c +++ b/gdb/gdbserver/linux-tic6x-low.c @@ -339,6 +339,14 @@ tic6x_arch_setup (void) current_process ()->tdesc = tic6x_read_description (); } +/* Support for hardware single step. */ + +static int +tic6x_supports_hardware_single_step (void) +{ + return 1; +} + static struct regsets_info tic6x_regsets_info = { tic6x_regsets, /* regsets */ @@ -377,6 +385,26 @@ struct linux_target_ops the_low_target = { NULL, 0, tic6x_breakpoint_at, + NULL, /* supports_z_point_type */ + NULL, /* insert_point */ + NULL, /* remove_point */ + NULL, /* stopped_by_watchpoint */ + NULL, /* stopped_data_address */ + NULL, /* collect_ptrace_register */ + NULL, /* supply_ptrace_register */ + NULL, /* siginfo_fixup */ + NULL, /* new_process */ + NULL, /* new_thread */ + NULL, /* new_fork */ + NULL, /* prepare_to_resume */ + NULL, /* process_qsupported */ + NULL, /* supports_tracepoints */ + NULL, /* get_thread_area */ + NULL, /* install_fast_tracepoint_jump_pad */ + NULL, /* emit_ops */ + NULL, /* get_min_fast_tracepoint_insn_len */ + NULL, /* supports_range_stepping */ + tic6x_supports_hardware_single_step, }; void diff --git a/gdb/gdbserver/linux-tile-low.c b/gdb/gdbserver/linux-tile-low.c index 802812b..b712b81 100644 --- a/gdb/gdbserver/linux-tile-low.c +++ b/gdb/gdbserver/linux-tile-low.c @@ -179,6 +179,14 @@ tile_arch_setup (void) current_process ()->tdesc = tdesc_tilegx; } +/* Support for hardware single step. */ + +static int +tile_supports_hardware_single_step (void) +{ + return 1; +} + struct linux_target_ops the_low_target = { @@ -190,9 +198,29 @@ struct linux_target_ops the_low_target = tile_get_pc, tile_set_pc, tile_breakpoint_from_pc, - NULL, + NULL, /* get_next_pcs */ 0, tile_breakpoint_at, + NULL, /* supports_z_point_type */ + NULL, /* insert_point */ + NULL, /* remove_point */ + NULL, /* stopped_by_watchpoint */ + NULL, /* stopped_data_address */ + NULL, /* collect_ptrace_register */ + NULL, /* supply_ptrace_register */ + NULL, /* siginfo_fixup */ + NULL, /* new_process */ + NULL, /* new_thread */ + NULL, /* new_fork */ + NULL, /* prepare_to_resume */ + NULL, /* process_qsupported */ + NULL, /* supports_tracepoints */ + NULL, /* get_thread_area */ + NULL, /* install_fast_tracepoint_jump_pad */ + NULL, /* emit_ops */ + NULL, /* get_min_fast_tracepoint_insn_len */ + NULL, /* supports_range_stepping */ + tile_supports_hardware_single_step, }; void diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c index 0731141..0c5b6a2 100644 --- a/gdb/gdbserver/linux-x86-low.c +++ b/gdb/gdbserver/linux-x86-low.c @@ -3256,6 +3256,14 @@ x86_supports_range_stepping (void) return 1; } +/* Support for hardware single step. */ + +static int +x86_supports_hardware_single_step (void) +{ + return 1; +} + /* This is initialized assuming an amd64 target. x86_arch_setup will correct it for i386 or amd64 targets. */ @@ -3295,6 +3303,7 @@ struct linux_target_ops the_low_target = x86_emit_ops, x86_get_min_fast_tracepoint_insn_len, x86_supports_range_stepping, + x86_supports_hardware_single_step, }; void diff --git a/gdb/gdbserver/linux-xtensa-low.c b/gdb/gdbserver/linux-xtensa-low.c index 1e2cf94..432b1b7 100644 --- a/gdb/gdbserver/linux-xtensa-low.c +++ b/gdb/gdbserver/linux-xtensa-low.c @@ -227,6 +227,14 @@ xtensa_arch_setup (void) current_process ()->tdesc = tdesc_xtensa; } +/* Support for hardware single step. */ + +static int +xtensa_supports_hardware_single_step (void) +{ + return 1; +} + static const struct regs_info * xtensa_regs_info (void) { @@ -245,6 +253,26 @@ struct linux_target_ops the_low_target = { NULL, 0, xtensa_breakpoint_at, + NULL, /* supports_z_point_type */ + NULL, /* insert_point */ + NULL, /* remove_point */ + NULL, /* stopped_by_watchpoint */ + NULL, /* stopped_data_address */ + NULL, /* collect_ptrace_register */ + NULL, /* supply_ptrace_register */ + NULL, /* siginfo_fixup */ + NULL, /* new_process */ + NULL, /* new_thread */ + NULL, /* new_fork */ + NULL, /* prepare_to_resume */ + NULL, /* process_qsupported */ + NULL, /* supports_tracepoints */ + NULL, /* get_thread_area */ + NULL, /* install_fast_tracepoint_jump_pad */ + NULL, /* emit_ops */ + NULL, /* get_min_fast_tracepoint_insn_len */ + NULL, /* supports_range_stepping */ + xtensa_supports_hardware_single_step, }; diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 5c0d83d..fb0e843 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -2192,13 +2192,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) strcat (own_buf, ";tracenz+"); } - if (target_supports_hardware_single_step ()) + if (target_supports_hardware_single_step () || + target_supports_software_single_step () ) { - /* Support target-side breakpoint conditions and commands. - GDBserver needs to step over the breakpoint if the condition - is false. GDBserver software single step is too simple, so - disable conditional breakpoints if the target doesn't have - hardware single step. */ strcat (own_buf, ";ConditionalBreakpoints+"); } strcat (own_buf, ";BreakpointCommands+"); diff --git a/gdb/gdbserver/target.c b/gdb/gdbserver/target.c index 17ff7a6..1ae42cc 100644 --- a/gdb/gdbserver/target.c +++ b/gdb/gdbserver/target.c @@ -224,3 +224,10 @@ target_can_do_hardware_single_step (void) { return 1; } + +/* Target can do software single step. */ +int +target_can_do_software_single_step (void) +{ + return 0; +} diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h index fc2dbd7..aa40c4a 100644 --- a/gdb/gdbserver/target.h +++ b/gdb/gdbserver/target.h @@ -443,6 +443,9 @@ struct target_ops can be NULL, the default breakpoint for the target should be returned in this case. */ const unsigned char *(*breakpoint_from_pc) (CORE_ADDR *pcptr, int *lenptr); + + /* Returns true if the target can do software single step. */ + int (*supports_software_single_step) (void); }; extern struct target_ops *the_target; @@ -621,6 +624,10 @@ int kill_inferior (int); (the_target->stopped_by_hw_breakpoint ? \ (*the_target->stopped_by_hw_breakpoint) () : 0) +#define target_supports_software_single_step() \ + (the_target->supports_software_single_step ? \ + (*the_target->supports_software_single_step) () : 0) + /* Start non-stop mode, returns 0 on success, -1 on failure. */ int start_non_stop (int nonstop); @@ -655,4 +662,6 @@ const char *target_pid_to_str (ptid_t); int target_can_do_hardware_single_step (void); +int target_can_do_software_single_step (void); + #endif /* TARGET_H */