+ LOG_DEBUG("target %s single-step thread %"PRIx64, target_name(ct), thread_id);
+ log_add_callback(gdb_log_callback, connection);
+ target_call_event_callbacks(ct, TARGET_EVENT_GDB_START);
+
+ /*
+ * work around an annoying gdb behaviour: when the current thread
+ * is changed in gdb, it assumes that the target can follow and also
+ * make the thread current. This is an assumption that cannot hold
+ * for a real target running a multi-threading OS. We just fake
+ * the step to not trigger an internal error in gdb. See
+ * https://sourceware.org/bugzilla/show_bug.cgi?id=22925 for details
+ */
+ if (fake_step) {
+ int sig_reply_len;
+ char sig_reply[128];
+
+ LOG_DEBUG("fake step thread %"PRIx64, thread_id);
+
+ sig_reply_len = snprintf(sig_reply, sizeof(sig_reply),
+ "T05thread:%016"PRIx64";", thread_id);
+
+ gdb_put_packet(connection, sig_reply, sig_reply_len);
+ log_remove_callback(gdb_log_callback, connection);
+
+ return true;
+ }
+
+ /* support for gdb_sync command */
+ if (gdb_connection->sync) {
+ gdb_connection->sync = false;
+ if (ct->state == TARGET_HALTED) {
+ LOG_WARNING("stepi ignored. GDB will now fetch the register state " \
+ "from the target.");
+ gdb_sig_halted(connection);
+ log_remove_callback(gdb_log_callback, connection);
+ } else
+ gdb_connection->frontend_state = TARGET_RUNNING;
+ return true;
+ }
+
+ retval = target_step(ct, current_pc, 0, 0);
+ if (retval == ERROR_TARGET_NOT_HALTED)
+ LOG_INFO("target %s was not halted when step was requested", target_name(ct));
+
+ /* if step was successful send a reply back to gdb */