[PATCH 4/8] winedbg: Support qXfer:features:read request.
Rémi Bernon
rbernon at codeweavers.com
Thu Apr 2 08:55:17 CDT 2020
Also introduces packet_reply_open_xfer and packet_reply_close_xfer,
supporting partial qXfer replies. It always allocates the whole reply
buffer for simplicity, but then trucates to the requested offset and
length.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
This makes gdb frontend stop trying to figure libraries by itself, so
we temporarily lose debug symbol lookup. It will be fixed by the
qXfer:libraries:read request.
programs/winedbg/gdbproxy.c | 199 +++++++++++++++++++++++++++++-------
1 file changed, 162 insertions(+), 37 deletions(-)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c
index 7c57caf9d1e8..5a273c4a3199 100644
--- a/programs/winedbg/gdbproxy.c
+++ b/programs/winedbg/gdbproxy.c
@@ -168,40 +168,6 @@ static unsigned char checksum(const char* ptr, int len)
return cksum;
}
-#ifdef __i386__
-static const char target_xml[] = "";
-#elif defined(__powerpc__)
-static const char target_xml[] = "";
-#elif defined(__x86_64__)
-static const char target_xml[] = "";
-#elif defined(__arm__)
-static const char target_xml[] =
- "l <target><architecture>arm</architecture>\n"
- "<feature name=\"org.gnu.gdb.arm.core\">\n"
- " <reg name=\"r0\" bitsize=\"32\" type=\"uint32\"/>\n"
- " <reg name=\"r1\" bitsize=\"32\" type=\"uint32\"/>\n"
- " <reg name=\"r2\" bitsize=\"32\" type=\"uint32\"/>\n"
- " <reg name=\"r3\" bitsize=\"32\" type=\"uint32\"/>\n"
- " <reg name=\"r4\" bitsize=\"32\" type=\"uint32\"/>\n"
- " <reg name=\"r5\" bitsize=\"32\" type=\"uint32\"/>\n"
- " <reg name=\"r6\" bitsize=\"32\" type=\"uint32\"/>\n"
- " <reg name=\"r7\" bitsize=\"32\" type=\"uint32\"/>\n"
- " <reg name=\"r8\" bitsize=\"32\" type=\"uint32\"/>\n"
- " <reg name=\"r9\" bitsize=\"32\" type=\"uint32\"/>\n"
- " <reg name=\"r10\" bitsize=\"32\" type=\"uint32\"/>\n"
- " <reg name=\"r11\" bitsize=\"32\" type=\"uint32\"/>\n"
- " <reg name=\"r12\" bitsize=\"32\" type=\"uint32\"/>\n"
- " <reg name=\"sp\" bitsize=\"32\" type=\"data_ptr\"/>\n"
- " <reg name=\"lr\" bitsize=\"32\"/>\n"
- " <reg name=\"pc\" bitsize=\"32\" type=\"code_ptr\"/>\n"
- " <reg name=\"cpsr\" bitsize=\"32\"/>\n"
- "</feature></target>\n";
-#elif defined(__aarch64__)
-static const char target_xml[] = "";
-#else
-# error Define the registers map for your CPU
-#endif
-
static inline void* cpu_register_ptr(struct gdb_context *gdbctx,
dbg_ctx_t *ctx, unsigned idx)
{
@@ -767,6 +733,35 @@ static void packet_reply_close(struct gdb_context* gdbctx)
gdbctx->out_curr_packet = -1;
}
+static void packet_reply_open_xfer(struct gdb_context* gdbctx)
+{
+ packet_reply_open(gdbctx);
+ packet_reply_add(gdbctx, "m");
+}
+
+static void packet_reply_close_xfer(struct gdb_context* gdbctx, int off, int len)
+{
+ int begin = gdbctx->out_curr_packet + 1;
+ int plen;
+
+ if (begin + off < gdbctx->out_len)
+ {
+ gdbctx->out_len -= off;
+ memmove(gdbctx->out_buf + begin, gdbctx->out_buf + begin + off, gdbctx->out_len);
+ }
+ else
+ {
+ gdbctx->out_buf[gdbctx->out_curr_packet] = 'l';
+ gdbctx->out_len = gdbctx->out_curr_packet + 1;
+ }
+
+ plen = gdbctx->out_len - begin;
+ if (len >= 0 && plen > len) gdbctx->out_len -= (plen - len);
+ else gdbctx->out_buf[gdbctx->out_curr_packet] = 'l';
+
+ packet_reply_close(gdbctx);
+}
+
static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet)
{
packet_reply_open(gdbctx);
@@ -1396,8 +1391,130 @@ static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx
return packet_reply_error(gdbctx, EINVAL);
}
+static void packet_query_target_xml(struct gdb_context* gdbctx, struct backend_cpu* cpu)
+{
+ const char* feature_prefix = NULL;
+ const char* feature = NULL;
+ char buffer[256];
+ int i;
+
+ packet_reply_add(gdbctx, "<target>");
+ switch (cpu->machine)
+ {
+ case IMAGE_FILE_MACHINE_AMD64:
+ packet_reply_add(gdbctx, "<architecture>i386:x86-64</architecture>");
+ feature_prefix = "org.gnu.gdb.i386.";
+ break;
+ case IMAGE_FILE_MACHINE_I386:
+ packet_reply_add(gdbctx, "<architecture>i386</architecture>");
+ feature_prefix = "org.gnu.gdb.i386.";
+ break;
+ case IMAGE_FILE_MACHINE_POWERPC:
+ packet_reply_add(gdbctx, "<architecture>powerpc:common</architecture>");
+ feature_prefix = "org.gnu.gdb.power.";
+ break;
+ case IMAGE_FILE_MACHINE_ARMNT:
+ packet_reply_add(gdbctx, "<architecture>arm</architecture>");
+ feature_prefix = "org.gnu.gdb.arm.";
+ break;
+ case IMAGE_FILE_MACHINE_ARM64:
+ packet_reply_add(gdbctx, "<architecture>aarch64</architecture>");
+ feature_prefix = "org.gnu.gdb.aarch64.";
+ break;
+ }
+
+ for (i = 0; i < cpu->gdb_num_regs; ++i)
+ {
+ if (cpu->gdb_register_map[i].feature)
+ {
+ if (feature) packet_reply_add(gdbctx, "</feature>");
+ feature = cpu->gdb_register_map[i].feature;
+
+ packet_reply_add(gdbctx, "<feature name=\"");
+ if (feature_prefix) packet_reply_add(gdbctx, feature_prefix);
+ packet_reply_add(gdbctx, feature);
+ packet_reply_add(gdbctx, "\">");
+
+ if (strcmp(feature_prefix, "org.gnu.gdb.i386.") == 0 &&
+ strcmp(feature, "core") == 0)
+ packet_reply_add(gdbctx, "<flags id=\"i386_eflags\" size=\"4\">"
+ "<field name=\"CF\" start=\"0\" end=\"0\"/>"
+ "<field name=\"\" start=\"1\" end=\"1\"/>"
+ "<field name=\"PF\" start=\"2\" end=\"2\"/>"
+ "<field name=\"AF\" start=\"4\" end=\"4\"/>"
+ "<field name=\"ZF\" start=\"6\" end=\"6\"/>"
+ "<field name=\"SF\" start=\"7\" end=\"7\"/>"
+ "<field name=\"TF\" start=\"8\" end=\"8\"/>"
+ "<field name=\"IF\" start=\"9\" end=\"9\"/>"
+ "<field name=\"DF\" start=\"10\" end=\"10\"/>"
+ "<field name=\"OF\" start=\"11\" end=\"11\"/>"
+ "<field name=\"NT\" start=\"14\" end=\"14\"/>"
+ "<field name=\"RF\" start=\"16\" end=\"16\"/>"
+ "<field name=\"VM\" start=\"17\" end=\"17\"/>"
+ "<field name=\"AC\" start=\"18\" end=\"18\"/>"
+ "<field name=\"VIF\" start=\"19\" end=\"19\"/>"
+ "<field name=\"VIP\" start=\"20\" end=\"20\"/>"
+ "<field name=\"ID\" start=\"21\" end=\"21\"/>"
+ "</flags>");
+
+ if (strcmp(feature_prefix, "org.gnu.gdb.i386.") == 0 &&
+ strcmp(feature, "sse") == 0)
+ packet_reply_add(gdbctx, "<vector id=\"v4f\" type=\"ieee_single\" count=\"4\"/>"
+ "<vector id=\"v2d\" type=\"ieee_double\" count=\"2\"/>"
+ "<vector id=\"v16i8\" type=\"int8\" count=\"16\"/>"
+ "<vector id=\"v8i16\" type=\"int16\" count=\"8\"/>"
+ "<vector id=\"v4i32\" type=\"int32\" count=\"4\"/>"
+ "<vector id=\"v2i64\" type=\"int64\" count=\"2\"/>"
+ "<union id=\"vec128\">"
+ "<field name=\"v4_float\" type=\"v4f\"/>"
+ "<field name=\"v2_double\" type=\"v2d\"/>"
+ "<field name=\"v16_int8\" type=\"v16i8\"/>"
+ "<field name=\"v8_int16\" type=\"v8i16\"/>"
+ "<field name=\"v4_int32\" type=\"v4i32\"/>"
+ "<field name=\"v2_int64\" type=\"v2i64\"/>"
+ "<field name=\"uint128\" type=\"uint128\"/>"
+ "</union>"
+ "<flags id=\"i386_mxcsr\" size=\"4\">"
+ "<field name=\"IE\" start=\"0\" end=\"0\"/>"
+ "<field name=\"DE\" start=\"1\" end=\"1\"/>"
+ "<field name=\"ZE\" start=\"2\" end=\"2\"/>"
+ "<field name=\"OE\" start=\"3\" end=\"3\"/>"
+ "<field name=\"UE\" start=\"4\" end=\"4\"/>"
+ "<field name=\"PE\" start=\"5\" end=\"5\"/>"
+ "<field name=\"DAZ\" start=\"6\" end=\"6\"/>"
+ "<field name=\"IM\" start=\"7\" end=\"7\"/>"
+ "<field name=\"DM\" start=\"8\" end=\"8\"/>"
+ "<field name=\"ZM\" start=\"9\" end=\"9\"/>"
+ "<field name=\"OM\" start=\"10\" end=\"10\"/>"
+ "<field name=\"UM\" start=\"11\" end=\"11\"/>"
+ "<field name=\"PM\" start=\"12\" end=\"12\"/>"
+ "<field name=\"FZ\" start=\"15\" end=\"15\"/>"
+ "</flags>");
+ }
+
+ snprintf(buffer, ARRAY_SIZE(buffer), "<reg name=\"%s\" bitsize=\"%zu\"",
+ cpu->gdb_register_map[i].name, 8 * cpu->gdb_register_map[i].gdb_length);
+ packet_reply_add(gdbctx, buffer);
+
+ if (cpu->gdb_register_map[i].type)
+ {
+ packet_reply_add(gdbctx, " type=\"");
+ packet_reply_add(gdbctx, cpu->gdb_register_map[i].type);
+ packet_reply_add(gdbctx, "\"");
+ }
+
+ packet_reply_add(gdbctx, "/>");
+ }
+
+ if (feature) packet_reply_add(gdbctx, "</feature>");
+ packet_reply_add(gdbctx, "</target>");
+}
+
static enum packet_return packet_query(struct gdb_context* gdbctx)
{
+ int off, len;
+ struct backend_cpu *cpu;
+
switch (gdbctx->in_packet[0])
{
case 'f':
@@ -1485,7 +1602,7 @@ static enum packet_return packet_query(struct gdb_context* gdbctx)
{
packet_reply_open(gdbctx);
packet_reply_add(gdbctx, "QStartNoAckMode+;");
- if (*target_xml) packet_reply_add(gdbctx, "PacketSize=400;qXfer:features:read+");
+ packet_reply_add(gdbctx, "qXfer:features:read+;");
packet_reply_close(gdbctx);
return packet_done;
}
@@ -1516,8 +1633,16 @@ static enum packet_return packet_query(struct gdb_context* gdbctx)
}
break;
case 'X':
- if (*target_xml && strncmp(gdbctx->in_packet, "Xfer:features:read:target.xml", 29) == 0)
- return packet_reply(gdbctx, target_xml);
+ if (sscanf(gdbctx->in_packet, "Xfer:features:read:target.xml:%x,%x", &off, &len) == 2)
+ {
+ if (!gdbctx->process) return packet_error;
+ if (!(cpu = gdbctx->process->be_cpu)) return packet_error;
+
+ packet_reply_open_xfer(gdbctx);
+ packet_query_target_xml(gdbctx, cpu);
+ packet_reply_close_xfer(gdbctx, off, len);
+ return packet_done;
+ }
break;
}
ERR("Unhandled query %s\n", debugstr_an(gdbctx->in_packet, gdbctx->in_packet_len));
--
2.26.0.rc2
More information about the wine-devel
mailing list