Implement the "vCont" GDB packet

This commit is contained in:
Palmer Dabbelt 2017-04-07 18:32:13 -07:00
parent ad157ec0f6
commit 3c5cb81a09
7 changed files with 74 additions and 13 deletions

View File

@ -10,6 +10,7 @@
static int riscv_update_threads(struct rtos *rtos);
static int riscv_gdb_thread_packet(struct connection *connection, const char *packet, int packet_size);
static int riscv_gdb_v_packet(struct connection *connection, const char *packet, int packet_size);
static int riscv_detect_rtos(struct target *target)
{
@ -34,6 +35,7 @@ static int riscv_create_rtos(struct target *target)
riscv_update_threads(target->rtos);
target->rtos->gdb_thread_packet = riscv_gdb_thread_packet;
target->rtos->gdb_v_packet = riscv_gdb_v_packet;
return JIM_OK;
}
@ -67,10 +69,10 @@ static int riscv_gdb_thread_packet(struct connection *connection, const char *pa
struct rtos *rtos = target->rtos;
struct riscv_rtos *r = (struct riscv_rtos *)(target->rtos->rtos_specific_params);
char *packet_stttrr = malloc(packet_size + 1);
memset(packet_stttrr, '\0', packet_size + 1);
memcpy(packet_stttrr, packet, packet_size);
LOG_DEBUG("riscv_gdb_thread_packet(%s)", packet_stttrr);
char *packet_stttrr = malloc(packet_size + 1);
memset(packet_stttrr, '\0', packet_size + 1);
memcpy(packet_stttrr, packet, packet_size);
LOG_DEBUG("handling packet '%s'", packet_stttrr);
switch (packet[0]) {
case 'q':
@ -205,7 +207,6 @@ static int riscv_gdb_thread_packet(struct connection *connection, const char *pa
}
}
case 'c':
case 's':
target->state = TARGET_HALTED;
@ -227,6 +228,44 @@ static int riscv_gdb_thread_packet(struct connection *connection, const char *pa
}
}
static int riscv_gdb_v_packet(struct connection *connection, const char *packet, int packet_size)
{
char *packet_stttrr = malloc(packet_size + 1);
memset(packet_stttrr, '\0', packet_size + 1);
memcpy(packet_stttrr, packet, packet_size);
LOG_DEBUG("handling packet '%s'", packet_stttrr);
struct target *target = get_target_from_connection(connection);
if (strcmp(packet_stttrr, "vCont?") == 0) {
static const char *message = "OK";
gdb_put_packet(connection, message, strlen(message));
return JIM_OK;
}
int threadid;
if (sscanf(packet_stttrr, "vCont;s:%d;c", &threadid) == 1) {
riscv_set_rtos_hartid(target, threadid - 1);
riscv_step_rtos_hart(target);
gdb_put_packet(connection, "S02", 3);
return JIM_OK;
}
if (strcmp(packet_stttrr, "vCont;c") == 0) {
riscv_resume_all_harts(target);
target->state = TARGET_RUNNING;
target_call_event_callbacks(target, TARGET_EVENT_GDB_START);
gdb_set_frontend_state_running(connection);
return JIM_OK;
}
if (strncmp(packet_stttrr, "vCont", 5) == 0)
LOG_ERROR("Got unknown vCont-type packet");
return GDB_THREAD_PACKET_NOT_CONSUMED;
}
static int riscv_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
{
LOG_DEBUG("Updating RISC-V regiser list for hart %d", (int)(thread_id - 1));

View File

@ -72,6 +72,7 @@ static int os_alloc(struct target *target, struct rtos_type *ostype)
/* RTOS drivers can override the packet handler in _create(). */
os->gdb_thread_packet = rtos_thread_packet;
os->gdb_v_packet = NULL;
return JIM_OK;
}

View File

@ -54,6 +54,7 @@ struct rtos {
struct thread_detail *thread_details;
int thread_count;
int (*gdb_thread_packet)(struct connection *connection, char const *packet, int packet_size);
int (*gdb_v_packet)(struct connection *connection, char const *packet, int packet_size);
void *rtos_specific_params;
};

View File

