Module: wine Branch: master Commit: 5477ee640b9d948cee8e4facec38ca0468372f61 URL: https://gitlab.winehq.org/wine/wine/-/commit/5477ee640b9d948cee8e4facec38ca0...
Author: Eric Pouech eric.pouech@gmail.com Date: Wed Mar 8 11:43:22 2023 +0100
dbghelp: Fix vdso.so lookup.
- should have been fixed when libwine.so has been removed - code was broken anyway - enhanced protect against error when reading debuggee's memory
Introducing helper to correctly read pointer's from debuggee (and other integral values).
vdso is now listed in ELF's module list (except if Wine's preloader removes it from auxilary vector)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
---
dlls/dbghelp/dbghelp_private.h | 9 +++++++++ dlls/dbghelp/elf_module.c | 44 +++++++++++++++++++++++++++--------------- 2 files changed, 37 insertions(+), 16 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index c11ccf81a92..9a9773269af 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -523,6 +523,15 @@ static inline BOOL read_process_memory(const struct process *process, UINT64 add return ReadProcessMemory(process->handle, (void*)(UINT_PTR)addr, buf, size, NULL); }
+static inline BOOL read_process_integral_value(const struct process* process, UINT64 addr, UINT64* pvalue, size_t size) +{ + /* Assuming that debugger and debuggee are little endian. */ + UINT64 value = 0; + if (size > sizeof(value) || !read_process_memory(process, addr, &value, size)) return FALSE; + *pvalue = value; + return TRUE; +} + struct line_info { ULONG_PTR is_first : 1, diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index ee8315c4a23..a2a60752a68 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -1339,39 +1339,51 @@ static BOOL elf_load_file_cb(void *param, HANDLE handle, const WCHAR *filename) /****************************************************************** * elf_search_auxv * - * locate some a value from the debuggee auxiliary vector + * Locate a value from the debuggee auxiliary vector */ static BOOL elf_search_auxv(const struct process* pcs, unsigned type, ULONG_PTR* val) { char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; SYMBOL_INFO*si = (SYMBOL_INFO*)buffer; - BYTE* addr; - BYTE* str; - BYTE* str_max; + const unsigned ptr_size = pcs->is_system_64bit ? 8 : 4; + UINT64 envp; + UINT64 addr; + UINT64 str; + UINT64 str_max;
si->SizeOfStruct = sizeof(*si); si->MaxNameLen = MAX_SYM_NAME; - if (!SymFromName(pcs->handle, "libwine.so.1!__wine_main_environ", si) || - !(addr = (void*)(DWORD_PTR)si->Address) || - !ReadProcessMemory(pcs->handle, addr, &addr, sizeof(addr), NULL) || - !addr) + if (!SymFromName(pcs->handle, "ntdll.so!main_envp", si) || + !si->Address || + !read_process_integral_value(pcs, si->Address, &envp, ptr_size) || + !envp) { FIXME("can't find symbol in module\n"); return FALSE; } /* walk through envp[] */ /* envp[] strings are located after the auxiliary vector, so protect the walk */ - str_max = (void*)(DWORD_PTR)~0L; - while (ReadProcessMemory(pcs->handle, addr, &str, sizeof(str), NULL) && - (addr = (void*)((DWORD_PTR)addr + sizeof(str))) != NULL && str != NULL) - str_max = min(str_max, str); + str_max = ~(UINT64)0u; + addr = envp; + for (;;) + { + if (!read_process_integral_value(pcs, addr, &str, ptr_size) || (addr += ptr_size) <= ptr_size) + return FALSE; + if (!str) break; + /* It can be some env vars have been changed, pointing to a different location */ + if (str >= envp) + str_max = min(str_max, str); + }
/* Walk through the end of envp[] array. * Actually, there can be several NULLs at the end of envp[]. This happens when an env variable is * deleted, the last entry is replaced by an extra NULL. */ - while (addr < str_max && ReadProcessMemory(pcs->handle, addr, &str, sizeof(str), NULL) && str == NULL) - addr = (void*)((DWORD_PTR)addr + sizeof(str)); + for (; addr < str_max; addr += ptr_size) + { + if (!read_process_integral_value(pcs, addr, &str, ptr_size)) return FALSE; + if (str) break; + }
if (pcs->is_system_64bit) { @@ -1381,7 +1393,7 @@ static BOOL elf_search_auxv(const struct process* pcs, unsigned type, ULONG_PTR* UINT64 a_val; } auxv;
- while (ReadProcessMemory(pcs->handle, addr, &auxv, sizeof(auxv), NULL) && auxv.a_type) + while (read_process_memory(pcs, addr, &auxv, sizeof(auxv)) && auxv.a_type) { if (auxv.a_type == type) { @@ -1399,7 +1411,7 @@ static BOOL elf_search_auxv(const struct process* pcs, unsigned type, ULONG_PTR* UINT32 a_val; } auxv;
- while (ReadProcessMemory(pcs->handle, addr, &auxv, sizeof(auxv), NULL) && auxv.a_type) + while (read_process_memory(pcs, addr, &auxv, sizeof(auxv)) && auxv.a_type) { if (auxv.a_type == type) {