[PATCH 1/3] dbghelp: On Mac, get the wineloader path from the target or our own process before resorting to guessing.
Ken Thomases
ken at codeweavers.com
Thu Sep 17 21:26:36 CDT 2015
This makes backtraces more reliably complete when WINELOADER isn't set and the
loader isn't in a typical location.
---
dlls/dbghelp/macho_module.c | 159 ++++++++++++++++++++++++++++++--------------
1 file changed, 110 insertions(+), 49 deletions(-)
diff --git a/dlls/dbghelp/macho_module.c b/dlls/dbghelp/macho_module.c
index 8d7091d..205c0c0 100644
--- a/dlls/dbghelp/macho_module.c
+++ b/dlls/dbghelp/macho_module.c
@@ -58,6 +58,7 @@
#include <mach-o/fat.h>
#include <mach-o/loader.h>
#include <mach-o/nlist.h>
+#include <mach-o/dyld.h>
#ifdef HAVE_MACH_O_DYLD_IMAGES_H
#include <mach-o/dyld_images.h>
@@ -1301,6 +1302,57 @@ static void macho_module_remove(struct process* pcs, struct module_format* modfm
HeapFree(GetProcessHeap(), 0, modfmt);
}
+
+/******************************************************************
+ * get_dyld_image_info_address
+ */
+static ULONG_PTR get_dyld_image_info_address(struct process* pcs)
+{
+ NTSTATUS status;
+ PROCESS_BASIC_INFORMATION pbi;
+ ULONG_PTR dyld_image_info_address = 0;
+
+ /* Get address of PEB */
+ status = NtQueryInformationProcess(pcs->handle, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
+ if (status == STATUS_SUCCESS)
+ {
+ /* Read dyld image info address from PEB */
+ if (ReadProcessMemory(pcs->handle, &pbi.PebBaseAddress->Reserved[0],
+ &dyld_image_info_address, sizeof(dyld_image_info_address), NULL))
+ {
+ TRACE("got dyld_image_info_address 0x%08lx from PEB %p MacDyldImageInfo %p\n",
+ (unsigned long)dyld_image_info_address, pbi.PebBaseAddress, &pbi.PebBaseAddress->Reserved);
+ }
+ }
+
+#ifndef __LP64__ /* No reading the symtab with nlist(3) in LP64 */
+ if (!dyld_image_info_address)
+ {
+ 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_address %p from /usr/lib/dyld symbol table\n",
+ dyld_all_image_infos_addr);
+ dyld_image_info_address = (ULONG_PTR)dyld_all_image_infos_addr;
+ }
+ }
+#endif
+
+ return dyld_image_info_address;
+}
+
/******************************************************************
* macho_load_file
*
@@ -1328,54 +1380,8 @@ static BOOL macho_load_file(struct process* pcs, const WCHAR* filename,
*/
if (macho_info->flags & MACHO_INFO_DEBUG_HEADER)
{
- PROCESS_BASIC_INFORMATION pbi;
- NTSTATUS status;
-
- ret = FALSE;
-
- /* Get address of PEB */
- status = NtQueryInformationProcess(pcs->handle, ProcessBasicInformation,
- &pbi, sizeof(pbi), NULL);
- if (status == STATUS_SUCCESS)
- {
- ULONG_PTR dyld_image_info;
-
- /* Read dyld image info address from PEB */
- if (ReadProcessMemory(pcs->handle, &pbi.PebBaseAddress->Reserved[0],
- &dyld_image_info, sizeof(dyld_image_info), NULL))
- {
- TRACE("got dyld_image_info 0x%08lx from PEB %p MacDyldImageInfo %p\n",
- (unsigned long)dyld_image_info, pbi.PebBaseAddress, &pbi.PebBaseAddress->Reserved);
- macho_info->dbg_hdr_addr = dyld_image_info;
- ret = TRUE;
- }
- }
-
-#ifndef __LP64__ /* No reading the symtab with nlist(3) in LP64 */
- 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;
- }
- }
-#endif
+ macho_info->dbg_hdr_addr = (unsigned long)get_dyld_image_info_address(pcs);
+ ret = TRUE;
}
if (macho_info->flags & MACHO_INFO_MODULE)
@@ -1695,7 +1701,62 @@ BOOL macho_synchronize_module_list(struct process* pcs)
*/
static BOOL macho_search_loader(struct process* pcs, struct macho_info* macho_info)
{
- return macho_search_and_load_file(pcs, get_wine_loader_name(), 0, macho_info);
+ BOOL ret = FALSE;
+ ULONG_PTR dyld_image_info_address;
+ struct dyld_all_image_infos image_infos;
+ struct dyld_image_info image_info;
+ uint32_t len;
+ char path[PATH_MAX];
+ BOOL got_path = FALSE;
+
+ dyld_image_info_address = get_dyld_image_info_address(pcs);
+ if (dyld_image_info_address &&
+ ReadProcessMemory(pcs->handle, (void*)dyld_image_info_address, &image_infos, sizeof(image_infos), NULL) &&
+ image_infos.infoArray && image_infos.infoArrayCount &&
+ ReadProcessMemory(pcs->handle, image_infos.infoArray, &image_info, sizeof(image_info), NULL) &&
+ image_info.imageFilePath)
+ {
+ for (len = sizeof(path); len > 0; len /= 2)
+ {
+ if (ReadProcessMemory(pcs->handle, image_info.imageFilePath, path, len, NULL))
+ {
+ path[len - 1] = 0;
+ got_path = TRUE;
+ TRACE("got executable path from target's dyld image info: %s\n", debugstr_a(path));
+ break;
+ }
+ }
+ }
+
+ /* If we couldn't get the executable path from the target process, try our
+ own. It will almost always be the same. */
+ if (!got_path)
+ {
+ len = sizeof(path);
+ if (!_NSGetExecutablePath(path, &len))
+ {
+ got_path = TRUE;
+ TRACE("using own executable path: %s\n", debugstr_a(path));
+ }
+ }
+
+ if (got_path)
+ {
+ WCHAR* pathW;
+
+ len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0);
+ pathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (pathW)
+ {
+ MultiByteToWideChar(CP_UNIXCP, 0, path, -1, pathW, len);
+ ret = macho_load_file(pcs, pathW, 0, macho_info);
+ HeapFree(GetProcessHeap(), 0, pathW);
+ }
+ }
+
+ if (!ret)
+ ret = macho_search_and_load_file(pcs, get_wine_loader_name(), 0, macho_info);
+ return ret;
}
/******************************************************************
--
2.4.3
More information about the wine-patches
mailing list