Re: Wine and mmap

From: Brian Fundakowski Feldman <green_at_freebsd.org>
Date: Sun, 12 Sep 2004 10:50:32 -0400
On Sat, Sep 11, 2004 at 07:54:55PM -0400, Anish Mistry wrote:
> On Saturday 11 September 2004 05:26 pm, you wrote:
> > On Sat, Sep 11, 2004 at 05:07:13PM -0400, Anish Mistry wrote:
> > > On Saturday 11 September 2004 02:00 pm, you wrote:
> > > > On Mon, Sep 06, 2004 at 01:49:35AM -0400, Anish Mistry wrote:
> > > > > On Sunday 05 September 2004 05:15 pm, Gerald Pfeifer wrote:
> > > > > > [ John, sorry for the duplicate message; this is the correct one. ]
> > > > > >
> > > > > > On Fri, 27 Aug 2004, John Birrell wrote:
> > > > > > > Anish Mistry <mistry.7_at_osu.edu> has developed a patch to choose
> > > > > > > an appropriate mmap address. He posted it to -current. I haven't
> > > > > > > had time to test it.
> > > > > >
> > > > > > Thanks for the note.  Will you have time to test/commit this before
> > > > > > 5.3?
> > > > > >
> > > > > > Anish, do you have any news on this patch?  (Wine has been broken
> > > > > > for a couple of months now, and it would be great to have at least
> > > > > > 5.3 fixed.)
> > > > >
> > > > > Well I guess this is my lucky day.  Apply the attached patch for
> > > > > vm_mmap to your kernel and patch the August wine sources with the
> > > > > wine-mmap.patch and compile and install wine (be sure to use gmake). 
> > > > > This is working on my dev system with 6-CURRENT as of Saturday night.
> > > > > The wine mmap patch just doesn't reserve the DOS area so DOS programs
> > > > > may not work.  This seems to just work around a side effect of the
> > > > > kernel mmap patch. I still think that the kernel mmap patch has
> > > > > issues so I'm hoping Alan can give us some feedback.
> > > > > Anyway this worked for me, YMMV.
> > > >
> > > > Do these combined work for you, minus any modifications to mmap(2)?  I
> > > > do not feel that the kernel mmap(2) should be modified in this manner,
> > > > that it is a strictly userland problem.
> > >
> > > With only these applied I get old message that wine can't mmap it's
> > > address space.
> >
> > Oh, I'm sorry for not explaining the last step.  You need to set the
> > environment variable "LD_LIBRARY_LOW_ADDR" to some address, like after
> > the first megabyte, or something like that, but before the first "data"
> > address.  Try, say, 1024000.
> Ok, I've tried that, with several different numbers and I either get something 
> like:
> wine: failed to initialize: /usr/local/lib/libwine_unicode.so.1: mmap returned 
> wrong address: wanted 0xc350000, got 0xc3bd000
> or just the normal:
> wine: failed to initialize: /usr/local/lib/wine/ntdll.dll.so: mmap of entire 
> address space failed: Cannot allocate memory
> 
> Any other suggestions?

Oops, can you try this instead?  Can you share with me exactly how you
run this "regression test" with WINE (what program, what .wine/config)?

cvs diff: Diffing .
Index: map_object.c
===================================================================
RCS file: /usr/ncvs/src/libexec/rtld-elf/map_object.c,v
retrieving revision 1.15
diff -u -r1.15 map_object.c
--- map_object.c	3 Aug 2004 08:50:58 -0000	1.15
+++ map_object.c	12 Sep 2004 14:49:16 -0000
_at__at_ -46,12 +46,15 _at__at_
  * Map a shared object into memory.  The "fd" argument is a file descriptor,
  * which must be open on the object and positioned at its beginning.
  * The "path" argument is a pathname that is used only for error messages.
+ * The "low_addr" argument allows for addresses below the normal data
+ * area start to be used for mapping if no space is available above.
  *
  * The return value is a pointer to a newly-allocated Obj_Entry structure
  * for the shared object.  Returns NULL on failure.
  */
 Obj_Entry *
