mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
gdbstub: make various helpers visible to the rest of the module
We will be needing to use these helpers between the user and softmmu files so declare them in the headers, add a system prefix and remove static from the implementations. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Message-Id: <20230302190846.2593720-10-alex.bennee@linaro.org> Message-Id: <20230303025805.625589-10-richard.henderson@linaro.org>
This commit is contained in:
parent
1678ea040e
commit
36e067b2f2
2 changed files with 165 additions and 136 deletions
|
@ -85,12 +85,13 @@ static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr,
|
|||
return cpu_memory_rw_debug(cpu, addr, buf, len, is_write);
|
||||
}
|
||||
|
||||
/* Return the GDB index for a given vCPU state.
|
||||
/*
|
||||
* Return the GDB index for a given vCPU state.
|
||||
*
|
||||
* For user mode this is simply the thread id. In system mode GDB
|
||||
* numbers CPUs from 1 as 0 is reserved as an "any cpu" index.
|
||||
*/
|
||||
static inline int cpu_gdb_index(CPUState *cpu)
|
||||
int gdb_get_cpu_index(CPUState *cpu)
|
||||
{
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
TaskState *ts = (TaskState *) cpu->opaque;
|
||||
|
@ -342,7 +343,7 @@ static GDBSystemState gdbserver_system_state;
|
|||
|
||||
static GDBState gdbserver_state;
|
||||
|
||||
static void init_gdbserver_state(void)
|
||||
void gdb_init_gdbserver_state(void)
|
||||
{
|
||||
g_assert(!gdbserver_state.init);
|
||||
memset(&gdbserver_state, 0, sizeof(GDBState));
|
||||
|
@ -524,7 +525,7 @@ static int gdb_continue_partial(char *newstates)
|
|||
return res;
|
||||
}
|
||||
|
||||
static void put_buffer(const uint8_t *buf, int len)
|
||||
void gdb_put_buffer(const uint8_t *buf, int len)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
int ret;
|
||||
|
@ -547,7 +548,7 @@ static void put_buffer(const uint8_t *buf, int len)
|
|||
}
|
||||
|
||||
/* writes 2*len+1 bytes in buf */
|
||||
static void memtohex(GString *buf, const uint8_t *mem, int len)
|
||||
void gdb_memtohex(GString *buf, const uint8_t *mem, int len)
|
||||
{
|
||||
int i, c;
|
||||
for(i = 0; i < len; i++) {
|
||||
|
@ -558,7 +559,7 @@ static void memtohex(GString *buf, const uint8_t *mem, int len)
|
|||
g_string_append_c(buf, '\0');
|
||||
}
|
||||
|
||||
static void hextomem(GByteArray *mem, const char *buf, int len)
|
||||
void gdb_hextomem(GByteArray *mem, const char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -603,7 +604,7 @@ static void hexdump(const char *buf, int len,
|
|||
}
|
||||
|
||||
/* return -1 if error, 0 if OK */
|
||||
static int put_packet_binary(const char *buf, int len, bool dump)
|
||||
int gdb_put_packet_binary(const char *buf, int len, bool dump)
|
||||
{
|
||||
int csum, i;
|
||||
uint8_t footer[3];
|
||||
|
@ -627,7 +628,7 @@ static int put_packet_binary(const char *buf, int len, bool dump)
|
|||
footer[2] = tohex((csum) & 0xf);
|
||||
g_byte_array_append(gdbserver_state.last_packet, footer, 3);
|
||||
|
||||
put_buffer(gdbserver_state.last_packet->data,
|
||||
gdb_put_buffer(gdbserver_state.last_packet->data,
|
||||
gdbserver_state.last_packet->len);
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
|
@ -644,20 +645,20 @@ static int put_packet_binary(const char *buf, int len, bool dump)
|
|||
}
|
||||
|
||||
/* return -1 if error, 0 if OK */
|
||||
static int put_packet(const char *buf)
|
||||
int gdb_put_packet(const char *buf)
|
||||
{
|
||||
trace_gdbstub_io_reply(buf);
|
||||
|
||||
return put_packet_binary(buf, strlen(buf), false);
|
||||
return gdb_put_packet_binary(buf, strlen(buf), false);
|
||||
}
|
||||
|
||||
static void put_strbuf(void)
|
||||
void gdb_put_strbuf(void)
|
||||
{
|
||||
put_packet(gdbserver_state.str_buf->str);
|
||||
gdb_put_packet(gdbserver_state.str_buf->str);
|
||||
}
|
||||
|
||||
/* Encode data using the encoding for 'x' packets. */
|
||||
static void memtox(GString *buf, const char *mem, int len)
|
||||
void gdb_memtox(GString *buf, const char *mem, int len)
|
||||
{
|
||||
char c;
|
||||
|
||||
|
@ -714,7 +715,7 @@ static CPUState *find_cpu(uint32_t thread_id)
|
|||
CPUState *cpu;
|
||||
|
||||
CPU_FOREACH(cpu) {
|
||||
if (cpu_gdb_index(cpu) == thread_id) {
|
||||
if (gdb_get_cpu_index(cpu) == thread_id) {
|
||||
return cpu;
|
||||
}
|
||||
}
|
||||
|
@ -768,7 +769,7 @@ static CPUState *gdb_next_attached_cpu(CPUState *cpu)
|
|||
}
|
||||
|
||||
/* Return the first attached cpu */
|
||||
static CPUState *gdb_first_attached_cpu(void)
|
||||
CPUState *gdb_first_attached_cpu(void)
|
||||
{
|
||||
CPUState *cpu = first_cpu;
|
||||
GDBProcess *process = gdb_get_cpu_process(cpu);
|
||||
|
@ -982,13 +983,13 @@ static void gdb_set_cpu_pc(target_ulong pc)
|
|||
cpu_set_pc(cpu, pc);
|
||||
}
|
||||
|
||||
static void gdb_append_thread_id(CPUState *cpu, GString *buf)
|
||||
void gdb_append_thread_id(CPUState *cpu, GString *buf)
|
||||
{
|
||||
if (gdbserver_state.multiprocess) {
|
||||
g_string_append_printf(buf, "p%02x.%02x",
|
||||
gdb_get_cpu_pid(cpu), cpu_gdb_index(cpu));
|
||||
gdb_get_cpu_pid(cpu), gdb_get_cpu_index(cpu));
|
||||
} else {
|
||||
g_string_append_printf(buf, "%02x", cpu_gdb_index(cpu));
|
||||
g_string_append_printf(buf, "%02x", gdb_get_cpu_index(cpu));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1359,7 +1360,7 @@ static void run_cmd_parser(const char *data, const GdbCmdParseEntry *cmd)
|
|||
/* In case there was an error during the command parsing we must
|
||||
* send a NULL packet to indicate the command is not supported */
|
||||
if (process_string_cmd(NULL, data, cmd, 1)) {
|
||||
put_packet("");
|
||||
gdb_put_packet("");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1370,7 +1371,7 @@ static void handle_detach(GArray *params, void *user_ctx)
|
|||
|
||||
if (gdbserver_state.multiprocess) {
|
||||
if (!params->len) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1394,7 +1395,7 @@ static void handle_detach(GArray *params, void *user_ctx)
|
|||
gdb_syscall_mode = GDB_SYS_DISABLED;
|
||||
gdb_continue();
|
||||
}
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
}
|
||||
|
||||
static void handle_thread_alive(GArray *params, void *user_ctx)
|
||||
|
@ -1402,23 +1403,23 @@ static void handle_thread_alive(GArray *params, void *user_ctx)
|
|||
CPUState *cpu;
|
||||
|
||||
if (!params->len) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_param(params, 0)->thread_id.kind == GDB_READ_THREAD_ERR) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
cpu = gdb_get_cpu(get_param(params, 0)->thread_id.pid,
|
||||
get_param(params, 0)->thread_id.tid);
|
||||
if (!cpu) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
}
|
||||
|
||||
static void handle_continue(GArray *params, void *user_ctx)
|
||||
|
@ -1455,24 +1456,24 @@ static void handle_set_thread(GArray *params, void *user_ctx)
|
|||
CPUState *cpu;
|
||||
|
||||
if (params->len != 2) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_param(params, 1)->thread_id.kind == GDB_READ_THREAD_ERR) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_param(params, 1)->thread_id.kind != GDB_ONE_THREAD) {
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
return;
|
||||
}
|
||||
|
||||
cpu = gdb_get_cpu(get_param(params, 1)->thread_id.pid,
|
||||
get_param(params, 1)->thread_id.tid);
|
||||
if (!cpu) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1483,14 +1484,14 @@ static void handle_set_thread(GArray *params, void *user_ctx)
|
|||
switch (get_param(params, 0)->opcode) {
|
||||
case 'c':
|
||||
gdbserver_state.c_cpu = cpu;
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
break;
|
||||
case 'g':
|
||||
gdbserver_state.g_cpu = cpu;
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
break;
|
||||
default:
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1500,7 +1501,7 @@ static void handle_insert_bp(GArray *params, void *user_ctx)
|
|||
int res;
|
||||
|
||||
if (params->len != 3) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1509,14 +1510,14 @@ static void handle_insert_bp(GArray *params, void *user_ctx)
|
|||
get_param(params, 1)->val_ull,
|
||||
get_param(params, 2)->val_ull);
|
||||
if (res >= 0) {
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
return;
|
||||
} else if (res == -ENOSYS) {
|
||||
put_packet("");
|
||||
gdb_put_packet("");
|
||||
return;
|
||||
}
|
||||
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
}
|
||||
|
||||
static void handle_remove_bp(GArray *params, void *user_ctx)
|
||||
|
@ -1524,7 +1525,7 @@ static void handle_remove_bp(GArray *params, void *user_ctx)
|
|||
int res;
|
||||
|
||||
if (params->len != 3) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1533,14 +1534,14 @@ static void handle_remove_bp(GArray *params, void *user_ctx)
|
|||
get_param(params, 1)->val_ull,
|
||||
get_param(params, 2)->val_ull);
|
||||
if (res >= 0) {
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
return;
|
||||
} else if (res == -ENOSYS) {
|
||||
put_packet("");
|
||||
gdb_put_packet("");
|
||||
return;
|
||||
}
|
||||
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1559,20 +1560,20 @@ static void handle_set_reg(GArray *params, void *user_ctx)
|
|||
int reg_size;
|
||||
|
||||
if (!gdb_has_xml) {
|
||||
put_packet("");
|
||||
gdb_put_packet("");
|
||||
return;
|
||||
}
|
||||
|
||||
if (params->len != 2) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
reg_size = strlen(get_param(params, 1)->data) / 2;
|
||||
hextomem(gdbserver_state.mem_buf, get_param(params, 1)->data, reg_size);
|
||||
gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 1)->data, reg_size);
|
||||
gdb_write_register(gdbserver_state.g_cpu, gdbserver_state.mem_buf->data,
|
||||
get_param(params, 0)->val_ull);
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
}
|
||||
|
||||
static void handle_get_reg(GArray *params, void *user_ctx)
|
||||
|
@ -1580,12 +1581,12 @@ static void handle_get_reg(GArray *params, void *user_ctx)
|
|||
int reg_size;
|
||||
|
||||
if (!gdb_has_xml) {
|
||||
put_packet("");
|
||||
gdb_put_packet("");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!params->len) {
|
||||
put_packet("E14");
|
||||
gdb_put_packet("E14");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1593,53 +1594,54 @@ static void handle_get_reg(GArray *params, void *user_ctx)
|
|||
gdbserver_state.mem_buf,
|
||||
get_param(params, 0)->val_ull);
|
||||
if (!reg_size) {
|
||||
put_packet("E14");
|
||||
gdb_put_packet("E14");
|
||||
return;
|
||||
} else {
|
||||
g_byte_array_set_size(gdbserver_state.mem_buf, reg_size);
|
||||
}
|
||||
|
||||
memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data, reg_size);
|
||||
put_strbuf();
|
||||
gdb_memtohex(gdbserver_state.str_buf,
|
||||
gdbserver_state.mem_buf->data, reg_size);
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
static void handle_write_mem(GArray *params, void *user_ctx)
|
||||
{
|
||||
if (params->len != 3) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
/* hextomem() reads 2*len bytes */
|
||||
/* gdb_hextomem() reads 2*len bytes */
|
||||
if (get_param(params, 1)->val_ull >
|
||||
strlen(get_param(params, 2)->data) / 2) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
hextomem(gdbserver_state.mem_buf, get_param(params, 2)->data,
|
||||
gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 2)->data,
|
||||
get_param(params, 1)->val_ull);
|
||||
if (target_memory_rw_debug(gdbserver_state.g_cpu,
|
||||
get_param(params, 0)->val_ull,
|
||||
gdbserver_state.mem_buf->data,
|
||||
gdbserver_state.mem_buf->len, true)) {
|
||||
put_packet("E14");
|
||||
gdb_put_packet("E14");
|
||||
return;
|
||||
}
|
||||
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
}
|
||||
|
||||
static void handle_read_mem(GArray *params, void *user_ctx)
|
||||
{
|
||||
if (params->len != 2) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
/* memtohex() doubles the required space */
|
||||
/* gdb_memtohex() doubles the required space */
|
||||
if (get_param(params, 1)->val_ull > MAX_PACKET_LENGTH / 2) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1650,13 +1652,13 @@ static void handle_read_mem(GArray *params, void *user_ctx)
|
|||
get_param(params, 0)->val_ull,
|
||||
gdbserver_state.mem_buf->data,
|
||||
gdbserver_state.mem_buf->len, false)) {
|
||||
put_packet("E14");
|
||||
gdb_put_packet("E14");
|
||||
return;
|
||||
}
|
||||
|
||||
memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data,
|
||||
gdb_memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data,
|
||||
gdbserver_state.mem_buf->len);
|
||||
put_strbuf();
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
static void handle_write_all_regs(GArray *params, void *user_ctx)
|
||||
|
@ -1671,7 +1673,7 @@ static void handle_write_all_regs(GArray *params, void *user_ctx)
|
|||
|
||||
cpu_synchronize_state(gdbserver_state.g_cpu);
|
||||
len = strlen(get_param(params, 0)->data) / 2;
|
||||
hextomem(gdbserver_state.mem_buf, get_param(params, 0)->data, len);
|
||||
gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 0)->data, len);
|
||||
registers = gdbserver_state.mem_buf->data;
|
||||
for (addr = 0; addr < gdbserver_state.g_cpu->gdb_num_g_regs && len > 0;
|
||||
addr++) {
|
||||
|
@ -1679,7 +1681,7 @@ static void handle_write_all_regs(GArray *params, void *user_ctx)
|
|||
len -= reg_size;
|
||||
registers += reg_size;
|
||||
}
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
}
|
||||
|
||||
static void handle_read_all_regs(GArray *params, void *user_ctx)
|
||||
|
@ -1696,8 +1698,8 @@ static void handle_read_all_regs(GArray *params, void *user_ctx)
|
|||
}
|
||||
g_assert(len == gdbserver_state.mem_buf->len);
|
||||
|
||||
memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data, len);
|
||||
put_strbuf();
|
||||
gdb_memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data, len);
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
static void handle_file_io(GArray *params, void *user_ctx)
|
||||
|
@ -1748,7 +1750,7 @@ static void handle_file_io(GArray *params, void *user_ctx)
|
|||
}
|
||||
|
||||
if (params->len >= 3 && get_param(params, 2)->opcode == (uint8_t)'C') {
|
||||
put_packet("T02");
|
||||
gdb_put_packet("T02");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1768,7 +1770,7 @@ static void handle_step(GArray *params, void *user_ctx)
|
|||
static void handle_backward(GArray *params, void *user_ctx)
|
||||
{
|
||||
if (!stub_can_reverse()) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
}
|
||||
if (params->len == 1) {
|
||||
switch (get_param(params, 0)->opcode) {
|
||||
|
@ -1776,26 +1778,26 @@ static void handle_backward(GArray *params, void *user_ctx)
|
|||
if (replay_reverse_step()) {
|
||||
gdb_continue();
|
||||
} else {
|
||||
put_packet("E14");
|
||||
gdb_put_packet("E14");
|
||||
}
|
||||
return;
|
||||
case 'c':
|
||||
if (replay_reverse_continue()) {
|
||||
gdb_continue();
|
||||
} else {
|
||||
put_packet("E14");
|
||||
gdb_put_packet("E14");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Default invalid command */
|
||||
put_packet("");
|
||||
gdb_put_packet("");
|
||||
}
|
||||
|
||||
static void handle_v_cont_query(GArray *params, void *user_ctx)
|
||||
{
|
||||
put_packet("vCont;c;C;s;S");
|
||||
gdb_put_packet("vCont;c;C;s;S");
|
||||
}
|
||||
|
||||
static void handle_v_cont(GArray *params, void *user_ctx)
|
||||
|
@ -1808,9 +1810,9 @@ static void handle_v_cont(GArray *params, void *user_ctx)
|
|||
|
||||
res = gdb_handle_vcont(get_param(params, 0)->data);
|
||||
if ((res == -EINVAL) || (res == -ERANGE)) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
} else if (res) {
|
||||
put_packet("");
|
||||
gdb_put_packet("");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1842,13 +1844,13 @@ static void handle_v_attach(GArray *params, void *user_ctx)
|
|||
gdb_append_thread_id(cpu, gdbserver_state.str_buf);
|
||||
g_string_append_c(gdbserver_state.str_buf, ';');
|
||||
cleanup:
|
||||
put_strbuf();
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
static void handle_v_kill(GArray *params, void *user_ctx)
|
||||
{
|
||||
/* Kill the target */
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
error_report("QEMU: Terminated via GDBstub");
|
||||
gdb_exit(0);
|
||||
exit(0);
|
||||
|
@ -1889,7 +1891,7 @@ static void handle_v_commands(GArray *params, void *user_ctx)
|
|||
if (process_string_cmd(NULL, get_param(params, 0)->data,
|
||||
gdb_v_commands_table,
|
||||
ARRAY_SIZE(gdb_v_commands_table))) {
|
||||
put_packet("");
|
||||
gdb_put_packet("");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1907,7 +1909,7 @@ static void handle_query_qemu_sstepbits(GArray *params, void *user_ctx)
|
|||
SSTEP_NOTIMER);
|
||||
}
|
||||
|
||||
put_strbuf();
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
static void handle_set_qemu_sstep(GArray *params, void *user_ctx)
|
||||
|
@ -1921,19 +1923,19 @@ static void handle_set_qemu_sstep(GArray *params, void *user_ctx)
|
|||
new_sstep_flags = get_param(params, 0)->val_ul;
|
||||
|
||||
if (new_sstep_flags & ~gdbserver_state.supported_sstep_flags) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
gdbserver_state.sstep_flags = new_sstep_flags;
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
}
|
||||
|
||||
static void handle_query_qemu_sstep(GArray *params, void *user_ctx)
|
||||
{
|
||||
g_string_printf(gdbserver_state.str_buf, "0x%x",
|
||||
gdbserver_state.sstep_flags);
|
||||
put_strbuf();
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
static void handle_query_curr_tid(GArray *params, void *user_ctx)
|
||||
|
@ -1950,19 +1952,19 @@ static void handle_query_curr_tid(GArray *params, void *user_ctx)
|
|||
cpu = get_first_cpu_in_process(process);
|
||||
g_string_assign(gdbserver_state.str_buf, "QC");
|
||||
gdb_append_thread_id(cpu, gdbserver_state.str_buf);
|
||||
put_strbuf();
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
static void handle_query_threads(GArray *params, void *user_ctx)
|
||||
{
|
||||
if (!gdbserver_state.query_cpu) {
|
||||
put_packet("l");
|
||||
gdb_put_packet("l");
|
||||
return;
|
||||
}
|
||||
|
||||
g_string_assign(gdbserver_state.str_buf, "m");
|
||||
gdb_append_thread_id(gdbserver_state.query_cpu, gdbserver_state.str_buf);
|
||||
put_strbuf();
|
||||
gdb_put_strbuf();
|
||||
gdbserver_state.query_cpu = gdb_next_attached_cpu(gdbserver_state.query_cpu);
|
||||
}
|
||||
|
||||
|
@ -1979,7 +1981,7 @@ static void handle_query_thread_extra(GArray *params, void *user_ctx)
|
|||
|
||||
if (!params->len ||
|
||||
get_param(params, 0)->thread_id.kind == GDB_READ_THREAD_ERR) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2004,8 +2006,8 @@ static void handle_query_thread_extra(GArray *params, void *user_ctx)
|
|||
cpu->halted ? "halted " : "running");
|
||||
}
|
||||
trace_gdbstub_op_extra_info(rs->str);
|
||||
memtohex(gdbserver_state.str_buf, (uint8_t *)rs->str, rs->len);
|
||||
put_strbuf();
|
||||
gdb_memtohex(gdbserver_state.str_buf, (uint8_t *)rs->str, rs->len);
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
|
@ -2021,7 +2023,7 @@ static void handle_query_offsets(GArray *params, void *user_ctx)
|
|||
ts->info->code_offset,
|
||||
ts->info->data_offset,
|
||||
ts->info->data_offset);
|
||||
put_strbuf();
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
#else
|
||||
static void handle_query_rcmd(GArray *params, void *user_ctx)
|
||||
|
@ -2030,24 +2032,24 @@ static void handle_query_rcmd(GArray *params, void *user_ctx)
|
|||
int len;
|
||||
|
||||
if (!params->len) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(get_param(params, 0)->data);
|
||||
if (len % 2) {
|
||||
put_packet("E01");
|
||||
gdb_put_packet("E01");
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert(gdbserver_state.mem_buf->len == 0);
|
||||
len = len / 2;
|
||||
hextomem(gdbserver_state.mem_buf, get_param(params, 0)->data, len);
|
||||
gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 0)->data, len);
|
||||
g_byte_array_append(gdbserver_state.mem_buf, &zero, 1);
|
||||
qemu_chr_be_write(gdbserver_system_state.mon_chr,
|
||||
gdbserver_state.mem_buf->data,
|
||||
gdbserver_state.mem_buf->len);
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2078,7 +2080,7 @@ static void handle_query_supported(GArray *params, void *user_ctx)
|
|||
}
|
||||
|
||||
g_string_append(gdbserver_state.str_buf, ";vContSupported+;multiprocess+");
|
||||
put_strbuf();
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
static void handle_query_xfer_features(GArray *params, void *user_ctx)
|
||||
|
@ -2090,14 +2092,14 @@ static void handle_query_xfer_features(GArray *params, void *user_ctx)
|
|||
const char *p;
|
||||
|
||||
if (params->len < 3) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
process = gdb_get_cpu_process(gdbserver_state.g_cpu);
|
||||
cc = CPU_GET_CLASS(gdbserver_state.g_cpu);
|
||||
if (!cc->gdb_core_xml_file) {
|
||||
put_packet("");
|
||||
gdb_put_packet("");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2105,7 +2107,7 @@ static void handle_query_xfer_features(GArray *params, void *user_ctx)
|
|||
p = get_param(params, 0)->data;
|
||||
xml = get_feature_xml(p, &p, process);
|
||||
if (!xml) {
|
||||
put_packet("E00");
|
||||
gdb_put_packet("E00");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2113,7 +2115,7 @@ static void handle_query_xfer_features(GArray *params, void *user_ctx)
|
|||
len = get_param(params, 2)->val_ul;
|
||||
total_len = strlen(xml);
|
||||
if (addr > total_len) {
|
||||
put_packet("E00");
|
||||
gdb_put_packet("E00");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2123,13 +2125,13 @@ static void handle_query_xfer_features(GArray *params, void *user_ctx)
|
|||
|
||||
if (len < total_len - addr) {
|
||||
g_string_assign(gdbserver_state.str_buf, "m");
|
||||
memtox(gdbserver_state.str_buf, xml + addr, len);
|
||||
gdb_memtox(gdbserver_state.str_buf, xml + addr, len);
|
||||
} else {
|
||||
g_string_assign(gdbserver_state.str_buf, "l");
|
||||
memtox(gdbserver_state.str_buf, xml + addr, total_len - addr);
|
||||
gdb_memtox(gdbserver_state.str_buf, xml + addr, total_len - addr);
|
||||
}
|
||||
|
||||
put_packet_binary(gdbserver_state.str_buf->str,
|
||||
gdb_put_packet_binary(gdbserver_state.str_buf->str,
|
||||
gdbserver_state.str_buf->len, true);
|
||||
}
|
||||
|
||||
|
@ -2140,7 +2142,7 @@ static void handle_query_xfer_auxv(GArray *params, void *user_ctx)
|
|||
unsigned long offset, len, saved_auxv, auxv_len;
|
||||
|
||||
if (params->len < 2) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2151,7 +2153,7 @@ static void handle_query_xfer_auxv(GArray *params, void *user_ctx)
|
|||
auxv_len = ts->info->auxv_len;
|
||||
|
||||
if (offset >= auxv_len) {
|
||||
put_packet("E00");
|
||||
gdb_put_packet("E00");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2169,20 +2171,20 @@ static void handle_query_xfer_auxv(GArray *params, void *user_ctx)
|
|||
g_byte_array_set_size(gdbserver_state.mem_buf, len);
|
||||
if (target_memory_rw_debug(gdbserver_state.g_cpu, saved_auxv + offset,
|
||||
gdbserver_state.mem_buf->data, len, false)) {
|
||||
put_packet("E14");
|
||||
gdb_put_packet("E14");
|
||||
return;
|
||||
}
|
||||
|
||||
memtox(gdbserver_state.str_buf,
|
||||
(const char *)gdbserver_state.mem_buf->data, len);
|
||||
put_packet_binary(gdbserver_state.str_buf->str,
|
||||
gdbserver_state.str_buf->len, true);
|
||||
gdb_memtox(gdbserver_state.str_buf,
|
||||
(const char *)gdbserver_state.mem_buf->data, len);
|
||||
gdb_put_packet_binary(gdbserver_state.str_buf->str,
|
||||
gdbserver_state.str_buf->len, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void handle_query_attached(GArray *params, void *user_ctx)
|
||||
{
|
||||
put_packet(GDB_ATTACHED);
|
||||
gdb_put_packet(GDB_ATTACHED);
|
||||
}
|
||||
|
||||
static void handle_query_qemu_supported(GArray *params, void *user_ctx)
|
||||
|
@ -2191,7 +2193,7 @@ static void handle_query_qemu_supported(GArray *params, void *user_ctx)
|
|||
#ifndef CONFIG_USER_ONLY
|
||||
g_string_append(gdbserver_state.str_buf, ";PhyMemMode");
|
||||
#endif
|
||||
put_strbuf();
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
@ -2199,13 +2201,13 @@ static void handle_query_qemu_phy_mem_mode(GArray *params,
|
|||
void *user_ctx)
|
||||
{
|
||||
g_string_printf(gdbserver_state.str_buf, "%d", phy_memory_mode);
|
||||
put_strbuf();
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
static void handle_set_qemu_phy_mem_mode(GArray *params, void *user_ctx)
|
||||
{
|
||||
if (!params->len) {
|
||||
put_packet("E22");
|
||||
gdb_put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2214,7 +2216,7 @@ static void handle_set_qemu_phy_mem_mode(GArray *params, void *user_ctx)
|
|||
} else {
|
||||
phy_memory_mode = 1;
|
||||
}
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2347,7 +2349,7 @@ static void handle_gen_query(GArray *params, void *user_ctx)
|
|||
if (process_string_cmd(NULL, get_param(params, 0)->data,
|
||||
gdb_gen_query_table,
|
||||
ARRAY_SIZE(gdb_gen_query_table))) {
|
||||
put_packet("");
|
||||
gdb_put_packet("");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2366,7 +2368,7 @@ static void handle_gen_set(GArray *params, void *user_ctx)
|
|||
if (process_string_cmd(NULL, get_param(params, 0)->data,
|
||||
gdb_gen_set_table,
|
||||
ARRAY_SIZE(gdb_gen_set_table))) {
|
||||
put_packet("");
|
||||
gdb_put_packet("");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2375,7 +2377,7 @@ static void handle_target_halt(GArray *params, void *user_ctx)
|
|||
g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP);
|
||||
gdb_append_thread_id(gdbserver_state.c_cpu, gdbserver_state.str_buf);
|
||||
g_string_append_c(gdbserver_state.str_buf, ';');
|
||||
put_strbuf();
|
||||
gdb_put_strbuf();
|
||||
/*
|
||||
* Remove all the breakpoints when this query is issued,
|
||||
* because gdb is doing an initial connect and the state
|
||||
|
@ -2392,7 +2394,7 @@ static int gdb_handle_packet(const char *line_buf)
|
|||
|
||||
switch (line_buf[0]) {
|
||||
case '!':
|
||||
put_packet("OK");
|
||||
gdb_put_packet("OK");
|
||||
break;
|
||||
case '?':
|
||||
{
|
||||
|
@ -2619,7 +2621,7 @@ static int gdb_handle_packet(const char *line_buf)
|
|||
break;
|
||||
default:
|
||||
/* put empty packet */
|
||||
put_packet("");
|
||||
gdb_put_packet("");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2660,7 +2662,7 @@ static void gdb_vm_state_change(void *opaque, bool running, RunState state)
|
|||
}
|
||||
/* Is there a GDB syscall waiting to be sent? */
|
||||
if (gdbserver_state.current_syscall_cb) {
|
||||
put_packet(gdbserver_state.syscall_buf);
|
||||
gdb_put_packet(gdbserver_state.syscall_buf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2685,7 +2687,7 @@ static void gdb_vm_state_change(void *opaque, bool running, RunState state)
|
|||
type = "";
|
||||
break;
|
||||
}
|
||||
trace_gdbstub_hit_watchpoint(type, cpu_gdb_index(cpu),
|
||||
trace_gdbstub_hit_watchpoint(type, gdb_get_cpu_index(cpu),
|
||||
(target_ulong)cpu->watchpoint_hit->vaddr);
|
||||
g_string_printf(buf, "T%02xthread:%s;%swatch:" TARGET_FMT_lx ";",
|
||||
GDB_SIGNAL_TRAP, tid->str, type,
|
||||
|
@ -2733,7 +2735,7 @@ static void gdb_vm_state_change(void *opaque, bool running, RunState state)
|
|||
g_string_printf(buf, "T%02xthread:%s;", ret, tid->str);
|
||||
|
||||
send_packet:
|
||||
put_packet(buf->str);
|
||||
gdb_put_packet(buf->str);
|
||||
|
||||
/* disable single step if it was enabled */
|
||||
cpu_single_step(cpu, 0);
|
||||
|
@ -2794,7 +2796,7 @@ void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
|
|||
}
|
||||
*p = 0;
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
put_packet(gdbserver_state.syscall_buf);
|
||||
gdb_put_packet(gdbserver_state.syscall_buf);
|
||||
/* Return control to gdb for it to process the syscall request.
|
||||
* Since the protocol requires that gdb hands control back to us
|
||||
* using a "here are the results" F packet, we don't need to check
|
||||
|
@ -2822,7 +2824,7 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
|
|||
va_end(va);
|
||||
}
|
||||
|
||||
static void gdb_read_byte(uint8_t ch)
|
||||
void gdb_read_byte(uint8_t ch)
|
||||
{
|
||||
uint8_t reply;
|
||||
|
||||
|
@ -2832,7 +2834,7 @@ static void gdb_read_byte(uint8_t ch)
|
|||
of a new command then abandon the previous response. */
|
||||
if (ch == '-') {
|
||||
trace_gdbstub_err_got_nack();
|
||||
put_buffer(gdbserver_state.last_packet->data,
|
||||
gdb_put_buffer(gdbserver_state.last_packet->data,
|
||||
gdbserver_state.last_packet->len);
|
||||
} else if (ch == '+') {
|
||||
trace_gdbstub_io_got_ack();
|
||||
|
@ -2954,12 +2956,12 @@ static void gdb_read_byte(uint8_t ch)
|
|||
trace_gdbstub_err_checksum_incorrect(gdbserver_state.line_sum, gdbserver_state.line_csum);
|
||||
/* send NAK reply */
|
||||
reply = '-';
|
||||
put_buffer(&reply, 1);
|
||||
gdb_put_buffer(&reply, 1);
|
||||
gdbserver_state.state = RS_IDLE;
|
||||
} else {
|
||||
/* send ACK reply */
|
||||
reply = '+';
|
||||
put_buffer(&reply, 1);
|
||||
gdb_put_buffer(&reply, 1);
|
||||
gdbserver_state.state = gdb_handle_packet(gdbserver_state.line_buf);
|
||||
}
|
||||
break;
|
||||
|
@ -2989,7 +2991,7 @@ void gdb_exit(int code)
|
|||
trace_gdbstub_op_exiting((uint8_t)code);
|
||||
|
||||
snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
|
||||
put_packet(buf);
|
||||
gdb_put_packet(buf);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
qemu_chr_fe_deinit(&gdbserver_system_state.chr, true);
|
||||
|
@ -3001,7 +3003,7 @@ void gdb_exit(int code)
|
|||
* part of a CPU cluster). Note that if this process contains no CPUs, it won't
|
||||
* be attachable and thus will be invisible to the user.
|
||||
*/
|
||||
static void create_default_process(GDBState *s)
|
||||
void gdb_create_default_process(GDBState *s)
|
||||
{
|
||||
GDBProcess *process;
|
||||
int max_pid = 0;
|
||||
|
@ -3042,10 +3044,12 @@ gdb_handlesig(CPUState *cpu, int sig)
|
|||
"T%02xthread:", target_signal_to_gdb(sig));
|
||||
gdb_append_thread_id(cpu, gdbserver_state.str_buf);
|
||||
g_string_append_c(gdbserver_state.str_buf, ';');
|
||||
put_strbuf();
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
/* put_packet() might have detected that the peer terminated the
|
||||
connection. */
|
||||
/*
|
||||
* gdb_put_packet() might have detected that the peer terminated the
|
||||
* connection.
|
||||
*/
|
||||
if (gdbserver_user_state.fd < 0) {
|
||||
return sig;
|
||||
}
|
||||
|
@ -3086,13 +3090,13 @@ void gdb_signalled(CPUArchState *env, int sig)
|
|||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "X%02x", target_signal_to_gdb(sig));
|
||||
put_packet(buf);
|
||||
gdb_put_packet(buf);
|
||||
}
|
||||
|
||||
static void gdb_accept_init(int fd)
|
||||
{
|
||||
init_gdbserver_state();
|
||||
create_default_process(&gdbserver_state);
|
||||
gdb_init_gdbserver_state();
|
||||
gdb_create_default_process(&gdbserver_state);
|
||||
gdbserver_state.processes[0].attached = true;
|
||||
gdbserver_state.c_cpu = gdb_first_attached_cpu();
|
||||
gdbserver_state.g_cpu = gdbserver_state.c_cpu;
|
||||
|
@ -3292,8 +3296,8 @@ static void gdb_chr_event(void *opaque, QEMUChrEvent event)
|
|||
static int gdb_monitor_write(Chardev *chr, const uint8_t *buf, int len)
|
||||
{
|
||||
g_autoptr(GString) hex_buf = g_string_new("O");
|
||||
memtohex(hex_buf, buf, len);
|
||||
put_packet(hex_buf->str);
|
||||
gdb_memtohex(hex_buf, buf, len);
|
||||
gdb_put_packet(hex_buf->str);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -3379,7 +3383,7 @@ static void create_processes(GDBState *s)
|
|||
qsort(gdbserver_state.processes, gdbserver_state.process_num, sizeof(gdbserver_state.processes[0]), pid_order);
|
||||
}
|
||||
|
||||
create_default_process(s);
|
||||
gdb_create_default_process(s);
|
||||
}
|
||||
|
||||
int gdbserver_start(const char *device)
|
||||
|
@ -3429,7 +3433,7 @@ int gdbserver_start(const char *device)
|
|||
}
|
||||
|
||||
if (!gdbserver_state.init) {
|
||||
init_gdbserver_state();
|
||||
gdb_init_gdbserver_state();
|
||||
|
||||
qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL);
|
||||
|
||||
|
|
|
@ -84,6 +84,31 @@ static inline int tohex(int v)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Connection helpers for both softmmu and user backends
|
||||
*/
|
||||
|
||||
void gdb_put_strbuf(void);
|
||||
int gdb_put_packet(const char *buf);
|
||||
int gdb_put_packet_binary(const char *buf, int len, bool dump);
|
||||
void gdb_hextomem(GByteArray *mem, const char *buf, int len);
|
||||
void gdb_memtohex(GString *buf, const uint8_t *mem, int len);
|
||||
void gdb_memtox(GString *buf, const char *mem, int len);
|
||||
void gdb_read_byte(uint8_t ch);
|
||||
|
||||
/* utility helpers */
|
||||
CPUState *gdb_first_attached_cpu(void);
|
||||
void gdb_append_thread_id(CPUState *cpu, GString *buf);
|
||||
int gdb_get_cpu_index(CPUState *cpu);
|
||||
|
||||
void gdb_init_gdbserver_state(void);
|
||||
void gdb_create_default_process(GDBState *s);
|
||||
|
||||
/*
|
||||
* Helpers with separate softmmu and user implementations
|
||||
*/
|
||||
void gdb_put_buffer(const uint8_t *buf, int len);
|
||||
|
||||
/*
|
||||
* Break/Watch point support - there is an implementation for softmmu
|
||||
* and user mode.
|
||||
|
|
Loading…
Reference in a new issue