From e3354e44f17d74f0ac4547d8a4494c83ea3d6d37 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek@codeweavers.com>
Date: Wed, 25 Mar 2020 17:42:06 +0100
Subject: [PATCH] dbghelp: Move reading debug base address from PEB to
 check_live_target.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
---
 dlls/dbghelp/dbghelp.c         | 22 ++++++++++--
 dlls/dbghelp/dbghelp_private.h |  4 +--
 dlls/dbghelp/elf_module.c      | 55 ++++++----------------------
 dlls/dbghelp/macho_module.c    | 66 +++++++++-------------------------
 4 files changed, 47 insertions(+), 100 deletions(-)

diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c
index 0372f901272..b54ebf1c547 100644
--- a/dlls/dbghelp/dbghelp.c
+++ b/dlls/dbghelp/dbghelp.c
@@ -274,11 +274,27 @@ static BOOL WINAPI process_invade_cb(PCWSTR name, ULONG64 base, ULONG size, PVOI
  */
 static BOOL check_live_target(struct process* pcs)
 {
+    PROCESS_BASIC_INFORMATION pbi;
+    ULONG_PTR base = 0;
+
     if (!GetProcessId(pcs->handle)) return FALSE;
     if (GetEnvironmentVariableA("DBGHELP_NOLIVE", NULL, 0)) return FALSE;
-    if (!elf_read_wine_loader_dbg_info(pcs))
-        macho_read_wine_loader_dbg_info(pcs);
-    return TRUE;
+
+    if (NtQueryInformationProcess( pcs->handle, ProcessBasicInformation,
+                                   &pbi, sizeof(pbi), NULL ))
+        return FALSE;
+
+    if (!pcs->is_64bit)
+    {
+        PEB32 *peb32 = (PEB32 *)pbi.PebBaseAddress;
+        DWORD base32 = 0;
+        ReadProcessMemory(pcs->handle, &peb32->Reserved[0], &base32, sizeof(base32), NULL);
+        base = base32;
+    }
+    else ReadProcessMemory(pcs->handle, &pbi.PebBaseAddress->Reserved[0], &base, sizeof(base), NULL);
+
+    TRACE("got debug info address %#lx from PEB %p\n", base, pbi.PebBaseAddress);
+    return elf_read_wine_loader_dbg_info(pcs, base) || macho_read_wine_loader_dbg_info(pcs, base);
 }
 
 /******************************************************************
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h
index b1e9bb0b211..9a9fb26e398 100644
--- a/dlls/dbghelp/dbghelp_private.h
+++ b/dlls/dbghelp/dbghelp_private.h
@@ -604,12 +604,12 @@ extern struct cpu*  cpu_find(DWORD) DECLSPEC_HIDDEN;
 extern DWORD calc_crc32(HANDLE handle) DECLSPEC_HIDDEN;
 
 /* elf_module.c */
-extern BOOL         elf_read_wine_loader_dbg_info(struct process* pcs) DECLSPEC_HIDDEN;
+extern BOOL         elf_read_wine_loader_dbg_info(struct process* pcs, ULONG_PTR addr) DECLSPEC_HIDDEN;
 struct elf_thunk_area;
 extern int          elf_is_in_thunk_area(unsigned long addr, const struct elf_thunk_area* thunks) DECLSPEC_HIDDEN;
 
 /* macho_module.c */
-extern BOOL         macho_read_wine_loader_dbg_info(struct process* pcs) DECLSPEC_HIDDEN;
+extern BOOL         macho_read_wine_loader_dbg_info(struct process* pcs, ULONG_PTR addr) DECLSPEC_HIDDEN;
 
 /* minidump.c */
 void minidump_add_memory_block(struct dump_context* dc, ULONG64 base, ULONG size, ULONG rva) DECLSPEC_HIDDEN;
diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c
index 20c68dc1ab3..50ad89f53f7 100644
--- a/dlls/dbghelp/elf_module.c
+++ b/dlls/dbghelp/elf_module.c
@@ -1661,48 +1661,6 @@ static BOOL elf_synchronize_module_list(struct process* pcs)
     return TRUE;
 }
 
