gdbstub: Implement v commands with new infra
Signed-off-by: Jon Doron <arilou@gmail.com> Message-Id: <20190529064148.19856-17-arilou@gmail.com> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
This commit is contained in:
parent
933f80dd42
commit
8536ec02fe
170
gdbstub.c
170
gdbstub.c
@ -1822,6 +1822,106 @@ static void handle_step(GdbCmdContext *gdb_ctx, void *user_ctx)
|
|||||||
gdb_continue(gdb_ctx->s);
|
gdb_continue(gdb_ctx->s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_v_cont_query(GdbCmdContext *gdb_ctx, void *user_ctx)
|
||||||
|
{
|
||||||
|
put_packet(gdb_ctx->s, "vCont;c;C;s;S");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_v_cont(GdbCmdContext *gdb_ctx, void *user_ctx)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (!gdb_ctx->num_params) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = gdb_handle_vcont(gdb_ctx->s, gdb_ctx->params[0].data);
|
||||||
|
if ((res == -EINVAL) || (res == -ERANGE)) {
|
||||||
|
put_packet(gdb_ctx->s, "E22");
|
||||||
|
} else if (res) {
|
||||||
|
put_packet(gdb_ctx->s, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_v_attach(GdbCmdContext *gdb_ctx, void *user_ctx)
|
||||||
|
{
|
||||||
|
GDBProcess *process;
|
||||||
|
CPUState *cpu;
|
||||||
|
char thread_id[16];
|
||||||
|
|
||||||
|
pstrcpy(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "E22");
|
||||||
|
if (!gdb_ctx->num_params) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
process = gdb_get_process(gdb_ctx->s, gdb_ctx->params[0].val_ul);
|
||||||
|
if (!process) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu = get_first_cpu_in_process(gdb_ctx->s, process);
|
||||||
|
if (!cpu) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
process->attached = true;
|
||||||
|
gdb_ctx->s->g_cpu = cpu;
|
||||||
|
gdb_ctx->s->c_cpu = cpu;
|
||||||
|
|
||||||
|
gdb_fmt_thread_id(gdb_ctx->s, cpu, thread_id, sizeof(thread_id));
|
||||||
|
snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "T%02xthread:%s;",
|
||||||
|
GDB_SIGNAL_TRAP, thread_id);
|
||||||
|
cleanup:
|
||||||
|
put_packet(gdb_ctx->s, gdb_ctx->str_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_v_kill(GdbCmdContext *gdb_ctx, void *user_ctx)
|
||||||
|
{
|
||||||
|
/* Kill the target */
|
||||||
|
put_packet(gdb_ctx->s, "OK");
|
||||||
|
error_report("QEMU: Terminated via GDBstub");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdbCmdParseEntry gdb_v_commands_table[] = {
|
||||||
|
/* Order is important if has same prefix */
|
||||||
|
{
|
||||||
|
.handler = handle_v_cont_query,
|
||||||
|
.cmd = "Cont?",
|
||||||
|
.cmd_startswith = 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.handler = handle_v_cont,
|
||||||
|
.cmd = "Cont",
|
||||||
|
.cmd_startswith = 1,
|
||||||
|
.schema = "s0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.handler = handle_v_attach,
|
||||||
|
.cmd = "Attach;",
|
||||||
|
.cmd_startswith = 1,
|
||||||
|
.schema = "l0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.handler = handle_v_kill,
|
||||||
|
.cmd = "Kill;",
|
||||||
|
.cmd_startswith = 1
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void handle_v_commands(GdbCmdContext *gdb_ctx, void *user_ctx)
|
||||||
|
{
|
||||||
|
if (!gdb_ctx->num_params) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process_string_cmd(gdb_ctx->s, NULL, gdb_ctx->params[0].data,
|
||||||
|
gdb_v_commands_table,
|
||||||
|
ARRAY_SIZE(gdb_v_commands_table))) {
|
||||||
|
put_packet(gdb_ctx->s, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int gdb_handle_packet(GDBState *s, const char *line_buf)
|
static int gdb_handle_packet(GDBState *s, const char *line_buf)
|
||||||
{
|
{
|
||||||
CPUState *cpu;
|
CPUState *cpu;
|
||||||
@ -1829,7 +1929,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
|
|||||||
CPUClass *cc;
|
CPUClass *cc;
|
||||||
const char *p;
|
const char *p;
|
||||||
uint32_t pid, tid;
|
uint32_t pid, tid;
|
||||||
int ch, type, res;
|
int ch, type;
|
||||||
uint8_t mem_buf[MAX_PACKET_LENGTH];
|
uint8_t mem_buf[MAX_PACKET_LENGTH];
|
||||||
char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
|
char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
|
||||||
char thread_id[16];
|
char thread_id[16];
|
||||||
@ -1878,66 +1978,16 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
if (strncmp(p, "Cont", 4) == 0) {
|
{
|
||||||
p += 4;
|
static const GdbCmdParseEntry v_cmd_desc = {
|
||||||
if (*p == '?') {
|
.handler = handle_v_commands,
|
||||||
put_packet(s, "vCont;c;C;s;S");
|
.cmd = "v",
|
||||||
break;
|
.cmd_startswith = 1,
|
||||||
}
|
.schema = "s0"
|
||||||
|
};
|
||||||
res = gdb_handle_vcont(s, p);
|
cmd_parser = &v_cmd_desc;
|
||||||
|
|
||||||
if (res) {
|
|
||||||
if ((res == -EINVAL) || (res == -ERANGE)) {
|
|
||||||
put_packet(s, "E22");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
goto unknown_command;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else if (strncmp(p, "Attach;", 7) == 0) {
|
|
||||||
unsigned long pid;
|
|
||||||
|
|
||||||
p += 7;
|
|
||||||
|
|
||||||
if (qemu_strtoul(p, &p, 16, &pid)) {
|
|
||||||
put_packet(s, "E22");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
process = gdb_get_process(s, pid);
|
|
||||||
|
|
||||||
if (process == NULL) {
|
|
||||||
put_packet(s, "E22");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu = get_first_cpu_in_process(s, process);
|
|
||||||
|
|
||||||
if (cpu == NULL) {
|
|
||||||
/* Refuse to attach an empty process */
|
|
||||||
put_packet(s, "E22");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
process->attached = true;
|
|
||||||
|
|
||||||
s->g_cpu = cpu;
|
|
||||||
s->c_cpu = cpu;
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "T%02xthread:%s;", GDB_SIGNAL_TRAP,
|
|
||||||
gdb_fmt_thread_id(s, cpu, thread_id, sizeof(thread_id)));
|
|
||||||
|
|
||||||
put_packet(s, buf);
|
|
||||||
break;
|
|
||||||
} else if (strncmp(p, "Kill;", 5) == 0) {
|
|
||||||
/* Kill the target */
|
|
||||||
put_packet(s, "OK");
|
|
||||||
error_report("QEMU: Terminated via GDBstub");
|
|
||||||
exit(0);
|
|
||||||
} else {
|
|
||||||
goto unknown_command;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
/* Kill the target */
|
/* Kill the target */
|
||||||
error_report("QEMU: Terminated via GDBstub");
|
error_report("QEMU: Terminated via GDBstub");
|
||||||
|
Loading…
Reference in New Issue
Block a user