From a4b206b384c9367d0add95d5a0c0bd84374f6cb9 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Fri, 3 Sep 2021 08:57:12 +0200 Subject: [PATCH] dbghelp: Handle the case where loader isn't what WINELOADER reports. use case, in a WoW setup: wine programs/winedbg/winedbg.exe.so notepad.exe where both winedbg and notepad are 64bit exec:s in this case, dbghelp (loaded from winedbg) reads '<...>/wine' from WINELOADER windows env block inside notepad (but the unix env block is correctly set to wine64 by the tweak in ntdll/unix/loader.c) as a consequence dbghelp doesn't get the ELF information (it tries to read 32bit ELF entities, and fails); hence misses all the loaded ELF libraries winedbg's command 'info share' only reports the PE modules note: the 'dual' case wine64 programs/winedbg/winedbg.exe.so c:\\windows\\syswow64\\notepad.exe where winedbg is a 64bit exec and notepad a 32bit shows the same failures workaround this in dbghelp by tweaking the value of WINELOADER whether the debuggee is 32 or 64bit Signed-off-by: Eric Pouech Signed-off-by: Alexandre Julliard --- dlls/dbghelp/dbghelp_private.h | 2 +- dlls/dbghelp/elf_module.c | 10 ++++++++-- dlls/dbghelp/macho_module.c | 10 +++++++++- dlls/dbghelp/module.c | 30 ++++++++++++++++++++++++++---- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index eb2b53e947a..d6280a5189b 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -644,7 +644,7 @@ extern void module_reset_debug_info(struct module* module) DECLSPEC_HIDD extern BOOL module_remove(struct process* pcs, struct module* module) DECLSPEC_HIDDEN; extern void module_set_module(struct module* module, const WCHAR* name) DECLSPEC_HIDDEN; -extern const WCHAR *get_wine_loader_name(struct process *pcs) DECLSPEC_HIDDEN; +extern WCHAR* get_wine_loader_name(struct process *pcs) DECLSPEC_HIDDEN; /* 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 d1a4454e043..7be7e8efce6 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -1752,10 +1752,16 @@ static const struct loader_ops elf_loader_ops = BOOL elf_read_wine_loader_dbg_info(struct process* pcs, ULONG_PTR addr) { struct elf_info elf_info; - BOOL ret; + BOOL ret = FALSE; + WCHAR* loader; elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE; - ret = elf_search_and_load_file(pcs, get_wine_loader_name(pcs), addr, 0, &elf_info); + loader = get_wine_loader_name(pcs); + if (loader) + { + ret = elf_search_and_load_file(pcs, loader, addr, 0, &elf_info); + HeapFree(GetProcessHeap(), 0, loader); + } if (!ret || !elf_info.dbg_hdr_addr) return FALSE; TRACE("Found ELF debug header %#lx\n", elf_info.dbg_hdr_addr); diff --git a/dlls/dbghelp/macho_module.c b/dlls/dbghelp/macho_module.c index 602f7e45c14..7b0b80c4900 100644 --- a/dlls/dbghelp/macho_module.c +++ b/dlls/dbghelp/macho_module.c @@ -1885,7 +1885,15 @@ static BOOL macho_search_loader(struct process* pcs, struct macho_info* macho_in } } - if (!ret) ret = macho_search_and_load_file(pcs, get_wine_loader_name(pcs), 0, macho_info); + if (!ret) + { + WCHAR* loader = get_wine_loader_name(pcs); + if (loader) + { + ret = macho_search_and_load_file(pcs, loader, 0, macho_info); + HeapFree(GetProcessHeap(), 0, loader); + } + } return ret; } diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index c278a627d37..3bc2a9e143a 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -138,12 +138,34 @@ void module_set_module(struct module* module, const WCHAR* name) } /* Returned string must be freed by caller */ -const WCHAR *get_wine_loader_name(struct process *pcs) +WCHAR *get_wine_loader_name(struct process *pcs) { - const WCHAR *name = process_getenv(pcs, L"WINELOADER"); + const WCHAR *name; + WCHAR* altname; + unsigned len; + + name = process_getenv(pcs, L"WINELOADER"); if (!name) name = pcs->is_64bit ? L"wine64" : L"wine"; - TRACE("returning %s\n", debugstr_w(name)); - return name; + len = lstrlenW(name); + + /* WINELOADER isn't properly updated in Wow64 process calling inside Windows env block + * (it's updated in ELF env block though) + * So do the adaptation ourselves. + */ + altname = HeapAlloc(GetProcessHeap(), 0, (len + 2 + 1) * sizeof(WCHAR)); + if (altname) + { + memcpy(altname, name, len * sizeof(WCHAR)); + if (pcs->is_64bit && len >= 2 && memcmp(name + len - 2, L"64", 2 * sizeof(WCHAR)) != 0) + lstrcpyW(altname + len, L"64"); + else if (!pcs->is_64bit && len >= 2 && !memcmp(name + len - 2, L"64", 2 * sizeof(WCHAR))) + altname[len - 2] = '\0'; + else + altname[len] = '\0'; + } + + TRACE("returning %s\n", debugstr_w(altname)); + return altname; } static const char* get_module_type(enum module_type type, BOOL virtual)