-/******************************************************************
- *		elf_search_loader
- *
- * Lookup in a running ELF process the loader, and sets its ELF link
- * address (for accessing the list of loaded .so libs) in pcs.
- * If flags is ELF_INFO_MODULE, the module for the loader is also
- * added as a module into pcs.
- */
-static BOOL elf_search_loader(struct process* pcs, struct elf_info* elf_info)
-{
-    WCHAR *loader = get_wine_loader_name(pcs);
-    PROCESS_BASIC_INFORMATION pbi;
-    ULONG_PTR base = 0;
-    BOOL ret;
-
-    if (NtQueryInformationProcess( pcs->handle, ProcessBasicInformation,
-                                   &pbi, sizeof(pbi), NULL ))
-        return FALSE;
-
-    if (!pcs->is_64bit)
-    {
-        PEB32 *peb32 = (PEB32 *)pbi.PebBaseAddress;
-        DWORD base32;
-
-        if (!ReadProcessMemory( pcs->handle, &peb32->Reserved[0], &base32,
-                                sizeof(base32), NULL ))
-            return FALSE;
-
-        base = base32;
-    }
-    else
-    {
-        if (!ReadProcessMemory( pcs->handle, &pbi.PebBaseAddress->Reserved[0],
-                                &base, sizeof(base), NULL ))
-            return FALSE;
-    }
-
-    ret = elf_search_and_load_file(pcs, loader, base, 0, elf_info);
-    heap_free(loader);
-    return ret;
-}
-
 static const struct loader_ops elf_loader_ops =
 {
     elf_synchronize_module_list,
@@ -1717,12 +1675,19 @@ static const struct loader_ops elf_loader_ops =
  *
  * Try to find a decent wine executable which could have loaded the debuggee
  */
-BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
+BOOL elf_read_wine_loader_dbg_info(struct process* pcs, ULONG_PTR addr)
 {
     struct elf_info     elf_info;
+    WCHAR *loader;
+    BOOL ret;
 
     elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE;
-    if (!elf_search_loader(pcs, &elf_info) || !elf_info.dbg_hdr_addr) return FALSE;
+    loader = get_wine_loader_name(pcs);
+    ret = elf_search_and_load_file(pcs, loader, addr, 0, &elf_info);
+    heap_free(loader);
+    if (!ret || !elf_info.dbg_hdr_addr) return FALSE;
+
+    TRACE("Found ELF debug header %#lx\n", elf_info.dbg_hdr_addr);
     elf_info.module->format_info[DFI_ELF]->u.elf_info->elf_loader = 1;
     module_set_module(elf_info.module, S_WineLoaderW);
     pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr;
@@ -1737,7 +1702,7 @@ BOOL elf_map_handle(HANDLE handle, struct image_file_map* fmap)
     return FALSE;
 }
 
-BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
+BOOL elf_read_wine_loader_dbg_info(struct process* pcs, ULONG_PTR addr)
 {
     return FALSE;
 }
diff --git a/dlls/dbghelp/macho_module.c b/dlls/dbghelp/macho_module.c
index 8e2fa796e03..43a98c9c726 100644
--- a/dlls/dbghelp/macho_module.c
+++ b/dlls/dbghelp/macho_module.c
@@ -129,14 +129,12 @@ struct section_info
     unsigned int    section_index;
 };
 
-#define MACHO_INFO_DEBUG_HEADER   0x0001
-#define MACHO_INFO_MODULE         0x0002
-#define MACHO_INFO_NAME           0x0004
+#define MACHO_INFO_MODULE         0x0001
+#define MACHO_INFO_NAME           0x0002
 
 struct macho_info
 {
     unsigned                    flags;          /* IN  one (or several) of the MACHO_INFO constants */
-    unsigned long               dbg_hdr_addr;   /* OUT address of debug header (if MACHO_INFO_DEBUG_HEADER is set) */
     struct module*              module;         /* OUT loaded module (if MACHO_INFO_MODULE is set) */
     const WCHAR*                module_name;    /* OUT found module name (if MACHO_INFO_NAME is set) */
 };
