[PATCH] kernel32: Also recognize and handle Mach-O fat binaries.
Charles Davis
cdavis5x at gmail.com
Fri Jan 23 00:30:56 CST 2015
This will be needed for WOW64 support on Mac OS, because there are no
separate directories for 32-bit and 64-bit libraries.
---
dlls/kernel32/module.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c
index f495e81..7b0f64d 100644
--- a/dlls/kernel32/module.c
+++ b/dlls/kernel32/module.c
@@ -250,6 +250,11 @@ void MODULE_get_binary_info( HANDLE hfile, struct binary_info *info )
unsigned int cpusubtype;
unsigned int filetype;
} macho;
+ struct
+ {
+ unsigned int magic;
+ unsigned int nfat_arch;
+ } macho_fat;
IMAGE_DOS_HEADER mz;
} header;
@@ -259,6 +264,7 @@ void MODULE_get_binary_info( HANDLE hfile, struct binary_info *info )
/* Seek to the start of the file and read the header information. */
if (SetFilePointer( hfile, 0, NULL, SEEK_SET ) == -1) return;
+read_header:
if (!ReadFile( hfile, &header, sizeof(header), &len, NULL ) || len != sizeof(header)) return;
if (!memcmp( header.elf.magic, "\177ELF", 4 ))
@@ -312,6 +318,76 @@ void MODULE_get_binary_info( HANDLE hfile, struct binary_info *info )
case 0x00000012: info->arch = IMAGE_FILE_MACHINE_POWERPC; break;
}
}
+ /* Mach-O fat file with Endian set to Big Endian or Little Endian */
+ else if (header.macho_fat.magic == 0xcafebabe || header.macho_fat.magic == 0xbebafeca)
+ {
+ struct
+ {
+ unsigned int cputype;
+ unsigned int cpusubtype;
+ unsigned int offset;
+ unsigned int size;
+ unsigned int align;
+ } fat_arch;
+ unsigned int i, offset = 0, first_offset = 0;
+#ifdef __i386__
+ BOOL is_wow64;
+ IsWow64Process( GetCurrentProcess(), &is_wow64 );
+#endif
+ if (header.macho_fat.magic == 0xbebafeca)
+ header.macho_fat.nfat_arch = RtlUlongByteSwap( header.macho_fat.nfat_arch );
+ /* Try and find an architecture we can execute */
+ for (i = 0; i < header.macho_fat.nfat_arch; i++)
+ {
+ if (!ReadFile( hfile, &fat_arch, sizeof(fat_arch), &len, NULL ) || len < sizeof(fat_arch)) return;
+ if (header.macho_fat.magic == 0xbebafeca)
+ {
+ fat_arch.cputype = RtlUlongByteSwap( fat_arch.cputype );
+ fat_arch.offset = RtlUlongByteSwap( fat_arch.offset );
+ }
+ if (!first_offset) first_offset = fat_arch.offset;
+#if defined(__x86_64__)
+ /* Always prefer x86_64 */
+ if (fat_arch.cputype == 0x010000007)
+ {
+ offset = fat_arch.offset;
+ break;
+ }
+ /* But consider i386, too */
+ if (fat_arch.cputype == 0x000000007)
+ offset = fat_arch.offset;
+#elif defined(__i386__)
+ /* If WOW64, prefer x86_64; otherwise, prefer i386 */
+ if ((is_wow64 && fat_arch.cputype == 0x01000007) ||
+ (!is_wow64 && fat_arch.cputype == 0x00000007))
+ {
+ offset = fat_arch.offset;
+ break;
+ }
+ /* If WOW64, consider i386, too */
+ if (is_wow64 && fat_arch.cputype == 0x00000007)
+ offset = fat_arch.offset;
+#elif defined(__aarch64__)
+ if (fat_arch.cputype == 0x0100000c)
+ offset = fat_arch.offset;
+#elif defined(__arm__)
+ if (fat_arch.cputype == 0x0000000c)
+ offset = fat_arch.offset;
+#elif defined(__powerpc__)
+ if (fat_arch.cputype == 0x00000012)
+ offset = fat_arch.offset;
+#endif
+ }
+ /* If we can't execute any of the architectures,
+ * just use the first one. We don't really have the
+ * support to say, "this file works on more than one
+ * architecture" yet. */
+ if (!offset) offset = first_offset;
+
+ /* Go and read the executable header */
+ if (SetFilePointer( hfile, offset, NULL, SEEK_SET ) == -1) return;
+ goto read_header;
+ }
/* Not ELF, try DOS */
else if (header.mz.e_magic == IMAGE_DOS_SIGNATURE)
{
--
2.2.2
More information about the wine-patches
mailing list