Mach-O Support in WineLib Loader (2) dlopen

Pierre d'Herbemont stegefin at free.fr
Mon Jul 21 08:57:37 CDT 2003


Hi!

This patch provides Mach-O support in WineLib. As Mach-O doesn't have 
init and fini section, it adds support for it in dlopen. A new file 
mach-o.c is created. It contains functions which add support for init, 
and fini section.
Moreover, ntdll needs to be loaded as global. I don't know what you 
will think about this, but tell me if you don't like the way it is 
done. I change dlopen_dll() test_only params, to a flag param. When we 
want to do a test_only we pass 0x1 to dlopen. And when we want dlopen 
to open a file with RTLD_GLOBAL, we use flags other bits, to tell 
dlopen_dll we are in a such case. We pass the value 0x2 to load a file 
as RTLD_GLOBAL. This option is commented out on other platform others 
than Mac OS X.

By the way I didn't add a specific Macro for Mach-O, because only 
Darwin use this file format, but we probably should add one.

Thanks,

Pierre.

ChangeLog:
- Add Support for Mach-O quirks when dlopening

-------------- next part --------------
Index: libs/wine/Makefile.in
===================================================================
RCS file: /home/wine/wine/libs/wine/Makefile.in,v
retrieving revision 1.3
diff -u -r1.3 Makefile.in
--- libs/wine/Makefile.in	1 May 2003 00:39:29 -0000	1.3
+++ libs/wine/Makefile.in	21 Jul 2003 13:45:23 -0000
@@ -4,7 +4,7 @@
 VPATH     = @srcdir@
 LIBRARY   = wine
 SOVERSION = 1
-EXTRADEFS = -D__WINESRC__ -DDLLDIR="\"$(dlldir)\""
+EXTRADEFS = @LIBCOMMONFLAGS@ -D__WINESRC__ -DDLLDIR="\"$(dlldir)\""
 EXTRALIBS = $(LIBPORT) @DLLIBS@ @CRTLIBS@
 
 C_SRCS = \
@@ -12,7 +12,8 @@
 	debug.c \
 	errno.c \
 	ldt.c \
-	loader.c
+	loader.c \
+        mach-o.c
 
 @MAKE_LIB_RULES@
 
Index: libs/wine/loader.c
===================================================================
RCS file: /home/wine/wine/libs/wine/loader.c,v
retrieving revision 1.4
diff -u -r1.4 loader.c
--- libs/wine/loader.c	3 Jul 2003 18:23:10 -0000	1.4
+++ libs/wine/loader.c	21 Jul 2003 13:45:24 -0000
@@ -125,9 +125,14 @@
 }
 
 /* open a library for a given dll, searching in the dll path
- * 'name' must be the Windows dll name (e.g. "kernel32.dll") */
+ * 'name' must be the Windows dll name (e.g. "kernel32.dll") 
+ * flags value : 
+ *  - 0 dlopen RTLD_NOW
+ *  - 1 test only
+ *  - 2 dlopen RTLD_NOW | RTLD_GLOBAL (only on Darwin)
+ */
 static void *dlopen_dll( const char *name, char *error, int errorsize,
-                         int test_only, int *exists )
+                         int flags, int *exists )
 {
     int i, namelen = strlen(name);
     char *buffer, *p;
@@ -149,7 +154,10 @@
         int len = strlen(dll_paths[i]);
         p = buffer + dll_path_maxlen - len;
         memcpy( p, dll_paths[i], len );
-        if (!test_only && (ret = wine_dlopen( p, RTLD_NOW, error, errorsize ))) break;
+        if (!flags && (ret = wine_dlopen( p, RTLD_NOW, error, errorsize ))) break;
+#ifdef __APPLE__
+        if ((flags == 0x2) && (ret = wine_dlopen( p, RTLD_NOW | RTLD_GLOBAL, error, errorsize ))) break;
+#endif
         if ((*exists = file_exists( p ))) break; /* exists but cannot be loaded, return the error */
     }
     free( buffer );
@@ -422,7 +430,7 @@
     void *ntdll;
     void (*init_func)(int, char **);
 
