Binary relocatability [4]

Mike Hearn mike at theoretic.com
Fri Jan 23 04:24:30 CST 2004


Here it is with the ability to switch it off in the configure script.

Mike Hearn <mike at theoretic.com>
Hongli Lai <h.lai at chello.nl>
Implement runtime binary relocatability

Index: configure.ac
===================================================================
RCS file: /home/wine/wine/configure.ac,v
retrieving revision 1.232
diff -u -r1.232 configure.ac
--- configure.ac	20 Jan 2004 00:21:42 -0000	1.232
+++ configure.ac	23 Jan 2004 10:17:36 -0000
@@ -15,6 +15,7 @@
 AC_ARG_ENABLE(win16, AC_HELP_STRING([--disable-win16],[do not include Win16 support]))
 AC_ARG_ENABLE(debug, AC_HELP_STRING([--disable-debug],[compile out all debugging messages]))
 AC_ARG_ENABLE(trace, AC_HELP_STRING([--disable-trace],[compile out TRACE messages]))
+AC_ARG_ENABLE(binreloc, AC_HELP_STRING([--disable-binreloc],[disable binary runtime relocatability]))
 
 AC_ARG_WITH(opengl,    AC_HELP_STRING([--without-opengl],[do not use OpenGL]))
 AC_ARG_WITH(curses,    AC_HELP_STRING([--without-curses],[do not use curses]))
@@ -1407,6 +1408,18 @@
 case $host_vendor in
   *sun*) WINE_CHECK_DEFINE([__sun__]) ;;
 esac
+
+dnl *** check for /proc/self/maps to see if we can do binary relocatability on linux ***
+
+if ! test "x$enable_binreloc" = "xno" -a -e /proc/self/maps; then
+   AC_DEFINE(ENABLE_BINRELOC, 1, [Use binary relocatability])
+   RPATH='-Wl,-rpath -Wl,$${ORIGIN}/../lib'
+else
+   RPATH=''
+fi
+AC_SUBST(RPATH)
+
+
 
 dnl **** Generate output files ****
 
Index: Make.rules.in
===================================================================
RCS file: /home/wine/wine/Make.rules.in,v
retrieving revision 1.164
diff -u -r1.164 Make.rules.in
--- Make.rules.in	13 Dec 2003 03:19:34 -0000	1.164
+++ Make.rules.in	23 Jan 2004 10:17:36 -0000
@@ -99,6 +99,7 @@
 sysconfdir      = @sysconfdir@
 includedir      = @includedir@/wine
 dlldir          = @libdir@/wine
+RPATH		 = @RPATH@
 prog_manext     = 1
 api_manext      = 3w
 conf_manext     = 5
Index: libs/wine/loader.c
===================================================================
RCS file: /home/wine/wine/libs/wine/loader.c,v
retrieving revision 1.16
diff -u -r1.16 loader.c
--- libs/wine/loader.c	2 Jan 2004 21:08:05 -0000	1.16
+++ libs/wine/loader.c	23 Jan 2004 10:17:36 -0000
@@ -41,6 +41,10 @@
 #include "winbase.h"
 #include "wine/library.h"
 
+#ifdef ENABLE_BINRELOC
+extern char *wine_locate (void *symbol);
+#endif
+
 /* argc/argv for the Windows application */
 int __wine_main_argc = 0;
 char **__wine_main_argv = NULL;
@@ -78,11 +82,32 @@
     static const char * const dlldir = DLLDIR;
     int len, count = 0;
     char *p, *path = getenv( "WINEDLLPATH" );
+    char *dynamic_dlldir = NULL;
+    
+#ifdef ENABLE_BINRELOC
+    char *slash;
+    char *relpath = "/wine";
+    
+    /* We want to determine the absolute path of this libwine from the linker mappings, then calculate a dlldir from that
+       For now, we'll assume a relative path of ./wine
+     */
+    dynamic_dlldir = wine_locate("");
+    slash = strrchr( dynamic_dlldir, '/' ); /* get to the prefix */
+    if (slash) {
+	*slash = '\0';
+	p = malloc( strlen(dynamic_dlldir) + strlen(relpath) + 1 );
+	strcpy( p, dynamic_dlldir );
+	strcat( p, relpath );
+	dynamic_dlldir = p;
+    } else dynamic_dlldir = NULL;
+    
+#endif
 
+    
     if (path)
     {
         /* count how many path elements we need */
-        path = strdup(path);
+	path = strdup(path);
         p = path;
         while (*p)
         {
@@ -93,8 +118,8 @@
         }
     }
 
-    dll_paths = malloc( (count+1) * sizeof(*dll_paths) );
-
+    dll_paths = malloc( (count + (dynamic_dlldir ? 1 : 2)) * sizeof(*dll_paths) );
+    
     if (count)
     {
         p = path;
@@ -116,6 +141,11 @@
     {
         if (len > dll_path_maxlen) dll_path_maxlen = len;
         dll_paths[nb_dll_paths++] = dlldir;
+    }
+
+    if (dynamic_dlldir && (len = strlen(dynamic_dlldir))) {
+	if (len > dll_path_maxlen) dll_path_maxlen = len;
+	dll_paths[nb_dll_paths++] = dynamic_dlldir;
     }
 }
 