@ -2445,6 +2445,13 @@ static int gdb_v_packet(struct connection *connection,
struct gdb_service *gdb_service = connection->service->priv;
int result;
struct target *target = get_target_from_connection(connection);
if (target->rtos != NULL && target->rtos->gdb_v_packet != NULL) {
int out = target->rtos->gdb_v_packet(connection, packet, packet_size);
if (out != GDB_THREAD_PACKET_NOT_CONSUMED)
return out;
}
/* if flash programming disabled - send a empty reply */
if (gdb_flash_program == 0) {
@ -2643,7 +2650,7 @@ static void gdb_log_callback(void *priv, const char *file, unsigned line,
gdb_output_con(connection, string);
}
static void gdb_sig_halted(struct connection *connection)
void gdb_sig_halted(struct connection *connection)
{
char sig_reply[4];
snprintf(sig_reply, 4, "T%2.2x", 2);
@ -3195,3 +3202,9 @@ int gdb_register_commands(struct command_context *cmd_ctx)
gdb_port_next = strdup("3333");
return register_commands(cmd_ctx, NULL, gdb_command_handlers);
}
void gdb_set_frontend_state_running(struct connection *connection)
{
struct gdb_connection *gdb_con = connection->priv;
gdb_con->frontend_state = TARGET_RUNNING;
}

View File

@ -45,6 +45,9 @@ static inline struct target *get_target_from_connection(struct connection *conne
return gdb_service->target;
}
void gdb_set_frontend_state_running(struct connection *connection);
void gdb_sig_halted(struct connection *connection);
#define ERROR_GDB_BUFFER_TOO_SMALL (-800)
#define ERROR_GDB_TIMEOUT (-801)

View File

@ -1355,8 +1355,6 @@ static int read_memory(struct target *target, uint32_t address,
return ERROR_FAIL;
}
LOG_INFO("read 0x%08x from 0x%08x", value, t_addr);
if (check_dmi_error(target)) {
LOG_ERROR("DMI error");
return ERROR_FAIL;
@ -1424,8 +1422,6 @@ static int write_memory(struct target *target, uint32_t address,
abstract_write_register(target, S1, riscv_xlen(target), value);
program_set_write(program, S1, value);
LOG_INFO("writing 0x%08x to 0x%08x", value, t_addr);
write_program(target, program);
execute_program(target, program);
uint32_t abstractcs;
@ -1622,7 +1618,7 @@ static void riscv013_on_step_or_resume(struct target *target, bool step)
static void riscv013_step_or_resume_current_hart(struct target *target, bool step)
{
RISCV_INFO(r);
LOG_DEBUG("resuming hart %d", r->current_hartid);
LOG_DEBUG("resuming hart %d (for step?=%d)", r->current_hartid, step);
assert(riscv_is_halted(target));
/* Issue the halt command, and then wait for the current hart to halt. */
@ -1654,4 +1650,7 @@ static void riscv013_step_or_resume_current_hart(struct target *target, bool ste
dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_RESUMEREQ, 0);
dmi_write(target, DMI_DMCONTROL, dmcontrol);
/* When stepping we need to go and restore the relevant registers. */
if (step) riscv013_on_halt(target);
}

View File

@ -726,6 +726,8 @@ int riscv_openocd_step(
uint32_t address,
int handle_breakpoints
) {
RISCV_INFO(r);
if (!current) {
LOG_ERROR("step-at-pc unimplemented");
return ERROR_FAIL;
@ -735,7 +737,11 @@ int riscv_openocd_step(
if (out != ERROR_OK)
return out;
/* step_rtos_hart blocks until the hart has actually stepped, but we
* need to cycle through OpenOCD to */
target->state = TARGET_RUNNING;
riscv_openocd_poll(target);
return out;
}
@ -888,8 +894,6 @@ int riscv_step_rtos_hart(struct target *target)
assert(r->hart_state[hartid] == RISCV_HART_HALTED);
r->on_step(target);
r->step_current_hart(target);
/* FIXME: There's a race condition with step. */
r->hart_state[hartid] = RISCV_HART_RUNNING;
return ERROR_OK;
}
@ -957,6 +961,7 @@ void riscv_set_all_rtos_harts(struct target *target)
void riscv_set_rtos_hartid(struct target *target, int hartid)
{
LOG_DEBUG("setting RTOS hartid %d", hartid);
RISCV_INFO(r);
r->rtos_hartid = hartid;
}