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, §ion_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