aboutsummaryrefslogtreecommitdiff
path: root/gdb/target-delegates.c
diff options
context:
space:
mode:
authorYao Qi <yao.qi@linaro.org>2015-09-15 14:09:18 +0100
committerYao Qi <yao.qi@linaro.org>2015-09-15 14:09:18 +0100
commit750ce8d1caf237464dd663de54ad055c0e58409d (patch)
tree8b3b9244ca6dbead401eb5f7a307724540763751 /gdb/target-delegates.c
parent70b90b91bf77e72a36abdef039234359195b1942 (diff)
downloadgdb-750ce8d1caf237464dd663de54ad055c0e58409d.zip
gdb-750ce8d1caf237464dd663de54ad055c0e58409d.tar.gz
gdb-750ce8d1caf237464dd663de54ad055c0e58409d.tar.bz2
Support single step by arch or target
Nowadays, GDB only knows whether architecture supports hardware single step or software single step (through gdbarch hook software_single_step), and for a given instruction or instruction sequence, GDB knows how to do single step (hardware or software). However, GDB doesn't know whether the target supports hardware single step. It is possible that the architecture doesn't support hardware single step, such as arm, but the target supports, such as simulator. This was discussed in this thread https://www.sourceware.org/ml/gdb/2009-12/msg00033.html before. I encounter this problem for aarch64 multi-arch support. When aarch64 debugs arm program, gdbarch is arm, so software single step is still used. However, the underneath linux kernel does support hardware single step, so IWBN to use it. This patch is to add a new target_ops hook to_can_do_single_step, and only use it in arm_linux_software_single_step to decide whether or not to use hardware single step. On the native aarch64 linux target, 1 is returned. On other targets, -1 is returned. On the remote target, if the target supports s and S actions in the vCont? reply, then target can do single step. However, old GDBserver will send s and S in the reply to vCont?, which will confuse new GDB. For example, old GDBserver on arm-linux will send s and S in the reply to vCont?, but it doesn't support hardware single step. On the other hand, new GDBserver, on arm-linux for example, will not send s and S in the reply to vCont?, but old GDB thinks it doesn't support vCont packet at all. In order to address this problem, I add a new qSupported feature vContSupported, which indicates GDB wants to know the supported actions in the reply to vCont?, and qSupported response contains vContSupported if the stub is able tell supported vCont actions in the reply of vCont?. If the patched GDB talks with patched GDBserver on x86, the RSP traffic is like this: -> $qSupported:...+;vContSupported+ <- ...+;vContSupported+ ... -> $vCont? <- vCont;c;C;t;s;S;r then, GDB knows the stub can do single step, and may stop using software single step even the architecture doesn't support hardware single step. If the patched GDB talks with patched GDBserver on arm, the last vCont? reply will become: <- vCont;c;C;t GDB thinks the target doesn't support single step, so it will use software single step. If the patched GDB talks with unpatched GDBserver, the RSP traffic is like this: -> $qSupported:...+;vContSupported+ <- ...+ ... -> $vCont? <- vCont;c;C;t;s;S;r although GDBserver returns s and S, GDB still thinks GDBserver may not support single step because it doesn't support vContSupported. If the unpatched GDB talks with patched GDBserver on x86, the RSP traffic is like: -> $qSupported:...+; <- ...+;vContSupported+ ... -> $vCont? <- vCont;c;C;t;s;S;r Since GDB doesn't sent vContSupported in the qSupported feature, GDBserver sends s and S regardless of the support of hardware single step. gdb: 2015-09-15 Yao Qi <yao.qi@linaro.org> * aarch64-linux-nat.c (aarch64_linux_can_do_single_step): New function. (_initialize_aarch64_linux_nat): Install it to to_can_do_single_step. * arm-linux-tdep.c (arm_linux_software_single_step): Return 0 if target_can_do_single_step returns 1. * remote.c (struct vCont_action_support) <s, S>: New fields. (PACKET_vContSupported): New enum. (remote_protocol_features): New element for vContSupported. (remote_query_supported): Append "vContSupported+". (remote_vcont_probe): Remove support_s and support_S, use rs->supports_vCont.s and rs->supports_vCont.S instead. Disable vCont packet if c and C actions are not supported. (remote_can_do_single_step): New function. (init_remote_ops): Install it to to_can_do_single_step. (_initialize_remote): Call add_packet_config_cmd. * target.h (struct target_ops) <to_can_do_single_step>: New field. (target_can_do_single_step): New macro. * target-delegates.c: Re-generated. gdb/gdbserver: 2015-09-15 Yao Qi <yao.qi@linaro.org> * server.c (vCont_supported): New global variable. (handle_query): Set vCont_supported to 1 if "vContSupported+" matches. Append ";vContSupported+" to own_buf. (handle_v_requests): Append ";s;S" to own_buf if target supports hardware single step or vCont_supported is false. (capture_main): Set vCont_supported to zero. gdb/doc: 2015-09-15 Yao Qi <yao.qi@linaro.org> * gdb.texinfo (General Query Packets): Add vContSupported to tables of 'gdbfeatures' and 'stub features' supported in the qSupported packet, as well as to the list containing stub feature details.
Diffstat (limited to 'gdb/target-delegates.c')
-rw-r--r--gdb/target-delegates.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index 87197f8..c358814 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -826,6 +826,33 @@ debug_masked_watch_num_registers (struct target_ops *self, CORE_ADDR arg1, CORE_
return result;
}
+static int
+delegate_can_do_single_step (struct target_ops *self)
+{
+ self = self->beneath;
+ return self->to_can_do_single_step (self);
+}
+
+static int
+tdefault_can_do_single_step (struct target_ops *self)
+{
+ return -1;
+}
+
+static int
+debug_can_do_single_step (struct target_ops *self)
+{
+ int result;
+ fprintf_unfiltered (gdb_stdlog, "-> %s->to_can_do_single_step (...)\n", debug_target.to_shortname);
+ result = debug_target.to_can_do_single_step (&debug_target);
+ fprintf_unfiltered (gdb_stdlog, "<- %s->to_can_do_single_step (", debug_target.to_shortname);
+ target_debug_print_struct_target_ops_p (&debug_target);
+ fputs_unfiltered (") = ", gdb_stdlog);
+ target_debug_print_int (result);
+ fputs_unfiltered ("\n", gdb_stdlog);
+ return result;
+}
+
static void
delegate_terminal_init (struct target_ops *self)
{
@@ -4028,6 +4055,8 @@ install_delegators (struct target_ops *ops)
ops->to_can_accel_watchpoint_condition = delegate_can_accel_watchpoint_condition;
if (ops->to_masked_watch_num_registers == NULL)
ops->to_masked_watch_num_registers = delegate_masked_watch_num_registers;
+ if (ops->to_can_do_single_step == NULL)
+ ops->to_can_do_single_step = delegate_can_do_single_step;
if (ops->to_terminal_init == NULL)
ops->to_terminal_init = delegate_terminal_init;
if (ops->to_terminal_inferior == NULL)
@@ -4298,6 +4327,7 @@ install_dummy_methods (struct target_ops *ops)
ops->to_region_ok_for_hw_watchpoint = default_region_ok_for_hw_watchpoint;
ops->to_can_accel_watchpoint_condition = tdefault_can_accel_watchpoint_condition;
ops->to_masked_watch_num_registers = tdefault_masked_watch_num_registers;
+ ops->to_can_do_single_step = tdefault_can_do_single_step;
ops->to_terminal_init = tdefault_terminal_init;
ops->to_terminal_inferior = tdefault_terminal_inferior;
ops->to_terminal_ours_for_output = tdefault_terminal_ours_for_output;
@@ -4450,6 +4480,7 @@ init_debug_target (struct target_ops *ops)
ops->to_region_ok_for_hw_watchpoint = debug_region_ok_for_hw_watchpoint;
ops->to_can_accel_watchpoint_condition = debug_can_accel_watchpoint_condition;
ops->to_masked_watch_num_registers = debug_masked_watch_num_registers;
+ ops->to_can_do_single_step = debug_can_do_single_step;
ops->to_terminal_init = debug_terminal_init;
ops->to_terminal_inferior = debug_terminal_inferior;
ops->to_terminal_ours_for_output = debug_terminal_ours_for_output;