-map_object(int fd, const char *path, const struct stat *sb)
+map_object(int fd, const char *path, const struct stat *sb,
+    unsigned long low_addr)
 {
     Obj_Entry *obj;
     Elf_Ehdr *hdr;
_at__at_ -152,6 +155,14 _at__at_
 
     mapbase = mmap(base_addr, mapsize, convert_prot(segs[0]->p_flags),
       convert_flags(segs[0]->p_flags), fd, base_offset);
+    /*
+     * If requested and out of space for the library, try again below
+     * the normal minimum data segment address.
+     */
+    if (mapbase == (caddr_t) -1 && base_addr == NULL && low_addr != 0)
+	mapbase = mmap((caddr_t) low_addr, mapsize,
+	  convert_prot(segs[0]->p_flags), convert_flags(segs[0]->p_flags),
+	  fd, base_offset);
     if (mapbase == (caddr_t) -1) {
 	_rtld_error("%s: mmap of entire address space failed: %s",
 	  path, strerror(errno));
Index: rtld.c
===================================================================
RCS file: /usr/ncvs/src/libexec/rtld-elf/rtld.c,v
retrieving revision 1.99
diff -u -r1.99 rtld.c
--- rtld.c	4 Aug 2004 19:12:14 -0000	1.99
+++ rtld.c	11 Sep 2004 17:51:00 -0000
_at__at_ -143,6 +143,9 _at__at_
 static char *ld_library_path;	/* Environment variable for search path */
 static char *ld_preload;	/* Environment variable for libraries to
 				   load first */
+static unsigned long ld_library_low_addr;	/* Environment variable for
+						   alternate data area to
+						   try to map into */
 static char *ld_tracing;	/* Called from ldd to print libs */
 static Obj_Entry *obj_list;	/* Head of linked list of shared objects */
 static Obj_Entry **obj_tail;	/* Link field of last object in list */
_at__at_ -287,6 +290,14 _at__at_
 
     ld_bind_now = getenv(LD_ "BIND_NOW");
     if (trust) {
+	const char *env_low_addr = getenv(LD_ "LIBRARY_LOW_ADDR");
+	if (env_low_addr != NULL) {
+	    char *low_addr_endptr = NULL;
+	    errno = 0;
+	    ld_library_low_addr = strtoul(env_low_addr, &low_addr_endptr, 0);
+	    if (*low_addr_endptr != '\0' || errno != 0)
+		ld_library_low_addr = 0;
+	}
 	ld_debug = getenv(LD_ "DEBUG");
 	libmap_disable = getenv(LD_ "LIBMAP_DISABLE") != NULL;
 	ld_library_path = getenv(LD_ "LIBRARY_PATH");
_at__at_ -308,7 +319,7 _at__at_
     if (aux_info[AT_EXECFD] != NULL) {	/* Load the main program. */
 	int fd = aux_info[AT_EXECFD]->a_un.a_val;
 	dbg("loading main program");
-	obj_main = map_object(fd, argv0, NULL);
+	obj_main = map_object(fd, argv0, NULL, 0);
 	close(fd);
 	if (obj_main == NULL)
 	    die();
_at__at_ -1249,7 +1260,7 _at__at_
 
     if (obj == NULL) {	/* First use of this object, so we must map it in */
 	dbg("loading \"%s\"", path);
-	obj = map_object(fd, path, &sb);
+	obj = map_object(fd, path, &sb, ld_library_low_addr);
 	close(fd);
 	if (obj == NULL) {
 	    free(path);
Index: rtld.h
===================================================================
RCS file: /usr/ncvs/src/libexec/rtld-elf/rtld.h,v
retrieving revision 1.34
diff -u -r1.34 rtld.h
--- rtld.h	3 Aug 2004 08:50:58 -0000	1.34
+++ rtld.h	11 Sep 2004 17:41:45 -0000
_at__at_ -209,7 +209,8 _at__at_
 } SymCache;
 
 extern void _rtld_error(const char *, ...) __printflike(1, 2);
-extern Obj_Entry *map_object(int, const char *, const struct stat *);
+extern Obj_Entry *map_object(int, const char *, const struct stat *,
+				unsigned long);
 extern void *xcalloc(size_t);
 extern void *xmalloc(size_t);
 extern char *xstrdup(const char *);
cvs diff: Diffing alpha
cvs diff: Diffing amd64
cvs diff: Diffing arm
cvs diff: Diffing i386
cvs diff: Diffing ia64
cvs diff: Diffing powerpc
cvs diff: Diffing sparc64

-- 
Brian Fundakowski Feldman                           \'[ FreeBSD ]''''''''''\
  <> green_at_FreeBSD.org                               \  The Power to Serve! \
 Opinions expressed are my own.                       \,,,,,,,,,,,,,,,,,,,,,,\
Received on Sun Sep 12 2004 - 12:50:43 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:11 UTC