Index: server/Makefile.in
===================================================================
RCS file: /home/wine/wine/server/Makefile.in,v
retrieving revision 1.48
diff -u -r1.48 Makefile.in
--- server/Makefile.in	10 Dec 2003 04:08:06 -0000	1.48
+++ server/Makefile.in	23 Jan 2004 10:17:36 -0000
@@ -53,7 +53,7 @@
 @MAKE_RULES@
 
 wineserver: $(OBJS)
-	$(CC) -o $(PROGRAMS) $(OBJS) $(LIBWINE) $(LIBUNICODE) $(LIBPORT) $(LDFLAGS) $(LIBS)
+	$(CC) -o $(PROGRAMS) $(OBJS) $(LIBWINE) $(LIBUNICODE) $(LIBPORT) $(LDFLAGS) $(LIBS) $(RPATH)
 
 install:: $(PROGRAMS)
 	$(MKINSTALLDIRS) $(bindir)
Index: loader/Makefile.in
===================================================================
RCS file: /home/wine/wine/loader/Makefile.in,v
retrieving revision 1.14
diff -u -r1.14 Makefile.in
--- loader/Makefile.in	22 Nov 2003 00:08:26 -0000	1.14
+++ loader/Makefile.in	23 Jan 2004 10:17:36 -0000
@@ -24,13 +24,13 @@
 LDEXECFLAGS = @LDEXECFLAGS@
 
 wine-glibc: glibc.o Makefile.in
-	$(CC) -o $@ $(LDEXECFLAGS) glibc.o $(LIBWINE) $(LIBPORT) $(LIBPTHREAD) $(EXTRALIBS) $(LDFLAGS)
+	$(CC) -o $@ $(LDEXECFLAGS) glibc.o $(LIBWINE) $(LIBPORT) $(LIBPTHREAD) $(EXTRALIBS) $(LDFLAGS) $(RPATH)
 
 wine-kthread: $(KTHREAD_OBJS) Makefile.in
-	$(CC) -o $@ $(LDEXECFLAGS) $(KTHREAD_OBJS) $(LIBWINE) $(LIBPORT) $(EXTRALIBS) $(LDFLAGS)
+	$(CC) -o $@ $(LDEXECFLAGS) $(KTHREAD_OBJS) $(LIBWINE) $(LIBPORT) $(EXTRALIBS) $(LDFLAGS) $(RPATH)
 
 wine-pthread: $(PTHREAD_OBJS) Makefile.in
-	$(CC) -o $@ $(LDEXECFLAGS) $(PTHREAD_OBJS) $(LIBWINE) $(LIBPORT) $(LIBPTHREAD) $(EXTRALIBS) $(LDFLAGS)
+	$(CC) -o $@ $(LDEXECFLAGS) $(PTHREAD_OBJS) $(LIBWINE) $(LIBPORT) $(LIBPTHREAD) $(EXTRALIBS) $(LDFLAGS) $(RPATH)
 
 $(MODULE): $(MAIN_BINARY)
 	$(RM) $(MODULE) && $(LN_S) $(MAIN_BINARY) $(MODULE)
--- /dev/null	2003-09-15 14:40:47.000000000 +0100
+++ libs/wine/prefix.c	2004-01-22 20:18:04.000000000 +0000
@@ -0,0 +1,109 @@
+/*
+ * Dynamic DLL path detection support
+ *
+ * Copyright 2004 Mike Hearn
+ * Copyright 2004 Hongli Lai
+ *
+ * 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
+ */
+
+#ifndef _PREFIX_C_
+#define _PREFIX_C_
+
+#include "config.h"
+
+#define __USE_GNU
+#include <features.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+
+#ifdef ENABLE_BINRELOC
+#define __USE_GNU
+#include <dlfcn.h>
+#include <link.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <unistd.h>
+
+
+/**
+ * wine_locate:
+ * symbol: A symbol that belongs to the app/library you want to locate.
+ * Returns: A newly allocated string containing the full path of the
+ *	    app/library that func belongs to, or NULL on error. This
+ *	    string should be freed when not when no longer needed.
+ *
+ * Finds out to which application or library symbol belongs, then locate
+ * the full path of that application or library.
+ * Note that symbol cannot be a pointer to a function. That will not work.
+ *
+ */
+char *
+wine_locate (void *symbol)
+{
+	Dl_info info;
+	char line[5000];
+	FILE *f;
+	char *path;
+
+	if (symbol == NULL) return NULL;
+	if (!dladdr (symbol, &info)) return NULL;
+	
+	f = fopen ("/proc/self/maps", "r");
+	if (f == NULL) return NULL;
+
+	while (fgets (line, sizeof (line), f))
+	{
+		unsigned int start;
+
+		sscanf (line, "%x-", &start);
+
+		if (start == (unsigned int) info.dli_fbase)
+		{
+			char *tmp;
+			size_t len;
+
+			/* Extract the filename; it is always an absolute path */
+			path = strchr (line, '/');
+
+			/* Get rid of the newline */
+			tmp = strrchr (path, '\n');
+			if (tmp) *tmp = 0;
+
+			/* Get rid of "(deleted)" */
+			len = strlen (path);
+			if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0)
+			{
+				tmp = path + len - 10;
+				*tmp = 0;
+			}
+
+			fclose(f);
+			return strdup (path);
+		}
+	}
+
+	fclose (f);
+	/* we should not get here */
+	return NULL;
+}
+
+
+#endif /* ENABLE_BINRELOC */
+
+#endif /* _PREFIX_C */





More information about the wine-patches mailing list