From 9877ba97320e8786437d4465816e281ad8b527e2 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Wed, 8 Mar 2023 11:43:22 +0100 Subject: [PATCH] dbghelp: Don't set ELF loader when wine's loader isn't accessible. For dbghelp in 32-bit, when accessing a live debuggee in multi-arch configuration, Wine's ELF loader is likely mapped above 4G, hence not accessible with 32bit Windows APIs. So don't try to expose the ELF libraries in that case. Introducing a new loader operation class to support live targets, for which system operations are not accessible, but pretending they are successful. Note: - when Wine's loader ELF module isn't registered by dbghelp, any other ELF module will not be registered by dbghelp. - further work may be needed for winedbg in auto mode (launched with AeDebug key on process exception) as in that mode winedbg doesn't relaunch itself in 64bit, so won't be able to access (64bit) ELF information (in multi-arch configuration). Signed-off-by: Eric Pouech --- dlls/dbghelp/dbghelp_private.h | 1 + dlls/dbghelp/elf_module.c | 12 ++++++--- dlls/dbghelp/module.c | 45 +++++++++++++++++++++++++--------- dlls/dbghelp/tests/dbghelp.c | 1 - 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 1852aef1795..c11ccf81a92 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -716,6 +716,7 @@ void minidump_add_memory_block(struct dump_context* dc, ULONG64 base, ULONG size extern const WCHAR S_ElfW[] DECLSPEC_HIDDEN; extern const WCHAR S_WineLoaderW[] DECLSPEC_HIDDEN; extern const struct loader_ops no_loader_ops DECLSPEC_HIDDEN; +extern const struct loader_ops empty_loader_ops DECLSPEC_HIDDEN; extern BOOL module_init_pair(struct module_pair* pair, HANDLE hProcess, DWORD64 addr) DECLSPEC_HIDDEN; diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index 3c1e225e195..ee8315c4a23 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -39,7 +39,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); struct elf_info { unsigned flags; /* IN one (or several) of the ELF_INFO constants */ - DWORD_PTR dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */ + DWORD64 dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */ struct module* module; /* OUT loaded module (if ELF_INFO_MODULE is set) */ const WCHAR* module_name; /* OUT found module name (if ELF_INFO_NAME is set) */ }; @@ -1769,8 +1769,14 @@ BOOL elf_read_wine_loader_dbg_info(struct process* pcs, ULONG_PTR addr) HeapFree(GetProcessHeap(), 0, loader); } if (!ret || !elf_info.dbg_hdr_addr) return FALSE; - - TRACE("Found ELF debug header %#Ix\n", elf_info.dbg_hdr_addr); + if (elf_info.dbg_hdr_addr != (ULONG_PTR)elf_info.dbg_hdr_addr) + { + ERR("Unable to access ELF libraries (outside 32bit limit)\n"); + module_remove(pcs, elf_info.module); + pcs->loader = &empty_loader_ops; + return FALSE; + } + TRACE("Found ELF debug header %#I64x\n", elf_info.dbg_hdr_addr); elf_info.module->format_info[DFI_ELF]->u.elf_info->elf_loader = 1; module_set_module(elf_info.module, S_WineLoaderW); pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr; diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index 8c7639dba38..ee559cfd99e 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -1548,11 +1548,6 @@ PVOID WINAPI SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) return module->cpu->find_runtime_function(module, AddrBase); } -static BOOL native_synchronize_module_list(struct process* pcs) -{ - return FALSE; -} - static struct module* native_load_module(struct process* pcs, const WCHAR* name, ULONG_PTR addr) { return NULL; @@ -1564,22 +1559,48 @@ static BOOL native_load_debug_info(struct process* process, struct module* modul return FALSE; } -static BOOL native_enum_modules(struct process *process, enum_modules_cb cb, void* user) -{ - return FALSE; -} - static BOOL native_fetch_file_info(struct process* process, const WCHAR* name, ULONG_PTR load_addr, DWORD_PTR* base, DWORD* size, DWORD* checksum) { return FALSE; } +static BOOL noloader_synchronize_module_list(struct process* pcs) +{ + return FALSE; +} + +static BOOL noloader_enum_modules(struct process *process, enum_modules_cb cb, void* user) +{ + return FALSE; +} + +static BOOL empty_synchronize_module_list(struct process* pcs) +{ + return TRUE; +} + +static BOOL empty_enum_modules(struct process *process, enum_modules_cb cb, void* user) +{ + return TRUE; +} + +/* to be used when debuggee isn't a live target */ const struct loader_ops no_loader_ops = { - native_synchronize_module_list, + noloader_synchronize_module_list, native_load_module, native_load_debug_info, - native_enum_modules, + noloader_enum_modules, + native_fetch_file_info, +}; + +/* to be used when debuggee is a live target, but which system information isn't available */ +const struct loader_ops empty_loader_ops = +{ + empty_synchronize_module_list, + native_load_module, + native_load_debug_info, + empty_enum_modules, native_fetch_file_info, }; diff --git a/dlls/dbghelp/tests/dbghelp.c b/dlls/dbghelp/tests/dbghelp.c index 445576532e6..339585993e0 100644 --- a/dlls/dbghelp/tests/dbghelp.c +++ b/dlls/dbghelp/tests/dbghelp.c @@ -735,7 +735,6 @@ static void test_loaded_modules(void) } ret = SymRefreshModuleList(pi.hProcess); - todo_wine_if(get_process_kind(pi.hProcess) == PCSKIND_WOW64) ok(ret || broken(GetLastError() == STATUS_PARTIAL_COPY /* Win11 in some cases */), "SymRefreshModuleList failed: %lu\n", GetLastError()); SymCleanup(pi.hProcess);