From: Ken Thomases Subject: [PATCH 2/2] dbghelp: For Mach-O, get the address of the process's image info from its PEB. (resend) Message-Id: Date: Wed, 4 Dec 2013 16:08:06 -0600 The previous technique assumed that dyld was always loaded at its base address in every process. This breaks with recent versions of OS X due to address space layout randomization (ASLR). For . --- dlls/dbghelp/macho_module.c | 57 +++++++++++++++++++++++++++++++++---------- 1 files changed, 44 insertions(+), 13 deletions(-) diff --git a/dlls/dbghelp/macho_module.c b/dlls/dbghelp/macho_module.c index 6d71168..2e22312 100644 --- a/dlls/dbghelp/macho_module.c +++ b/dlls/dbghelp/macho_module.c @@ -24,6 +24,8 @@ #include "config.h" #include "wine/port.h" +#include "ntstatus.h" +#define WIN32_NO_STATUS #include "dbghelp_private.h" #ifdef HAVE_MACH_O_LOADER_H @@ -964,23 +966,52 @@ static BOOL macho_load_file(struct process* pcs, const WCHAR* filename, */ if (macho_info->flags & MACHO_INFO_DEBUG_HEADER) { - static void* dyld_all_image_infos_addr; + PROCESS_BASIC_INFORMATION pbi; + NTSTATUS status; - /* This symbol should be in the same place in all processes. */ - if (!dyld_all_image_infos_addr) + ret = FALSE; + + /* Get address of PEB */ + status = NtQueryInformationProcess(pcs->handle, ProcessBasicInformation, + &pbi, sizeof(pbi), NULL); + if (status == STATUS_SUCCESS) { - struct nlist nl[2]; - memset(nl, 0, sizeof(nl)); - nl[0].n_un.n_name = (char*)"_dyld_all_image_infos"; - if (!nlist("/usr/lib/dyld", nl)) - dyld_all_image_infos_addr = (void*)nl[0].n_value; + ULONG dyld_image_info; + + /* Read dyld image info address from PEB */ + if (ReadProcessMemory(pcs->handle, &pbi.PebBaseAddress->MacDyldImageInfo, + &dyld_image_info, sizeof(dyld_image_info), NULL)) + { + TRACE("got dyld_image_info 0x%08x from PEB %p MacDyldImageInfo %p\n", + dyld_image_info, pbi.PebBaseAddress, &pbi.PebBaseAddress->MacDyldImageInfo); + macho_info->dbg_hdr_addr = dyld_image_info; + ret = TRUE; + } } - if (dyld_all_image_infos_addr) - macho_info->dbg_hdr_addr = (unsigned long)dyld_all_image_infos_addr; - else - ret = FALSE; - TRACE("dbg_hdr_addr = 0x%08lx\n", macho_info->dbg_hdr_addr); + if (!ret) + { + static void* dyld_all_image_infos_addr; + + /* Our next best guess is that dyld was loaded at its base address + and we can find the dyld image infos address by looking up its symbol. */ + if (!dyld_all_image_infos_addr) + { + struct nlist nl[2]; + memset(nl, 0, sizeof(nl)); + nl[0].n_un.n_name = (char*)"_dyld_all_image_infos"; + if (!nlist("/usr/lib/dyld", nl)) + dyld_all_image_infos_addr = (void*)nl[0].n_value; + } + + if (dyld_all_image_infos_addr) + { + TRACE("got dyld_image_info %p from /usr/lib/dyld symbol table\n", + dyld_all_image_infos_addr); + macho_info->dbg_hdr_addr = (unsigned long)dyld_all_image_infos_addr; + ret = TRUE; + } + } } if (macho_info->flags & MACHO_INFO_MODULE)