aboutsummaryrefslogtreecommitdiff
path: root/gdbstub.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-03-18 20:25:23 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-03-18 20:25:23 +0000
commit9214813489eb29de71d37f57e1bcabf5facecc8f (patch)
tree4a7317768744cda3fa35cd08a6615bfdce13ee79 /gdbstub.c
parentcf4b64406c0e7542b4e1852f5e5a743ad63cf36e (diff)
parent3bc2609d478779be600fd66744eb4e3730ec5e33 (diff)
Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-and-gdbstub-170320-1' into staging
Testing and gdbstub updates: - docker updates for VirGL - re-factor gdbstub for static GDBState - re-factor gdbstub for dynamic arrays - add SVE support to arm gdbstub - add some guest debug tests to check-tcg - add aarch64 userspace register tests - remove packet size limit to gdbstub - simplify gdbstub monitor code - report vContSupported in gdbstub to use proper single-step # gpg: Signature made Tue 17 Mar 2020 17:47:46 GMT # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * remotes/stsquad/tags/pull-testing-and-gdbstub-170320-1: (28 commits) gdbstub: Fix single-step issue by confirming 'vContSupported+' feature to gdb gdbstub: do not split gdb_monitor_write payload gdbstub: change GDBState.last_packet to GByteArray tests/tcg/aarch64: add test-sve-ioctl guest-debug test tests/tcg/aarch64: add SVE iotcl test tests/tcg/aarch64: add a gdbstub testcase for SVE registers tests/guest-debug: add a simple test runner configure: allow user to specify what gdb to use tests/tcg/aarch64: userspace system register test target/arm: don't bother with id_aa64pfr0_read for USER_ONLY target/arm: generate xml description of our SVE registers target/arm: default SVE length to 64 bytes for linux-user target/arm: explicitly encode regnum in our XML target/arm: prepare for multiple dynamic XMLs gdbstub: extend GByteArray to read register helpers target/i386: use gdb_get_reg helpers target/m68k: use gdb_get_reg helpers target/arm: use gdb_get_reg helpers gdbstub: add helper for 128 bit registers gdbstub: move mem_buf to GDBState and use GByteArray ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'gdbstub.c')
-rw-r--r--gdbstub.c936
1 files changed, 455 insertions, 481 deletions
diff --git a/gdbstub.c b/gdbstub.c
index 22a2d630cd..013fb1ac0f 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -319,8 +319,8 @@ static int gdb_signal_to_target (int sig)
typedef struct GDBRegisterState {
int base_reg;
int num_regs;
- gdb_reg_cb get_reg;
- gdb_reg_cb set_reg;
+ gdb_get_reg_cb get_reg;
+ gdb_set_reg_cb set_reg;
const char *xml;
struct GDBRegisterState *next;
} GDBRegisterState;
@@ -342,6 +342,7 @@ enum RSState {
RS_CHKSUM2,
};
typedef struct GDBState {
+ bool init; /* have we been initialised? */
CPUState *c_cpu; /* current CPU for step/continue ops */
CPUState *g_cpu; /* current CPU for other ops */
CPUState *query_cpu; /* for q{f|s}ThreadInfo */
@@ -350,8 +351,7 @@ typedef struct GDBState {
int line_buf_index;
int line_sum; /* running checksum */
int line_csum; /* checksum at the end of the packet */
- uint8_t last_packet[MAX_PACKET_LENGTH + 4];
- int last_packet_len;
+ GByteArray *last_packet;
int signal;
#ifdef CONFIG_USER_ONLY
int fd;
@@ -365,6 +365,8 @@ typedef struct GDBState {
int process_num;
char syscall_buf[256];
gdb_syscall_complete_cb current_syscall_cb;
+ GString *str_buf;
+ GByteArray *mem_buf;
} GDBState;
/* By default use no IRQs and no timers while single stepping so as to
@@ -372,7 +374,26 @@ typedef struct GDBState {
*/
static int sstep_flags = SSTEP_ENABLE|SSTEP_NOIRQ|SSTEP_NOTIMER;
-static GDBState *gdbserver_state;
+static GDBState gdbserver_state;
+
+static void init_gdbserver_state(void)
+{
+ g_assert(!gdbserver_state.init);
+ memset(&gdbserver_state, 0, sizeof(GDBState));
+ gdbserver_state.init = true;
+ gdbserver_state.str_buf = g_string_new(NULL);
+ gdbserver_state.mem_buf = g_byte_array_sized_new(MAX_PACKET_LENGTH);
+ gdbserver_state.last_packet = g_byte_array_sized_new(MAX_PACKET_LENGTH + 4);
+}
+
+#ifndef CONFIG_USER_ONLY
+static void reset_gdbserver_state(void)
+{
+ g_free(gdbserver_state.processes);
+ gdbserver_state.processes = NULL;
+ gdbserver_state.process_num = 0;
+}
+#endif
bool gdb_has_xml;
@@ -380,21 +401,21 @@ bool gdb_has_xml;
/* XXX: This is not thread safe. Do we care? */
static int gdbserver_fd = -1;
-static int get_char(GDBState *s)
+static int get_char(void)
{
uint8_t ch;
int ret;
for(;;) {
- ret = qemu_recv(s->fd, &ch, 1, 0);
+ ret = qemu_recv(gdbserver_state.fd, &ch, 1, 0);
if (ret < 0) {
if (errno == ECONNRESET)
- s->fd = -1;
+ gdbserver_state.fd = -1;
if (errno != EINTR)
return -1;
} else if (ret == 0) {
- close(s->fd);
- s->fd = -1;
+ close(gdbserver_state.fd);
+ gdbserver_state.fd = -1;
return -1;
} else {
break;
@@ -425,18 +446,18 @@ int use_gdb_syscalls(void)
/* -semihosting-config target=auto */
/* On the first call check if gdb is connected and remember. */
if (gdb_syscall_mode == GDB_SYS_UNKNOWN) {
- gdb_syscall_mode = (gdbserver_state ? GDB_SYS_ENABLED
- : GDB_SYS_DISABLED);
+ gdb_syscall_mode = gdbserver_state.init ?
+ GDB_SYS_ENABLED : GDB_SYS_DISABLED;
}
return gdb_syscall_mode == GDB_SYS_ENABLED;
}
/* Resume execution. */
-static inline void gdb_continue(GDBState *s)
+static inline void gdb_continue(void)
{
#ifdef CONFIG_USER_ONLY
- s->running_state = 1;
+ gdbserver_state.running_state = 1;
trace_gdbstub_op_continue();
#else
if (!runstate_needs_reset()) {
@@ -450,7 +471,7 @@ static inline void gdb_continue(GDBState *s)
* Resume execution, per CPU actions. For user-mode emulation it's
* equivalent to gdb_continue.
*/
-static int gdb_continue_partial(GDBState *s, char *newstates)
+static int gdb_continue_partial(char *newstates)
{
CPUState *cpu;
int res = 0;
@@ -465,7 +486,7 @@ static int gdb_continue_partial(GDBState *s, char *newstates)
cpu_single_step(cpu, sstep_flags);
}
}
- s->running_state = 1;
+ gdbserver_state.running_state = 1;
#else
int flag = 0;
@@ -503,13 +524,13 @@ static int gdb_continue_partial(GDBState *s, char *newstates)
return res;
}
-static void put_buffer(GDBState *s, const uint8_t *buf, int len)
+static void put_buffer(const uint8_t *buf, int len)
{
#ifdef CONFIG_USER_ONLY
int ret;
while (len > 0) {
- ret = send(s->fd, buf, len, 0);
+ ret = send(gdbserver_state.fd, buf, len, 0);
if (ret < 0) {
if (errno != EINTR)
return;
@@ -521,7 +542,7 @@ static void put_buffer(GDBState *s, const uint8_t *buf, int len)
#else
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
- qemu_chr_fe_write_all(&s->chr, buf, len);
+ qemu_chr_fe_write_all(&gdbserver_state.chr, buf, len);
#endif
}
@@ -546,25 +567,24 @@ static inline int tohex(int v)
}
/* writes 2*len+1 bytes in buf */
-static void memtohex(char *buf, const uint8_t *mem, int len)
+static void memtohex(GString *buf, const uint8_t *mem, int len)
{
int i, c;
- char *q;
- q = buf;
for(i = 0; i < len; i++) {
c = mem[i];
- *q++ = tohex(c >> 4);
- *q++ = tohex(c & 0xf);
+ g_string_append_c(buf, tohex(c >> 4));
+ g_string_append_c(buf, tohex(c & 0xf));
}
- *q = '\0';
+ g_string_append_c(buf, '\0');
}
-static void hextomem(uint8_t *mem, const char *buf, int len)
+static void hextomem(GByteArray *mem, const char *buf, int len)
{
int i;
for(i = 0; i < len; i++) {
- mem[i] = (fromhex(buf[0]) << 4) | fromhex(buf[1]);
+ guint8 byte = fromhex(buf[0]) << 4 | fromhex(buf[1]);
+ g_byte_array_append(mem, &byte, 1);
buf += 2;
}
}
@@ -603,33 +623,35 @@ static void hexdump(const char *buf, int len,
}
/* return -1 if error, 0 if OK */
-static int put_packet_binary(GDBState *s, const char *buf, int len, bool dump)
+static int put_packet_binary(const char *buf, int len, bool dump)
{
int csum, i;
- uint8_t *p;
+ uint8_t footer[3];
if (dump && trace_event_get_state_backends(TRACE_GDBSTUB_IO_BINARYREPLY)) {
hexdump(buf, len, trace_gdbstub_io_binaryreply);
}
for(;;) {
- p = s->last_packet;
- *(p++) = '$';
- memcpy(p, buf, len);
- p += len;
+ g_byte_array_set_size(gdbserver_state.last_packet, 0);
+ g_byte_array_append(gdbserver_state.last_packet,
+ (const uint8_t *) "$", 1);
+ g_byte_array_append(gdbserver_state.last_packet,
+ (const uint8_t *) buf, len);
csum = 0;
for(i = 0; i < len; i++) {
csum += buf[i];
}
- *(p++) = '#';
- *(p++) = tohex((csum >> 4) & 0xf);
- *(p++) = tohex((csum) & 0xf);
+ footer[0] = '#';
+ footer[1] = tohex((csum >> 4) & 0xf);
+ footer[2] = tohex((csum) & 0xf);
+ g_byte_array_append(gdbserver_state.last_packet, footer, 3);
- s->last_packet_len = p - s->last_packet;
- put_buffer(s, (uint8_t *)s->last_packet, s->last_packet_len);
+ put_buffer(gdbserver_state.last_packet->data,
+ gdbserver_state.last_packet->len);
#ifdef CONFIG_USER_ONLY
- i = get_char(s);
+ i = get_char();
if (i < 0)
return -1;
if (i == '+')
@@ -642,65 +664,69 @@ static int put_packet_binary(GDBState *s, const char *buf, int len, bool dump)
}
/* return -1 if error, 0 if OK */
-static int put_packet(GDBState *s, const char *buf)
+static int put_packet(const char *buf)
{
trace_gdbstub_io_reply(buf);
- return put_packet_binary(s, buf, strlen(buf), false);
+ return put_packet_binary(buf, strlen(buf), false);
+}
+
+static void put_strbuf(void)
+{
+ put_packet(gdbserver_state.str_buf->str);
}
/* Encode data using the encoding for 'x' packets. */
-static int memtox(char *buf, const char *mem, int len)
+static void memtox(GString *buf, const char *mem, int len)
{
- char *p = buf;
char c;
while (len--) {
c = *(mem++);
switch (c) {
case '#': case '$': case '*': case '}':
- *(p++) = '}';
- *(p++) = c ^ 0x20;
+ g_string_append_c(buf, '}');
+ g_string_append_c(buf, c ^ 0x20);
break;
default:
- *(p++) = c;
+ g_string_append_c(buf, c);
break;
}
}
- return p - buf;
}
-static uint32_t gdb_get_cpu_pid(const GDBState *s, CPUState *cpu)
+static uint32_t gdb_get_cpu_pid(CPUState *cpu)
{
/* TODO: In user mode, we should use the task state PID */
if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) {
/* Return the default process' PID */
- return s->processes[s->process_num - 1].pid;
+ int index = gdbserver_state.process_num - 1;
+ return gdbserver_state.processes[index].pid;
}
return cpu->cluster_index + 1;
}
-static GDBProcess *gdb_get_process(const GDBState *s, uint32_t pid)
+static GDBProcess *gdb_get_process(uint32_t pid)
{
int i;
if (!pid) {
/* 0 means any process, we take the first one */
- return &s->processes[0];
+ return &gdbserver_state.processes[0];
}
- for (i = 0; i < s->process_num; i++) {
- if (s->processes[i].pid == pid) {
- return &s->processes[i];
+ for (i = 0; i < gdbserver_state.process_num; i++) {
+ if (gdbserver_state.processes[i].pid == pid) {
+ return &gdbserver_state.processes[i];
}
}
return NULL;
}
-static GDBProcess *gdb_get_cpu_process(const GDBState *s, CPUState *cpu)
+static GDBProcess *gdb_get_cpu_process(CPUState *cpu)
{
- return gdb_get_process(s, gdb_get_cpu_pid(s, cpu));
+ return gdb_get_process(gdb_get_cpu_pid(cpu));
}
static CPUState *find_cpu(uint32_t thread_id)
@@ -716,13 +742,12 @@ static CPUState *find_cpu(uint32_t thread_id)
return NULL;
}
-static CPUState *get_first_cpu_in_process(const GDBState *s,
- GDBProcess *process)
+static CPUState *get_first_cpu_in_process(GDBProcess *process)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
- if (gdb_get_cpu_pid(s, cpu) == process->pid) {
+ if (gdb_get_cpu_pid(cpu) == process->pid) {
return cpu;
}
}
@@ -730,13 +755,13 @@ static CPUState *get_first_cpu_in_process(const GDBState *s,
return NULL;
}
-static CPUState *gdb_next_cpu_in_process(const GDBState *s, CPUState *cpu)
+static CPUState *gdb_next_cpu_in_process(CPUState *cpu)
{
- uint32_t pid = gdb_get_cpu_pid(s, cpu);
+ uint32_t pid = gdb_get_cpu_pid(cpu);
cpu = CPU_NEXT(cpu);
while (cpu) {
- if (gdb_get_cpu_pid(s, cpu) == pid) {
+ if (gdb_get_cpu_pid(cpu) == pid) {
break;
}
@@ -747,12 +772,12 @@ static CPUState *gdb_next_cpu_in_process(const GDBState *s, CPUState *cpu)
}
/* Return the cpu following @cpu, while ignoring unattached processes. */
-static CPUState *gdb_next_attached_cpu(const GDBState *s, CPUState *cpu)
+static CPUState *gdb_next_attached_cpu(CPUState *cpu)
{
cpu = CPU_NEXT(cpu);
while (cpu) {
- if (gdb_get_cpu_process(s, cpu)->attached) {
+ if (gdb_get_cpu_process(cpu)->attached) {
break;
}
@@ -763,29 +788,29 @@ static CPUState *gdb_next_attached_cpu(const GDBState *s, CPUState *cpu)
}
/* Return the first attached cpu */
-static CPUState *gdb_first_attached_cpu(const GDBState *s)
+static CPUState *gdb_first_attached_cpu(void)
{
CPUState *cpu = first_cpu;
- GDBProcess *process = gdb_get_cpu_process(s, cpu);
+ GDBProcess *process = gdb_get_cpu_process(cpu);
if (!process->attached) {
- return gdb_next_attached_cpu(s, cpu);
+ return gdb_next_attached_cpu(cpu);
}
return cpu;
}
-static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid)
+static CPUState *gdb_get_cpu(uint32_t pid, uint32_t tid)
{
GDBProcess *process;
CPUState *cpu;
if (!pid && !tid) {
/* 0 means any process/thread, we take the first attached one */
- return gdb_first_attached_cpu(s);
+ return gdb_first_attached_cpu();
} else if (pid && !tid) {
/* any thread in a specific process */
- process = gdb_get_process(s, pid);
+ process = gdb_get_process(pid);
if (process == NULL) {
return NULL;
@@ -795,7 +820,7 @@ static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid)
return NULL;
}
- return get_first_cpu_in_process(s, process);
+ return get_first_cpu_in_process(process);
} else {
/* a specific thread */
cpu = find_cpu(tid);
@@ -804,7 +829,7 @@ static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid)
return NULL;
}
- process = gdb_get_cpu_process(s, cpu);
+ process = gdb_get_cpu_process(cpu);
if (pid && process->pid != pid) {
return NULL;
@@ -818,13 +843,13 @@ static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid)
}
}
-static const char *get_feature_xml(const GDBState *s, const char *p,
- const char **newp, GDBProcess *process)
+static const char *get_feature_xml(const char *p, const char **newp,
+ GDBProcess *process)
{
size_t len;
int i;
const char *name;
- CPUState *cpu = get_first_cpu_in_process(s, process);
+ CPUState *cpu = get_first_cpu_in_process(process);
CPUClass *cc = CPU_GET_CLASS(cpu);
len = 0;
@@ -881,19 +906,19 @@ static const char *get_feature_xml(const GDBState *s, const char *p,
return name ? xml_builtin[i][1] : NULL;
}
-static int gdb_read_register(CPUState *cpu, uint8_t *mem_buf, int reg)
+static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
CPUArchState *env = cpu->env_ptr;
GDBRegisterState *r;
if (reg < cc->gdb_num_core_regs) {
- return cc->gdb_read_register(cpu, mem_buf, reg);
+ return cc->gdb_read_register(cpu, buf, reg);
}
for (r = cpu->gdb_regs; r; r = r->next) {
if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
- return r->get_reg(env, mem_buf, reg - r->base_reg);
+ return r->get_reg(env, buf, reg - r->base_reg);
}
}
return 0;
@@ -924,7 +949,7 @@ static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
*/
void gdb_register_coprocessor(CPUState *cpu,
- gdb_reg_cb get_reg, gdb_reg_cb set_reg,
+ gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
int num_regs, const char *xml, int g_pos)
{
GDBRegisterState *s;
@@ -984,7 +1009,7 @@ static int gdb_breakpoint_insert(int type, target_ulong addr, target_ulong len)
int err = 0;
if (kvm_enabled()) {
- return kvm_insert_breakpoint(gdbserver_state->c_cpu, addr, len, type);
+ return kvm_insert_breakpoint(gdbserver_state.c_cpu, addr, len, type);
}
switch (type) {
@@ -1021,7 +1046,7 @@ static int gdb_breakpoint_remove(int type, target_ulong addr, target_ulong len)
int err = 0;
if (kvm_enabled()) {
- return kvm_remove_breakpoint(gdbserver_state->c_cpu, addr, len, type);
+ return kvm_remove_breakpoint(gdbserver_state.c_cpu, addr, len, type);
}
switch (type) {
@@ -1059,13 +1084,13 @@ static inline void gdb_cpu_breakpoint_remove_all(CPUState *cpu)
#endif
}
-static void gdb_process_breakpoint_remove_all(const GDBState *s, GDBProcess *p)
+static void gdb_process_breakpoint_remove_all(GDBProcess *p)
{
- CPUState *cpu = get_first_cpu_in_process(s, p);
+ CPUState *cpu = get_first_cpu_in_process(p);
while (cpu) {
gdb_cpu_breakpoint_remove_all(cpu);
- cpu = gdb_next_cpu_in_process(s, cpu);
+ cpu = gdb_next_cpu_in_process(cpu);
}
}
@@ -1074,7 +1099,7 @@ static void gdb_breakpoint_remove_all(void)
CPUState *cpu;
if (kvm_enabled()) {
- kvm_remove_all_breakpoints(gdbserver_state->c_cpu);
+ kvm_remove_all_breakpoints(gdbserver_state.c_cpu);
return;
}
@@ -1083,25 +1108,22 @@ static void gdb_breakpoint_remove_all(void)
}
}
-static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
+static void gdb_set_cpu_pc(target_ulong pc)
{
- CPUState *cpu = s->c_cpu;
+ CPUState *cpu = gdbserver_state.c_cpu;
cpu_synchronize_state(cpu);
cpu_set_pc(cpu, pc);
}
-static char *gdb_fmt_thread_id(const GDBState *s, CPUState *cpu,
- char *buf, size_t buf_size)
+static void gdb_append_thread_id(CPUState *cpu, GString *buf)
{
- if (s->multiprocess) {
- snprintf(buf, buf_size, "p%02x.%02x",
- gdb_get_cpu_pid(s, cpu), cpu_gdb_index(cpu));
+ if (gdbserver_state.multiprocess) {
+ g_string_append_printf(buf, "p%02x.%02x",
+ gdb_get_cpu_pid(cpu), cpu_gdb_index(cpu));
} else {
- snprintf(buf, buf_size, "%02x", cpu_gdb_index(cpu));
+ g_string_append_printf(buf, "%02x", cpu_gdb_index(cpu));
}
-
- return buf;
}
typedef enum GDBThreadIdKind {
@@ -1163,7 +1185,7 @@ static GDBThreadIdKind read_thread_id(const char *buf, const char **end_buf,
* returns -ENOTSUP if a command is unsupported, -EINVAL or -ERANGE if there is
* a format error, 0 on success.
*/
-static int gdb_handle_vcont(GDBState *s, const char *p)
+static int gdb_handle_vcont(const char *p)
{
int res, signal = 0;
char cur_action;
@@ -1238,36 +1260,36 @@ static int gdb_handle_vcont(GDBState *s, const char *p)
goto out;
case GDB_ALL_PROCESSES:
- cpu = gdb_first_attached_cpu(s);
+ cpu = gdb_first_attached_cpu();
while (cpu) {
if (newstates[cpu->cpu_index] == 1) {
newstates[cpu->cpu_index] = cur_action;
}
- cpu = gdb_next_attached_cpu(s, cpu);
+ cpu = gdb_next_attached_cpu(cpu);
}
break;
case GDB_ALL_THREADS:
- process = gdb_get_process(s, pid);
+ process = gdb_get_process(pid);
if (!process->attached) {
res = -EINVAL;
goto out;
}
- cpu = get_first_cpu_in_process(s, process);
+ cpu = get_first_cpu_in_process(process);
while (cpu) {
if (newstates[cpu->cpu_index] == 1) {
newstates[cpu->cpu_index] = cur_action;
}
- cpu = gdb_next_cpu_in_process(s, cpu);
+ cpu = gdb_next_cpu_in_process(cpu);
}
break;
case GDB_ONE_THREAD:
- cpu = gdb_get_cpu(s, pid, tid);
+ cpu = gdb_get_cpu(pid, tid);
/* invalid CPU/thread specified */
if (!cpu) {
@@ -1282,8 +1304,8 @@ static int gdb_handle_vcont(GDBState *s, const char *p)
break;
}
}
- s->signal = signal;
- gdb_continue_partial(s, newstates);
+ gdbserver_state.signal = signal;
+ gdb_continue_partial(newstates);
out:
g_free(newstates);
@@ -1392,11 +1414,8 @@ static int cmd_parse_params(const char *data, const char *schema,
}
typedef struct GdbCmdContext {
- GDBState *s;
GdbCmdVariant *params;
int num_params;
- uint8_t mem_buf[MAX_PACKET_LENGTH];
- char str_buf[MAX_PACKET_LENGTH + 1];
} GdbCmdContext;
typedef void (*GdbCmdHandler)(GdbCmdContext *gdb_ctx, void *user_ctx);
@@ -1436,7 +1455,7 @@ static inline int startswith(const char *string, const char *pattern)
return !strncmp(string, pattern, strlen(pattern));
}
-static int process_string_cmd(GDBState *s, void *user_ctx, const char *data,
+static int process_string_cmd(void *user_ctx, const char *data,
const GdbCmdParseEntry *cmds, int num_cmds)
{
int i, schema_len, max_num_params = 0;
@@ -1473,7 +1492,6 @@ static int process_string_cmd(GDBState *s, void *user_ctx, const char *data,
return -1;
}
- gdb_ctx.s = s;
cmd->handler(&gdb_ctx, user_ctx);
return 0;
}
@@ -1481,53 +1499,54 @@ static int process_string_cmd(GDBState *s, void *user_ctx, const char *data,
return -1;
}
-static void run_cmd_parser(GDBState *s, const char *data,
- const GdbCmdParseEntry *cmd)
+static void run_cmd_parser(const char *data, const GdbCmdParseEntry *cmd)
{
if (!data) {
return;
}
+ g_string_set_size(gdbserver_state.str_buf, 0);
+ g_byte_array_set_size(gdbserver_state.mem_buf, 0);
+
/* 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(s, NULL, data, cmd, 1)) {
- put_packet(s, "");
+ if (process_string_cmd(NULL, data, cmd, 1)) {
+ put_packet("");
}
}
static void handle_detach(GdbCmdContext *gdb_ctx, void *user_ctx)
{
GDBProcess *process;
- GDBState *s = gdb_ctx->s;
uint32_t pid = 1;
- if (s->multiprocess) {
+ if (gdbserver_state.multiprocess) {
if (!gdb_ctx->num_params) {
- put_packet(s, "E22");
+ put_packet("E22");
return;
}
pid = gdb_ctx->params[0].val_ul;
}
- process = gdb_get_process(s, pid);
- gdb_process_breakpoint_remove_all(s, process);
+ process = gdb_get_process(pid);
+ gdb_process_breakpoint_remove_all(process);
process->attached = false;
- if (pid == gdb_get_cpu_pid(s, s->c_cpu)) {
- s->c_cpu = gdb_first_attached_cpu(s);
+ if (pid == gdb_get_cpu_pid(gdbserver_state.c_cpu)) {
+ gdbserver_state.c_cpu = gdb_first_attached_cpu();
}
- if (pid == gdb_get_cpu_pid(s, s->g_cpu)) {
- s->g_cpu = gdb_first_attached_cpu(s);
+ if (pid == gdb_get_cpu_pid(gdbserver_state.g_cpu)) {
+ gdbserver_state.g_cpu = gdb_first_attached_cpu();
}
- if (!s->c_cpu) {
+ if (!gdbserver_state.c_cpu) {
/* No more process attached */
gdb_syscall_mode = GDB_SYS_DISABLED;
- gdb_continue(s);
+ gdb_continue();
}
- put_packet(s, "OK");
+ put_packet("OK");
}
static void handle_thread_alive(GdbCmdContext *gdb_ctx, void *user_ctx)
@@ -1535,33 +1554,33 @@ static void handle_thread_alive(GdbCmdContext *gdb_ctx, void *user_ctx)
CPUState *cpu;
if (!gdb_ctx->num_params) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
if (gdb_ctx->params[0].thread_id.kind == GDB_READ_THREAD_ERR) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
- cpu = gdb_get_cpu(gdb_ctx->s, gdb_ctx->params[0].thread_id.pid,
+ cpu = gdb_get_cpu(gdb_ctx->params[0].thread_id.pid,
gdb_ctx->params[0].thread_id.tid);
if (!cpu) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
- put_packet(gdb_ctx->s, "OK");
+ put_packet("OK");
}
static void handle_continue(GdbCmdContext *gdb_ctx, void *user_ctx)
{
if (gdb_ctx->num_params) {
- gdb_set_cpu_pc(gdb_ctx->s, gdb_ctx->params[0].val_ull);
+ gdb_set_cpu_pc(gdb_ctx->params[0].val_ull);
}
- gdb_ctx->s->signal = 0;
- gdb_continue(gdb_ctx->s);
+ gdbserver_state.signal = 0;
+ gdb_continue();
}
static void handle_cont_with_sig(GdbCmdContext *gdb_ctx, void *user_ctx)
@@ -1576,11 +1595,11 @@ static void handle_cont_with_sig(GdbCmdContext *gdb_ctx, void *user_ctx)
signal = gdb_ctx->params[0].val_ul;
}
- gdb_ctx->s->signal = gdb_signal_to_target(signal);
- if (gdb_ctx->s->signal == -1) {
- gdb_ctx->s->signal = 0;
+ gdbserver_state.signal = gdb_signal_to_target(signal);
+ if (gdbserver_state.signal == -1) {
+ gdbserver_state.signal = 0;
}
- gdb_continue(gdb_ctx->s);
+ gdb_continue();
}
static void handle_set_thread(GdbCmdContext *gdb_ctx, void *user_ctx)
@@ -1588,24 +1607,24 @@ static void handle_set_thread(GdbCmdContext *gdb_ctx, void *user_ctx)
CPUState *cpu;
if (gdb_ctx->num_params != 2) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
if (gdb_ctx->params[1].thread_id.kind == GDB_READ_THREAD_ERR) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
if (gdb_ctx->params[1].thread_id.kind != GDB_ONE_THREAD) {
- put_packet(gdb_ctx->s, "OK");
+ put_packet("OK");
return;
}
- cpu = gdb_get_cpu(gdb_ctx->s, gdb_ctx->params[1].thread_id.pid,
+ cpu = gdb_get_cpu(gdb_ctx->params[1].thread_id.pid,
gdb_ctx->params[1].thread_id.tid);
if (!cpu) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
@@ -1615,15 +1634,15 @@ static void handle_set_thread(GdbCmdContext *gdb_ctx, void *user_ctx)
*/
switch (gdb_ctx->params[0].opcode) {
case 'c':
- gdb_ctx->s->c_cpu = cpu;
- put_packet(gdb_ctx->s, "OK");
+ gdbserver_state.c_cpu = cpu;
+ put_packet("OK");
break;
case 'g':
- gdb_ctx->s->g_cpu = cpu;
- put_packet(gdb_ctx->s, "OK");
+ gdbserver_state.g_cpu = cpu;
+ put_packet("OK");
break;
default:
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
break;
}
}
@@ -1633,7 +1652,7 @@ static void handle_insert_bp(GdbCmdContext *gdb_ctx, void *user_ctx)
int res;
if (gdb_ctx->num_params != 3) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
@@ -1641,14 +1660,14 @@ static void handle_insert_bp(GdbCmdContext *gdb_ctx, void *user_ctx)
gdb_ctx->params[1].val_ull,
gdb_ctx->params[2].val_ull);
if (res >= 0) {
- put_packet(gdb_ctx->s, "OK");
+ put_packet("OK");
return;
} else if (res == -ENOSYS) {
- put_packet(gdb_ctx->s, "");
+ put_packet("");
return;
}
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
}
static void handle_remove_bp(GdbCmdContext *gdb_ctx, void *user_ctx)
@@ -1656,7 +1675,7 @@ static void handle_remove_bp(GdbCmdContext *gdb_ctx, void *user_ctx)
int res;
if (gdb_ctx->num_params != 3) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
@@ -1664,14 +1683,14 @@ static void handle_remove_bp(GdbCmdContext *gdb_ctx, void *user_ctx)
gdb_ctx->params[1].val_ull,
gdb_ctx->params[2].val_ull);
if (res >= 0) {
- put_packet(gdb_ctx->s, "OK");
+ put_packet("OK");
return;
} else if (res == -ENOSYS) {
- put_packet(gdb_ctx->s, "");
+ put_packet("");
return;
}
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
}
/*
@@ -1690,20 +1709,20 @@ static void handle_set_reg(GdbCmdContext *gdb_ctx, void *user_ctx)
int reg_size;
if (!gdb_has_xml) {
- put_packet(gdb_ctx->s, "");
+ put_packet("");
return;
}
if (gdb_ctx->num_params != 2) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
reg_size = strlen(gdb_ctx->params[1].data) / 2;
- hextomem(gdb_ctx->mem_buf, gdb_ctx->params[1].data, reg_size);
- gdb_write_register(gdb_ctx->s->g_cpu, gdb_ctx->mem_buf,
+ hextomem(gdbserver_state.mem_buf, gdb_ctx->params[1].data, reg_size);
+ gdb_write_register(gdbserver_state.g_cpu, gdbserver_state.mem_buf->data,
gdb_ctx->params[0].val_ull);
- put_packet(gdb_ctx->s, "OK");
+ put_packet("OK");
}
static void handle_get_reg(GdbCmdContext *gdb_ctx, void *user_ctx)
@@ -1711,73 +1730,79 @@ static void handle_get_reg(GdbCmdContext *gdb_ctx, void *user_ctx)
int reg_size;
if (!gdb_has_xml) {
- put_packet(gdb_ctx->s, "");
+ put_packet("");
return;
}
if (!gdb_ctx->num_params) {
- put_packet(gdb_ctx->s, "E14");
+ put_packet("E14");
return;
}
- reg_size = gdb_read_register(gdb_ctx->s->g_cpu, gdb_ctx->mem_buf,
+ reg_size = gdb_read_register(gdbserver_state.g_cpu,
+ gdbserver_state.mem_buf,
gdb_ctx->params[0].val_ull);
if (!reg_size) {
- put_packet(gdb_ctx->s, "E14");
+ put_packet("E14");
return;
+ } else {
+ g_byte_array_set_size(gdbserver_state.mem_buf, reg_size);
}
- memtohex(gdb_ctx->str_buf, gdb_ctx->mem_buf, reg_size);
- put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+ memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data, reg_size);
+ put_strbuf();
}
static void handle_write_mem(GdbCmdContext *gdb_ctx, void *user_ctx)
{
if (gdb_ctx->num_params != 3) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
/* hextomem() reads 2*len bytes */
if (gdb_ctx->params[1].val_ull > strlen(gdb_ctx->params[2].data) / 2) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
- hextomem(gdb_ctx->mem_buf, gdb_ctx->params[2].data,
+ hextomem(gdbserver_state.mem_buf, gdb_ctx->params[2].data,
gdb_ctx->params[1].val_ull);
- if (target_memory_rw_debug(gdb_ctx->s->g_cpu, gdb_ctx->params[0].val_ull,
- gdb_ctx->mem_buf,
- gdb_ctx->params[1].val_ull, true)) {
- put_packet(gdb_ctx->s, "E14");
+ if (target_memory_rw_debug(gdbserver_state.g_cpu, gdb_ctx->params[0].val_ull,
+ gdbserver_state.mem_buf->data,
+ gdbserver_state.mem_buf->len, true)) {
+ put_packet("E14");
return;
}
- put_packet(gdb_ctx->s, "OK");
+ put_packet("OK");
}
static void handle_read_mem(GdbCmdContext *gdb_ctx, void *user_ctx)
{
if (gdb_ctx->num_params != 2) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
/* memtohex() doubles the required space */
if (gdb_ctx->params[1].val_ull > MAX_PACKET_LENGTH / 2) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
- if (target_memory_rw_debug(gdb_ctx->s->g_cpu, gdb_ctx->params[0].val_ull,
- gdb_ctx->mem_buf,
- gdb_ctx->params[1].val_ull, false)) {
- put_packet(gdb_ctx->s, "E14");
+ g_byte_array_set_size(gdbserver_state.mem_buf, gdb_ctx->params[1].val_ull);
+
+ if (target_memory_rw_debug(gdbserver_state.g_cpu, gdb_ctx->params[0].val_ull,
+ gdbserver_state.mem_buf->data,
+ gdbserver_state.mem_buf->len, false)) {
+ put_packet("E14");
return;
}
- memtohex(gdb_ctx->str_buf, gdb_ctx->mem_buf, gdb_ctx->params[1].val_ull);
- put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+ memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data,
+ gdbserver_state.mem_buf->len);
+ put_strbuf();
}
static void handle_write_all_regs(GdbCmdContext *gdb_ctx, void *user_ctx)
@@ -1790,37 +1815,40 @@ static void handle_write_all_regs(GdbCmdContext *gdb_ctx, void *user_ctx)
return;
}
- cpu_synchronize_state(gdb_ctx->s->g_cpu);
- registers = gdb_ctx->mem_buf;
+ cpu_synchronize_state(gdbserver_state.g_cpu);
len = strlen(gdb_ctx->params[0].data) / 2;
- hextomem(registers, gdb_ctx->params[0].data, len);
- for (addr = 0; addr < gdb_ctx->s->g_cpu->gdb_num_g_regs && len > 0;
+ hextomem(gdbserver_state.mem_buf, gdb_ctx->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++) {
- reg_size = gdb_write_register(gdb_ctx->s->g_cpu, registers, addr);
+ reg_size = gdb_write_register(gdbserver_state.g_cpu, registers, addr);
len -= reg_size;
registers += reg_size;
}
- put_packet(gdb_ctx->s, "OK");
+ put_packet("OK");
}
static void handle_read_all_regs(GdbCmdContext *gdb_ctx, void *user_ctx)
{
target_ulong addr, len;
- cpu_synchronize_state(gdb_ctx->s->g_cpu);
+ cpu_synchronize_state(gdbserver_state.g_cpu);
+ g_byte_array_set_size(gdbserver_state.mem_buf, 0);
len = 0;
- for (addr = 0; addr < gdb_ctx->s->g_cpu->gdb_num_g_regs; addr++) {
- len += gdb_read_register(gdb_ctx->s->g_cpu, gdb_ctx->mem_buf + len,
+ for (addr = 0; addr < gdbserver_state.g_cpu->gdb_num_g_regs; addr++) {
+ len += gdb_read_register(gdbserver_state.g_cpu,
+ gdbserver_state.mem_buf,
addr);
}
+ g_assert(len == gdbserver_state.mem_buf->len);
- memtohex(gdb_ctx->str_buf, gdb_ctx->mem_buf, len);
- put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+ memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data, len);
+ put_strbuf();
}
static void handle_file_io(GdbCmdContext *gdb_ctx, void *user_ctx)
{
- if (gdb_ctx->num_params >= 1 && gdb_ctx->s->current_syscall_cb) {
+ if (gdb_ctx->num_params >= 1 && gdbserver_state.current_syscall_cb) {
target_ulong ret, err;
ret = (target_ulong)gdb_ctx->params[0].val_ull;
@@ -1829,31 +1857,31 @@ static void handle_file_io(GdbCmdContext *gdb_ctx, void *user_ctx)
} else {
err = 0;
}
- gdb_ctx->s->current_syscall_cb(gdb_ctx->s->c_cpu, ret, err);
- gdb_ctx->s->current_syscall_cb = NULL;
+ gdbserver_state.current_syscall_cb(gdbserver_state.c_cpu, ret, err);
+ gdbserver_state.current_syscall_cb = NULL;
}
if (gdb_ctx->num_params >= 3 && gdb_ctx->params[2].opcode == (uint8_t)'C') {
- put_packet(gdb_ctx->s, "T02");
+ put_packet("T02");
return;
}
- gdb_continue(gdb_ctx->s);
+ gdb_continue();
}
static void handle_step(GdbCmdContext *gdb_ctx, void *user_ctx)
{
if (gdb_ctx->num_params) {
- gdb_set_cpu_pc(gdb_ctx->s, (target_ulong)gdb_ctx->params[0].val_ull);
+ gdb_set_cpu_pc((target_ulong)gdb_ctx->params[0].val_ull);
}
- cpu_single_step(gdb_ctx->s->c_cpu, sstep_flags);
- gdb_continue(gdb_ctx->s);
+ cpu_single_step(gdbserver_state.c_cpu, sstep_flags);
+ gdb_continue();
}
static void handle_v_cont_query(GdbCmdContext *gdb_ctx, void *user_ctx)
{
- put_packet(gdb_ctx->s, "vCont;c;C;s;S");
+ put_packet("vCont;c;C;s;S");
}
static void handle_v_cont(GdbCmdContext *gdb_ctx, void *user_ctx)
@@ -1864,11 +1892,11 @@ static void handle_v_cont(GdbCmdContext *gdb_ctx, void *user_ctx)
return;
}
- res = gdb_handle_vcont(gdb_ctx->s, gdb_ctx->params[0].data);
+ res = gdb_handle_vcont(gdb_ctx->params[0].data);
if ((res == -EINVAL) || (res == -ERANGE)) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
} else if (res) {
- put_packet(gdb_ctx->s, "");
+ put_packet("");
}
}
@@ -1876,38 +1904,37 @@ 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");
+ g_string_assign(gdbserver_state.str_buf, "E22");
if (!gdb_ctx->num_params) {
goto cleanup;
}
- process = gdb_get_process(gdb_ctx->s, gdb_ctx->params[0].val_ul);
+ process = gdb_get_process(gdb_ctx->params[0].val_ul);
if (!process) {
goto cleanup;
}
- cpu = get_first_cpu_in_process(gdb_ctx->s, process);
+ cpu = get_first_cpu_in_process(process);
if (!cpu) {
goto cleanup;
}
process->attached = true;
- gdb_ctx->s->g_cpu = cpu;
- gdb_ctx->s->c_cpu = cpu;
+ gdbserver_state.g_cpu = cpu;
+ gdbserver_state.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);
+ g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP);
+ gdb_append_thread_id(cpu, gdbserver_state.str_buf);
+ g_string_append_c(gdbserver_state.str_buf, ';');
cleanup:
- put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+ put_strbuf();
}
static void handle_v_kill(GdbCmdContext *gdb_ctx, void *user_ctx)
{
/* Kill the target */
- put_packet(gdb_ctx->s, "OK");
+ put_packet("OK");
error_report("QEMU: Terminated via GDBstub");
exit(0);
}
@@ -1944,19 +1971,18 @@ static void handle_v_commands(GdbCmdContext *gdb_ctx, void *user_ctx)
return;
}
- if (process_string_cmd(gdb_ctx->s, NULL, gdb_ctx->params[0].data,
+ if (process_string_cmd(NULL, gdb_ctx->params[0].data,
gdb_v_commands_table,
ARRAY_SIZE(gdb_v_commands_table))) {
- put_packet(gdb_ctx->s, "");
+ put_packet("");
}
}
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);
+ g_string_printf(gdbserver_state.str_buf, "ENABLE=%x,NOIRQ=%x,NOTIMER=%x",
+ SSTEP_ENABLE, SSTEP_NOIRQ, SSTEP_NOTIMER);
+ put_strbuf();
}
static void handle_set_qemu_sstep(GdbCmdContext *gdb_ctx, void *user_ctx)
@@ -1966,68 +1992,63 @@ static void handle_set_qemu_sstep(GdbCmdContext *gdb_ctx, void *user_ctx)
}
sstep_flags = gdb_ctx->params[0].val_ul;
- put_packet(gdb_ctx->s, "OK");
+ put_packet("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);
+ g_string_printf(gdbserver_state.str_buf, "0x%x", sstep_flags);
+ put_strbuf();
}
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);
+ process = gdb_get_cpu_process(gdbserver_state.g_cpu);
+ 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();
}
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");
+ if (!gdbserver_state.query_cpu) {
+ put_packet("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);
+ g_string_assign(gdbserver_state.str_buf, "m");
+ gdb_append_thread_id(gdbserver_state.query_cpu, gdbserver_state.str_buf);
+ put_strbuf();
+ gdbserver_state.query_cpu = gdb_next_attached_cpu(gdbserver_state.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);
+ gdbserver_state.query_cpu = gdb_first_attached_cpu();
handle_query_threads(gdb_ctx, user_ctx);
}
static void handle_query_thread_extra(GdbCmdContext *gdb_ctx, void *user_ctx)
{
+ g_autoptr(GString) rs = g_string_new(NULL);
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");
+ put_packet("E22");
return;
}
- cpu = gdb_get_cpu(gdb_ctx->s, gdb_ctx->params[0].thread_id.pid,
+ cpu = gdb_get_cpu(gdb_ctx->params[0].thread_id.pid,
gdb_ctx->params[0].thread_id.tid);
if (!cpu) {
return;
@@ -2035,24 +2056,21 @@ static void handle_query_thread_extra(GdbCmdContext *gdb_ctx, void *user_ctx)
cpu_synchronize_state(cpu);
- if (gdb_ctx->s->multiprocess && (gdb_ctx->s->process_num > 1)) {
+ if (gdbserver_state.multiprocess && (gdbserver_state.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);
+ g_autofree char *cpu_name;
+ cpu_name = object_get_canonical_path_component(OBJECT(cpu));
+ g_string_printf(rs, "%s %s [%s]", cpu_model, cpu_name,
+ cpu->halted ? "halted " : "running");
} 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,
+ g_string_printf(rs, "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);
+ trace_gdbstub_op_extra_info(rs->str);
+ memtohex(gdbserver_state.str_buf, (uint8_t *)rs->str, rs->len);
+ put_strbuf();
}
#ifdef CONFIG_USER_ONLY
@@ -2060,37 +2078,40 @@ 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);
+ ts = gdbserver_state.c_cpu->opaque;
+ g_string_printf(gdbserver_state.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_strbuf();
}
#else
static void handle_query_rcmd(GdbCmdContext *gdb_ctx, void *user_ctx)
{
+ const guint8 zero = 0;
int len;
if (!gdb_ctx->num_params) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
len = strlen(gdb_ctx->params[0].data);
if (len % 2) {
- put_packet(gdb_ctx->s, "E01");
+ put_packet("E01");
return;
}
+ g_assert(gdbserver_state.mem_buf->len == 0);
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");
-
+ hextomem(gdbserver_state.mem_buf, gdb_ctx->params[0].data, len);
+ g_byte_array_append(gdbserver_state.mem_buf, &zero, 1);
+ qemu_chr_be_write(gdbserver_state.mon_chr, gdbserver_state.mem_buf->data,
+ gdbserver_state.mem_buf->len);
+ put_packet("OK");
}
#endif
@@ -2098,21 +2119,19 @@ static void handle_query_supported(GdbCmdContext *gdb_ctx, void *user_ctx)
{
CPUClass *cc;
- snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "PacketSize=%x",
- MAX_PACKET_LENGTH);
+ g_string_printf(gdbserver_state.str_buf, "PacketSize=%x", MAX_PACKET_LENGTH);
cc = CPU_GET_CLASS(first_cpu);
if (cc->gdb_core_xml_file) {
- pstrcat(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf),
- ";qXfer:features:read+");
+ g_string_append(gdbserver_state.str_buf, ";qXfer:features:read+");
}
if (gdb_ctx->num_params &&
strstr(gdb_ctx->params[0].data, "multiprocess+")) {
- gdb_ctx->s->multiprocess = true;
+ gdbserver_state.multiprocess = true;
}
- pstrcat(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), ";multiprocess+");
- put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+ g_string_append(gdbserver_state.str_buf, ";vContSupported+;multiprocess+");
+ put_strbuf();
}
static void handle_query_xfer_features(GdbCmdContext *gdb_ctx, void *user_ctx)
@@ -2124,22 +2143,22 @@ static void handle_query_xfer_features(GdbCmdContext *gdb_ctx, void *user_ctx)
const char *p;
if (gdb_ctx->num_params < 3) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
- process = gdb_get_cpu_process(gdb_ctx->s, gdb_ctx->s->g_cpu);
- cc = CPU_GET_CLASS(gdb_ctx->s->g_cpu);
+ 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_ctx->s, "");
+ put_packet("");
return;
}
gdb_has_xml = true;
p = gdb_ctx->params[0].data;
- xml = get_feature_xml(gdb_ctx->s, p, &p, process);
+ xml = get_feature_xml(p, &p, process);
if (!xml) {
- put_packet(gdb_ctx->s, "E00");
+ put_packet("E00");
return;
}
@@ -2147,7 +2166,7 @@ static void handle_query_xfer_features(GdbCmdContext *gdb_ctx, void *user_ctx)
len = gdb_ctx->params[2].val_ul;
total_len = strlen(xml);
if (addr > total_len) {
- put_packet(gdb_ctx->s, "E00");
+ put_packet("E00");
return;
}
@@ -2156,42 +2175,43 @@ static void handle_query_xfer_features(GdbCmdContext *gdb_ctx, void *user_ctx)
}
if (len < total_len - addr) {
- gdb_ctx->str_buf[0] = 'm';
- len = memtox(gdb_ctx->str_buf + 1, xml + addr, len);
+ g_string_assign(gdbserver_state.str_buf, "m");
+ memtox(gdbserver_state.str_buf, xml + addr, len);
} else {
- gdb_ctx->str_buf[0] = 'l';
- len = memtox(gdb_ctx->str_buf + 1, xml + addr, total_len - addr);
+ g_string_assign(gdbserver_state.str_buf, "l");
+ memtox(gdbserver_state.str_buf, xml + addr, total_len - addr);
}
- put_packet_binary(gdb_ctx->s, gdb_ctx->str_buf, len + 1, true);
+ put_packet_binary(gdbserver_state.str_buf->str,
+ gdbserver_state.str_buf->len, true);
}
static void handle_query_attached(GdbCmdContext *gdb_ctx, void *user_ctx)
{
- put_packet(gdb_ctx->s, GDB_ATTACHED);
+ put_packet(GDB_ATTACHED);
}
static void handle_query_qemu_supported(GdbCmdContext *gdb_ctx, void *user_ctx)
{
- snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "sstepbits;sstep");
+ g_string_printf(gdbserver_state.str_buf, "sstepbits;sstep");
#ifndef CONFIG_USER_ONLY
- pstrcat(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), ";PhyMemMode");
+ g_string_append(gdbserver_state.str_buf, ";PhyMemMode");
#endif
- put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+ put_strbuf();
}
#ifndef CONFIG_USER_ONLY
static void handle_query_qemu_phy_mem_mode(GdbCmdContext *gdb_ctx,
void *user_ctx)
{
- snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "%d", phy_memory_mode);
- put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+ g_string_printf(gdbserver_state.str_buf, "%d", phy_memory_mode);
+ put_strbuf();
}
static void handle_set_qemu_phy_mem_mode(GdbCmdContext *gdb_ctx, void *user_ctx)
{
if (!gdb_ctx->num_params) {
- put_packet(gdb_ctx->s, "E22");
+ put_packet("E22");
return;
}
@@ -2200,7 +2220,7 @@ static void handle_set_qemu_phy_mem_mode(GdbCmdContext *gdb_ctx, void *user_ctx)
} else {
phy_memory_mode = 1;
}
- put_packet(gdb_ctx->s, "OK");
+ put_packet("OK");
}
#endif
@@ -2316,16 +2336,16 @@ static void handle_gen_query(GdbCmdContext *gdb_ctx, void *user_ctx)
return;
}
- if (!process_string_cmd(gdb_ctx->s, NULL, gdb_ctx->params[0].data,
+ if (!process_string_cmd(NULL, gdb_ctx->params[0].data,
gdb_gen_query_set_common_table,
ARRAY_SIZE(gdb_gen_query_set_common_table))) {
return;
}
- if (process_string_cmd(gdb_ctx->s, NULL, gdb_ctx->params[0].data,
+ if (process_string_cmd(NULL, gdb_ctx->params[0].data,
gdb_gen_query_table,
ARRAY_SIZE(gdb_gen_query_table))) {
- put_packet(gdb_ctx->s, "");
+ put_packet("");
}
}
@@ -2335,28 +2355,25 @@ static void handle_gen_set(GdbCmdContext *gdb_ctx, void *user_ctx)
return;
}
- if (!process_string_cmd(gdb_ctx->s, NULL, gdb_ctx->params[0].data,
+ if (!process_string_cmd(NULL, gdb_ctx->params[0].data,
gdb_gen_query_set_common_table,
ARRAY_SIZE(gdb_gen_query_set_common_table))) {
return;
}
- if (process_string_cmd(gdb_ctx->s, NULL, gdb_ctx->params[0].data,
+ if (process_string_cmd(NULL, gdb_ctx->params[0].data,
gdb_gen_set_table,
ARRAY_SIZE(gdb_gen_set_table))) {
- put_packet(gdb_ctx->s, "");
+ put_packet("");
}
}
static void handle_target_halt(GdbCmdContext *gdb_ctx, void *user_ctx)
{
- char thread_id[16];
-
- gdb_fmt_thread_id(gdb_ctx->s, gdb_ctx->s->c_cpu, thread_id,
- sizeof(thread_id));
- snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "T%02xthread:%s;",
- GDB_SIGNAL_TRAP, thread_id);
- put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+ 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();
/*
* Remove all the breakpoints when this query is issued,
* because gdb is doing an initial connect and the state
@@ -2365,7 +2382,7 @@ static void handle_target_halt(GdbCmdContext *gdb_ctx, void *user_ctx)
gdb_breakpoint_remove_all();
}
-static int gdb_handle_packet(GDBState *s, const char *line_buf)
+static int gdb_handle_packet(const char *line_buf)
{
const GdbCmdParseEntry *cmd_parser = NULL;
@@ -2373,7 +2390,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
switch (line_buf[0]) {
case '!':
- put_packet(s, "OK");
+ put_packet("OK");
break;
case '?':
{
@@ -2588,12 +2605,12 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
break;
default:
/* put empty packet */
- put_packet(s, "");
+ put_packet("");
break;
}
if (cmd_parser) {
- run_cmd_parser(s, line_buf, cmd_parser);
+ run_cmd_parser(line_buf, cmd_parser);
}
return RS_IDLE;
@@ -2601,7 +2618,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
void gdb_set_stop_cpu(CPUState *cpu)
{
- GDBProcess *p = gdb_get_cpu_process(gdbserver_state, cpu);
+ GDBProcess *p = gdb_get_cpu_process(cpu);
if (!p->attached) {
/*
@@ -2611,26 +2628,25 @@ void gdb_set_stop_cpu(CPUState *cpu)
return;
}
- gdbserver_state->c_cpu = cpu;
- gdbserver_state->g_cpu = cpu;
+ gdbserver_state.c_cpu = cpu;
+ gdbserver_state.g_cpu = cpu;
}
#ifndef CONFIG_USER_ONLY
static void gdb_vm_state_change(void *opaque, int running, RunState state)
{
- GDBState *s = gdbserver_state;
- CPUState *cpu = s->c_cpu;
- char buf[256];
- char thread_id[16];
+ CPUState *cpu = gdbserver_state.c_cpu;
+ g_autoptr(GString) buf = g_string_new(NULL);
+ g_autoptr(GString) tid = g_string_new(NULL);
const char *type;
int ret;
- if (running || s->state == RS_INACTIVE) {
+ if (running || gdbserver_state.state == RS_INACTIVE) {
return;
}
/* Is there a GDB syscall waiting to be sent? */
- if (s->current_syscall_cb) {
- put_packet(s, s->syscall_buf);
+ if (gdbserver_state.current_syscall_cb) {
+ put_packet(gdbserver_state.syscall_buf);
return;
}
@@ -2639,7 +2655,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
return;
}
- gdb_fmt_thread_id(s, cpu, thread_id, sizeof(thread_id));
+ gdb_append_thread_id(cpu, tid);
switch (state) {
case RUN_STATE_DEBUG:
@@ -2657,10 +2673,9 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
}
trace_gdbstub_hit_watchpoint(type, cpu_gdb_index(cpu),
(target_ulong)cpu->watchpoint_hit->vaddr);
- snprintf(buf, sizeof(buf),
- "T%02xthread:%s;%swatch:" TARGET_FMT_lx ";",
- GDB_SIGNAL_TRAP, thread_id, type,
- (target_ulong)cpu->watchpoint_hit->vaddr);
+ g_string_printf(buf, "T%02xthread:%s;%swatch:" TARGET_FMT_lx ";",
+ GDB_SIGNAL_TRAP, tid->str, type,
+ (target_ulong)cpu->watchpoint_hit->vaddr);
cpu->watchpoint_hit = NULL;
goto send_packet;
} else {
@@ -2701,10 +2716,10 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
break;
}
gdb_set_stop_cpu(cpu);
- snprintf(buf, sizeof(buf), "T%02xthread:%s;", ret, thread_id);
+ g_string_printf(buf, "T%02xthread:%s;", ret, tid->str);
send_packet:
- put_packet(s, buf);
+ put_packet(buf->str);
/* disable single step if it was enabled */
cpu_single_step(cpu, 0);
@@ -2722,17 +2737,17 @@ void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
char *p_end;
target_ulong addr;
uint64_t i64;
- GDBState *s;
- s = gdbserver_state;
- if (!s)
+ if (!gdbserver_state.init) {
return;
- s->current_syscall_cb = cb;
+ }
+
+ gdbserver_state.current_syscall_cb = cb;
#ifndef CONFIG_USER_ONLY
vm_stop(RUN_STATE_DEBUG);
#endif
- p = s->syscall_buf;
- p_end = &s->syscall_buf[sizeof(s->syscall_buf)];
+ p = &gdbserver_state.syscall_buf[0];
+ p_end = &gdbserver_state.syscall_buf[sizeof(gdbserver_state.syscall_buf)];
*(p++) = 'F';
while (*fmt) {
if (*fmt == '%') {
@@ -2765,14 +2780,14 @@ void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
}
*p = 0;
#ifdef CONFIG_USER_ONLY
- put_packet(s, s->syscall_buf);
+ 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
* gdb_handlesig's return value (which is the signal to deliver if
* execution was resumed via a continue packet).
*/
- gdb_handlesig(s->c_cpu, 0);
+ gdb_handlesig(gdbserver_state.c_cpu, 0);
#else
/* In this case wait to send the syscall packet until notification that
the CPU has stopped. This must be done because if the packet is sent
@@ -2780,7 +2795,7 @@ void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
is still in the running state, which can cause packets to be dropped
and state transition 'T' packets to be sent while the syscall is still
being processed. */
- qemu_cpu_kick(s->c_cpu);
+ qemu_cpu_kick(gdbserver_state.c_cpu);
#endif
}
@@ -2793,25 +2808,27 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
va_end(va);
}
-static void gdb_read_byte(GDBState *s, uint8_t ch)
+static void gdb_read_byte(uint8_t ch)
{
uint8_t reply;
#ifndef CONFIG_USER_ONLY
- if (s->last_packet_len) {
+ if (gdbserver_state.last_packet->len) {
/* Waiting for a response to the last packet. If we see the start
of a new command then abandon the previous response. */
if (ch == '-') {
trace_gdbstub_err_got_nack();
- put_buffer(s, (uint8_t *)s->last_packet, s->last_packet_len);
+ put_buffer(gdbserver_state.last_packet->data,
+ gdbserver_state.last_packet->len);
} else if (ch == '+') {
trace_gdbstub_io_got_ack();
} else {
trace_gdbstub_io_got_unexpected(ch);
}
- if (ch == '+' || ch == '$')
- s->last_packet_len = 0;
+ if (ch == '+' || ch == '$') {
+ g_byte_array_set_size(gdbserver_state.last_packet, 0);
+ }
if (ch != '$')
return;
}
@@ -2822,13 +2839,13 @@ static void gdb_read_byte(GDBState *s, uint8_t ch)
} else
#endif
{
- switch(s->state) {
+ switch(gdbserver_state.state) {
case RS_IDLE:
if (ch == '$') {
/* start of command packet */
- s->line_buf_index = 0;
- s->line_sum = 0;
- s->state = RS_GETLINE;
+ gdbserver_state.line_buf_index = 0;
+ gdbserver_state.line_sum = 0;
+ gdbserver_state.state = RS_GETLINE;
} else {
trace_gdbstub_err_garbage(ch);
}
@@ -2836,37 +2853,37 @@ static void gdb_read_byte(GDBState *s, uint8_t ch)
case RS_GETLINE:
if (ch == '}') {
/* start escape sequence */
- s->state = RS_GETLINE_ESC;
- s->line_sum += ch;
+ gdbserver_state.state = RS_GETLINE_ESC;
+ gdbserver_state.line_sum += ch;
} else if (ch == '*') {
/* start run length encoding sequence */
- s->state = RS_GETLINE_RLE;
- s->line_sum += ch;
+ gdbserver_state.state = RS_GETLINE_RLE;
+ gdbserver_state.line_sum += ch;
} else if (ch == '#') {
/* end of command, start of checksum*/
- s->state = RS_CHKSUM1;
- } else if (s->line_buf_index >= sizeof(s->line_buf) - 1) {
+ gdbserver_state.state = RS_CHKSUM1;
+ } else if (gdbserver_state.line_buf_index >= sizeof(gdbserver_state.line_buf) - 1) {
trace_gdbstub_err_overrun();
- s->state = RS_IDLE;
+ gdbserver_state.state = RS_IDLE;
} else {
/* unescaped command character */
- s->line_buf[s->line_buf_index++] = ch;
- s->line_sum += ch;
+ gdbserver_state.line_buf[gdbserver_state.line_buf_index++] = ch;
+ gdbserver_state.line_sum += ch;
}
break;
case RS_GETLINE_ESC:
if (ch == '#') {
/* unexpected end of command in escape sequence */
- s->state = RS_CHKSUM1;
- } else if (s->line_buf_index >= sizeof(s->line_buf) - 1) {
+ gdbserver_state.state = RS_CHKSUM1;
+ } else if (gdbserver_state.line_buf_index >= sizeof(gdbserver_state.line_buf) - 1) {
/* command buffer overrun */
trace_gdbstub_err_overrun();
- s->state = RS_IDLE;
+ gdbserver_state.state = RS_IDLE;
} else {
/* parse escaped character and leave escape state */
- s->line_buf[s->line_buf_index++] = ch ^ 0x20;
- s->line_sum += ch;
- s->state = RS_GETLINE;
+ gdbserver_state.line_buf[gdbserver_state.line_buf_index++] = ch ^ 0x20;
+ gdbserver_state.line_sum += ch;
+ gdbserver_state.state = RS_GETLINE;
}
break;
case RS_GETLINE_RLE:
@@ -2877,25 +2894,25 @@ static void gdb_read_byte(GDBState *s, uint8_t ch)
if (ch < ' ' || ch == '#' || ch == '$' || ch > 126) {
/* invalid RLE count encoding */
trace_gdbstub_err_invalid_repeat(ch);
- s->state = RS_GETLINE;
+ gdbserver_state.state = RS_GETLINE;
} else {
/* decode repeat length */
int repeat = ch - ' ' + 3;
- if (s->line_buf_index + repeat >= sizeof(s->line_buf) - 1) {
+ if (gdbserver_state.line_buf_index + repeat >= sizeof(gdbserver_state.line_buf) - 1) {
/* that many repeats would overrun the command buffer */
trace_gdbstub_err_overrun();
- s->state = RS_IDLE;
- } else if (s->line_buf_index < 1) {
+ gdbserver_state.state = RS_IDLE;
+ } else if (gdbserver_state.line_buf_index < 1) {
/* got a repeat but we have nothing to repeat */
trace_gdbstub_err_invalid_rle();
- s->state = RS_GETLINE;
+ gdbserver_state.state = RS_GETLINE;
} else {
/* repeat the last character */
- memset(s->line_buf + s->line_buf_index,
- s->line_buf[s->line_buf_index - 1], repeat);
- s->line_buf_index += repeat;
- s->line_sum += ch;
- s->state = RS_GETLINE;
+ memset(gdbserver_state.line_buf + gdbserver_state.line_buf_index,
+ gdbserver_state.line_buf[gdbserver_state.line_buf_index - 1], repeat);
+ gdbserver_state.line_buf_index += repeat;
+ gdbserver_state.line_sum += ch;
+ gdbserver_state.state = RS_GETLINE;
}
}
break;
@@ -2903,33 +2920,33 @@ static void gdb_read_byte(GDBState *s, uint8_t ch)
/* get high hex digit of checksum */
if (!isxdigit(ch)) {
trace_gdbstub_err_checksum_invalid(ch);
- s->state = RS_GETLINE;
+ gdbserver_state.state = RS_GETLINE;
break;
}
- s->line_buf[s->line_buf_index] = '\0';
- s->line_csum = fromhex(ch) << 4;
- s->state = RS_CHKSUM2;
+ gdbserver_state.line_buf[gdbserver_state.line_buf_index] = '\0';
+ gdbserver_state.line_csum = fromhex(ch) << 4;
+ gdbserver_state.state = RS_CHKSUM2;
break;
case RS_CHKSUM2:
/* get low hex digit of checksum */
if (!isxdigit(ch)) {
trace_gdbstub_err_checksum_invalid(ch);
- s->state = RS_GETLINE;
+ gdbserver_state.state = RS_GETLINE;
break;
}
- s->line_csum |= fromhex(ch);
+ gdbserver_state.line_csum |= fromhex(ch);
- if (s->line_csum != (s->line_sum & 0xff)) {
- trace_gdbstub_err_checksum_incorrect(s->line_sum, s->line_csum);
+ if (gdbserver_state.line_csum != (gdbserver_state.line_sum & 0xff)) {
+ trace_gdbstub_err_checksum_incorrect(gdbserver_state.line_sum, gdbserver_state.line_csum);
/* send NAK reply */
reply = '-';
- put_buffer(s, &reply, 1);
- s->state = RS_IDLE;
+ put_buffer(&reply, 1);
+ gdbserver_state.state = RS_IDLE;
} else {
/* send ACK reply */
reply = '+';
- put_buffer(s, &reply, 1);
- s->state = gdb_handle_packet(s, s->line_buf);
+ put_buffer(&reply, 1);
+ gdbserver_state.state = gdb_handle_packet(gdbserver_state.line_buf);
}
break;
default:
@@ -2941,15 +2958,13 @@ static void gdb_read_byte(GDBState *s, uint8_t ch)
/* Tell the remote gdb that the process has exited. */
void gdb_exit(CPUArchState *env, int code)
{
- GDBState *s;
char buf[4];
- s = gdbserver_state;
- if (!s) {
+ if (!gdbserver_state.init) {
return;
}
#ifdef CONFIG_USER_ONLY
- if (gdbserver_fd < 0 || s->fd < 0) {
+ if (gdbserver_fd < 0 || gdbserver_state.fd < 0) {
return;
}
#endif
@@ -2957,10 +2972,10 @@ void gdb_exit(CPUArchState *env, int code)
trace_gdbstub_op_exiting((uint8_t)code);
snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
- put_packet(s, buf);
+ put_packet(buf);
#ifndef CONFIG_USER_ONLY
- qemu_chr_fe_deinit(&s->chr, true);
+ qemu_chr_fe_deinit(&gdbserver_state.chr, true);
#endif
}
@@ -2974,7 +2989,7 @@ static void create_default_process(GDBState *s)
GDBProcess *process;
int max_pid = 0;
- if (s->process_num) {
+ if (gdbserver_state.process_num) {
max_pid = s->processes[s->process_num - 1].pid;
}
@@ -2993,12 +3008,10 @@ static void create_default_process(GDBState *s)
int
gdb_handlesig(CPUState *cpu, int sig)
{
- GDBState *s;
char buf[256];
int n;
- s = gdbserver_state;
- if (gdbserver_fd < 0 || s->fd < 0) {
+ if (gdbserver_fd < 0 || gdbserver_state.fd < 0) {
return sig;
}
@@ -3008,58 +3021,55 @@ gdb_handlesig(CPUState *cpu, int sig)
if (sig != 0) {
snprintf(buf, sizeof(buf), "S%02x", target_signal_to_gdb(sig));
- put_packet(s, buf);
+ put_packet(buf);
}
/* put_packet() might have detected that the peer terminated the
connection. */
- if (s->fd < 0) {
+ if (gdbserver_state.fd < 0) {
return sig;
}
sig = 0;
- s->state = RS_IDLE;
- s->running_state = 0;
- while (s->running_state == 0) {
- n = read(s->fd, buf, 256);
+ gdbserver_state.state = RS_IDLE;
+ gdbserver_state.running_state = 0;
+ while (gdbserver_state.running_state == 0) {
+ n = read(gdbserver_state.fd, buf, 256);
if (n > 0) {
int i;
for (i = 0; i < n; i++) {
- gdb_read_byte(s, buf[i]);
+ gdb_read_byte(buf[i]);
}
} else {
/* XXX: Connection closed. Should probably wait for another
connection before continuing. */
if (n == 0) {
- close(s->fd);
+ close(gdbserver_state.fd);
}
- s->fd = -1;
+ gdbserver_state.fd = -1;
return sig;
}
}
- sig = s->signal;
- s->signal = 0;
+ sig = gdbserver_state.signal;
+ gdbserver_state.signal = 0;
return sig;
}
/* Tell the remote gdb that the process has exited due to SIG. */
void gdb_signalled(CPUArchState *env, int sig)
{
- GDBState *s;
char buf[4];
- s = gdbserver_state;
- if (gdbserver_fd < 0 || s->fd < 0) {
+ if (gdbserver_fd < 0 || gdbserver_state.fd < 0) {
return;
}
snprintf(buf, sizeof(buf), "X%02x", target_signal_to_gdb(sig));
- put_packet(s, buf);
+ put_packet(buf);
}
static bool gdb_accept(void)
{
- GDBState *s;
struct sockaddr_in sockaddr;
socklen_t len;
int fd;
@@ -3083,15 +3093,13 @@ static bool gdb_accept(void)
return false;
}
- s = g_malloc0(sizeof(GDBState));
- create_default_process(s);
- s->processes[0].attached = true;
- s->c_cpu = gdb_first_attached_cpu(s);
- s->g_cpu = s->c_cpu;
- s->fd = fd;
+ init_gdbserver_state();
+ 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;
+ gdbserver_state.fd = fd;
gdb_has_xml = false;
-
- gdbserver_state = s;
return true;
}
@@ -3144,13 +3152,11 @@ int gdbserver_start(int port)
/* Disable gdb stub for child processes. */
void gdbserver_fork(CPUState *cpu)
{
- GDBState *s = gdbserver_state;
-
- if (gdbserver_fd < 0 || s->fd < 0) {
+ if (gdbserver_fd < 0 || gdbserver_state.fd < 0) {
return;
}
- close(s->fd);
- s->fd = -1;
+ close(gdbserver_state.fd);
+ gdbserver_state.fd = -1;
cpu_breakpoint_remove_all(cpu, BP_GDB);
cpu_watchpoint_remove_all(cpu, BP_GDB);
}
@@ -3167,7 +3173,7 @@ static void gdb_chr_receive(void *opaque, const uint8_t *buf, int size)
int i;
for (i = 0; i < size; i++) {
- gdb_read_byte(gdbserver_state, buf[i]);
+ gdb_read_byte(buf[i]);
}
}
@@ -3183,7 +3189,7 @@ static void gdb_chr_event(void *opaque, QEMUChrEvent event)
s->processes[i].attached = !i;
}
- s->c_cpu = gdb_first_attached_cpu(s);
+ s->c_cpu = gdb_first_attached_cpu();
s->g_cpu = s->c_cpu;
vm_stop(RUN_STATE_PAUSED);
@@ -3194,32 +3200,11 @@ static void gdb_chr_event(void *opaque, QEMUChrEvent event)
}
}
-static void gdb_monitor_output(GDBState *s, const char *msg, int len)
-{
- char buf[MAX_PACKET_LENGTH];
-
- buf[0] = 'O';
- if (len > (MAX_PACKET_LENGTH/2) - 1)
- len = (MAX_PACKET_LENGTH/2) - 1;
- memtohex(buf + 1, (uint8_t *)msg, len);
- put_packet(s, buf);
-}
-
static int gdb_monitor_write(Chardev *chr, const uint8_t *buf, int len)
{
- const char *p = (const char *)buf;
- int max_sz;
-
- max_sz = (sizeof(gdbserver_state->last_packet) - 2) / 2;
- for (;;) {
- if (len <= max_sz) {
- gdb_monitor_output(gdbserver_state, p, len);
- break;
- }
- gdb_monitor_output(gdbserver_state, p, max_sz);
- p += max_sz;
- len -= max_sz;
- }
+ g_autoptr(GString) hex_buf = g_string_new("O");
+ memtohex(hex_buf, buf, len);
+ put_packet(hex_buf->str);
return len;
}
@@ -3300,26 +3285,18 @@ static void create_processes(GDBState *s)
{
object_child_foreach(object_get_root(), find_cpu_clusters, s);
- if (s->processes) {
+ if (gdbserver_state.processes) {
/* Sort by PID */
- qsort(s->processes, s->process_num, sizeof(s->processes[0]), pid_order);
+ qsort(gdbserver_state.processes, gdbserver_state.process_num, sizeof(gdbserver_state.processes[0]), pid_order);
}
create_default_process(s);
}
-static void cleanup_processes(GDBState *s)
-{
- g_free(s->processes);
- s->process_num = 0;
- s->processes = NULL;
-}
-
int gdbserver_start(const char *device)
{
trace_gdbstub_op_start(device);
- GDBState *s;
char gdbstub_device_name[128];
Chardev *chr = NULL;
Chardev *mon_chr;
@@ -3357,10 +3334,8 @@ int gdbserver_start(const char *device)
return -1;
}
- s = gdbserver_state;
- if (!s) {
- s = g_malloc0(sizeof(GDBState));
- gdbserver_state = s;
+ if (!gdbserver_state.init) {
+ init_gdbserver_state();
qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL);
@@ -3369,31 +3344,30 @@ int gdbserver_start(const char *device)
NULL, NULL, &error_abort);
monitor_init_hmp(mon_chr, false, &error_abort);
} else {
- qemu_chr_fe_deinit(&s->chr, true);
- mon_chr = s->mon_chr;
- cleanup_processes(s);
- memset(s, 0, sizeof(GDBState));
- s->mon_chr = mon_chr;
+ qemu_chr_fe_deinit(&gdbserver_state.chr, true);
+ mon_chr = gdbserver_state.mon_chr;
+ reset_gdbserver_state();
}
- create_processes(s);
+ create_processes(&gdbserver_state);
if (chr) {
- qemu_chr_fe_init(&s->chr, chr, &error_abort);
- qemu_chr_fe_set_handlers(&s->chr, gdb_chr_can_receive, gdb_chr_receive,
- gdb_chr_event, NULL, s, NULL, true);
+ qemu_chr_fe_init(&gdbserver_state.chr, chr, &error_abort);
+ qemu_chr_fe_set_handlers(&gdbserver_state.chr, gdb_chr_can_receive,
+ gdb_chr_receive, gdb_chr_event,
+ NULL, &gdbserver_state, NULL, true);
}
- s->state = chr ? RS_IDLE : RS_INACTIVE;
- s->mon_chr = mon_chr;
- s->current_syscall_cb = NULL;
+ gdbserver_state.state = chr ? RS_IDLE : RS_INACTIVE;
+ gdbserver_state.mon_chr = mon_chr;
+ gdbserver_state.current_syscall_cb = NULL;
return 0;
}
void gdbserver_cleanup(void)
{
- if (gdbserver_state) {
- put_packet(gdbserver_state, "W00");
+ if (gdbserver_state.init) {
+ put_packet("W00");
}
}