-- v2: dbghelp: Use GetCurrentProcess() special handle in EnumerateLoadedModulesW64() if possible.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/dbghelp/module.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index 3f009b6b1ef..6d2f9d5a12c 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -1280,6 +1280,7 @@ BOOL WINAPI EnumerateLoadedModulesW64(HANDLE process, PENUMLOADED_MODULES_CALLBACKW64 enum_cb, PVOID user) { + OBJECT_BASIC_INFORMATION obi; HMODULE* hmods; unsigned alloc = 256, count, count32, i; USHORT pcs_machine, native_machine; @@ -1290,6 +1291,14 @@ BOOL WINAPI EnumerateLoadedModulesW64(HANDLE process, WCHAR* wowdir = NULL; size_t sysdir_len = 0, wowdir_len = 0;
+ if (process != GetCurrentProcess() && GetCurrentProcessId() == GetProcessId(process) + && !NtQueryObject(process, ObjectBasicInformation, &obi, sizeof(obi), NULL) + && obi.GrantedAccess & PROCESS_VM_READ) + { + TRACE("same process.\n"); + process = GetCurrentProcess(); + } + /* process might not be a handle to a live process */ if (!IsWow64Process2(process, &pcs_machine, &native_machine)) {
Thanks, I updated the patch to check access.
WRT second point, whatever we are going to do optimizing this without touching dbghelp looks impossible. Our dbghelp.EnumerateLoadedModulesW64 works ~25 times slower on Windows compared to Windows dbghelp. And 800 times slower on Wine than on Windows without substituting current process; with this patch it only 20 times slower for the same process (vs 26 on Windows).
In the current design EnumerateLoadedModulesW64 calls EnumProcessModulesEx, GetModuleInformation and GetModuleFileNameExW. Checking if the process is current takes two server calls, so only that will deliver ~400 server calls in concerned case.
Then, it seems to me that on higher level (dbghelp vs kernelbase) we might use a tiny bit more freedom in choosing performance optimizations ways which look a bit tweaky rather than on lower level, isn't that the case? Also, while it looks a bit tweaky, the same process case is probably not that exceptional, at least when it is not an post-crash report and that performance may matter a lot.
v2: - check current process handle access rights.
On Thu Aug 28 09:37:11 2025 +0000, Paul Gofman wrote:
Thanks, I updated the patch to check access. WRT second point, whatever we are going to do optimizing this without touching dbghelp looks impossible. Our dbghelp.EnumerateLoadedModulesW64 works ~25 times slower on Windows compared to Windows dbghelp. And 800 times slower on Wine than on Windows without substituting current process; with this patch it only 20 times slower for the same process (vs 26 on Windows). In the current design EnumerateLoadedModulesW64 calls EnumProcessModulesEx, GetModuleInformation and GetModuleFileNameExW. Checking if the process is current takes two server calls, so only that will deliver ~400 server calls in concerned case. Then, it seems to me that on higher level (dbghelp vs kernelbase) we might use a tiny bit more freedom in choosing performance optimizations ways which look a bit tweaky rather than on lower level, isn't that the case? Also, while it looks a bit tweaky, the same process case is probably not that exceptional, at least when it is not an post-crash report and that performance may matter a lot.
My second point is about long terme goal. MR as it is (thanks for the v2 update) looks good to me as a first improvement.
For the long term: if we consider complexity based on number of server calls, current implementation is O(n^2) (where n is the number of modules). Walking once the process list in dbghelp will give us O(n) which is a signficant improvement.
I would favor solutions using a constant number of server calls (which your measurements on native tend to confirm).
It seems to me that the Pss*Snapshot Apis have been designed to do a single kernel query and avoid one syscall per module. We still need to implement these properly in Wine. Didn't look at the faisabilité touche.
Side note: i've seen exec with more than 600 loaded Dlls.