Wine and mmap
Brian Fundakowski Feldman
green at freebsd.org
Sat Sep 11 11:00:16 PDT 2004
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.
Index: lib/libpthread/thread/thr_stack.c
===================================================================
RCS file: /usr/ncvs/src/lib/libpthread/thread/thr_stack.c,v
retrieving revision 1.8
diff -u -r1.8 thr_stack.c
--- lib/libpthread/thread/thr_stack.c 14 Sep 2003 22:39:44 -0000 1.8
+++ lib/libpthread/thread/thr_stack.c 11 Sep 2004 17:17:32 -0000
@@ -61,7 +61,7 @@
* Base address of the last stack allocated (including its red zone, if
* there is one). Stacks are allocated contiguously, starting beyond the
* top of the main stack. When a new stack is created, a red zone is
- * typically created (actually, the red zone is simply left unmapped) above
+ * typically created (actually, the red zone is mapped with PROT_NONE) above
* the top of the stack, such that the stack will not be able to grow all
* the way to the bottom of the next stack. This isn't fool-proof. It is
* possible for a stack to grow by a large amount, such that it grows into
@@ -134,6 +134,7 @@
kse_critical_t crit;
size_t stacksize;
size_t guardsize;
+ char *stackaddr;
/*
* Round up stack size to nearest multiple of _thr_page_size so
@@ -194,7 +195,7 @@
_thr_guard_default;
/* Allocate a new stack. */
- attr->stackaddr_attr = last_stack - stacksize;
+ stackaddr = last_stack - stacksize - guardsize;
/*
* Even if stack allocation fails, we don't want to try to
@@ -209,11 +210,20 @@
KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
_kse_critical_leave(crit);
- /* Map the stack, but not the guard page: */
- if ((attr->stackaddr_attr = mmap(attr->stackaddr_attr,
- stacksize, PROT_READ | PROT_WRITE, MAP_STACK,
- -1, 0)) == MAP_FAILED)
- attr->stackaddr_attr = NULL;
+ /* Map the stack and guard page together, and split guard
+ page from allocated space: */
+ if ((stackaddr = mmap(stackaddr, stacksize+guardsize,
+ PROT_READ | PROT_WRITE, MAP_STACK,
+ -1, 0)) != MAP_FAILED &&
+ (guardsize == 0 ||
+ mprotect(stackaddr, guardsize, PROT_NONE) == 0)) {
+ stackaddr += guardsize;
+ } else {
+ if (stackaddr != MAP_FAILED)
+ munmap(stackaddr, stacksize + guardsize);
+ stackaddr = NULL;
+ }
+ attr->stackaddr_attr = stackaddr;
}
if (attr->stackaddr_attr != NULL)
return (0);
Index: libexec/rtld-elf/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
--- libexec/rtld-elf/map_object.c 3 Aug 2004 08:50:58 -0000 1.15
+++ libexec/rtld-elf/map_object.c 11 Sep 2004 17:41:28 -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,15 @@
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) {
+ base_addr = (caddr_t) low_addr;
+ mapbase = mmap(base_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: libexec/rtld-elf/rtld.c
===================================================================
RCS file: /usr/ncvs/src/libexec/rtld-elf/rtld.c,v
retrieving revision 1.99
diff -u -r1.99 rtld.c
--- libexec/rtld-elf/rtld.c 4 Aug 2004 19:12:14 -0000 1.99
+++ libexec/rtld-elf/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: libexec/rtld-elf/rtld.h
===================================================================
RCS file: /usr/ncvs/src/libexec/rtld-elf/rtld.h,v
retrieving revision 1.34
diff -u -r1.34 rtld.h
--- libexec/rtld-elf/rtld.h 3 Aug 2004 08:50:58 -0000 1.34
+++ libexec/rtld-elf/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 *);
--
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