@@ -1373,32 +1371,7 @@ static void macho_module_remove(struct process* pcs, struct module_format* modfm
  */
 static ULONG_PTR get_dyld_image_info_address(struct process* pcs)
 {
-    NTSTATUS status;
-    PROCESS_BASIC_INFORMATION pbi;
     ULONG_PTR dyld_image_info_address = 0;
-    BOOL ret;
-
-    /* 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 (pcs->is_64bit)
-            ret = ReadProcessMemory(pcs->handle, &pbi.PebBaseAddress->Reserved[0],
-                &dyld_image_info_address, sizeof(dyld_image_info_address), NULL);
-        else
-        {
-            PEB32 *peb32 = (PEB32 *)pbi.PebBaseAddress;
-            ULONG addr32;
-            ret = ReadProcessMemory(pcs->handle, &peb32->Reserved[0], &addr32,
-                sizeof(addr32), NULL);
-            dyld_image_info_address = addr32;
-        }
-
-        if (ret)
-            TRACE("got dyld_image_info_address %#lx from PEB %p\n",
-                dyld_image_info_address, pbi.PebBaseAddress);
-    }
 
 #ifndef __LP64__ /* No reading the symtab with nlist(3) in LP64 */
     if (!dyld_image_info_address)
@@ -1451,14 +1424,6 @@ static BOOL macho_load_file(struct process* pcs, const WCHAR* filename,
     split_segs = image_uses_split_segs(pcs, load_addr);
     if (!macho_map_file(pcs, filename, split_segs, &fmap)) return FALSE;
 
-    /* Find the dynamic loader's table of images loaded into the process.
-     */
-    if (macho_info->flags & MACHO_INFO_DEBUG_HEADER)
-    {
-        macho_info->dbg_hdr_addr = (unsigned long)get_dyld_image_info_address(pcs);
-        ret = TRUE;
-    }
-
     if (macho_info->flags & MACHO_INFO_MODULE)
     {
         struct macho_module_info *macho_module_info;
@@ -1736,7 +1701,7 @@ static BOOL macho_enum_modules(struct process* process, enum_modules_cb cb, void
     BOOL                ret;
 
     TRACE("(%p, %p, %p)\n", process->handle, cb, user);
-    macho_info.flags = MACHO_INFO_DEBUG_HEADER | MACHO_INFO_NAME;
+    macho_info.flags = MACHO_INFO_NAME;
     ret = macho_enum_modules_internal(process, macho_info.module_name, cb, user);
     HeapFree(GetProcessHeap(), 0, (char*)macho_info.module_name);
     return ret;
@@ -1823,9 +1788,7 @@ static struct module* macho_load_module(struct process* pcs, const WCHAR* name,
  */
 static BOOL macho_search_loader(struct process* pcs, struct macho_info* macho_info)
 {
-    WCHAR *loader = get_wine_loader_name(pcs);
     BOOL ret = FALSE;
-    ULONG_PTR dyld_image_info_address;
     union wine_all_image_infos image_infos;
     union wine_image_info image_info;
     uint32_t len;
@@ -1836,9 +1799,8 @@ static BOOL macho_search_loader(struct process* pcs, struct macho_info* macho_in
         len = sizeof(image_infos.infos64);
     else
         len = sizeof(image_infos.infos32);
-    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, len, NULL))
+    if (pcs->dbg_hdr_addr &&
+        ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr, &image_infos, len, NULL))
     {
         if (pcs->is_64bit)
             len = sizeof(image_info.info64);
@@ -1898,8 +1860,11 @@ static BOOL macho_search_loader(struct process* pcs, struct macho_info* macho_in
     }
 
     if (!ret)
-        ret = macho_search_and_load_file(pcs, loader, 0, macho_info);
-    heap_free(loader);
+    {
+        WCHAR *loader = get_wine_loader_name(pcs);
+        ret = loader && macho_search_and_load_file(pcs, loader, 0, macho_info);
+        heap_free(loader);
+    }
     return ret;
 }
 
@@ -1917,23 +1882,24 @@ static const struct loader_ops macho_loader_ops =
  *
  * Try to find a decent wine executable which could have loaded the debuggee
  */
-BOOL macho_read_wine_loader_dbg_info(struct process* pcs)
+BOOL macho_read_wine_loader_dbg_info(struct process* pcs, ULONG_PTR addr)
 {
     struct macho_info     macho_info;
 
     TRACE("(%p/%p)\n", pcs, pcs->handle);
-    macho_info.flags = MACHO_INFO_DEBUG_HEADER | MACHO_INFO_MODULE;
-    if (!macho_search_loader(pcs, &macho_info) || !macho_info.dbg_hdr_addr) return FALSE;
+    pcs->dbg_hdr_addr = addr ? addr : get_dyld_image_info_address(pcs);
+    macho_info.flags = MACHO_INFO_MODULE;
+    if (!macho_search_loader(pcs, &macho_info)) return FALSE;
     macho_info.module->format_info[DFI_MACHO]->u.macho_info->is_loader = 1;
     module_set_module(macho_info.module, S_WineLoaderW);
-    pcs->dbg_hdr_addr = macho_info.dbg_hdr_addr;
     pcs->loader = &macho_loader_ops;
+    TRACE("Found macho debug header %#lx\n", pcs->dbg_hdr_addr);
     return TRUE;
 }
 
 #else  /* HAVE_MACH_O_LOADER_H */
 
-BOOL macho_read_wine_loader_dbg_info(struct process* pcs)
+BOOL macho_read_wine_loader_dbg_info(struct process* pcs, ULONG_PTR addr)
 {
     return FALSE;
 }