Re: [Qemu-devel] [PATCH v9 18/27] gdbstub: Implement generic query (q pkt) with new infra
Jon Doron writes: A bit more for the commit message here as there seems to be a fair amount going on. > Signed-off-by: Jon Doron > --- > gdbstub.c | 327 ++ > 1 file changed, 327 insertions(+) > > diff --git a/gdbstub.c b/gdbstub.c > index d56d0fd235..83ae8738cc 100644 > --- a/gdbstub.c > +++ b/gdbstub.c > @@ -1915,6 +1915,323 @@ static void handle_v_commands(GdbCmdContext *gdb_ctx, > void *user_ctx) > } > } > > +static void handle_query_qemu_sstepbits(GdbCmdContext *gdb_ctx, void > *user_ctx) > +{ > +snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), > + "ENABLE=%x,NOIRQ=%x,NOTIMER=%x", SSTEP_ENABLE, > + SSTEP_NOIRQ, SSTEP_NOTIMER); > +put_packet(gdb_ctx->s, gdb_ctx->str_buf); > +} > + > +static void handle_set_qemu_sstep(GdbCmdContext *gdb_ctx, void *user_ctx) > +{ > +if (!gdb_ctx->num_params) { > +return; > +} > + > +sstep_flags = gdb_ctx->params[0].val_ul; > +put_packet(gdb_ctx->s, "OK"); > +} > + > +static void handle_query_qemu_sstep(GdbCmdContext *gdb_ctx, void *user_ctx) > +{ > +snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "0x%x", > sstep_flags); > +put_packet(gdb_ctx->s, gdb_ctx->str_buf); > +} > + > +static void handle_query_curr_tid(GdbCmdContext *gdb_ctx, void *user_ctx) > +{ > +CPUState *cpu; > +GDBProcess *process; > +char thread_id[16]; > + > +/* > + * "Current thread" remains vague in the spec, so always return > + * the first thread of the current process (gdb returns the > + * first thread). > + */ > +process = gdb_get_cpu_process(gdb_ctx->s, gdb_ctx->s->g_cpu); > +cpu = get_first_cpu_in_process(gdb_ctx->s, process); > +gdb_fmt_thread_id(gdb_ctx->s, cpu, thread_id, sizeof(thread_id)); > +snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "QC%s", thread_id); > +put_packet(gdb_ctx->s, gdb_ctx->str_buf); > +} > + > +static void handle_query_threads(GdbCmdContext *gdb_ctx, void *user_ctx) > +{ > +char thread_id[16]; > + > +if (!gdb_ctx->s->query_cpu) { > +put_packet(gdb_ctx->s, "l"); > +return; > +} > + > +gdb_fmt_thread_id(gdb_ctx->s, gdb_ctx->s->query_cpu, thread_id, > + sizeof(thread_id)); > +snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "m%s", thread_id); > +put_packet(gdb_ctx->s, gdb_ctx->str_buf); > +gdb_ctx->s->query_cpu = > +gdb_next_attached_cpu(gdb_ctx->s, gdb_ctx->s->query_cpu); > +} > + > +static void handle_query_first_threads(GdbCmdContext *gdb_ctx, void > *user_ctx) > +{ > +gdb_ctx->s->query_cpu = gdb_first_attached_cpu(gdb_ctx->s); > +handle_query_threads(gdb_ctx, user_ctx); > +} > + > +static void handle_query_thread_extra(GdbCmdContext *gdb_ctx, void *user_ctx) > +{ > +CPUState *cpu; > +int len; > + > +if (!gdb_ctx->num_params || > +gdb_ctx->params[0].thread_id.kind == GDB_READ_THREAD_ERR) { > +put_packet(gdb_ctx->s, "E22"); > +return; > +} > + > +cpu = gdb_get_cpu(gdb_ctx->s, gdb_ctx->params[0].thread_id.pid, > + gdb_ctx->params[0].thread_id.tid); > +if (!cpu) { > +return; > +} > + > +cpu_synchronize_state(cpu); > + > +if (gdb_ctx->s->multiprocess && (gdb_ctx->s->process_num > 1)) { > +/* Print the CPU model and name in multiprocess mode */ > +ObjectClass *oc = object_get_class(OBJECT(cpu)); > +const char *cpu_model = object_class_get_name(oc); > +char *cpu_name = object_get_canonical_path_component(OBJECT(cpu)); > +len = snprintf((char *)gdb_ctx->mem_buf, sizeof(gdb_ctx->str_buf) / > 2, > + "%s %s [%s]", cpu_model, cpu_name, > + cpu->halted ? "halted " : "running"); > +g_free(cpu_name); > +} else { > +/* memtohex() doubles the required space */ > +len = snprintf((char *)gdb_ctx->mem_buf, sizeof(gdb_ctx->str_buf) / > 2, > +"CPU#%d [%s]", cpu->cpu_index, > +cpu->halted ? "halted " : "running"); > +} > +trace_gdbstub_op_extra_info((char *)gdb_ctx->mem_buf); > +memtohex(gdb_ctx->str_buf, gdb_ctx->mem_buf, len); > +put_packet(gdb_ctx->s, gdb_ctx->str_buf); > +} > + > +#ifdef CONFIG_USER_ONLY > +static void handle_query_offsets(GdbCmdContext *gdb_ctx, void *user_ctx) > +{ > +TaskState *ts; > + > +ts = gdb_ctx->s->c_cpu->opaque; > +snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), > + "Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx > + ";Bss=" TARGET_ABI_FMT_lx, > + ts->info->code_offset, > + ts->info->data_offset, > + ts->info->data_offset); > +put_packet(gdb_ctx->s, gdb_ctx->str_buf); > +} > +#else > +static void handle_query_rcmd(GdbCmdContext *gdb_ctx, void *user_ctx) > +{ > +int len; > + > +if (!gdb_ctx->num_params) { > +put_packet(gdb
[Qemu-devel] [PATCH v9 18/27] gdbstub: Implement generic query (q pkt) with new infra
Signed-off-by: Jon Doron --- gdbstub.c | 327 ++ 1 file changed, 327 insertions(+) diff --git a/gdbstub.c b/gdbstub.c index d56d0fd235..83ae8738cc 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -1915,6 +1915,323 @@ static void handle_v_commands(GdbCmdContext *gdb_ctx, void *user_ctx) } } +static void handle_query_qemu_sstepbits(GdbCmdContext *gdb_ctx, void *user_ctx) +{ +snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), + "ENABLE=%x,NOIRQ=%x,NOTIMER=%x", SSTEP_ENABLE, + SSTEP_NOIRQ, SSTEP_NOTIMER); +put_packet(gdb_ctx->s, gdb_ctx->str_buf); +} + +static void handle_set_qemu_sstep(GdbCmdContext *gdb_ctx, void *user_ctx) +{ +if (!gdb_ctx->num_params) { +return; +} + +sstep_flags = gdb_ctx->params[0].val_ul; +put_packet(gdb_ctx->s, "OK"); +} + +static void handle_query_qemu_sstep(GdbCmdContext *gdb_ctx, void *user_ctx) +{ +snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "0x%x", sstep_flags); +put_packet(gdb_ctx->s, gdb_ctx->str_buf); +} + +static void handle_query_curr_tid(GdbCmdContext *gdb_ctx, void *user_ctx) +{ +CPUState *cpu; +GDBProcess *process; +char thread_id[16]; + +/* + * "Current thread" remains vague in the spec, so always return + * the first thread of the current process (gdb returns the + * first thread). + */ +process = gdb_get_cpu_process(gdb_ctx->s, gdb_ctx->s->g_cpu); +cpu = get_first_cpu_in_process(gdb_ctx->s, process); +gdb_fmt_thread_id(gdb_ctx->s, cpu, thread_id, sizeof(thread_id)); +snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "QC%s", thread_id); +put_packet(gdb_ctx->s, gdb_ctx->str_buf); +} + +static void handle_query_threads(GdbCmdContext *gdb_ctx, void *user_ctx) +{ +char thread_id[16]; + +if (!gdb_ctx->s->query_cpu) { +put_packet(gdb_ctx->s, "l"); +return; +} + +gdb_fmt_thread_id(gdb_ctx->s, gdb_ctx->s->query_cpu, thread_id, + sizeof(thread_id)); +snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "m%s", thread_id); +put_packet(gdb_ctx->s, gdb_ctx->str_buf); +gdb_ctx->s->query_cpu = +gdb_next_attached_cpu(gdb_ctx->s, gdb_ctx->s->query_cpu); +} + +static void handle_query_first_threads(GdbCmdContext *gdb_ctx, void *user_ctx) +{ +gdb_ctx->s->query_cpu = gdb_first_attached_cpu(gdb_ctx->s); +handle_query_threads(gdb_ctx, user_ctx); +} + +static void handle_query_thread_extra(GdbCmdContext *gdb_ctx, void *user_ctx) +{ +CPUState *cpu; +int len; + +if (!gdb_ctx->num_params || +gdb_ctx->params[0].thread_id.kind == GDB_READ_THREAD_ERR) { +put_packet(gdb_ctx->s, "E22"); +return; +} + +cpu = gdb_get_cpu(gdb_ctx->s, gdb_ctx->params[0].thread_id.pid, + gdb_ctx->params[0].thread_id.tid); +if (!cpu) { +return; +} + +cpu_synchronize_state(cpu); + +if (gdb_ctx->s->multiprocess && (gdb_ctx->s->process_num > 1)) { +/* Print the CPU model and name in multiprocess mode */ +ObjectClass *oc = object_get_class(OBJECT(cpu)); +const char *cpu_model = object_class_get_name(oc); +char *cpu_name = object_get_canonical_path_component(OBJECT(cpu)); +len = snprintf((char *)gdb_ctx->mem_buf, sizeof(gdb_ctx->str_buf) / 2, + "%s %s [%s]", cpu_model, cpu_name, + cpu->halted ? "halted " : "running"); +g_free(cpu_name); +} else { +/* memtohex() doubles the required space */ +len = snprintf((char *)gdb_ctx->mem_buf, sizeof(gdb_ctx->str_buf) / 2, +"CPU#%d [%s]", cpu->cpu_index, +cpu->halted ? "halted " : "running"); +} +trace_gdbstub_op_extra_info((char *)gdb_ctx->mem_buf); +memtohex(gdb_ctx->str_buf, gdb_ctx->mem_buf, len); +put_packet(gdb_ctx->s, gdb_ctx->str_buf); +} + +#ifdef CONFIG_USER_ONLY +static void handle_query_offsets(GdbCmdContext *gdb_ctx, void *user_ctx) +{ +TaskState *ts; + +ts = gdb_ctx->s->c_cpu->opaque; +snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), + "Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx + ";Bss=" TARGET_ABI_FMT_lx, + ts->info->code_offset, + ts->info->data_offset, + ts->info->data_offset); +put_packet(gdb_ctx->s, gdb_ctx->str_buf); +} +#else +static void handle_query_rcmd(GdbCmdContext *gdb_ctx, void *user_ctx) +{ +int len; + +if (!gdb_ctx->num_params) { +put_packet(gdb_ctx->s, "E22"); +return; +} + +len = strlen(gdb_ctx->params[0].data); +if (len % 2) { +put_packet(gdb_ctx->s, "E01"); +return; +} + +len = len / 2; +hextomem(gdb_ctx->mem_buf, gdb_ctx->params[0].data, len); +gdb_ctx->mem_buf[len++] = 0; +qemu_chr_be_write(gdb_ctx->s->mon_chr, gdb_ctx->mem_buf, len); +put_packet(gdb_ctx->s, "OK"); + +}