mirror of https://gitee.com/openkylin/qemu.git
gdbstub: add multiprocess support to '?' packets
The gdb_get_cpu_pid() function does the PID lookup for the given CPU. It checks if the CPU is a direct child of a CPU cluster. If it is, the returned PID is the cluster ID plus one (cluster IDs start at 0, GDB PIDs at 1). When the CPU is not a child of such a container, the PID of the default process is returned. The gdb_fmt_thread_id() function generates the string to be used to identify a given thread, in a response packet for the peer. This function supports generating thread IDs when multiprocess mode is enabled (in the form `p<pid>.<tid>'). Use them in the reply to a '?' request. Signed-off-by: Luc Michel <luc.michel@greensocs.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Message-id: 20181207090135.7651-4-luc.michel@greensocs.com [PMM: fixed checkpatch blockquote style nit] Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
8f46863618
commit
1a22733697
66
gdbstub.c
66
gdbstub.c
|
@ -640,6 +640,54 @@ static int memtox(char *buf, const char *mem, int len)
|
|||
return p - buf;
|
||||
}
|
||||
|
||||
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) {
|
||||
/* Return the default process' PID */
|
||||
ret = s->processes[s->process_num - 1].pid;
|
||||
goto out;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
static const char *get_feature_xml(const char *p, const char **newp,
|
||||
CPUClass *cc)
|
||||
{
|
||||
|
@ -909,6 +957,19 @@ static CPUState *find_cpu(uint32_t thread_id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static char *gdb_fmt_thread_id(const GDBState *s, CPUState *cpu,
|
||||
char *buf, size_t buf_size)
|
||||
{
|
||||
if (s->multiprocess) {
|
||||
snprintf(buf, buf_size, "p%02x.%02x",
|
||||
gdb_get_cpu_pid(s, cpu), cpu_gdb_index(cpu));
|
||||
} else {
|
||||
snprintf(buf, buf_size, "%02x", cpu_gdb_index(cpu));
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int is_query_packet(const char *p, const char *query, char separator)
|
||||
{
|
||||
unsigned int query_len = strlen(query);
|
||||
|
@ -1020,6 +1081,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
|
|||
int ch, reg_size, type, res;
|
||||
uint8_t mem_buf[MAX_PACKET_LENGTH];
|
||||
char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
|
||||
char thread_id[16];
|
||||
uint8_t *registers;
|
||||
target_ulong addr, len;
|
||||
|
||||
|
@ -1030,8 +1092,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
|
|||
switch(ch) {
|
||||
case '?':
|
||||
/* TODO: Make this return the correct value for user-mode. */
|
||||
snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP,
|
||||
cpu_gdb_index(s->c_cpu));
|
||||
snprintf(buf, sizeof(buf), "T%02xthread:%s;", GDB_SIGNAL_TRAP,
|
||||
gdb_fmt_thread_id(s, s->c_cpu, thread_id, sizeof(thread_id)));
|
||||
put_packet(s, buf);
|
||||
/* Remove all the breakpoints when this query is issued,
|
||||
* because gdb is doing and initial connect and the state
|
||||
|
|
Loading…
Reference in New Issue