Date: Tue, 26 Feb 2013 22:52:15 +0200 From: Damjan Jovanovic <damjan.jov@gmail.com> To: Konstantin Belousov <kostikbel@gmail.com> Cc: freebsd-hackers@freebsd.org, freebsd-emulation@freebsd.org, Tijl Coosemans <tijl@coosemans.org> Subject: Re: [patch] Wine DLL base address patches Message-ID: <CAJm2B-nRFMsROdBOB5K6fmNrX0O-PV1%2B-g--80UE81Z7hatssA@mail.gmail.com> In-Reply-To: <CAJm2B-kGcAu%2B=-wcHxRdC9M1vjtXk429TPb9RwfmcO78oOtNUg@mail.gmail.com> References: <CAJm2B-mtXqZn0nQH4B9=fYik9gxSM8KAD5QcrLeqDOjXEnYfmg@mail.gmail.com> <20130220154855.GF2598@kib.kiev.ua> <51253759.70508@coosemans.org> <CAJm2B-=_HokZx5kOn0MDFAU8OrEBgFAE-32tBboX9%2BmubwenCQ@mail.gmail.com> <20130221154433.GY2598@kib.kiev.ua> <CAJm2B-kGcAu%2B=-wcHxRdC9M1vjtXk429TPb9RwfmcO78oOtNUg@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Feb 22, 2013 at 5:19 AM, Damjan Jovanovic <damjan.jov@gmail.com> wrote: > On Thu, Feb 21, 2013 at 5:44 PM, Konstantin Belousov > <kostikbel@gmail.com> wrote: >> On Thu, Feb 21, 2013 at 12:57:45AM +0200, Damjan Jovanovic wrote: >>> On Wed, Feb 20, 2013 at 10:51 PM, Tijl Coosemans <tijl@coosemans.org> 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. >>> > >>> >>> All of that occurred to me as well. >>> >>> The problem with that one-line rtld patch is that loading an >>> application will now fail if any of its libraries cannot be loaded at >>> their requested address. >> But this is intended behaviour. Also, the default virtaddr base for the >> shared libraries is 0, so the existing binaries should be not affected. > > In that case, and since failing to load a library only causes the > process to exit when starting up and not when it calls dlopen(), I > approve. > >>> >>> The problem with -Ttext-segment (and isn't it just -Ttext?) is that it >>> doesn't seem to work: the base_vaddr seen by rtld will remain 0, and >>> the address listed in /proc/.../map is different from what it should >>> be. Also run "readelf -l" on a library compiled that way and compare >>> with the output of one run through "prelink --reloc-only", you'll see >>> the lowest VirtAddr and PhysAddr in LOAD headers change only with >>> prelink. I really ported prelink because there was no other choice. >> The -Ttext-segment does work. As indicated by Tijl, you need recent >> binutils. I just verified that ld 2.32.1 obeys -Ttext-segment. >> >> You can also take a look at the default linker script to see how >> -Ttext-segment is used, look for SEGMENT_START("text-segment"). >> > > My apologies: I confused -Ttext which is documented but doesn't work, > with -Ttext-segment which is undocumented in FreeBSD 9.1 and might > work. I would test it further, but -CURRENT doesn't installworld > (ERROR: Required auditdistd user is missing, see /usr/src/UPDATING.) > and I am away until next week. > > Prelink is now in Ports. What I'd recommend is checking if the > binaries are the same, and if not, doing a diff between "readelf -a" > outputs of the prelinked binary vs -Ttext-segmented binary. Also run > this a few times and make sure the address is what's expected: > > #include <windows.h> > #include <stdio.h> > int main(int argc, char **argv) > { > printf("%p\n", LoadLibrary("KERNEL32")); > return 0; > } > > mingw32-gcc hello.c -o hello.exe > wine hello.exe With binutils 2.23.1 (in ports), comparing the output of "ld -Ttext-segment=0x7b800000" and "prelink --reloc-only 0x7b800000" using diffs of "readelf -a" outputs gives this: - 11: 000000007b800000 0 OBJECT LOCAL DEFAULT 6 _GLOBAL_OFFSET_TABLE_ + 11: 0000000000000000 0 OBJECT LOCAL DEFAULT 6 _GLOBAL_OFFSET_TABLE_ in other words, prelink also shifts the global offset table to the requested base address, ld does not. I don't think this matters since it's only ELF segments that get loaded - sections are irrelevant. "objdump -s" finds no differences. So I am happy with all of Tijl's patches, please commit them.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAJm2B-nRFMsROdBOB5K6fmNrX0O-PV1%2B-g--80UE81Z7hatssA>