This makes gdb frontend able to list loaded libraries so it can then parse debug information. It seems that it also supports PE/ELF mix, so this is nice but debug info for PE files is still completely off.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- programs/winedbg/gdbproxy.c | 72 +++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c index 70735afd0646..4f1e2a3c2fd8 100644 --- a/programs/winedbg/gdbproxy.c +++ b/programs/winedbg/gdbproxy.c @@ -1472,6 +1472,66 @@ static void packet_query_target_xml(struct gdb_context* gdbctx, struct backend_c packet_reply_add(gdbctx, "</target>"); }
+static BOOL CALLBACK packet_query_libraries_cb(PCSTR mod_name, DWORD64 base, PVOID ctx) +{ + struct gdb_context* gdbctx = ctx; + IMAGEHLP_MODULE64 mod; + DWORD64 addr; + BOOL is_wow64; + char* tmp; + + mod.SizeOfStruct = sizeof(mod); + SymGetModuleInfo64(gdbctx->process->handle, base, &mod); + + packet_reply_add(gdbctx, "<library name=""); + if (strcmp(mod.LoadedImageName, "[vdso].so") == 0) + packet_reply_add(gdbctx, "linux-vdso.so.1"); + else if (mod.LoadedImageName[0] == '/') + packet_reply_add(gdbctx, mod.LoadedImageName); + else + { + UNICODE_STRING nt_name; + ANSI_STRING ansi_name; + char * unix_path; + + RtlInitAnsiString(&ansi_name, mod.LoadedImageName); + RtlAnsiStringToUnicodeString(&nt_name, &ansi_name, TRUE); + + if ((unix_path = wine_get_unix_file_name(nt_name.Buffer))) + { + if (IsWow64Process(gdbctx->process->handle, &is_wow64) && + is_wow64 && (tmp = strstr(unix_path, "system32"))) + memcpy(tmp, "syswow64", 8); + packet_reply_add(gdbctx, unix_path); + } + else + packet_reply_add(gdbctx, mod.LoadedImageName); + + HeapFree(GetProcessHeap(), 0, unix_path); + RtlFreeUnicodeString(&nt_name); + } + + addr = mod.BaseOfImage; + + packet_reply_add(gdbctx, ""><segment address="0x"); + packet_reply_val(gdbctx, addr, sizeof(addr)); + packet_reply_add(gdbctx, ""/></library>"); + + return TRUE; +} + +static void packet_query_libraries(struct gdb_context* gdbctx) +{ + BOOL opt; + /* this will resynchronize builtin dbghelp's internal ELF module list */ + SymLoadModule(gdbctx->process->handle, 0, 0, 0, 0, 0); + packet_reply_add(gdbctx, "<library-list>"); + opt = SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, TRUE); + SymEnumerateModules64(gdbctx->process->handle, packet_query_libraries_cb, gdbctx); + SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, opt); + packet_reply_add(gdbctx, "</library-list>"); +} + static enum packet_return packet_query(struct gdb_context* gdbctx) { int off, len; @@ -1565,6 +1625,7 @@ static enum packet_return packet_query(struct gdb_context* gdbctx) packet_reply_open(gdbctx); packet_reply_add(gdbctx, "QStartNoAckMode+;"); packet_reply_add(gdbctx, "qXfer:features:read+;"); + packet_reply_add(gdbctx, "qXfer:libraries:read+;"); packet_reply_close(gdbctx); return packet_done; } @@ -1605,6 +1666,17 @@ static enum packet_return packet_query(struct gdb_context* gdbctx) packet_reply_close_xfer(gdbctx, off, len); return packet_done; } + + if (sscanf(gdbctx->in_packet, "Xfer:libraries:read::%x,%x", &off, &len) == 2) + { + if (!gdbctx->process) + return packet_error; + + packet_reply_open_xfer(gdbctx); + packet_query_libraries(gdbctx); + 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));