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>
This commit is contained in:
Eric Pouech 2023-03-08 11:43:22 +01:00 committed by Alexandre Julliard
parent 9877ba9732
commit 5477ee640b
2 changed files with 37 additions and 16 deletions

View file

@ -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,

View file

@ -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)
{