Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- v2: check WINELOADER
dlls/dbghelp/module.c | 46 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-)
diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index 9f90d5e..7a23812 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -29,6 +29,7 @@ #include "psapi.h" #include "winternl.h" #include "wine/debug.h" +#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
@@ -75,9 +76,42 @@ static const WCHAR* get_filename(const WCHAR* name, const WCHAR* endptr) return ++ptr; }
+static BOOL is_wine_loader(const WCHAR *module) +{ + static const WCHAR wineW[] = {'w','i','n','e',0}; + static const WCHAR suffixW[] = {'6','4',0}; + const WCHAR *filename = get_filename(module, NULL); + const char *ptr, *p; + BOOL ret = FALSE; + WCHAR *buffer; + DWORD len; + + if ((ptr = getenv("WINELOADER"))) + { + if ((p = strrchr(ptr, '/'))) ptr = p + 1; + len = 2 + MultiByteToWideChar( CP_UNIXCP, 0, ptr, -1, NULL, 0 ); + buffer = heap_alloc( len * sizeof(WCHAR) ); + MultiByteToWideChar( CP_UNIXCP, 0, ptr, -1, buffer, len ); + } + else + { + buffer = heap_alloc( sizeof(wineW) + 2 * sizeof(WCHAR) ); + strcpyW( buffer, wineW ); + } + + if (!strcmpW( filename, buffer )) + ret = TRUE; + + strcatW( buffer, suffixW ); + if (!strcmpW( filename, buffer )) + ret = TRUE; + + heap_free( buffer ); + return ret; +} + static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size) { - const WCHAR *loader = get_wine_loader_name(); const WCHAR *ptr, *endptr; size_t len, l;
@@ -87,7 +121,7 @@ static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size) out[len] = '\0'; if (len > 4 && (l = match_ext(out, len))) out[len - l] = '\0'; - else if (len > strlenW(loader) && !strcmpiW(out + len - strlenW(loader), loader)) + else if (is_wine_loader(out)) lstrcpynW(out, S_WineLoaderW, size); else { @@ -455,8 +489,7 @@ static BOOL module_is_container_loaded(const struct process* pcs, */ enum module_type module_get_type_by_name(const WCHAR* name) { - int loader_len, len = strlenW(name); - const WCHAR *loader; + int len = strlenW(name);
/* Skip all version extensions (.[digits]) regex: "(.\d+)*$" */ do @@ -491,10 +524,7 @@ enum module_type module_get_type_by_name(const WCHAR* name) return DMT_DBG;
/* wine is also a native module (Mach-O on Mac OS X, ELF elsewhere) */ - loader = get_wine_loader_name(); - loader_len = strlenW( loader ); - if ((len == loader_len || (len > loader_len && name[len - loader_len - 1] == '/')) && - !strcmpiW(name + len - loader_len, loader)) + if (is_wine_loader(name)) { #ifdef __APPLE__ return DMT_MACHO;
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/dbghelp/dbghelp.c | 7 ++++++ dlls/dbghelp/dbghelp_private.h | 4 ++- dlls/dbghelp/elf_module.c | 7 +++++- dlls/dbghelp/macho_module.c | 4 ++- dlls/dbghelp/module.c | 57 +++++++++++++++++++----------------------- 5 files changed, 45 insertions(+), 34 deletions(-)
diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c index a0424aa..0bb591b 100644 --- a/dlls/dbghelp/dbghelp.c +++ b/dlls/dbghelp/dbghelp.c @@ -295,6 +295,7 @@ static BOOL check_live_target(struct process* pcs) BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeProcess) { struct process* pcs; + BOOL wow64, child_wow64;
TRACE("(%p %s %u)\n", hProcess, debugstr_w(UserSearchPath), fInvadeProcess);
@@ -312,6 +313,12 @@ BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeP
pcs->handle = hProcess;
+ IsWow64Process(GetCurrentProcess(), &wow64); + + if (!IsWow64Process(hProcess, &child_wow64)) + return FALSE; + pcs->is_64bit = (sizeof(void *) == 8 || wow64) && !child_wow64; + if (UserSearchPath) { pcs->search_path = lstrcpyW(HeapAlloc(GetProcessHeap(), 0, diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index f37991d..3c1b3dd 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -403,6 +403,8 @@ struct process
unsigned buffer_size; void* buffer; + + BOOL is_64bit; };
struct line_info @@ -609,7 +611,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(void) 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 e841b1b..4d877b4 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -50,6 +50,7 @@
#include "wine/library.h" #include "wine/debug.h" +#include "wine/heap.h"
#ifdef __ELF__
@@ -1568,13 +1569,17 @@ static BOOL elf_enum_modules_internal(const struct process* pcs, */ static BOOL elf_search_loader(struct process* pcs, struct elf_info* elf_info) { + WCHAR *loader = get_wine_loader_name(pcs); PROCESS_BASIC_INFORMATION pbi; ULONG_PTR base = 0; + BOOL ret;
if (!NtQueryInformationProcess( pcs->handle, ProcessBasicInformation, &pbi, sizeof(pbi), NULL )) ReadProcessMemory( pcs->handle, &pbi.PebBaseAddress->Reserved[0], &base, sizeof(base), NULL );
- return elf_search_and_load_file(pcs, get_wine_loader_name(), base, 0, elf_info); + ret = elf_search_and_load_file(pcs, loader, base, 0, elf_info); + heap_free(loader); + return ret; }
/****************************************************************** diff --git a/dlls/dbghelp/macho_module.c b/dlls/dbghelp/macho_module.c index 01fa300..4018c9d 100644 --- a/dlls/dbghelp/macho_module.c +++ b/dlls/dbghelp/macho_module.c @@ -1703,6 +1703,7 @@ BOOL macho_synchronize_module_list(struct process* pcs) */ static BOOL macho_search_loader(struct process* pcs, struct macho_info* macho_info) { + WCHAR *loader = get_wine_loader_name(pcs); BOOL ret = FALSE; ULONG_PTR dyld_image_info_address; struct dyld_all_image_infos image_infos; @@ -1757,7 +1758,8 @@ 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(), 0, macho_info); + ret = macho_search_and_load_file(pcs, loader, 0, macho_info); + heap_free(loader); return ret; }
diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index 7a23812..3659873 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -139,43 +139,38 @@ void module_set_module(struct module* module, const WCHAR* name) module_fill_module(name, module->modulename, sizeof(module->modulename) / sizeof(module->modulename[0])); }
-const WCHAR *get_wine_loader_name(void) +/* Returned string must be freed by caller */ +WCHAR *get_wine_loader_name(struct process *pcs) { - static const BOOL is_win64 = sizeof(void *) > sizeof(int); /* FIXME: should depend on target process */ static const WCHAR wineW[] = {'w','i','n','e',0}; static const WCHAR suffixW[] = {'6','4',0}; - static const WCHAR *loader; + WCHAR *buffer, *p; + const char *env;
- if (!loader) + /* All binaries are loaded with WINELOADER (if run from tree) or by the + * main executable + */ + if ((env = getenv("WINELOADER"))) { - WCHAR *p, *buffer; - const char *ptr; - - /* All binaries are loaded with WINELOADER (if run from tree) or by the - * main executable - */ - if ((ptr = getenv("WINELOADER"))) - { - DWORD len = 2 + MultiByteToWideChar( CP_UNIXCP, 0, ptr, -1, NULL, 0 ); - buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); - MultiByteToWideChar( CP_UNIXCP, 0, ptr, -1, buffer, len ); - } - else - { - buffer = HeapAlloc( GetProcessHeap(), 0, sizeof(wineW) + 2 * sizeof(WCHAR) ); - strcpyW( buffer, wineW ); - } - p = buffer + strlenW( buffer ) - strlenW( suffixW ); - if (p > buffer && !strcmpW( p, suffixW )) - { - if (!is_win64) *p = 0; - } - else if (is_win64) strcatW( buffer, suffixW ); - - TRACE( "returning %s\n", debugstr_w(buffer) ); - loader = buffer; + DWORD len = 2 + MultiByteToWideChar( CP_UNIXCP, 0, env, -1, NULL, 0 ); + buffer = heap_alloc( len * sizeof(WCHAR) ); + MultiByteToWideChar( CP_UNIXCP, 0, env, -1, buffer, len ); } - return loader; + else + { + buffer = heap_alloc( sizeof(wineW) + 2 * sizeof(WCHAR) ); + strcpyW( buffer, wineW ); + } + + p = buffer + strlenW( buffer ) - strlenW( suffixW ); + if (p > buffer && !strcmpW( p, suffixW )) + *p = 0; + + if (pcs->is_64bit) + strcatW(buffer, suffixW); + + TRACE( "returning %s\n", debugstr_w(buffer) ); + return buffer; }
static const char* get_module_type(enum module_type type, BOOL virtual)
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 21 +++++++++++++++++++++ dlls/dbghelp/elf_module.c | 23 +++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 3c1b3dd..935e766 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -542,6 +542,27 @@ struct cpu
extern struct cpu* dbghelp_current_cpu DECLSPEC_HIDDEN;
+/* Abbreviated 32-bit PEB */ +typedef struct _PEB32 +{ + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + BOOLEAN SpareBool; + DWORD Mutant; + DWORD ImageBaseAddress; + DWORD LdrData; + DWORD ProcessParameters; + DWORD SubSystemData; + DWORD ProcessHeap; + DWORD FastPebLock; + DWORD FastPebLockRoutine; + DWORD FastPebUnlockRoutine; + ULONG EnvironmentUpdateCount; + DWORD KernelCallbackTable; + ULONG Reserved[2]; +} PEB32; + /* dbghelp.c */ extern struct process* process_find_by_handle(HANDLE hProcess) DECLSPEC_HIDDEN; extern BOOL validate_addr64(DWORD64 addr) DECLSPEC_HIDDEN; diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index 4d877b4..e047a7f 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -1574,8 +1574,27 @@ static BOOL elf_search_loader(struct process* pcs, struct elf_info* elf_info) ULONG_PTR base = 0; BOOL ret;
- if (!NtQueryInformationProcess( pcs->handle, ProcessBasicInformation, &pbi, sizeof(pbi), NULL )) - ReadProcessMemory( pcs->handle, &pbi.PebBaseAddress->Reserved[0], &base, sizeof(base), NULL ); + if (NtQueryInformationProcess( pcs->handle, ProcessBasicInformation, + &pbi, sizeof(pbi), NULL )) + return FALSE; + + if (!pcs->is_64bit) + { + PEB32 *peb32 = (PEB32 *)pbi.PebBaseAddress; + DWORD base32; + + if (!ReadProcessMemory( pcs->handle, &peb32->Reserved[0], &base32, + sizeof(base32), NULL )) + return FALSE; + + base = base32; + } + else + { + if (!ReadProcessMemory( pcs->handle, &pbi.PebBaseAddress->Reserved[0], + &base, sizeof(base), NULL )) + return FALSE; + }
ret = elf_search_and_load_file(pcs, loader, base, 0, elf_info); heap_free(loader);