[patch] Wine DLL base address patches

Konstantin Belousov kostikbel at gmail.com
Wed Feb 20 21:16:36 UTC 2013


On Wed, Feb 20, 2013 at 09:51:37PM +0100, Tijl Coosemans wrote:
> On 20-02-2013 16:48, Konstantin Belousov wrote:
> > On Wed, Feb 20, 2013 at 05:29:01PM +0200, Damjan Jovanovic wrote:
> >> Hi
> >>
> >> Wine needs some of its libraries to be loaded at specific base
> >> addresses (https://wiki.freebsd.org/Wine), something FreeBSD currently
> >> lacks.
> >>
> >> I've written a patch to the dynamic loader (/libexec/ld-elf.so.1) that
> >> loads libraries at their preferred base addresses
> >> (http://www.freebsd.org/cgi/query-pr.cgi?pr=176216), as well as a port
> >> of Prelink to FreeBSD which Wine uses to set base addresses
> >> (http://www.freebsd.org/cgi/query-pr.cgi?pr=176283). Both work :-),
> >> the changed dynamic loader doesn't show any problems in a few days of
> >> testing, and prelink works with the --reloc-only option as used by
> >> Wine.
> >>
> >> Please review/test/comment/commit.
> > 
> > Unfortunately, it is not safe. MAP_FIXED overrides any previous mappings
> > which could exist at the specified address.
> 
> I've simplified the rtld patch to a single line. The second patch makes
> Wine use -Ttext-segment linker flag instead of prelink. This requires
> binutils from ports, but it's easier than porting prelink.
> 
> Index: libexec/rtld-elf/map_object.c
> ===================================================================
> --- libexec/rtld-elf/map_object.c	(revision 246986)
> +++ libexec/rtld-elf/map_object.c	(working copy)
> @@ -175,7 +175,7 @@ map_object(int fd, const char *path, const struct
>      base_vaddr = trunc_page(segs[0]->p_vaddr);
>      base_vlimit = round_page(segs[nsegs]->p_vaddr + segs[nsegs]->p_memsz);
>      mapsize = base_vlimit - base_vaddr;
> -    base_addr = hdr->e_type == ET_EXEC ? (caddr_t) base_vaddr : NULL;
> +    base_addr = (caddr_t) base_vaddr;
>  
>      mapbase = mmap(base_addr, mapsize, PROT_NONE, MAP_ANON | MAP_PRIVATE |
>        MAP_NOCORE, -1, 0);

If this is enough for wine, I definitely have no objection.  The typical
dso has zero virtual base for the first segment, so the patch should change
nothing for dso built without special map file.


> Index: Makefile
> ===================================================================
> --- Makefile	(revision 312556)
> +++ Makefile	(working copy)
> @@ -28,7 +28,7 @@
>  LATEST_LINK=	wine-devel
>  CPPFLAGS+=	-I${LOCALBASE}/include
>  LDFLAGS+=	-L${LOCALBASE}/lib
> -USE_GCC=	any
> +USE_GCC=	4.7
>  GNU_CONFIGURE=	yes
>  CONFIGURE_ARGS+=--verbose --disable-tests \
>  		--without-alsa --without-capi --without-dbus \
> Index: files/patch-tools-winegcc-utils.h
> ===================================================================
> --- files/patch-tools-winegcc-utils.h	(revision 0)
> +++ files/patch-tools-winegcc-utils.h	(working copy)
> @@ -0,0 +1,12 @@
> +--- tools/winegcc/utils.h.orig
> ++++ tools/winegcc/utils.h
> +@@ -42,7 +42,8 @@
> + 
> + enum target_platform
> + {
> +-    PLATFORM_UNSPECIFIED, PLATFORM_APPLE, PLATFORM_SOLARIS, PLATFORM_WINDOWS, PLATFORM_CYGWIN
> ++    PLATFORM_UNSPECIFIED, PLATFORM_APPLE, PLATFORM_FREEBSD, PLATFORM_SOLARIS,
> ++    PLATFORM_WINDOWS, PLATFORM_CYGWIN
> + };
> + 
> + void error(const char* s, ...) DECLSPEC_NORETURN;
> Index: files/patch-tools-winegcc-winegcc.c
> ===================================================================
> --- files/patch-tools-winegcc-winegcc.c	(revision 0)
> +++ files/patch-tools-winegcc-winegcc.c	(working copy)
> @@ -0,0 +1,32 @@
> +--- tools/winegcc/winegcc.c.orig
> ++++ tools/winegcc/winegcc.c
> +@@ -172,6 +172,7 @@
> + {
> +     { "macos",   PLATFORM_APPLE },
> +     { "darwin",  PLATFORM_APPLE },
> ++    { "freebsd", PLATFORM_FREEBSD },
> +     { "solaris", PLATFORM_SOLARIS },
> +     { "cygwin",  PLATFORM_CYGWIN },
> +     { "mingw32", PLATFORM_WINDOWS },
> +@@ -232,6 +233,8 @@
> + 
> + #ifdef __APPLE__
> + static enum target_platform build_platform = PLATFORM_APPLE;
> ++#elif defined(__FreeBSD__)
> ++static enum target_platform build_platform = PLATFORM_FREEBSD;
> + #elif defined(__sun)
> + static enum target_platform build_platform = PLATFORM_SOLARIS;
> + #elif defined(__CYGWIN__)
> +@@ -1020,6 +1023,12 @@
> +         if (opts->strip)
> +             strarray_add(link_args, "-Wl,-x");
> +         break;
> ++    case PLATFORM_FREEBSD:
> ++        if (opts->image_base)
> ++        {
> ++            strarray_add(link_args, strmake("-Wl,-Ttext-segment=%s", opts->image_base));
> ++        }
> ++        break;
> +     case PLATFORM_SOLARIS:
> +         {
> +             char *mapfile = get_temp_file( output_name, ".map" );



-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 834 bytes
Desc: not available
URL: <http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20130220/d946a71e/attachment.sig>


More information about the freebsd-hackers mailing list