From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp.c | 22 ++++++-------------- dlls/dbghelp/dbghelp_private.h | 1 + dlls/dbghelp/elf_module.c | 1 - dlls/dbghelp/module.c | 37 ++++++++++++++++++++++++++++++---- dlls/dbghelp/tests/dbghelp.c | 10 --------- 5 files changed, 40 insertions(+), 31 deletions(-)
diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c index cc1b91d5e77..5a023152ec4 100644 --- a/dlls/dbghelp/dbghelp.c +++ b/dlls/dbghelp/dbghelp.c @@ -300,20 +300,6 @@ BOOL WINAPI SymGetSearchPath(HANDLE hProcess, PSTR szSearchPath, return ret; }
-/****************************************************************** - * invade_process - * - * SymInitialize helper: loads in dbghelp all known (and loaded modules) - * this assumes that hProcess is a handle on a valid process - */ -static BOOL WINAPI process_invade_cb(PCWSTR name, ULONG64 base, ULONG size, PVOID user) -{ - HANDLE hProcess = user; - - SymLoadModuleExW(hProcess, 0, name, NULL, base, size, NULL, 0); - return TRUE; -} - const WCHAR *process_getenv(const struct process *process, const WCHAR *name) { size_t name_len; @@ -432,7 +418,10 @@ static BOOL check_live_target(struct process* pcs, BOOL wow64, BOOL child_wow64)
TRACE("got debug info address %#I64x from PEB %p\n", base, pbi.PebBaseAddress); if (!elf_read_wine_loader_dbg_info(pcs, base) && !macho_read_wine_loader_dbg_info(pcs, base)) + { WARN("couldn't load process debug info at %#I64x\n", base); + pcs->loader = &empty_loader_ops; + } return TRUE; }
@@ -510,8 +499,9 @@ BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeP if (check_live_target(pcs, wow64, child_wow64)) { if (fInvadeProcess) - EnumerateLoadedModulesW64(hProcess, process_invade_cb, hProcess); - if (pcs->loader) pcs->loader->synchronize_module_list(pcs); + module_refresh_list(pcs); + else + pcs->loader->synchronize_module_list(pcs); } else if (fInvadeProcess) { diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 33714e73bc1..d8761bd599a 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -743,6 +743,7 @@ extern BOOL module_remove(struct process* pcs, extern void module_set_module(struct module* module, const WCHAR* name); extern WCHAR* get_wine_loader_name(struct process *pcs) __WINE_DEALLOC(HeapFree, 3) __WINE_MALLOC; extern BOOL module_is_wine_host(const WCHAR* module_name, const WCHAR* ext); +extern BOOL module_refresh_list(struct process *pcs);
/* msc.c */ extern BOOL pe_load_debug_directory(const struct process* pcs, diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index da4486a00c8..a4cf37942f0 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -1785,7 +1785,6 @@ BOOL elf_read_wine_loader_dbg_info(struct process* pcs, ULONG_PTR 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); diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index 0ade470961b..4b4dbbaf595 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -24,6 +24,8 @@ #include <string.h> #include <assert.h>
+#include "ntstatus.h" +#define WIN32_NO_STATUS #include "dbghelp_private.h" #include "image_private.h" #include "psapi.h" @@ -1317,7 +1319,11 @@ BOOL WINAPI EnumerateLoadedModulesW64(HANDLE process, size_t sysdir_len = 0, wowdir_len = 0;
/* process might not be a handle to a live process */ - if (!IsWow64Process2(process, &pcs_machine, &native_machine)) return FALSE; + if (!IsWow64Process2(process, &pcs_machine, &native_machine)) + { + SetLastError(STATUS_INVALID_CID); + return FALSE; + } with_32bit_modules = sizeof(void*) > sizeof(int) && pcs_machine != IMAGE_FILE_MACHINE_UNKNOWN && (dbghelp_options & SYMOPT_INCLUDE_32BIT_MODULES); @@ -1600,18 +1606,41 @@ void module_reset_debug_info(struct module* module) module->sources = NULL; }
+static BOOL WINAPI process_invade_cb(PCWSTR name, ULONG64 base, ULONG size, PVOID user) +{ + HANDLE hProcess = user; + + /* Note: this follows native behavior: + * If a PE module has been unloaded from debuggee, it's not immediately removed + * from module list in dbghelp. + * Removal may eventually happen when loading a another module with SymLoadModule: + * if the module to be loaded overlaps an existing one, SymLoadModule will + * automatically unload the eldest one. + */ + SymLoadModuleExW(hProcess, 0, name, NULL, base, size, NULL, 0); + return TRUE; +} + +BOOL module_refresh_list(struct process *pcs) +{ + BOOL ret; + + ret = pcs->loader->synchronize_module_list(pcs); + ret = EnumerateLoadedModulesW64(pcs->handle, process_invade_cb, pcs->handle) && ret; + return ret; +} + /****************************************************************** * SymRefreshModuleList (DBGHELP.@) */ BOOL WINAPI SymRefreshModuleList(HANDLE hProcess) { - struct process* pcs; + struct process *pcs;
TRACE("(%p)\n", hProcess);
if (!(pcs = process_find_by_handle(hProcess))) return FALSE; - - return pcs->loader->synchronize_module_list(pcs); + return module_refresh_list(pcs); }
/*********************************************************************** diff --git a/dlls/dbghelp/tests/dbghelp.c b/dlls/dbghelp/tests/dbghelp.c index fab1c670b5d..f7313c3ab4f 100644 --- a/dlls/dbghelp/tests/dbghelp.c +++ b/dlls/dbghelp/tests/dbghelp.c @@ -537,7 +537,6 @@ static BOOL test_modules(void)
ret = SymRefreshModuleList(dummy); ok(!ret, "SymRefreshModuleList should have failed\n"); - todo_wine ok(GetLastError() == STATUS_INVALID_CID, "Unexpected last error %lx\n", GetLastError());
count = get_module_count(dummy); @@ -875,7 +874,6 @@ static void test_loaded_modules(void) /* testing invalid process handle */ ret = wrapper_EnumerateLoadedModulesW64((HANDLE)(ULONG_PTR)0xffffffc0, NULL, FALSE); ok(!ret, "EnumerateLoadedModulesW64 should have failed\n"); - todo_wine ok(GetLastError() == STATUS_INVALID_CID, "Unexpected last error %lx\n", GetLastError());
/* testing with child process of different machines */ @@ -939,7 +937,6 @@ static void test_loaded_modules(void) pcskind = get_process_kind(pi.hProcess);
ret = wrapper_SymRefreshModuleList(pi.hProcess); - todo_wine_if(pcskind == PCSKIND_WOW64) ok(ret || broken(GetLastError() == STATUS_PARTIAL_COPY /* Win11 in some cases */ || GetLastError() == STATUS_INFO_LENGTH_MISMATCH /* Win11 in some cases */), "SymRefreshModuleList failed: %lx\n", GetLastError()); @@ -1613,7 +1610,6 @@ static void test_refresh_modules(void) ok(ret, "SymRefreshModuleList failed: %lx\n", GetLastError());
count_current = get_module_count(GetCurrentProcess()); - todo_wine ok(count == count_current, "Unexpected module count %u, %u\n", count, count_current);
hmod = GetModuleHandleW(unused_dll); @@ -1623,7 +1619,6 @@ static void test_refresh_modules(void) ok(hmod != NULL, "LoadLibraryW failed: %lu\n", GetLastError());
count_current = get_module_count(GetCurrentProcess()); - todo_wine ok(count == count_current, "Unexpected module count %u, %u\n", count, count_current); ret = is_module_present(GetCurrentProcess(), unused_dll); ok(!ret, "Couldn't find module %ls\n", unused_dll); @@ -1632,17 +1627,14 @@ static void test_refresh_modules(void) ok(ret, "SymRefreshModuleList failed: %lx\n", GetLastError());
count_current = get_module_count(GetCurrentProcess()); - todo_wine ok(count + 1 == count_current, "Unexpected module count %u, %u\n", count, count_current); ret = is_module_present(GetCurrentProcess(), unused_dll); - todo_wine ok(ret, "Couldn't find module %ls\n", unused_dll);
ret = FreeLibrary(hmod); ok(ret, "LoadLibraryW failed: %lu\n", GetLastError());
count_current = get_module_count(GetCurrentProcess()); - todo_wine ok(count + 1 == count_current, "Unexpected module count %u, %u\n", count, count_current);
ret = wrapper_SymRefreshModuleList(GetCurrentProcess()); @@ -1650,10 +1642,8 @@ static void test_refresh_modules(void)
/* SymRefreshModuleList() doesn't remove the unloaded modules... */ count_current = get_module_count(GetCurrentProcess()); - todo_wine ok(count + 1 == count_current, "Unexpected module count %u != %u\n", count, count_current); ret = is_module_present(GetCurrentProcess(), unused_dll); - todo_wine ok(ret, "Couldn't find module %ls\n", unused_dll);
ret = SymCleanup(GetCurrentProcess());