gdbstub: add multiprocess support to Xfer:features:read:

Change the Xfer:features:read: packet handling to support the
multiprocess extension. This packet is used to request the XML
description of the CPU. In multiprocess mode, different descriptions can
be sent for different processes.

This function now takes the process to send the description for as a
parameter, and use a buffer in the process structure to store the
generated description.

It takes the first CPU of the process to generate the description.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-id: 20181207090135.7651-9-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Luc Michel 2019-01-07 15:23:46 +00:00 committed by Peter Maydell
parent 7cf48f6752
commit c145eeae1c

View File

@ -300,6 +300,8 @@ typedef struct GDBRegisterState {
typedef struct GDBProcess { typedef struct GDBProcess {
uint32_t pid; uint32_t pid;
bool attached; bool attached;
char target_xml[1024];
} GDBProcess; } GDBProcess;
enum RSState { enum RSState {
@ -812,13 +814,14 @@ static CPUState *gdb_first_attached_cpu(const GDBState *s)
return cpu; return cpu;
} }
static const char *get_feature_xml(const char *p, const char **newp, static const char *get_feature_xml(const GDBState *s, const char *p,
CPUClass *cc) const char **newp, GDBProcess *process)
{ {
size_t len; size_t len;
int i; int i;
const char *name; const char *name;
static char target_xml[1024]; CPUState *cpu = get_first_cpu_in_process(s, process);
CPUClass *cc = CPU_GET_CLASS(cpu);
len = 0; len = 0;
while (p[len] && p[len] != ':') while (p[len] && p[len] != ':')
@ -827,36 +830,37 @@ static const char *get_feature_xml(const char *p, const char **newp,
name = NULL; name = NULL;
if (strncmp(p, "target.xml", len) == 0) { if (strncmp(p, "target.xml", len) == 0) {
/* Generate the XML description for this CPU. */ char *buf = process->target_xml;
if (!target_xml[0]) { const size_t buf_sz = sizeof(process->target_xml);
GDBRegisterState *r;
CPUState *cpu = first_cpu;
pstrcat(target_xml, sizeof(target_xml), /* Generate the XML description for this CPU. */
if (!buf[0]) {
GDBRegisterState *r;
pstrcat(buf, buf_sz,
"<?xml version=\"1.0\"?>" "<?xml version=\"1.0\"?>"
"<!DOCTYPE target SYSTEM \"gdb-target.dtd\">" "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
"<target>"); "<target>");
if (cc->gdb_arch_name) { if (cc->gdb_arch_name) {
gchar *arch = cc->gdb_arch_name(cpu); gchar *arch = cc->gdb_arch_name(cpu);
pstrcat(target_xml, sizeof(target_xml), "<architecture>"); pstrcat(buf, buf_sz, "<architecture>");
pstrcat(target_xml, sizeof(target_xml), arch); pstrcat(buf, buf_sz, arch);
pstrcat(target_xml, sizeof(target_xml), "</architecture>"); pstrcat(buf, buf_sz, "</architecture>");
g_free(arch); g_free(arch);
} }
pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\""); pstrcat(buf, buf_sz, "<xi:include href=\"");
pstrcat(target_xml, sizeof(target_xml), cc->gdb_core_xml_file); pstrcat(buf, buf_sz, cc->gdb_core_xml_file);
pstrcat(target_xml, sizeof(target_xml), "\"/>"); pstrcat(buf, buf_sz, "\"/>");
for (r = cpu->gdb_regs; r; r = r->next) { for (r = cpu->gdb_regs; r; r = r->next) {
pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\""); pstrcat(buf, buf_sz, "<xi:include href=\"");
pstrcat(target_xml, sizeof(target_xml), r->xml); pstrcat(buf, buf_sz, r->xml);
pstrcat(target_xml, sizeof(target_xml), "\"/>"); pstrcat(buf, buf_sz, "\"/>");
} }
pstrcat(target_xml, sizeof(target_xml), "</target>"); pstrcat(buf, buf_sz, "</target>");
} }
return target_xml; return buf;
} }
if (cc->gdb_get_dynamic_xml) { if (cc->gdb_get_dynamic_xml) {
CPUState *cpu = first_cpu;
char *xmlname = g_strndup(p, len); char *xmlname = g_strndup(p, len);
const char *xml = cc->gdb_get_dynamic_xml(cpu, xmlname); const char *xml = cc->gdb_get_dynamic_xml(cpu, xmlname);
@ -1266,6 +1270,7 @@ out:
static int gdb_handle_packet(GDBState *s, const char *line_buf) static int gdb_handle_packet(GDBState *s, const char *line_buf)
{ {
CPUState *cpu; CPUState *cpu;
GDBProcess *process;
CPUClass *cc; CPUClass *cc;
const char *p; const char *p;
uint32_t pid, tid; uint32_t pid, tid;
@ -1650,14 +1655,15 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
const char *xml; const char *xml;
target_ulong total_len; target_ulong total_len;
cc = CPU_GET_CLASS(first_cpu); process = gdb_get_cpu_process(s, s->g_cpu);
cc = CPU_GET_CLASS(s->g_cpu);
if (cc->gdb_core_xml_file == NULL) { if (cc->gdb_core_xml_file == NULL) {
goto unknown_command; goto unknown_command;
} }
gdb_has_xml = true; gdb_has_xml = true;
p += 19; p += 19;
xml = get_feature_xml(p, &p, cc); xml = get_feature_xml(s, p, &p, process);
if (!xml) { if (!xml) {
snprintf(buf, sizeof(buf), "E00"); snprintf(buf, sizeof(buf), "E00");
put_packet(s, buf); put_packet(s, buf);
@ -2070,6 +2076,7 @@ static void create_default_process(GDBState *s)
process->pid = max_pid + 1; process->pid = max_pid + 1;
process->attached = false; process->attached = false;
process->target_xml[0] = '\0';
} }
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
@ -2345,6 +2352,7 @@ static int find_cpu_clusters(Object *child, void *opaque)
assert(cluster->cluster_id != UINT32_MAX); assert(cluster->cluster_id != UINT32_MAX);
process->pid = cluster->cluster_id + 1; process->pid = cluster->cluster_id + 1;
process->attached = false; process->attached = false;
process->target_xml[0] = '\0';
return 0; return 0;
} }