[PATCH 1/2] libwine: Export our own wrapper around the mmap() syscall on Mac OS X.

Charles Davis cdavis at mymail.mines.edu
Wed May 12 14:30:29 CDT 2010


From: Charles Davis <cdavis at mines.edu>

This allows us to use unaligned file offsets on Mac OS X.
---
 include/wine/library.h |    2 +
 libs/wine/mmap.c       |   85 ++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/include/wine/library.h b/include/wine/library.h
index 242bb69..2fcc6d4 100644
--- a/include/wine/library.h
+++ b/include/wine/library.h
@@ -76,6 +76,8 @@ extern int wine_call_on_stack( int (*func)(void *), void *arg, void *stack );
 /* memory mappings */
 
 extern void *wine_anon_mmap( void *start, size_t size, int prot, int flags );
+extern void *wine_mmap( void *start, size_t size, int prot, int flags, int fd,
+                        off_t off );
 extern void wine_mmap_add_reserved_area( void *addr, size_t size );
 extern void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap );
 extern int wine_mmap_is_in_reserved_area( void *addr, size_t size );
diff --git a/libs/wine/mmap.c b/libs/wine/mmap.c
index b400189..6cac2c7 100644
--- a/libs/wine/mmap.c
+++ b/libs/wine/mmap.c
@@ -63,6 +63,85 @@ static const unsigned int granularity_mask = 0xffff;  /* reserved areas have 64k
 #define MAP_ANON 0
 #endif
 
+/*
+ * In Mac OS 10.5, the mmap() function was changed to match UNIX '03 (as
+ * Linux does). In particular, this means that unaligned file offsets fail
+ * with EINVAL. However, that check is done at the LIBRARY level, not the
+ * kernel level. This is done to maintain backwards compatibility with old
+ * programs that expect unaligned offsets to succeed.
+ * Because the syscall itself still supports unaligned file offsets, instead
+ * of calling the wrapper in libc, we define our own function to make the
+ * syscall directly.
+ */
+#ifdef __APPLE__
+# ifdef __i386__
+extern int *__error(void);
+__ASM_GLOBAL_FUNC( wine_mmap,
+                   "movl $197,%eax\n\t"     /* SYS_mmap */
+                   "int $0x80\n\t"
+                   "jae 1f\n\t"
+                   "calll 2f\n"             /* PIC reference to errno */
+                   "2:\tpopl %edx\n\t"
+                   "movl L_errno__non_lazy_ptr-2b(%edx),%edx\n\t"
+                   "movl %eax,(%edx)\n\t"
+                   ".section __IMPORT,__pointers,non_lazy_symbol_pointers\n"
+                   "L_errno__non_lazy_ptr:\n\t"
+                   ".indirect_symbol _errno\n\t"
+                   ".long 0\n\t"
+                   ".text\n\t"
+                   "movl %esp,%edx\n\t"
+                   "andl $0xFFFFFFF0,%esp\n\t"
+                   "subl $16,%esp\n\t"
+                   "movl %edx,4(%esp)\n\t"
+                   "movl %eax,(%esp)\n\t"
+                   "calll 2f\n"             /* PIC call to cthread_set_errno_self() */
+                   "2:\tpopl %edx\n\t"
+                   "movl L_cthread_set_errno_self__non_lazy_ptr-2b(%edx),%edx\n\t"
+                   "calll *%edx\n\t"
+                   ".section __IMPORT,__pointers,non_lazy_symbol_pointers\n"
+                   "L_cthread_set_errno_self__non_lazy_ptr:\n\t"
+                   ".indirect_symbol _cthread_set_errno_self\n\t"
+                   ".long 0\n\t"
+                   ".text\n\t"
+                   "movl 4(%esp),%esp\n\t"
+                   "stc\n\t"
+                   "sbbl %edx,%edx\n\t"
+                   "sbbl %eax,%eax\n\t"
+                   "1:\tret\n\t" )
+# elif defined __x86_64__
+extern int *__error(void);
+__ASM_GLOBAL_FUNC( wine_mmap,
+                   "movq %rcx,%r10\n\t"
+                   "movl $0x020000c5,%eax\n\t"  /* SYS_mmap (decorated) */
+                   "syscall\n\t"
+                   "jae 1f\n\t"
+                   "movq _errno at GOTPCREL(%rip),%r11\n\t"
+                   "movq %rax,(%r11)\n\t"
+                   "movq %rsp,%rdx\n\t"
+                   "andq $~16,%rsp\n\t"
+                   "subq $16,%rsp\n\t"
+                   "movq %rdx,(%rsp)\n\t"
+                   "movq %rax,%rdi\n\t"
+                   "callq _cthread_set_errno_self\n\t"
+                   "movq (%rsp),%rsp\n\t"
+                   "stc\n\t"
+                   "sbbq %rdx,%rdx\n\t"
+                   "sbbq %rax,%rax\n\t"
+                   "1:\tret\n\t" )
+}
+# else
+void *wine_mmap( void *addr, size_t len, int prot, int flags, int fd, off_t off )
+{
+    return mmap( addr, len, prot, flags, fd, off );
+}
+# endif
+#else
+void *wine_mmap( void *addr, size_t len, int prot, int flags, int fd, off_t off )
+{
+    return mmap( addr, len, prot, flags, fd, off );
+}
+#endif
+
 static inline int get_fdzero(void)
 {
     static int fd = -1;
@@ -174,7 +253,7 @@ static int try_mmap_fixed (void *addr, size_t len, int prot, int flags,
 
     if (!vm_allocate(mach_task_self(),&result,len,0))
     {
-        if (mmap( (void *)result, len, prot, flags | MAP_FIXED, fildes, off ) != MAP_FAILED)
+        if (wine_mmap( (void *)result, len, prot, flags | MAP_FIXED, fildes, off ) != MAP_FAILED)
             return 1;
         vm_deallocate(mach_task_self(),result,len);
     }
@@ -213,7 +292,7 @@ void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
             return start;
 #endif
     }
-    return mmap( start, size, prot, flags, get_fdzero(), 0 );
+    return wine_mmap( start, size, prot, flags, get_fdzero(), 0 );
 }
 
 
@@ -232,7 +311,7 @@ static inline int mmap_reserve( void *addr, size_t size )
 #elif defined(__APPLE__)
     return try_mmap_fixed( addr, size, PROT_NONE, flags, get_fdzero(), 0 );
 #endif
-    ptr = mmap( addr, size, PROT_NONE, flags, get_fdzero(), 0 );
+    ptr = wine_mmap( addr, size, PROT_NONE, flags, get_fdzero(), 0 );
     if (ptr != addr && ptr != (void *)-1)  munmap( ptr, size );
     return (ptr == addr);
 }
-- 
1.7.1




More information about the wine-patches mailing list