[PATCH 09/11] dbghelp: Implement the image_private.h functions for Mach-O modules.

Ken Thomases ken at codeweavers.com
Wed Jun 24 17:17:47 CDT 2015


---
 dlls/dbghelp/image_private.h |  33 ++++++---
 dlls/dbghelp/macho_module.c  | 161 ++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 167 insertions(+), 27 deletions(-)

diff --git a/dlls/dbghelp/image_private.h b/dlls/dbghelp/image_private.h
index 297d393..218ffa3 100644
--- a/dlls/dbghelp/image_private.h
+++ b/dlls/dbghelp/image_private.h
@@ -123,6 +123,7 @@ struct image_file_map
             struct
             {
                 const macho_section*            section;
+                const char*                     mapped;
             }*                          sect;
 #endif
         } macho;
@@ -155,6 +156,13 @@ extern void         elf_unmap_section(struct image_section_map* ism) DECLSPEC_HI
 extern DWORD_PTR    elf_get_map_rva(const struct image_section_map* ism) DECLSPEC_HIDDEN;
 extern unsigned     elf_get_map_size(const struct image_section_map* ism) DECLSPEC_HIDDEN;
 
+extern BOOL         macho_find_section(struct image_file_map* ifm, const char* segname,
+                                       const char* sectname, struct image_section_map* ism) DECLSPEC_HIDDEN;
+extern const char*  macho_map_section(struct image_section_map* ism) DECLSPEC_HIDDEN;
+extern void         macho_unmap_section(struct image_section_map* ism) DECLSPEC_HIDDEN;
+extern DWORD_PTR    macho_get_map_rva(const struct image_section_map* ism) DECLSPEC_HIDDEN;
+extern unsigned     macho_get_map_size(const struct image_section_map* ism) DECLSPEC_HIDDEN;
+
 extern BOOL         pe_find_section(struct image_file_map* fmap, const char* name,
                                     struct image_section_map* ism) DECLSPEC_HIDDEN;
 extern const char*  pe_map_section(struct image_section_map* psm) DECLSPEC_HIDDEN;
@@ -167,8 +175,9 @@ static inline BOOL image_find_section(struct image_file_map* fmap, const char* n
 {
     switch (fmap->modtype)
     {
-    case DMT_ELF: return elf_find_section(fmap, name, SHT_NULL, ism);
-    case DMT_PE:  return pe_find_section(fmap, name, ism);
+    case DMT_ELF:   return elf_find_section(fmap, name, SHT_NULL, ism);
+    case DMT_MACHO: return macho_find_section(fmap, NULL, name, ism);
+    case DMT_PE:    return pe_find_section(fmap, name, ism);
     default: assert(0); return FALSE;
     }
 }
@@ -178,8 +187,9 @@ static inline const char* image_map_section(struct image_section_map* ism)
     if (!ism->fmap) return NULL;
     switch (ism->fmap->modtype)
     {
-    case DMT_ELF: return elf_map_section(ism);
-    case DMT_PE:  return pe_map_section(ism);
+    case DMT_ELF:   return elf_map_section(ism);
+    case DMT_MACHO: return macho_map_section(ism);
+    case DMT_PE:    return pe_map_section(ism);
     default: assert(0); return NULL;
     }
 }
@@ -189,8 +199,9 @@ static inline void image_unmap_section(struct image_section_map* ism)
     if (!ism->fmap) return;
     switch (ism->fmap->modtype)
     {
-    case DMT_ELF: elf_unmap_section(ism); break;
-    case DMT_PE:  pe_unmap_section(ism);   break;
+    case DMT_ELF:   elf_unmap_section(ism); break;
+    case DMT_MACHO: macho_unmap_section(ism); break;
+    case DMT_PE:    pe_unmap_section(ism);   break;
     default: assert(0); return;
     }
 }
@@ -200,8 +211,9 @@ static inline DWORD_PTR image_get_map_rva(const struct image_section_map* ism)
     if (!ism->fmap) return 0;
     switch (ism->fmap->modtype)
     {
-    case DMT_ELF: return elf_get_map_rva(ism);
-    case DMT_PE:  return pe_get_map_rva(ism);
+    case DMT_ELF:   return elf_get_map_rva(ism);
+    case DMT_MACHO: return macho_get_map_rva(ism);
+    case DMT_PE:    return pe_get_map_rva(ism);
     default: assert(0); return 0;
     }
 }
