diff options
-rw-r--r-- | src/server/gdb_server.c | 185 |
1 files changed, 92 insertions, 93 deletions
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 1e50b43..5cffa23 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -3030,128 +3030,127 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p gdb_running_type = 's'; bool fake_step = false; - if (strncmp(parse, "s:", 2) == 0) { - struct target *ct = target; - int current_pc = 1; - int64_t thread_id; + struct target *ct = target; + int current_pc = 1; + int64_t thread_id; + parse++; + packet_size--; + if (parse[0] == ':') { char *endp; - - parse += 2; - packet_size -= 2; - + parse++; + packet_size--; thread_id = strtoll(parse, &endp, 16); if (endp) { packet_size -= endp - parse; parse = endp; } + } else { + thread_id = 0; + } + + if (target->rtos) { + /* FIXME: why is this necessary? rtos state should be up-to-date here already! */ + rtos_update_threads(target); - if (target->rtos) { - /* FIXME: why is this necessary? rtos state should be up-to-date here already! */ - rtos_update_threads(target); + target->rtos->gdb_target_for_threadid(connection, thread_id, &ct); - target->rtos->gdb_target_for_threadid(connection, thread_id, &ct); + /* + * check if the thread to be stepped is the current rtos thread + * if not, we must fake the step + */ + if (target->rtos->current_thread != thread_id) + fake_step = true; + } - /* - * check if the thread to be stepped is the current rtos thread - * if not, we must fake the step - */ - if (target->rtos->current_thread != thread_id) - fake_step = true; - } + if (parse[0] == ';') { + ++parse; + --packet_size; - if (parse[0] == ';') { - ++parse; - --packet_size; + if (parse[0] == 'c') { + parse += 1; - if (parse[0] == 'c') { + /* check if thread-id follows */ + if (parse[0] == ':') { + int64_t tid; parse += 1; - /* check if thread-id follows */ - if (parse[0] == ':') { - int64_t tid; - parse += 1; - - tid = strtoll(parse, &endp, 16); - if (tid == thread_id) { - /* - * Special case: only step a single thread (core), - * keep the other threads halted. Currently, only - * aarch64 target understands it. Other target types don't - * care (nobody checks the actual value of 'current') - * and it doesn't really matter. This deserves - * a symbolic constant and a formal interface documentation - * at a later time. - */ - LOG_DEBUG("request to step current core only"); - /* uncomment after checking that indeed other targets are safe */ - /*current_pc = 2;*/ - } + tid = strtoll(parse, NULL, 16); + if (tid == thread_id) { + /* + * Special case: only step a single thread (core), + * keep the other threads halted. Currently, only + * aarch64 target understands it. Other target types don't + * care (nobody checks the actual value of 'current') + * and it doesn't really matter. This deserves + * a symbolic constant and a formal interface documentation + * at a later time. + */ + LOG_DEBUG("request to step current core only"); + /* uncomment after checking that indeed other targets are safe */ + /*current_pc = 2;*/ } } } + } - LOG_DEBUG("target %s single-step thread %"PRIx64, target_name(ct), thread_id); - gdb_connection->output_flag = GDB_OUTPUT_ALL; - 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); + LOG_DEBUG("target %s single-step thread %"PRIx64, target_name(ct), thread_id); + gdb_connection->output_flag = GDB_OUTPUT_ALL; + target_call_event_callbacks(ct, TARGET_EVENT_GDB_START); - sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), - "T05thread:%016"PRIx64";", thread_id); + /* + * 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]; - gdb_put_packet(connection, sig_reply, sig_reply_len); - gdb_connection->output_flag = GDB_OUTPUT_NO; + LOG_DEBUG("fake step thread %"PRIx64, thread_id); - return true; - } + sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), + "T05thread:%016"PRIx64";", thread_id); - /* support for gdb_sync command */ - if (gdb_connection->sync) { - gdb_connection->sync = false; - if (ct->state == TARGET_HALTED) { - LOG_DEBUG("stepi ignored. GDB will now fetch the register state " - "from the target."); - gdb_sig_halted(connection); - gdb_connection->output_flag = GDB_OUTPUT_NO; - } else - gdb_connection->frontend_state = TARGET_RUNNING; - return true; - } + gdb_put_packet(connection, sig_reply, sig_reply_len); + gdb_connection->output_flag = GDB_OUTPUT_NO; - 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)); + return true; + } - /* if step was successful send a reply back to gdb */ - if (retval == ERROR_OK) { - retval = target_poll(ct); - if (retval != ERROR_OK) - LOG_DEBUG("error polling target %s after successful step", target_name(ct)); - /* send back signal information */ - gdb_signal_reply(ct, connection); - /* stop forwarding log packets! */ + /* support for gdb_sync command */ + if (gdb_connection->sync) { + gdb_connection->sync = false; + if (ct->state == TARGET_HALTED) { + LOG_DEBUG("stepi ignored. GDB will now fetch the register state " + "from the target."); + gdb_sig_halted(connection); gdb_connection->output_flag = GDB_OUTPUT_NO; } else gdb_connection->frontend_state = TARGET_RUNNING; - } else { - LOG_ERROR("Unknown vCont packet"); - return false; + 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 */ + if (retval == ERROR_OK) { + retval = target_poll(ct); + if (retval != ERROR_OK) + LOG_DEBUG("error polling target %s after successful step", target_name(ct)); + /* send back signal information */ + gdb_signal_reply(ct, connection); + /* stop forwarding log packets! */ + gdb_connection->output_flag = GDB_OUTPUT_NO; + } else + gdb_connection->frontend_state = TARGET_RUNNING; return true; } - + LOG_ERROR("Unknown vCont packet"); return false; } |