+static bool gdb_handle_vcont_packet(struct connection *connection, const char *packet, int packet_size)
+{
+ struct gdb_connection *gdb_connection = connection->priv;
+ struct target *target = get_target_from_connection(connection);
+ const char *parse = packet;
+ int retval;
+
+ /* query for vCont supported */
+ if (parse[0] == '?') {
+ if (target->type->step != NULL) {
+ /* gdb doesn't accept c without C and s without S */
+ gdb_put_packet(connection, "vCont;c;C;s;S", 13);
+ return true;
+ }
+ return false;
+ }
+
+ if (parse[0] == ';') {
+ ++parse;
+ --packet_size;
+ }
+
+ /* simple case, a continue packet */
+ if (parse[0] == 'c') {
+ LOG_DEBUG("target %s continue", target_name(target));
+ log_add_callback(gdb_log_callback, connection);
+ retval = target_resume(target, 1, 0, 0, 0);
+ if (retval == ERROR_OK) {
+ gdb_connection->frontend_state = TARGET_RUNNING;
+ target_call_event_callbacks(target, TARGET_EVENT_GDB_START);
+ }
+ return true;
+ }
+
+ /* single-step or step-over-breakpoint */
+ if (parse[0] == 's') {
+ if (strncmp(parse, "s:", 2) == 0) {
+ int handle_breakpoint = 1;
+ struct target *ct = target;
+ int64_t thread_id;
+ char *endp;
+
+ parse += 2;
+ packet_size -= 2;
+
+ thread_id = strtoll(parse, &endp, 16);
+ if (endp != NULL) {
+ packet_size -= endp - parse;
+ parse = endp;
+ }
+
+ if (parse[0] == ';') {
+ ++parse;
+ --packet_size;
+
+ if (parse[0] == 'c') {
+ parse += 1;
+ packet_size -= 1;
+
+ handle_breakpoint = 0;
+ }
+ }
+
+ LOG_DEBUG("target %s single-step thread %"PRId64, target_name(ct), thread_id);
+ retval = target_step(ct, 1, 0, handle_breakpoint);
+ if (retval == ERROR_OK) {
+ gdb_signal_reply(target, connection);
+ /* stop forwarding log packets! */
+ log_remove_callback(gdb_log_callback, connection);
+ } else
+ if (retval == ERROR_TARGET_TIMEOUT) {
+ gdb_connection->frontend_state = TARGET_RUNNING;
+ target_call_event_callbacks(ct, TARGET_EVENT_GDB_START);
+ }
+ } else {
+ LOG_ERROR("Unknown vCont packet");
+ return false;
+ }
+ return true;
+ }
+
+ return false;
+}
+