@@ -211,8 +223,9 @@ static inline unsigned image_get_map_size(const struct image_section_map* ism)
     if (!ism->fmap) return 0;
     switch (ism->fmap->modtype)
     {
-    case DMT_ELF: return elf_get_map_size(ism);
-    case DMT_PE:  return pe_get_map_size(ism);
+    case DMT_ELF:   return elf_get_map_size(ism);
+    case DMT_MACHO: return macho_get_map_size(ism);
+    case DMT_PE:    return pe_get_map_size(ism);
     default: assert(0); return 0;
     }
 }
diff --git a/dlls/dbghelp/macho_module.c b/dlls/dbghelp/macho_module.c
index 76280c8..4e89435 100644
--- a/dlls/dbghelp/macho_module.c
+++ b/dlls/dbghelp/macho_module.c
@@ -146,7 +146,8 @@ static void macho_calc_range(const struct macho_file_map* fmap, unsigned long of
  *
  * Maps a range (offset, length in bytes) from a Mach-O file into memory
  */
-static const char* macho_map_range(const struct macho_file_map* fmap, unsigned long offset, unsigned long len)
+static const char* macho_map_range(const struct macho_file_map* fmap, unsigned long offset, unsigned long len,
+                                   const char** base)
 {
     unsigned long   misalign, aligned_offset, aligned_map_end, map_size;
     const void*     aligned_ptr;
@@ -161,6 +162,8 @@ static const char* macho_map_range(const struct macho_file_map* fmap, unsigned l
     TRACE("Mapped (0x%08lx - 0x%08lx) to %p\n", aligned_offset, aligned_map_end, aligned_ptr);
 
     if (aligned_ptr == MAP_FAILED) return IMAGE_NO_MAP;
+    if (base)
+        *base = aligned_ptr;
     return (const char*)aligned_ptr + misalign;
 }
 
@@ -169,12 +172,12 @@ static const char* macho_map_range(const struct macho_file_map* fmap, unsigned l
  *
  * Unmaps a range (offset, length in bytes) of a Mach-O file from memory
  */
-static void macho_unmap_range(const void** mapped, const struct macho_file_map* fmap,
+static void macho_unmap_range(const char** base, const void** mapped, const struct macho_file_map* fmap,
                               unsigned long offset, unsigned long len)
 {
-    TRACE("(%p, %p/%d, 0x%08lx, 0x%08lx)\n", mapped, fmap, fmap->fd, offset, len);
+    TRACE("(%p, %p, %p/%d, 0x%08lx, 0x%08lx)\n", base, mapped, fmap, fmap->fd, offset, len);
 
-    if (mapped && *mapped != IMAGE_NO_MAP)
+    if ((mapped && *mapped != IMAGE_NO_MAP) || (base && *base != IMAGE_NO_MAP))
     {
         unsigned long   misalign, aligned_offset, aligned_map_end, map_size;
         void*           aligned_ptr;
@@ -182,11 +185,17 @@ static void macho_unmap_range(const void** mapped, const struct macho_file_map*
         macho_calc_range(fmap, offset, len, &aligned_offset, &aligned_map_end,
                          &map_size, &misalign);
 
-        aligned_ptr = (char*)*mapped - misalign;
+        if (mapped)
+            aligned_ptr = (char*)*mapped - misalign;
+        else
+            aligned_ptr = (void*)*base;
         if (munmap(aligned_ptr, map_size) < 0)
             WARN("Couldn't unmap the range\n");
         TRACE("Unmapped (0x%08lx - 0x%08lx) from %p - %p\n", aligned_offset, aligned_map_end, aligned_ptr, (char*)aligned_ptr + map_size);
-        *mapped = IMAGE_NO_MAP;
+        if (mapped)
+            *mapped = IMAGE_NO_MAP;
+        if (base)
+            *base = IMAGE_NO_MAP;
     }
 }
 
@@ -213,25 +222,25 @@ static BOOL macho_map_ranges(const struct macho_file_map* fmap,
 
     if (aligned_map_end1 < aligned_offset2 || aligned_map_end2 < aligned_offset1)
     {
-        *mapped1 = macho_map_range(fmap, offset1, len1);
+        *mapped1 = macho_map_range(fmap, offset1, len1, NULL);
         if (*mapped1 != IMAGE_NO_MAP)
         {
-            *mapped2 = macho_map_range(fmap, offset2, len2);
+            *mapped2 = macho_map_range(fmap, offset2, len2, NULL);
             if (*mapped2 == IMAGE_NO_MAP)
-                macho_unmap_range(mapped1, fmap, offset1, len1);
+                macho_unmap_range(NULL, mapped1, fmap, offset1, len1);
         }
     }
     else
     {
         if (offset1 < offset2)
         {
-            *mapped1 = macho_map_range(fmap, offset1, offset2 + len2 - offset1);
+            *mapped1 = macho_map_range(fmap, offset1, offset2 + len2 - offset1, NULL);
             if (*mapped1 != IMAGE_NO_MAP)
                 *mapped2 = (const char*)*mapped1 + offset2 - offset1;
         }
         else
         {
-            *mapped2 = macho_map_range(fmap, offset2, offset1 + len1 - offset2);
+            *mapped2 = macho_map_range(fmap, offset2, offset1 + len1 - offset2, NULL);
             if (*mapped2 != IMAGE_NO_MAP)
                 *mapped1 = (const char*)*mapped2 + offset1 - offset2;
         }
@@ -265,25 +274,109 @@ static void macho_unmap_ranges(const struct macho_file_map* fmap,
 
     if (aligned_map_end1 < aligned_offset2 || aligned_map_end2 < aligned_offset1)
     {
-        macho_unmap_range(mapped1, fmap, offset1, len1);
-        macho_unmap_range(mapped2, fmap, offset2, len2);
+        macho_unmap_range(NULL, mapped1, fmap, offset1, len1);
+        macho_unmap_range(NULL, mapped2, fmap, offset2, len2);
     }
     else
     {
         if (offset1 < offset2)
         {
-            macho_unmap_range(mapped1, fmap, offset1, offset2 + len2 - offset1);
+            macho_unmap_range(NULL, mapped1, fmap, offset1, offset2 + len2 - offset1);
             *mapped2 = IMAGE_NO_MAP;
         }
         else
         {
-            macho_unmap_range(mapped2, fmap, offset2, offset1 + len1 - offset2);
+            macho_unmap_range(NULL, mapped2, fmap, offset2, offset1 + len1 - offset2);
             *mapped1 = IMAGE_NO_MAP;
         }
     }
 }
 
 /******************************************************************
+ *              macho_find_section
+ */
+BOOL macho_find_section(struct image_file_map* ifm, const char* segname, const char* sectname, struct image_section_map* ism)
+{
+    struct macho_file_map* fmap;
+    unsigned i;
+    char tmp[sizeof(fmap->sect[0].section->sectname)];
+
+    /* Other parts of dbghelp use section names like ".eh_frame".  Mach-O uses
+       names like "__eh_frame".  Convert those. */
+    if (sectname[0] == '.')
+    {
+        lstrcpynA(tmp, "__", sizeof(tmp));
+        lstrcpynA(tmp + 2, sectname + 1, sizeof(tmp) - 2);
+        sectname = tmp;
+    }
+
+    fmap = &ifm->u.macho;
+    for (i = 0; i < fmap->num_sections; i++)
+    {
+        if (strcmp(fmap->sect[i].section->sectname, sectname) == 0 &&
+            (!segname || strcmp(fmap->sect[i].section->sectname, segname) == 0))
+        {
+            ism->fmap = ifm;
+            ism->sidx = i;
+            return TRUE;
+        }
+    }
+
+    ism->fmap = NULL;
+    ism->sidx = -1;
+    return FALSE;
+}
+
+/******************************************************************
+ *              macho_map_section
+ */
+const char* macho_map_section(struct image_section_map* ism)
+{
+    struct macho_file_map* fmap = &ism->fmap->u.macho;
+
+    assert(ism->fmap->modtype == DMT_MACHO);
+    if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections)
+        return IMAGE_NO_MAP;
+
+    return macho_map_range(fmap, fmap->sect[ism->sidx].section->offset, fmap->sect[ism->sidx].section->size,
+                           &fmap->sect[ism->sidx].mapped);
+}
+
+/******************************************************************
+ *              macho_unmap_section
+ */
+void macho_unmap_section(struct image_section_map* ism)
+{
+    struct macho_file_map* fmap = &ism->fmap->u.macho;
+
+    if (ism->sidx >= 0 && ism->sidx < fmap->num_sections && fmap->sect[ism->sidx].mapped != IMAGE_NO_MAP)
+    {
+        macho_unmap_range(&fmap->sect[ism->sidx].mapped, NULL, fmap, fmap->sect[ism->sidx].section->offset,
+                          fmap->sect[ism->sidx].section->size);
+    }
+}
+
+/******************************************************************
+ *              macho_get_map_rva
+ */
+DWORD_PTR macho_get_map_rva(const struct image_section_map* ism)
+{
+    if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections)
+        return 0;
+    return ism->fmap->u.macho.sect[ism->sidx].section->addr - ism->fmap->u.macho.segs_start;
+}
+
+/******************************************************************
+ *              macho_get_map_size
+ */
+unsigned macho_get_map_size(const struct image_section_map* ism)
+{
+    if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections)
+        return 0;
+    return ism->fmap->u.macho.sect[ism->sidx].section->size;
+}
+
+/******************************************************************
  *              macho_map_load_commands
  *
  * Maps the load commands from a Mach-O file into memory
@@ -293,7 +386,7 @@ static const struct load_command* macho_map_load_commands(struct macho_file_map*
     if (fmap->load_commands == IMAGE_NO_MAP)
     {
         fmap->load_commands = (const struct load_command*) macho_map_range(
-                fmap, sizeof(fmap->mach_header), fmap->mach_header.sizeofcmds);
+                fmap, sizeof(fmap->mach_header), fmap->mach_header.sizeofcmds, NULL);
         TRACE("Mapped load commands: %p\n", fmap->load_commands);
     }
 
@@ -310,7 +403,7 @@ static void macho_unmap_load_commands(struct macho_file_map* fmap)
     if (fmap->load_commands != IMAGE_NO_MAP)
     {
         TRACE("Unmapping load commands: %p\n", fmap->load_commands);
-        macho_unmap_range((const void**)&fmap->load_commands, fmap,
+        macho_unmap_range(NULL, (const void**)&fmap->load_commands, fmap,
                     sizeof(fmap->mach_header), fmap->mach_header.sizeofcmds);
     }
 }
@@ -423,6 +516,7 @@ static int macho_load_section_info(struct macho_file_map* fmap, const struct loa
     for (i = 0; i < sc->nsects; i++)
     {
         fmap->sect[*section_index].section = &section[i];
+        fmap->sect[*section_index].mapped = IMAGE_NO_MAP;
         (*section_index)++;
     }
 
@@ -556,7 +650,10 @@ static BOOL macho_map_file(const WCHAR* filenameW, struct image_file_map* ifm)
 
     i = 0;
     if (macho_enum_load_commands(fmap, TARGET_SEGMENT_COMMAND, macho_load_section_info, &i) < 0)
+    {
+        fmap->num_sections = 0;
         goto done;
+    }
 
     fmap->segs_size -= fmap->segs_start;
     TRACE("segs_start: 0x%08lx, segs_size: 0x%08lx\n", (unsigned long)fmap->segs_start,
@@ -580,6 +677,12 @@ static void macho_unmap_file(struct image_file_map* ifm)
     TRACE("(%p/%d)\n", ifm, ifm->u.macho.fd);
     if (ifm->u.macho.fd != -1)
     {
+        struct image_section_map ism;
+
+        ism.fmap = ifm;
+        for (ism.sidx = 0; ism.sidx < ifm->u.macho.num_sections; ism.sidx++)
+            macho_unmap_section(&ism);
+
         HeapFree(GetProcessHeap(), 0, ifm->u.macho.sect);
         macho_unmap_load_commands(&ifm->u.macho);
         close(ifm->u.macho.fd);
@@ -1443,6 +1546,30 @@ struct module*  macho_load_module(struct process* pcs, const WCHAR* name, unsign
 
 #else  /* HAVE_MACH_O_LOADER_H */
 
+BOOL macho_find_section(struct image_file_map* ifm, const char* segname, const char* sectname, struct image_section_map* ism)
+{
+    return FALSE;
+}
+
+const char* macho_map_section(struct image_section_map* ism)
+{
+    return NULL;
+}
+
+void macho_unmap_section(struct image_section_map* ism)
+{
+}
+
+DWORD_PTR macho_get_map_rva(const struct image_section_map* ism)
+{
+    return 0;
+}
+
+unsigned macho_get_map_size(const struct image_section_map* ism)
+{
+    return 0;
+}
+
 BOOL    macho_synchronize_module_list(struct process* pcs)
 {
     return FALSE;
-- 
1.9.5 (Apple Git-50.3)




More information about the wine-patches mailing list