From 99b7e2bb32caa407bc53fcf29f6c6900c639f857 Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9mi=20Bernon?= Date: Fri, 3 Apr 2020 15:35:50 +0200 Subject: [PATCH] winedbg: Support qXfer:features:read request. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This reports the full register sets to gdb, telling it about custom offsets and sizes. It will make the gdb specific register length not required anymore. We also have to report architecture specific vector types and flags that are normally builtin in gdb as it does not load them anymore when custom register set is reported. This makes gdb stop using its incorrect heuristics and actually request the library list, it now correctly gets PE modules information and is able to correctly use debug info from mixed modules. Signed-off-by: RĂ©mi Bernon Signed-off-by: Alexandre Julliard --- programs/winedbg/gdbproxy.c | 168 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 131 insertions(+), 37 deletions(-) diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c index 2bc69639925..46e56b6f190 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 arm\n" - "\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\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) { @@ -1540,9 +1506,129 @@ static void packet_query_threads(struct gdb_context* gdbctx) packet_reply_add(gdbctx, ""); } +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, ""); + switch (cpu->machine) + { + case IMAGE_FILE_MACHINE_AMD64: + packet_reply_add(gdbctx, "i386:x86-64"); + feature_prefix = "org.gnu.gdb.i386."; + break; + case IMAGE_FILE_MACHINE_I386: + packet_reply_add(gdbctx, "i386"); + feature_prefix = "org.gnu.gdb.i386."; + break; + case IMAGE_FILE_MACHINE_POWERPC: + packet_reply_add(gdbctx, "powerpc:common"); + feature_prefix = "org.gnu.gdb.power."; + break; + case IMAGE_FILE_MACHINE_ARMNT: + packet_reply_add(gdbctx, "arm"); + feature_prefix = "org.gnu.gdb.arm."; + break; + case IMAGE_FILE_MACHINE_ARM64: + packet_reply_add(gdbctx, "aarch64"); + 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 = cpu->gdb_register_map[i].feature; + + packet_reply_add(gdbctx, ""); + + if (strcmp(feature_prefix, "org.gnu.gdb.i386.") == 0 && + strcmp(feature, "core") == 0) + packet_reply_add(gdbctx, "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""); + + if (strcmp(feature_prefix, "org.gnu.gdb.i386.") == 0 && + strcmp(feature, "sse") == 0) + packet_reply_add(gdbctx, "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""); + } + + snprintf(buffer, ARRAY_SIZE(buffer), "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, ""); + packet_reply_add(gdbctx, ""); +} + static enum packet_return packet_query(struct gdb_context* gdbctx) { int off, len; + struct backend_cpu *cpu; switch (gdbctx->in_packet[0]) { @@ -1633,7 +1719,7 @@ static enum packet_return packet_query(struct gdb_context* gdbctx) packet_reply_add(gdbctx, "QStartNoAckMode+;"); packet_reply_add(gdbctx, "qXfer:libraries:read+;"); packet_reply_add(gdbctx, "qXfer:threads:read+;"); - 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; } @@ -1684,8 +1770,16 @@ static enum packet_return packet_query(struct gdb_context* gdbctx) return packet_done; } - 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.11.4.GIT