X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=gdbstub.c;h=d54abd17cc29ea9f6d7a7a9952aa12217e33463c;hb=2fa23277d58ce7ec527541b3baf52894ded530cc;hp=432e7d2f7da41da34b33204d6f1618adaa1fa599;hpb=970ed9064aa9f997fd9e65d707dd5cafc7360703;p=mirror_qemu.git diff --git a/gdbstub.c b/gdbstub.c index 432e7d2f7d..d54abd17cc 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -644,50 +644,12 @@ static int memtox(char *buf, const char *mem, int len) static uint32_t gdb_get_cpu_pid(const GDBState *s, CPUState *cpu) { -#ifndef CONFIG_USER_ONLY - gchar *path, *name = NULL; - Object *obj; - CPUClusterState *cluster; - uint32_t ret; - - path = object_get_canonical_path(OBJECT(cpu)); - - if (path == NULL) { - /* Return the default process' PID */ - ret = s->processes[s->process_num - 1].pid; - goto out; - } - - name = object_get_canonical_path_component(OBJECT(cpu)); - assert(name != NULL); - - /* - * Retrieve the CPU parent path by removing the last '/' and the CPU name - * from the CPU canonical path. - */ - path[strlen(path) - strlen(name) - 1] = '\0'; - - obj = object_resolve_path_type(path, TYPE_CPU_CLUSTER, NULL); - - if (obj == NULL) { + /* TODO: In user mode, we should use the task state PID */ + if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) { /* Return the default process' PID */ - ret = s->processes[s->process_num - 1].pid; - goto out; + return s->processes[s->process_num - 1].pid; } - - cluster = CPU_CLUSTER(obj); - ret = cluster->cluster_id + 1; - -out: - g_free(name); - g_free(path); - - return ret; - -#else - /* TODO: In user mode, we should use the task state PID */ - return s->processes[s->process_num - 1].pid; -#endif + return cpu->cluster_index + 1; } static GDBProcess *gdb_get_process(const GDBState *s, uint32_t pid) @@ -756,35 +718,6 @@ static CPUState *gdb_next_cpu_in_process(const GDBState *s, CPUState *cpu) return cpu; } -static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid) -{ - GDBProcess *process; - CPUState *cpu; - - if (!tid) { - /* 0 means any thread, we take the first one */ - tid = 1; - } - - cpu = find_cpu(tid); - - if (cpu == NULL) { - return NULL; - } - - process = gdb_get_cpu_process(s, cpu); - - if (process->pid != pid) { - return NULL; - } - - if (!process->attached) { - return NULL; - } - - return cpu; -} - /* Return the cpu following @cpu, while ignoring unattached processes. */ static CPUState *gdb_next_attached_cpu(const GDBState *s, CPUState *cpu) { @@ -814,6 +747,49 @@ static CPUState *gdb_first_attached_cpu(const GDBState *s) return cpu; } +static CPUState *gdb_get_cpu(const GDBState *s, 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); + } else if (pid && !tid) { + /* any thread in a specific process */ + process = gdb_get_process(s, pid); + + if (process == NULL) { + return NULL; + } + + if (!process->attached) { + return NULL; + } + + return get_first_cpu_in_process(s, process); + } else { + /* a specific thread */ + cpu = find_cpu(tid); + + if (cpu == NULL) { + return NULL; + } + + process = gdb_get_cpu_process(s, cpu); + + if (pid && process->pid != pid) { + return NULL; + } + + if (!process->attached) { + return NULL; + } + + return cpu; + } +} + static const char *get_feature_xml(const GDBState *s, const char *p, const char **newp, GDBProcess *process) { @@ -1176,6 +1152,7 @@ static int gdb_handle_vcont(GDBState *s, const char *p) uint32_t pid, tid; GDBProcess *process; CPUState *cpu; + GDBThreadIdKind kind; #ifdef CONFIG_USER_ONLY int max_cpus = 1; /* global variable max_cpus exists only in system mode */ @@ -1218,12 +1195,21 @@ static int gdb_handle_vcont(GDBState *s, const char *p) goto out; } - if (*p++ != ':') { + if (*p == '\0' || *p == ';') { + /* + * No thread specifier, action is on "all threads". The + * specification is unclear regarding the process to act on. We + * choose all processes. + */ + kind = GDB_ALL_PROCESSES; + } else if (*p++ == ':') { + kind = read_thread_id(p, &p, &pid, &tid); + } else { res = -ENOTSUP; goto out; } - switch (read_thread_id(p, &p, &pid, &tid)) { + switch (kind) { case GDB_READ_THREAD_ERR: res = -EINVAL; goto out; @@ -1383,6 +1369,11 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) put_packet(s, buf); break; + } else if (strncmp(p, "Kill;", 5) == 0) { + /* Kill the target */ + put_packet(s, "OK"); + error_report("QEMU: Terminated via GDBstub"); + exit(0); } else { goto unknown_command; } @@ -1732,6 +1723,12 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) if (cc->gdb_core_xml_file != NULL) { pstrcat(buf, sizeof(buf), ";qXfer:features:read+"); } + + if (strstr(p, "multiprocess+")) { + s->multiprocess = true; + } + pstrcat(buf, sizeof(buf), ";multiprocess+"); + put_packet(s, buf); break; } @@ -1798,6 +1795,16 @@ 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); + + if (!p->attached) { + /* + * Having a stop CPU corresponding to a process that is not attached + * confuses GDB. So we ignore the request. + */ + return; + } + gdbserver_state->c_cpu = cpu; gdbserver_state->g_cpu = cpu; } @@ -2535,7 +2542,7 @@ int gdbserver_start(const char *device) * FIXME: it's a bit weird to allow using a mux chardev here * and implicitly setup a monitor. We may want to break this. */ - chr = qemu_chr_new_noreplay("gdb", device, true); + chr = qemu_chr_new_noreplay("gdb", device, true, NULL); if (!chr) return -1; } @@ -2549,7 +2556,7 @@ int gdbserver_start(const char *device) /* Initialize a monitor terminal for gdb */ mon_chr = qemu_chardev_new(NULL, TYPE_CHARDEV_GDB, - NULL, &error_abort); + NULL, NULL, &error_abort); monitor_init(mon_chr, 0); } else { qemu_chr_fe_deinit(&s->chr, true);