dbghelp: Use debuggee environment variables in search_dll_path.
This fixes searching wow32 binaries, where debuggee search path is different than debugger's. Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
0527cf89fb
commit
2b0977fc71
|
@ -267,6 +267,23 @@ static BOOL WINAPI process_invade_cb(PCWSTR name, ULONG64 base, ULONG size, PVOI
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const WCHAR *process_getenv(const struct process *process, const WCHAR *name)
|
||||||
|
{
|
||||||
|
size_t name_len;
|
||||||
|
const WCHAR *iter;
|
||||||
|
|
||||||
|
if (!process->environment) return NULL;
|
||||||
|
name_len = lstrlenW(name);
|
||||||
|
|
||||||
|
for (iter = process->environment; *iter; iter += lstrlenW(iter) + 1)
|
||||||
|
{
|
||||||
|
if (!wcsnicmp(iter, name, name_len) && iter[name_len] == '=')
|
||||||
|
return iter + name_len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* check_live_target
|
* check_live_target
|
||||||
*
|
*
|
||||||
|
@ -274,7 +291,7 @@ static BOOL WINAPI process_invade_cb(PCWSTR name, ULONG64 base, ULONG size, PVOI
|
||||||
static BOOL check_live_target(struct process* pcs)
|
static BOOL check_live_target(struct process* pcs)
|
||||||
{
|
{
|
||||||
PROCESS_BASIC_INFORMATION pbi;
|
PROCESS_BASIC_INFORMATION pbi;
|
||||||
ULONG_PTR base = 0;
|
ULONG_PTR base = 0, env = 0;
|
||||||
|
|
||||||
if (!GetProcessId(pcs->handle)) return FALSE;
|
if (!GetProcessId(pcs->handle)) return FALSE;
|
||||||
if (GetEnvironmentVariableA("DBGHELP_NOLIVE", NULL, 0)) return FALSE;
|
if (GetEnvironmentVariableA("DBGHELP_NOLIVE", NULL, 0)) return FALSE;
|
||||||
|
@ -285,12 +302,57 @@ static BOOL check_live_target(struct process* pcs)
|
||||||
|
|
||||||
if (!pcs->is_64bit)
|
if (!pcs->is_64bit)
|
||||||
{
|
{
|
||||||
PEB32 *peb32 = (PEB32 *)pbi.PebBaseAddress;
|
DWORD env32;
|
||||||
DWORD base32 = 0;
|
PEB32 peb32;
|
||||||
ReadProcessMemory(pcs->handle, &peb32->Reserved[0], &base32, sizeof(base32), NULL);
|
C_ASSERT(sizeof(void*) != 4 || FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment) == 0x48);
|
||||||
base = base32;
|
if (!ReadProcessMemory(pcs->handle, pbi.PebBaseAddress, &peb32, sizeof(peb32), NULL)) return FALSE;
|
||||||
|
base = peb32.Reserved[0];
|
||||||
|
if (read_process_memory(pcs, peb32.ProcessParameters + 0x48, &env32, sizeof(env32))) env = env32;
|
||||||
}
|
}
|
||||||
else ReadProcessMemory(pcs->handle, &pbi.PebBaseAddress->Reserved[0], &base, sizeof(base), NULL);
|
else
|
||||||
|
{
|
||||||
|
PEB peb;
|
||||||
|
if (!ReadProcessMemory(pcs->handle, pbi.PebBaseAddress, &peb, sizeof(peb), NULL)) return FALSE;
|
||||||
|
base = peb.Reserved[0];
|
||||||
|
ReadProcessMemory(pcs->handle, &peb.ProcessParameters->Environment, &env, sizeof(env), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read debuggee environment block */
|
||||||
|
if (env)
|
||||||
|
{
|
||||||
|
size_t buf_size = 0, i, last_null = -1;
|
||||||
|
WCHAR *buf = NULL;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
size_t read_size = sysinfo.dwAllocationGranularity - (env & (sysinfo.dwAllocationGranularity - 1));
|
||||||
|
if (buf)
|
||||||
|
{
|
||||||
|
WCHAR *new_buf;
|
||||||
|
if (!(new_buf = realloc(buf, buf_size + read_size))) break;
|
||||||
|
buf = new_buf;
|
||||||
|
}
|
||||||
|
else if(!(buf = malloc(read_size))) break;
|
||||||
|
|
||||||
|
if (!read_process_memory(pcs, env, (char*)buf + buf_size, read_size)) break;
|
||||||
|
for (i = buf_size / sizeof(WCHAR); i < (buf_size + read_size) / sizeof(WCHAR); i++)
|
||||||
|
{
|
||||||
|
if (buf[i]) continue;
|
||||||
|
if (last_null + 1 == i)
|
||||||
|
{
|
||||||
|
pcs->environment = realloc(buf, (i + 1) * sizeof(WCHAR));
|
||||||
|
buf = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last_null = i;
|
||||||
|
}
|
||||||
|
env += read_size;
|
||||||
|
buf_size += read_size;
|
||||||
|
}
|
||||||
|
while (buf);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
if (!base) return FALSE;
|
if (!base) return FALSE;
|
||||||
|
|
||||||
TRACE("got debug info address %#lx from PEB %p\n", base, pbi.PebBaseAddress);
|
TRACE("got debug info address %#lx from PEB %p\n", base, pbi.PebBaseAddress);
|
||||||
|
@ -448,6 +510,7 @@ BOOL WINAPI SymCleanup(HANDLE hProcess)
|
||||||
while ((*ppcs)->lmodules) module_remove(*ppcs, (*ppcs)->lmodules);
|
while ((*ppcs)->lmodules) module_remove(*ppcs, (*ppcs)->lmodules);
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, (*ppcs)->search_path);
|
HeapFree(GetProcessHeap(), 0, (*ppcs)->search_path);
|
||||||
|
free((*ppcs)->environment);
|
||||||
next = (*ppcs)->next;
|
next = (*ppcs)->next;
|
||||||
HeapFree(GetProcessHeap(), 0, *ppcs);
|
HeapFree(GetProcessHeap(), 0, *ppcs);
|
||||||
*ppcs = next;
|
*ppcs = next;
|
||||||
|
|
|
@ -403,6 +403,7 @@ struct process
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
const struct loader_ops* loader;
|
const struct loader_ops* loader;
|
||||||
WCHAR* search_path;
|
WCHAR* search_path;
|
||||||
|
WCHAR* environment;
|
||||||
|
|
||||||
PSYMBOL_REGISTERED_CALLBACK64 reg_cb;
|
PSYMBOL_REGISTERED_CALLBACK64 reg_cb;
|
||||||
PSYMBOL_REGISTERED_CALLBACK reg_cb32;
|
PSYMBOL_REGISTERED_CALLBACK reg_cb32;
|
||||||
|
@ -605,6 +606,7 @@ extern BOOL pcs_callback(const struct process* pcs, ULONG action, void*
|
||||||
extern void* fetch_buffer(struct process* pcs, unsigned size) DECLSPEC_HIDDEN;
|
extern void* fetch_buffer(struct process* pcs, unsigned size) DECLSPEC_HIDDEN;
|
||||||
extern const char* wine_dbgstr_addr(const ADDRESS64* addr) DECLSPEC_HIDDEN;
|
extern const char* wine_dbgstr_addr(const ADDRESS64* addr) DECLSPEC_HIDDEN;
|
||||||
extern struct cpu* cpu_find(DWORD) DECLSPEC_HIDDEN;
|
extern struct cpu* cpu_find(DWORD) DECLSPEC_HIDDEN;
|
||||||
|
extern const WCHAR *process_getenv(const struct process *process, const WCHAR *name);
|
||||||
extern DWORD calc_crc32(HANDLE handle) DECLSPEC_HIDDEN;
|
extern DWORD calc_crc32(HANDLE handle) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* elf_module.c */
|
/* elf_module.c */
|
||||||
|
@ -670,7 +672,8 @@ extern BOOL path_find_symbol_file(const struct process* pcs, const struc
|
||||||
PCSTR full_path, enum module_type type, const GUID* guid, DWORD dw1, DWORD dw2,
|
PCSTR full_path, enum module_type type, const GUID* guid, DWORD dw1, DWORD dw2,
|
||||||
WCHAR *buffer, BOOL* is_unmatched) DECLSPEC_HIDDEN;
|
WCHAR *buffer, BOOL* is_unmatched) DECLSPEC_HIDDEN;
|
||||||
extern WCHAR *get_dos_file_name(const WCHAR *filename) DECLSPEC_HIDDEN;
|
extern WCHAR *get_dos_file_name(const WCHAR *filename) DECLSPEC_HIDDEN;
|
||||||
extern BOOL search_dll_path(const WCHAR *name, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param) DECLSPEC_HIDDEN;
|
extern BOOL search_dll_path(const struct process* process, const WCHAR *name,
|
||||||
|
BOOL (*match)(void*, HANDLE, const WCHAR*), void *param) DECLSPEC_HIDDEN;
|
||||||
extern BOOL search_unix_path(const WCHAR *name, const char *path, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param) DECLSPEC_HIDDEN;
|
extern BOOL search_unix_path(const WCHAR *name, const char *path, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param) DECLSPEC_HIDDEN;
|
||||||
extern const WCHAR* file_name(const WCHAR* str) DECLSPEC_HIDDEN;
|
extern const WCHAR* file_name(const WCHAR* str) DECLSPEC_HIDDEN;
|
||||||
extern const char* file_nameA(const char* str) DECLSPEC_HIDDEN;
|
extern const char* file_nameA(const char* str) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -1436,7 +1436,7 @@ static BOOL elf_search_and_load_file(struct process* pcs, const WCHAR* filename,
|
||||||
load_elf.elf_info = elf_info;
|
load_elf.elf_info = elf_info;
|
||||||
|
|
||||||
ret = search_unix_path(filename, getenv("LD_LIBRARY_PATH"), elf_load_file_cb, &load_elf)
|
ret = search_unix_path(filename, getenv("LD_LIBRARY_PATH"), elf_load_file_cb, &load_elf)
|
||||||
|| search_dll_path(filename, elf_load_file_cb, &load_elf);
|
|| search_dll_path(pcs, filename, elf_load_file_cb, &load_elf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -1588,7 +1588,7 @@ static BOOL macho_search_and_load_file(struct process* pcs, const WCHAR* filenam
|
||||||
ret = search_unix_path(p, fallback, macho_load_file_cb, &load_params);
|
ret = search_unix_path(p, fallback, macho_load_file_cb, &load_params);
|
||||||
}
|
}
|
||||||
if (!ret && p == filename)
|
if (!ret && p == filename)
|
||||||
ret = search_dll_path(filename, macho_load_file_cb, &load_params);
|
ret = search_dll_path(pcs, filename, macho_load_file_cb, &load_params);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -691,19 +691,17 @@ WCHAR *get_dos_file_name(const WCHAR *filename)
|
||||||
return dos_path;
|
return dos_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL search_dll_path(const WCHAR *name, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param)
|
BOOL search_dll_path(const struct process *process, const WCHAR *name, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param)
|
||||||
{
|
{
|
||||||
|
const WCHAR *env;
|
||||||
size_t len, i;
|
size_t len, i;
|
||||||
HANDLE file;
|
HANDLE file;
|
||||||
WCHAR *buf;
|
WCHAR *buf;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
|
||||||
static const WCHAR winebuilddirW[] = {'W','I','N','E','B','U','I','L','D','D','I','R',0};
|
|
||||||
static const WCHAR winedlldirW[] = {'W','I','N','E','D','L','L','D','I','R','%','u',0};
|
|
||||||
|
|
||||||
name = file_name(name);
|
name = file_name(name);
|
||||||
|
|
||||||
if ((len = GetEnvironmentVariableW(winebuilddirW, NULL, 0)))
|
if ((env = process_getenv(process, L"WINEBUILDDIR")))
|
||||||
{
|
{
|
||||||
WCHAR *p, *end;
|
WCHAR *p, *end;
|
||||||
const WCHAR dllsW[] = { '\\','d','l','l','s','\\' };
|
const WCHAR dllsW[] = { '\\','d','l','l','s','\\' };
|
||||||
|
@ -712,8 +710,11 @@ BOOL search_dll_path(const WCHAR *name, BOOL (*match)(void*, HANDLE, const WCHAR
|
||||||
const WCHAR dot_exeW[] = {'.','e','x','e',0};
|
const WCHAR dot_exeW[] = {'.','e','x','e',0};
|
||||||
const WCHAR dot_soW[] = {'.','s','o',0};
|
const WCHAR dot_soW[] = {'.','s','o',0};
|
||||||
|
|
||||||
|
|
||||||
|
len = lstrlenW(env);
|
||||||
if (!(buf = heap_alloc((len + 8 + 3 * lstrlenW(name)) * sizeof(WCHAR)))) return FALSE;
|
if (!(buf = heap_alloc((len + 8 + 3 * lstrlenW(name)) * sizeof(WCHAR)))) return FALSE;
|
||||||
end = buf + GetEnvironmentVariableW(winebuilddirW, buf, len);
|
wcscpy(buf, env);
|
||||||
|
end = buf + len;
|
||||||
|
|
||||||
memcpy(end, dllsW, sizeof(dllsW));
|
memcpy(end, dllsW, sizeof(dllsW));
|
||||||
lstrcpyW(end + ARRAY_SIZE(dllsW), name);
|
lstrcpyW(end + ARRAY_SIZE(dllsW), name);
|
||||||
|
@ -752,8 +753,9 @@ BOOL search_dll_path(const WCHAR *name, BOOL (*match)(void*, HANDLE, const WCHAR
|
||||||
for (i = 0;; i++)
|
for (i = 0;; i++)
|
||||||
{
|
{
|
||||||
WCHAR env_name[64];
|
WCHAR env_name[64];
|
||||||
swprintf(env_name, ARRAY_SIZE(env_name), winedlldirW, i);
|
swprintf(env_name, ARRAY_SIZE(env_name), L"WINEDLLDIR%u", i);
|
||||||
if (!(len = GetEnvironmentVariableW(env_name, NULL, 0))) break;
|
if (!(env = process_getenv(process, env_name))) return FALSE;
|
||||||
|
len = lstrlenW(env);
|
||||||
if (!(buf = heap_alloc((len + lstrlenW(name) + 2) * sizeof(WCHAR)))) return FALSE;
|
if (!(buf = heap_alloc((len + lstrlenW(name) + 2) * sizeof(WCHAR)))) return FALSE;
|
||||||
|
|
||||||
len = GetEnvironmentVariableW(env_name, buf, len);
|
len = GetEnvironmentVariableW(env_name, buf, len);
|
||||||
|
|
|
@ -786,7 +786,7 @@ struct module* pe_load_native_module(struct process* pcs, const WCHAR* name,
|
||||||
if (pe_map_file(hFile, &modfmt->u.pe_info->fmap, DMT_PE))
|
if (pe_map_file(hFile, &modfmt->u.pe_info->fmap, DMT_PE))
|
||||||
{
|
{
|
||||||
struct builtin_search builtin = { NULL };
|
struct builtin_search builtin = { NULL };
|
||||||
if (modfmt->u.pe_info->fmap.u.pe.builtin && search_dll_path(loaded_name, search_builtin_pe, &builtin))
|
if (modfmt->u.pe_info->fmap.u.pe.builtin && search_dll_path(pcs, loaded_name, search_builtin_pe, &builtin))
|
||||||
{
|
{
|
||||||
TRACE("reloaded %s from %s\n", debugstr_w(loaded_name), debugstr_w(builtin.path));
|
TRACE("reloaded %s from %s\n", debugstr_w(loaded_name), debugstr_w(builtin.path));
|
||||||
image_unmap_file(&modfmt->u.pe_info->fmap);
|
image_unmap_file(&modfmt->u.pe_info->fmap);
|
||||||
|
|
Loading…
Reference in New Issue