-    if (!(ntdll = dlopen_dll( "ntdll.dll", error, error_size, 0, &file_exists ))) return;
+    if (!(ntdll = dlopen_dll( "ntdll.dll", error, error_size, 0x2, &file_exists ))) return;
     if (!(init_func = wine_dlsym( ntdll, "__wine_process_init", error, error_size ))) return;
     init_func( argc, argv );
 }
@@ -506,7 +514,7 @@
 
     return result == addr;
 }
-#endif  /* __svr4__ || __NetBSD__ */
+#endif  /* __svr4__ || __NetBSD__  */
 
 
 /***********************************************************************
@@ -580,6 +588,12 @@
         error[errorsize - 1] = '\0';
     }
     dlerror();
+    
+# ifdef __APPLE__
+    if(ret)
+        macho_call_functions_from_section_name( ret, "__wine_init");
+# endif
+
     return ret;
 #else
     if (error)
@@ -627,6 +641,11 @@
 #ifdef HAVE_DLOPEN
     int ret;
     const char *s;
+    
+# ifdef __APPLE__
+    macho_call_functions_from_section_name( handle, "__wine_fini");
+# endif
+
     dlerror(); dlerror();
     ret = dlclose( handle );
     s = dlerror();
--- /dev/null	Mon Jul 21 14:57:03 2003
+++ libs/wine/mach-o.c	Mon Jul 21 15:46:05 2003
@@ -0,0 +1,126 @@
+/*
+ * Mach-O (Mac OS X file format) Support
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef __APPLE__
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <mach-o/loader.h>
+#include <mach-o/dyld.h>
+#include <mach-o/getsect.h>
+
+/* This is our (dlcompat) central data structure. Whenever a module is loaded via
+ * dlopen(), we create such a struct.
+ * (from the dlcompat lib)
+ */
+typedef struct dlstatus
+{
+	struct dlstatus *next;		/* pointer to next element in the linked list */
+	NSModule module;
+	const struct mach_header *lib;
+        /* skipped things */
+} dlstatus ;
+
+
+/***********************************************************************
+ *		mach_header_from_module
+ */
+static const struct mach_header *mach_header_from_module(NSModule * module)
+{
+	struct mach_header *mach_header;
+	const char *name = NSNameOfModule(module);
+	unsigned int count = _dyld_image_count();
+	unsigned int i;
+        
+        if(!module) return 0;
+        if(!name) return 0;
+        
+	for (i = 0; i < count; i++)
+	{
+		if (!strcmp(name, _dyld_get_image_name(i)))
+		{
+			mach_header = _dyld_get_image_header(i);
+			return mach_header;
+		}
+	}
+	return 0;
+}
+
+
+/***********************************************************************
+ *		macho_call_functions_from_section_name
+ *
+ * Mach-O doesn't have an init and a fini sections. Here is a Hack to
+ * provide one. Note that the section is a data section, with names of
+ * each function Separated by a '\0'.
+ */
+void macho_call_functions_from_section_name( dlstatus *status, char * section_name )
+{
+    const struct mach_header	*mach_header;
+    char *wine_init_section ;
+    unsigned long section_size;
+    char *function_name;
+    int	i;
+    /* Check for the module */
+    if(!status->module) return;
+    
+    /* Get the Mach Header */
+    mach_header = mach_header_from_module(status->module);
+    if(!mach_header) return;
+    
+    /* point to the relative address of the section */
+    wine_init_section = (void *)getsectdatafromheader(mach_header, "__DATA", section_name, &section_size);
+		
+    if(!wine_init_section)
+	return; /* No section defined */
+        
+    /* point to the absolut address of the section */
+    wine_init_section = (char *)((long)wine_init_section + (long)mach_header);
+    
+    function_name = wine_init_section;
+    for(i = 0; i < section_size ; i++)
+    {
+        /* Are we at the end of the name */ 
+        if(wine_init_section[i] == '\0')
+        {
+            void (*func)();
+            if(!function_name)
+                    continue;
+
+            /* Check for function_name */
+            func = dlsym(status, function_name);
+
+            /* Call the function if it does exist */
+            if(func)
+                func();
+
+            /* Set function_name to the new name we are looking for */
+            function_name = wine_init_section + i + 1;
+        }
+    }
+}
+
+#endif /* __APPLE__ */


More information about the wine-patches mailing list