Wine and mmap
Brian Fundakowski Feldman
green at freebsd.org
Sun Sep 12 07:50:43 PDT 2004
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
@@ -46,12 +46,15 @@
* 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;
@@ -152,6 +155,14 @@
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
@@ -143,6 +143,9 @@
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 */
@@ -287,6 +290,14 @@
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");
@@ -308,7 +319,7 @@
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();
@@ -1249,7 +1260,7 @@
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
@@ -209,7 +209,8 @@
} 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. \,,,,,,,,,,,,,,,,,,,,,,\
More information about the freebsd-current
mailing list