Ken Thomases : dbghelp: Fix reading the target's dyld image info, based on its CPU architecture.

Alexandre Julliard julliard at winehq.org
Fri Dec 13 15:27:21 CST 2019


Module: wine
Branch: master
Commit: 4b9defe09a24e77547cde4e8211f701a4984681b
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=4b9defe09a24e77547cde4e8211f701a4984681b

Author: Ken Thomases <ken at codeweavers.com>
Date:   Thu Dec 12 19:43:19 2019 -0600

dbghelp: Fix reading the target's dyld image info, based on its CPU architecture.

Signed-off-by: Ken Thomases <ken at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dbghelp/macho_module.c | 134 ++++++++++++++++++++++++++++++++------------
 1 file changed, 97 insertions(+), 37 deletions(-)

diff --git a/dlls/dbghelp/macho_module.c b/dlls/dbghelp/macho_module.c
index 8eda11ab91..f957439d43 100644
--- a/dlls/dbghelp/macho_module.c
+++ b/dlls/dbghelp/macho_module.c
@@ -60,23 +60,39 @@
 #include <mach-o/nlist.h>
 #include <mach-o/dyld.h>
 
-#ifdef HAVE_MACH_O_DYLD_IMAGES_H
-#include <mach-o/dyld_images.h>
-#else
-struct dyld_image_info {
-    const struct mach_header *imageLoadAddress;
-    const char               *imageFilePath;
-    uintptr_t                 imageFileModDate;
+struct dyld_image_info32 {
+    uint32_t /* const struct mach_header* */    imageLoadAddress;
+    uint32_t /* const char* */                  imageFilePath;
+    uint32_t /* uintptr_t */                    imageFileModDate;
 };
 
-struct dyld_all_image_infos {
-    uint32_t                      version;
-    uint32_t                      infoArrayCount;
-    const struct dyld_image_info *infoArray;
-    void*                         notification;
-    int                           processDetachedFromSharedRegion;
+struct dyld_all_image_infos32 {
+    uint32_t                                        version;
+    uint32_t                                        infoArrayCount;
+    uint32_t /* const struct dyld_image_info* */    infoArray;
+};
+
+struct dyld_image_info64 {
+    uint64_t /* const struct mach_header* */    imageLoadAddress;
+    uint64_t /* const char* */                  imageFilePath;
+    uint64_t /* uintptr_t */                    imageFileModDate;
+};
+
+struct dyld_all_image_infos64 {
+    uint32_t                                        version;
+    uint32_t                                        infoArrayCount;
+    uint64_t /* const struct dyld_image_info* */    infoArray;
+};
+
+union wine_image_info {
+    struct dyld_image_info32 info32;
+    struct dyld_image_info64 info64;
+};
+
+union wine_all_image_infos {
+    struct dyld_all_image_infos32 infos32;
+    struct dyld_all_image_infos64 infos64;
 };
-#endif
 
 #ifdef WORDS_BIGENDIAN
 #define swap_ulong_be_to_host(n) (n)
@@ -1649,8 +1665,8 @@ static BOOL macho_enum_modules_internal(const struct process* pcs,
                                         const WCHAR* main_name,
                                         enum_modules_cb cb, void* user)
 {
-    struct dyld_all_image_infos image_infos;
-    struct dyld_image_info*     info_array = NULL;
+    union wine_all_image_infos  image_infos;
+    union wine_image_info*      info_array = NULL;
     unsigned long               len;
     int                         i;
     char                        bufstr[256];
@@ -1660,31 +1676,55 @@ static BOOL macho_enum_modules_internal(const struct process* pcs,
     TRACE("(%p/%p, %s, %p, %p)\n", pcs, pcs->handle, debugstr_w(main_name), cb,
             user);
 
+    if (pcs->is_64bit)
+        len = sizeof(image_infos.infos64);
+    else
+        len = sizeof(image_infos.infos32);
     if (!pcs->dbg_hdr_addr ||
         !ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr,
-                           &image_infos, sizeof(image_infos), NULL) ||
-        !image_infos.infoArray)
+                           &image_infos, len, NULL))
         goto done;
-    TRACE("Process has %u image infos at %p\n", image_infos.infoArrayCount, image_infos.infoArray);
+    if (!pcs->is_64bit)
+    {
+        struct dyld_all_image_infos32 temp = image_infos.infos32;
+        image_infos.infos64.infoArrayCount = temp.infoArrayCount;
+        image_infos.infos64.infoArray = temp.infoArray;
+    }
+    if (!image_infos.infos64.infoArray)
+        goto done;
+    TRACE("Process has %u image infos at %p\n", image_infos.infos64.infoArrayCount, (void*)image_infos.infos64.infoArray);
 
-    len = image_infos.infoArrayCount * sizeof(info_array[0]);
+    if (pcs->is_64bit)
+        len = sizeof(info_array->info64);
+    else
+        len = sizeof(info_array->info32);
+    len *= image_infos.infos64.infoArrayCount;
     info_array = HeapAlloc(GetProcessHeap(), 0, len);
     if (!info_array ||
-        !ReadProcessMemory(pcs->handle, image_infos.infoArray,
+        !ReadProcessMemory(pcs->handle, (void*)image_infos.infos64.infoArray,
                            info_array, len, NULL))
         goto done;
     TRACE("... read image infos\n");
 
-    for (i = 0; i < image_infos.infoArrayCount; i++)
+    for (i = 0; i < image_infos.infos64.infoArrayCount; i++)
     {
-        if (info_array[i].imageFilePath != NULL &&
-            ReadProcessMemory(pcs->handle, info_array[i].imageFilePath, bufstr, sizeof(bufstr), NULL))
+        struct dyld_image_info64 info;
+        if (pcs->is_64bit)
+            info = info_array[i].info64;
+        else
+        {
+            struct dyld_image_info32 *info32 = &info_array->info32 + i;
+            info.imageLoadAddress = info32->imageLoadAddress;
+            info.imageFilePath = info32->imageFilePath;
+        }
+        if (info.imageFilePath &&
+            ReadProcessMemory(pcs->handle, (void*)info.imageFilePath, bufstr, sizeof(bufstr), NULL))
         {
             bufstr[sizeof(bufstr) - 1] = '\0';
             TRACE("[%d] image file %s\n", i, debugstr_a(bufstr));
             MultiByteToWideChar(CP_UNIXCP, 0, bufstr, -1, bufstrW, ARRAY_SIZE(bufstrW));
             if (main_name && !bufstrW[0]) strcpyW(bufstrW, main_name);
-            if (!cb(bufstrW, (unsigned long)info_array[i].imageLoadAddress, user)) break;
+            if (!cb(bufstrW, info.imageLoadAddress, user)) break;
         }
     }
 
@@ -1764,27 +1804,47 @@ static BOOL macho_search_loader(struct process* pcs, struct macho_info* macho_in
     WCHAR *loader = get_wine_loader_name(pcs);
     BOOL ret = FALSE;
     ULONG_PTR dyld_image_info_address;
-    struct dyld_all_image_infos image_infos;
-    struct dyld_image_info image_info;
+    union wine_all_image_infos image_infos;
+    union wine_image_info image_info;
     uint32_t len;
     char path[PATH_MAX];
     BOOL got_path = FALSE;
 
+    if (pcs->is_64bit)
+        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, 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)
+        ReadProcessMemory(pcs->handle, (void*)dyld_image_info_address, &image_infos, len, NULL))
     {
-        for (len = sizeof(path); len > 0; len /= 2)
+        if (pcs->is_64bit)
+            len = sizeof(image_info.info64);
+        else
         {
-            if (ReadProcessMemory(pcs->handle, image_info.imageFilePath, path, len, NULL))
+            struct dyld_all_image_infos32 temp = image_infos.infos32;
+            image_infos.infos64.infoArrayCount = temp.infoArrayCount;
+            image_infos.infos64.infoArray = temp.infoArray;
+            len = sizeof(image_info.info32);
+        }
+        if (image_infos.infos64.infoArray && image_infos.infos64.infoArrayCount &&
+            ReadProcessMemory(pcs->handle, (void*)image_infos.infos64.infoArray, &image_info, len, NULL))
+        {
+            if (!pcs->is_64bit)
             {
-                path[len - 1] = 0;
-                got_path = TRUE;
-                TRACE("got executable path from target's dyld image info: %s\n", debugstr_a(path));
-                break;
+                struct dyld_image_info32 temp = image_info.info32;
+                image_info.info64.imageLoadAddress = temp.imageLoadAddress;
+                image_info.info64.imageFilePath = temp.imageFilePath;
+            }
+            for (len = sizeof(path); image_info.info64.imageFilePath && len > 0; len /= 2)
+            {
+                if (ReadProcessMemory(pcs->handle, (void*)image_info.info64.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;
+                }
             }
         }
     }




More information about the wine-cvs mailing list