[PATCH 07/11] dbghelp: Move the macho_file_map structure into image_file_map.

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


---
 dlls/dbghelp/image_private.h |  32 +++++++
 dlls/dbghelp/macho_module.c  | 210 +++++++++++++++++++------------------------
 2 files changed, 124 insertions(+), 118 deletions(-)

diff --git a/dlls/dbghelp/image_private.h b/dlls/dbghelp/image_private.h
index 2afed79..297d393 100644
--- a/dlls/dbghelp/image_private.h
+++ b/dlls/dbghelp/image_private.h
@@ -42,6 +42,17 @@
 #ifdef HAVE_SYS_LINK_H
 # include <sys/link.h>
 #endif
+#ifdef HAVE_MACH_O_LOADER_H
+#include <mach-o/loader.h>
+
+#ifdef _WIN64
+typedef struct mach_header_64       macho_mach_header;
+typedef struct section_64           macho_section;
+#else
+typedef struct mach_header          macho_mach_header;
+typedef struct section              macho_section;
+#endif
+#endif
 
 #define IMAGE_NO_MAP  ((void*)-1)
 
@@ -94,6 +105,27 @@ struct image_file_map
             }*                          sect;
 #endif
         } elf;
+        struct macho_file_map
+        {
+            size_t                      segs_size;
+            size_t                      segs_start;
+            int                         fd;
+
+#ifdef HAVE_MACH_O_LOADER_H
+            macho_mach_header           mach_header;
+            const struct load_command*  load_commands;
+
+            /* The offset in the file which is this architecture.  mach_header was
+             * read from arch_offset. */
+            unsigned                    arch_offset;
+
+            int                         num_sections;
+            struct
+            {
+                const macho_section*            section;
+            }*                          sect;
+#endif
+        } macho;
         struct pe_file_map
         {
             HANDLE                      hMap;
diff --git a/dlls/dbghelp/macho_module.c b/dlls/dbghelp/macho_module.c
index ac9ea5e..234812a 100644
--- a/dlls/dbghelp/macho_module.c
+++ b/dlls/dbghelp/macho_module.c
@@ -77,18 +77,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_macho);
 
 
 #ifdef _WIN64
-typedef struct mach_header_64       macho_mach_header;
 typedef struct segment_command_64   macho_segment_command;
-typedef struct section_64           macho_section;
 typedef struct nlist_64             macho_nlist;
 
 #define TARGET_CPU_TYPE         CPU_TYPE_X86_64
 #define TARGET_MH_MAGIC         MH_MAGIC_64
 #define TARGET_SEGMENT_COMMAND  LC_SEGMENT_64
 #else
-typedef struct mach_header          macho_mach_header;
 typedef struct segment_command      macho_segment_command;
-typedef struct section              macho_section;
 typedef struct nlist                macho_nlist;
 
 #define TARGET_CPU_TYPE         CPU_TYPE_X86
@@ -116,35 +112,7 @@ struct macho_info
     const WCHAR*                module_name;    /* OUT found module name (if MACHO_INFO_NAME is set) */
 };
 
-/* structure holding information while handling a Mach-O image */
-#define BITS_PER_ULONG (sizeof(ULONG) * 8)
-#define ULONGS_FOR_BITS(nbits) (((nbits) + BITS_PER_ULONG - 1) / BITS_PER_ULONG)
-struct macho_file_map
-{
-    /* A copy of the Mach-O header for an individual architecture. */
-    macho_mach_header           mach_header;
-
-    /* The mapped load commands. */
-    const struct load_command*  load_commands;
-
-    /* The portion of the file which is this architecture.  mach_header was
-     * read from arch_offset. */
-    unsigned                    arch_offset;
-
-    /* The range of address space covered by all segments. */
-    size_t                      segs_start;
-    size_t                      segs_size;
-
-    /* Map of which sections contain code.  Sections are accessed using 1-based
-     * index.  Bit 0 of this bitset indicates if the bitset has been initialized. */
-    RTL_BITMAP                  sect_is_code;
-    ULONG                       sect_is_code_buff[ULONGS_FOR_BITS(MAX_SECT + 1)];
-
-    /* The file. */
-    int                         fd;
-};
-
-static void macho_unmap_file(struct macho_file_map* fmap);
+static void macho_unmap_file(struct image_file_map* fmap);
 
 /******************************************************************
  *              macho_calc_range
@@ -397,16 +365,35 @@ static int macho_enum_load_commands(struct macho_file_map* fmap, unsigned cmd,
 }
 
 /******************************************************************
- *              macho_accum_segs_range
+ *              macho_count_sections
+ *
+ * Callback for macho_enum_load_commands.  Counts the number of
+ * significant sections in a Mach-O file.  All commands are
+ * expected to be of LC_SEGMENT[_64] type.
+ */
+static int macho_count_sections(struct macho_file_map* fmap, const struct load_command* lc, void* user)
+{
+    const macho_segment_command* sc = (const macho_segment_command*)lc;
+
+    TRACE("(%p/%d, %p, %p) segment %s\n", fmap, fmap->fd, lc, user, debugstr_an(sc->segname, sizeof(sc->segname)));
+
+    fmap->num_sections += sc->nsects;
+    return 0;
+}
+
+/******************************************************************
+ *              macho_load_section_info
  *
  * Callback for macho_enum_load_commands.  Accumulates the address
- * range covered by the segments of a Mach-O file.  All commands
- * are expected to be of LC_SEGMENT[_64] type.
+ * range covered by the segments of a Mach-O file and builds the
+ * section map.  All commands are expected to be of LC_SEGMENT[_64] type.
  */
