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));