[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 = §ion[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