+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.
+
2015-09-15 Yao Qi <yao.qi@linaro.org>
* aarch64-linux-nat.c (aarch64_linux_siginfo_fixup): New function.
return start <= addr && start + length - 1 >= addr;
}
+/* Implement the "to_can_do_single_step" target_ops method. */
+
+static int
+aarch64_linux_can_do_single_step (struct target_ops *target)
+{
+ return 1;
+}
+
/* Define AArch64 maintenance commands. */
static void
t->to_stopped_data_address = aarch64_linux_stopped_data_address;
t->to_watchpoint_addr_within_range =
aarch64_linux_watchpoint_addr_within_range;
+ t->to_can_do_single_step = aarch64_linux_can_do_single_step;
/* Override the GNU/Linux inferior startup hook. */
super_post_startup_inferior = t->to_post_startup_inferior;
if (arm_deal_with_atomic_sequence (frame))
return 1;
+ /* If the target does have hardware single step, GDB doesn't have
+ to bother software single step. */
+ if (target_can_do_single_step () == 1)
+ return 0;
+
next_pc = arm_get_next_pc (frame, get_frame_pc (frame));
/* The Linux kernel offers some user-mode helpers in a high page. We can
+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.
+
2015-09-11 Don Breazeal <donb@codesourcery.com>
* gdb.texinfo (Remote Configuration): Add exec event
extensions to the remote protocol. @value{GDBN} does not use such
extensions unless the stub also reports that it supports them by
including @samp{exec-events+} in its @samp{qSupported} reply.
+
+@item vContSupported
+This feature indicates whether @value{GDBN} wants to know the
+supported actions in the reply to @samp{vCont?} packet.
@end table
Stubs should ignore any unknown values for
@item exec-events
The remote stub reports the @samp{exec} stop reason for exec events.
+@item vContSupported
+The remote stub reports the supported actions in the reply to
+@samp{vCont?} packet.
+
@end table
@item qSymbol::
+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.
+
2015-09-15 Yao Qi <yao.qi@linaro.org>
* linux-low.c (linux_supports_conditional_breakpoints): Rename
int swbreak_feature;
int hwbreak_feature;
+/* True if the "vContSupported" feature is active. In that case, GDB
+ wants us to report whether single step is supported in the reply to
+ "vCont?" packet. */
+static int vCont_supported;
+
/* Whether we should attempt to disable the operating system's address
space randomization feature before starting an inferior. */
int disable_randomization = 1;
if (target_supports_exec_events ())
report_exec_events = 1;
}
+ else if (strcmp (p, "vContSupported+") == 0)
+ vCont_supported = 1;
else
target_process_qsupported (p);
if (the_target->pid_to_exec_file != NULL)
strcat (own_buf, ";qXfer:exec-file:read+");
+ strcat (own_buf, ";vContSupported+");
+
/* Reinitialize components as needed for the new connection. */
hostio_handle_new_gdb_connection ();
target_handle_new_gdb_connection ();
if (startswith (own_buf, "vCont?"))
{
- strcpy (own_buf, "vCont;c;C;s;S;t");
+ strcpy (own_buf, "vCont;c;C;t");
+
+ if (target_supports_hardware_single_step () || !vCont_supported)
+ {
+ /* If target supports hardware single step, add actions s
+ and S to the list of supported actions. On the other
+ hand, if GDB doesn't request the supported vCont actions
+ in qSupported packet, add s and S to the list too. */
+ own_buf = own_buf + strlen (own_buf);
+ strcpy (own_buf, ";s;S");
+ }
+
if (target_supports_range_stepping ())
{
own_buf = own_buf + strlen (own_buf);
cont_thread = null_ptid;
swbreak_feature = 0;
hwbreak_feature = 0;
+ vCont_supported = 0;
remote_open (port);
/* vCont;r */
int r;
+
+ /* vCont;s */
+ int s;
+
+ /* vCont;S */
+ int S;
};
/* Controls whether GDB is willing to use range stepping. */
/* Support for exec events. */
PACKET_exec_event_feature,
+ /* Support for query supported vCont actions. */
+ PACKET_vContSupported,
+
PACKET_MAX
};
{ "exec-events", PACKET_DISABLE, remote_supported_packet,
PACKET_exec_event_feature },
{ "Qbtrace-conf:pt:size", PACKET_DISABLE, remote_supported_packet,
- PACKET_Qbtrace_conf_pt_size }
+ PACKET_Qbtrace_conf_pt_size },
+ { "vContSupported", PACKET_DISABLE, remote_supported_packet, PACKET_vContSupported }
};
static char *remote_support_xml;
q = remote_query_supported_append (q, "exec-events+");
}
+ if (packet_set_cmd_state (PACKET_vContSupported) != AUTO_BOOLEAN_FALSE)
+ q = remote_query_supported_append (q, "vContSupported+");
+
q = reconcat (q, "qSupported:", q, (char *) NULL);
putpkt (q);
if (startswith (buf, "vCont"))
{
char *p = &buf[5];
- int support_s, support_S, support_c, support_C;
+ int support_c, support_C;
- support_s = 0;
- support_S = 0;
+ rs->supports_vCont.s = 0;
+ rs->supports_vCont.S = 0;
support_c = 0;
support_C = 0;
rs->supports_vCont.t = 0;
{
p++;
if (*p == 's' && (*(p + 1) == ';' || *(p + 1) == 0))
- support_s = 1;
+ rs->supports_vCont.s = 1;
else if (*p == 'S' && (*(p + 1) == ';' || *(p + 1) == 0))
- support_S = 1;
+ rs->supports_vCont.S = 1;
else if (*p == 'c' && (*(p + 1) == ';' || *(p + 1) == 0))
support_c = 1;
else if (*p == 'C' && (*(p + 1) == ';' || *(p + 1) == 0))
p = strchr (p, ';');
}
- /* If s, S, c, and C are not all supported, we can't use vCont. Clearing
- BUF will make packet_ok disable the packet. */
- if (!support_s || !support_S || !support_c || !support_C)
+ /* If c, and C are not all supported, we can't use vCont. Clearing
+ BUF will make packet_ok disable the packet. */
+ if (!support_c || !support_C)
buf[0] = 0;
}
return filename;
}
+/* Implement the to_can_do_single_step target_ops method. */
+
+static int
+remote_can_do_single_step (struct target_ops *ops)
+{
+ /* We can only tell whether target supports single step or not by
+ supported s and S vCont actions if the stub supports vContSupported
+ feature. If the stub doesn't support vContSupported feature,
+ we have conservatively to think target doesn't supports single
+ step. */
+ if (packet_support (PACKET_vContSupported) == PACKET_ENABLE)
+ {
+ struct remote_state *rs = get_remote_state ();
+
+ if (packet_support (PACKET_vCont) == PACKET_SUPPORT_UNKNOWN)
+ remote_vcont_probe (rs);
+
+ return rs->supports_vCont.s && rs->supports_vCont.S;
+ }
+ else
+ return 0;
+}
+
static void
init_remote_ops (void)
{
remote_ops.to_can_async_p = remote_can_async_p;
remote_ops.to_is_async_p = remote_is_async_p;
remote_ops.to_async = remote_async;
+ remote_ops.to_can_do_single_step = remote_can_do_single_step;
remote_ops.to_terminal_inferior = remote_terminal_inferior;
remote_ops.to_terminal_ours = remote_terminal_ours;
remote_ops.to_supports_non_stop = remote_supports_non_stop;
add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace_conf_pt_size],
"Qbtrace-conf:pt:size", "btrace-conf-pt-size", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vContSupported],
+ "vContSupported", "verbose-resume-supported", 0);
+
add_packet_config_cmd (&remote_protocol_packets[PACKET_exec_event_feature],
"exec-event-feature", "exec-event-feature", 0);
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)
{
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)
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;
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;
int (*to_masked_watch_num_registers) (struct target_ops *,
CORE_ADDR, CORE_ADDR)
TARGET_DEFAULT_RETURN (-1);
+
+ /* Return 1 for sure target can do single step. Return -1 for
+ unknown. Return 0 for target can't do. */
+ int (*to_can_do_single_step) (struct target_ops *)
+ TARGET_DEFAULT_RETURN (-1);
+
void (*to_terminal_init) (struct target_ops *)
TARGET_DEFAULT_IGNORE ();
void (*to_terminal_inferior) (struct target_ops *)
addr, len)
+#define target_can_do_single_step() \
+ (*current_target.to_can_do_single_step) (¤t_target)
+
/* Set/clear a hardware watchpoint starting at ADDR, for LEN bytes.
TYPE is 0 for write, 1 for read, and 2 for read/write accesses.
COND is the expression for its condition, or NULL if there's none.