-static int macho_accum_segs_range(struct macho_file_map* fmap,
-                                  const struct load_command* lc, void* user)
+static int macho_load_section_info(struct macho_file_map* fmap, const struct load_command* lc, void* user)
 {
     const macho_segment_command*    sc = (const macho_segment_command*)lc;
+    int*                            section_index = (int*)user;
+    const macho_section*            section;
+    int                             i;
     unsigned long                   tmp, page_mask = sysconf( _SC_PAGESIZE ) - 1;
 
     TRACE("(%p/%d, %p, %p) before: 0x%08lx - 0x%08lx\n", fmap, fmap->fd, lc, user,
@@ -415,27 +402,28 @@ static int macho_accum_segs_range(struct macho_file_map* fmap,
             (unsigned long)(sc->vmaddr + sc->vmsize));
 
     if (!strncmp(sc->segname, "WINE_", 5))
-    {
         TRACE("Ignoring special Wine segment %s\n", debugstr_an(sc->segname, sizeof(sc->segname)));
-        return 0;
-    }
-    if (!strncmp(sc->segname, "__PAGEZERO", 10))
-    {
+    else if (!strncmp(sc->segname, "__PAGEZERO", 10))
         TRACE("Ignoring __PAGEZERO segment\n");
-        return 0;
-    }
+    else
+    {
+        /* If this segment starts before previously-known earliest, record new earliest. */
+        if (sc->vmaddr < fmap->segs_start)
+            fmap->segs_start = sc->vmaddr;
 
-    /* If this segment starts before previously-known earliest, record
-     * new earliest. */
-    if (sc->vmaddr < fmap->segs_start)
-        fmap->segs_start = sc->vmaddr;
+        /* If this segment extends beyond previously-known furthest, record new furthest. */
+        tmp = (sc->vmaddr + sc->vmsize + page_mask) & ~page_mask;
+        if (fmap->segs_size < tmp) fmap->segs_size = tmp;
 
-    /* If this segment extends beyond previously-known furthest, record
-     * new furthest. */
-    tmp = (sc->vmaddr + sc->vmsize + page_mask) & ~page_mask;
-    if (fmap->segs_size < tmp) fmap->segs_size = tmp;
+        TRACE("after: 0x%08lx - 0x%08lx\n", (unsigned long)fmap->segs_start, (unsigned long)fmap->segs_size);
+    }
 
-    TRACE("after: 0x%08lx - 0x%08lx\n", (unsigned long)fmap->segs_start, (unsigned long)fmap->segs_size);
+    section = (const macho_section*)(sc + 1);
+    for (i = 0; i < sc->nsects; i++)
+    {
+        fmap->sect[*section_index].section = &section[i];
+        (*section_index)++;
+    }
 
     return 0;
 }
@@ -445,8 +433,9 @@ static int macho_accum_segs_range(struct macho_file_map* fmap,
  *
  * Maps a Mach-O file into memory (and checks it's a real Mach-O file)
  */
-static BOOL macho_map_file(const WCHAR* filenameW, struct macho_file_map* fmap)
+static BOOL macho_map_file(const WCHAR* filenameW, struct image_file_map* ifm)
 {
+    struct macho_file_map* fmap = &ifm->u.macho;
     struct fat_header   fat_header;
     struct stat         statbuf;
     int                 i;
@@ -458,7 +447,15 @@ static BOOL macho_map_file(const WCHAR* filenameW, struct macho_file_map* fmap)
 
     fmap->fd = -1;
     fmap->load_commands = IMAGE_NO_MAP;
-    RtlInitializeBitMap(&fmap->sect_is_code, fmap->sect_is_code_buff, MAX_SECT + 1);
+    fmap->num_sections = 0;
+    fmap->sect = NULL;
+
+    ifm->modtype = DMT_MACHO;
+#ifdef _WIN64
+    ifm->addr_size = 64;
+#else
+    ifm->addr_size = 32;
+#endif
 
     len = WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, NULL, 0, NULL, NULL);
     if (!(filename = HeapAlloc(GetProcessHeap(), 0, len)))
@@ -534,10 +531,20 @@ static BOOL macho_map_file(const WCHAR* filenameW, struct macho_file_map* fmap)
     }
     TRACE("... verified Mach header\n");
 
+    fmap->num_sections = 0;
+    if (macho_enum_load_commands(fmap, TARGET_SEGMENT_COMMAND, macho_count_sections, NULL) < 0)
+        goto done;
+    TRACE("%d sections\n", fmap->num_sections);
+
+    fmap->sect = HeapAlloc(GetProcessHeap(), 0, fmap->num_sections * sizeof(fmap->sect[0]));
+    if (!fmap->sect)
+        goto done;
+
     fmap->segs_size = 0;
     fmap->segs_start = ~0L;
 
-    if (macho_enum_load_commands(fmap, TARGET_SEGMENT_COMMAND, macho_accum_segs_range, NULL) < 0)
+    i = 0;
+    if (macho_enum_load_commands(fmap, TARGET_SEGMENT_COMMAND, macho_load_section_info, &i) < 0)
         goto done;
 
     fmap->segs_size -= fmap->segs_start;
@@ -547,7 +554,7 @@ static BOOL macho_map_file(const WCHAR* filenameW, struct macho_file_map* fmap)
     ret = TRUE;
 done:
     if (!ret)
-        macho_unmap_file(fmap);
+        macho_unmap_file(ifm);
     HeapFree(GetProcessHeap(), 0, filename);
     return ret;
 }
@@ -557,54 +564,19 @@ done:
  *
  * Unmaps a Mach-O file from memory (previously mapped with macho_map_file)
  */
-static void macho_unmap_file(struct macho_file_map* fmap)
+static void macho_unmap_file(struct image_file_map* ifm)
 {
-    TRACE("(%p/%d)\n", fmap, fmap->fd);
-    if (fmap->fd != -1)
+    TRACE("(%p/%d)\n", ifm, ifm->u.macho.fd);
+    if (ifm->u.macho.fd != -1)
     {
-        macho_unmap_load_commands(fmap);
-        close(fmap->fd);
-        fmap->fd = -1;
+        HeapFree(GetProcessHeap(), 0, ifm->u.macho.sect);
+        macho_unmap_load_commands(&ifm->u.macho);
+        close(ifm->u.macho.fd);
+        ifm->u.macho.fd = -1;
     }
 }
 
 /******************************************************************
- *              macho_fill_sect_is_code
- *
- * Callback for macho_enum_load_commands.  Determines which segments
- * of a Mach-O file contain code.  All commands are expected to be
- * of LC_SEGMENT[_64] type.
- */
-static int macho_fill_sect_is_code(struct macho_file_map* fmap,
-                                   const struct load_command* lc, void* user)
-{
-    const macho_segment_command*    sc = (const macho_segment_command*)lc;
-    const macho_section*            sections;
-    int*                            cursect = user;
-    int                             i;
-
-    TRACE("(%p/%d, %p, %p/%d) scanning %u sections\n", fmap, fmap->fd, lc,
-            cursect, *cursect, sc->nsects);
-
-    sections = (const macho_section*)(sc + 1);
-    for (i = 0; i < sc->nsects; i++)
-    {
-        if (*cursect > MAX_SECT) return -1;
-        (*cursect)++;
-
-        if (!(sections[i].flags & SECTION_TYPE) &&
-            (sections[i].flags & (S_ATTR_PURE_INSTRUCTIONS|S_ATTR_SOME_INSTRUCTIONS)))
-            RtlSetBits(&fmap->sect_is_code, *cursect, 1);
-        else
-            RtlClearBits(&fmap->sect_is_code, *cursect, 1);
-        TRACE("Section %d (%d of this segment) is%s code\n", *cursect, i,
-                (RtlAreBitsSet(&fmap->sect_is_code, *cursect, 1) ? "" : " not"));
-    }
-
-    return 0;
-}
-
-/******************************************************************
  *              macho_sect_is_code
  *
  * Checks if a section, identified by sectidx which is a 1-based
@@ -613,17 +585,19 @@ static int macho_fill_sect_is_code(struct macho_file_map* fmap,
  */
 static BOOL macho_sect_is_code(struct macho_file_map* fmap, unsigned char sectidx)
 {
+    BOOL ret;
+
     TRACE("(%p/%d, %u)\n", fmap, fmap->fd, sectidx);
 
-    if (!RtlAreBitsSet(&fmap->sect_is_code, 0, 1))
-    {
-        int cursect = 0;
-        if (macho_enum_load_commands(fmap, TARGET_SEGMENT_COMMAND, macho_fill_sect_is_code, &cursect) < 0)
-            WARN("Couldn't load sect_is_code map\n");
-        RtlSetBits(&fmap->sect_is_code, 0, 1);
-    }
+    if (!sectidx) return FALSE;
 
-    return RtlAreBitsSet(&fmap->sect_is_code, sectidx, 1);
+    sectidx--; /* convert from 1-based to 0-based */
+    if (sectidx >= fmap->num_sections) return FALSE;
+
+    ret = (!(fmap->sect[sectidx].section->flags & SECTION_TYPE) &&
+           (fmap->sect[sectidx].section->flags & (S_ATTR_PURE_INSTRUCTIONS|S_ATTR_SOME_INSTRUCTIONS)));
+    TRACE("-> %d\n", ret);
+    return ret;
 }
 
 struct symtab_elt
@@ -923,7 +897,7 @@ static BOOL macho_load_debug_info_from_map(struct module* module,
 BOOL macho_load_debug_info(struct module* module)
 {
     BOOL                    ret = TRUE;
-    struct macho_file_map   fmap;
+    struct image_file_map   fmap;
 
     TRACE("(%p)\n", module);
 
@@ -935,7 +909,7 @@ BOOL macho_load_debug_info(struct module* module)
 
     ret = macho_map_file(module->module.LoadedImageName, &fmap);
     if (ret)
-        ret = macho_load_debug_info_from_map(module, &fmap);
+        ret = macho_load_debug_info_from_map(module, &fmap.u.macho);
 
     macho_unmap_file(&fmap);
     return ret;
@@ -949,14 +923,14 @@ BOOL macho_load_debug_info(struct module* module)
 BOOL macho_fetch_file_info(const WCHAR* name, DWORD_PTR* base,
                            DWORD* size, DWORD* checksum)
 {
-    struct macho_file_map fmap;
+    struct image_file_map fmap;
 
     TRACE("(%s, %p, %p, %p)\n", debugstr_w(name), base, size, checksum);
 
     if (!macho_map_file(name, &fmap)) return FALSE;
-    if (base) *base = fmap.segs_start;
-    *size = fmap.segs_size;
-    *checksum = calc_crc32(fmap.fd);
+    if (base) *base = fmap.u.macho.segs_start;
+    *size = fmap.u.macho.segs_size;
+    *checksum = calc_crc32(fmap.u.macho.fd);
     macho_unmap_file(&fmap);
     return TRUE;
 }
@@ -983,7 +957,7 @@ static BOOL macho_load_file(struct process* pcs, const WCHAR* filename,
                             unsigned long load_addr, struct macho_info* macho_info)
 {
     BOOL                    ret = TRUE;
-    struct macho_file_map   fmap;
+    struct image_file_map   fmap;
 
     TRACE("(%p/%p, %s, 0x%08lx, %p/0x%08x)\n", pcs, pcs->handle, debugstr_w(filename),
             load_addr, macho_info, macho_info->flags);
@@ -1051,9 +1025,9 @@ static BOOL macho_load_file(struct process* pcs, const WCHAR* filename,
             HeapAlloc(GetProcessHeap(), 0, sizeof(struct module_format) + sizeof(struct macho_module_info));
         if (!modfmt) goto leave;
         if (!load_addr)
-            load_addr = fmap.segs_start;
+            load_addr = fmap.u.macho.segs_start;
         macho_info->module = module_new(pcs, filename, DMT_MACHO, FALSE, load_addr,
-                                        fmap.segs_size, 0, calc_crc32(fmap.fd));
+                                        fmap.u.macho.segs_size, 0, calc_crc32(fmap.u.macho.fd));
         if (!macho_info->module)
         {
             HeapFree(GetProcessHeap(), 0, modfmt);
@@ -1071,7 +1045,7 @@ static BOOL macho_load_file(struct process* pcs, const WCHAR* filename,
 
         if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
             macho_info->module->module.SymType = SymDeferred;
-        else if (!macho_load_debug_info_from_map(macho_info->module, &fmap))
+        else if (!macho_load_debug_info_from_map(macho_info->module, &fmap.u.macho))
             ret = FALSE;
 
         macho_info->module->format_info[DFI_MACHO]->u.macho_info->in_use = 1;
-- 
1.9.5 (Apple Git-50.3)




More information about the wine-patches mailing list