- {
- int retval = ERROR_OK;
-
- struct gdb_connection *gdb_con = connection->priv;
- log_add_callback(gdb_log_callback, connection);
-
- bool nostep = false;
- if (target->state == TARGET_RUNNING)
- {
- LOG_WARNING("The target is already running. Halt target before stepi/continue.");
- retval = target_halt(target);
- if (retval == ERROR_OK)
- retval = target_wait_state(target, TARGET_HALTED, 100);
- } else if (target->state != TARGET_HALTED)
- {
- LOG_WARNING("The target is not in the halted nor running stated, stepi/continue ignored.");
- nostep = true;
- } else if ((packet[0] == 's') && gdb_con->sync)
- {
- /* Hmm..... when you issue a continue in GDB, then a "stepi" is
- * sent by GDB first to OpenOCD, thus defeating the check to
- * make only the single stepping have the sync feature...
- */
- nostep = true;
- LOG_WARNING("stepi ignored. GDB will now fetch the register state from the target.");
- }
- gdb_con->sync = false;
-
- if ((retval!=ERROR_OK) || nostep)
- {
- /* Either the target isn't in the halted state, then we can't
- * step/continue. This might be early setup, etc.
- *
- * Or we want to allow GDB to pick up a fresh set of
- * register values without modifying the target state.
- *
- */
- gdb_sig_halted(connection);
-
- /* stop forwarding log packets! */
- log_remove_callback(gdb_log_callback, connection);
- } else
- {
- /* We're running/stepping, in which case we can
- * forward log output until the target is halted
- */
- gdb_con->frontend_state = TARGET_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_GDB_START);
- int retval = gdb_step_continue_packet(connection, target, packet, packet_size);
- if (retval != ERROR_OK)
- {
- /* we'll never receive a halted condition... issue a false one.. */
+ {
+ gdb_thread_packet(connection, packet, packet_size);
+ log_add_callback(gdb_log_callback, connection);
+
+ if (gdb_con->mem_write_error) {
+ LOG_ERROR("Memory write failure!");
+
+ /* now that we have reported the memory write error,
+ * we can clear the condition */
+ gdb_con->mem_write_error = false;
+ }
+
+ bool nostep = false;
+ bool already_running = false;
+ if (target->state == TARGET_RUNNING) {
+ LOG_WARNING("WARNING! The target is already running. "
+ "All changes GDB did to registers will be discarded! "
+ "Waiting for target to halt.");
+ already_running = true;
+ } else if (target->state != TARGET_HALTED) {
+ LOG_WARNING("The target is not in the halted nor running stated, " \
+ "stepi/continue ignored.");
+ nostep = true;
+ } else if ((packet[0] == 's') && gdb_con->sync) {
+ /* Hmm..... when you issue a continue in GDB, then a "stepi" is
+ * sent by GDB first to OpenOCD, thus defeating the check to
+ * make only the single stepping have the sync feature...
+ */
+ nostep = true;
+ LOG_WARNING("stepi ignored. GDB will now fetch the register state " \
+ "from the target.");
+ }
+ gdb_con->sync = false;
+
+ if (!already_running && nostep) {
+ /* Either the target isn't in the halted state, then we can't
+ * step/continue. This might be early setup, etc.
+ *
+ * Or we want to allow GDB to pick up a fresh set of
+ * register values without modifying the target state.
+ *
+ */
+ gdb_sig_halted(connection);
+
+ /* stop forwarding log packets! */
+ log_remove_callback(gdb_log_callback, connection);
+ } else {
+ /* We're running/stepping, in which case we can
+ * forward log output until the target is halted
+ */
+ gdb_con->frontend_state = TARGET_RUNNING;
+ target_call_event_callbacks(target, TARGET_EVENT_GDB_START);
+
+ if (!already_running) {
+ /* Here we don't want packet processing to stop even if this fails,
+ * so we use a local variable instead of retval. */
+ retval = gdb_step_continue_packet(connection, packet, packet_size);
+ if (retval != ERROR_OK) {
+ /* we'll never receive a halted
+ * condition... issue a false one..
+ */