X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fserver%2Fgdb_server.c;h=428547b460764982da6088bd373ffb4e83a43f11;hb=refs%2Fchanges%2F59%2F4459%2F12;hp=712c393417353c5a90bcf532a5c1daa5f66ac8d9;hpb=cbf7889873c16e80109ee7d46995a0adf08af84c;p=openocd.git diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 712c393417..428547b460 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1909,6 +1909,8 @@ static int gdb_memory_map(struct connection *connection, static const char *gdb_get_reg_type_name(enum reg_type type) { switch (type) { + case REG_TYPE_BOOL: + return "bool"; case REG_TYPE_INT: return "int"; case REG_TYPE_INT8: @@ -1921,6 +1923,8 @@ static const char *gdb_get_reg_type_name(enum reg_type type) return "int64"; case REG_TYPE_INT128: return "int128"; + case REG_TYPE_UINT: + return "uint"; case REG_TYPE_UINT8: return "uint8"; case REG_TYPE_UINT16: @@ -2040,9 +2044,9 @@ static int gdb_generate_reg_type_description(struct target *target, type->id, type->reg_type_struct->size); while (field != NULL) { xml_printf(&retval, tdesc, pos, size, - "\n", - field->name, field->bitfield->start, - field->bitfield->end); + "\n", + field->name, field->bitfield->start, field->bitfield->end, + gdb_get_reg_type_name(field->bitfield->type)); field = field->next; } @@ -2088,8 +2092,9 @@ static int gdb_generate_reg_type_description(struct target *target, field = type->reg_type_flags->fields; while (field != NULL) { xml_printf(&retval, tdesc, pos, size, - "\n", - field->name, field->bitfield->start, field->bitfield->end); + "\n", + field->name, field->bitfield->start, field->bitfield->end, + gdb_get_reg_type_name(field->bitfield->type)); field = field->next; } @@ -2695,6 +2700,8 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p /* single-step or step-over-breakpoint */ if (parse[0] == 's') { + bool fake_step = false; + if (strncmp(parse, "s:", 2) == 0) { struct target *ct = target; int current_pc = 1; @@ -2710,9 +2717,20 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p parse = endp; } - if (target->rtos != NULL) + if (target->rtos != NULL) { + /* 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); + /* + * 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; @@ -2746,10 +2764,33 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p } } - LOG_DEBUG("target %s single-step thread %"PRId64, target_name(ct), thread_id); + 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;