https://bugs.winehq.org/show_bug.cgi?id=51539
Bug ID: 51539 Summary: "server: Get the process entry point from the exe image info" breaks running if exe is loaded at a non-default address Product: Wine Version: unspecified Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: ntdll Assignee: wine-bugs@winehq.org Reporter: martin@martin.st CC: jacek@codeweavers.com, julliard@winehq.org Regression SHA1: a3c92a02cc7014cfdb1f90f1d070037868067097 Distribution: ---
Since "server: Get the process entry point from the exe image info", a3c92a02cc7014cfdb1f90f1d070037868067097, starting a process fails if the exe image ends up loaded at a non-default address.
This can be easily triggered e.g. with this patch:
---8<--- diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 8ceba611875..2515d73ee9e 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -2405,8 +2405,10 @@ static NTSTATUS virtual_map_image( HANDLE mapping, ACCESS_MASK access, void **ad base = wine_server_get_ptr( image_info->base ); if ((ULONG_PTR)base != image_info->base) base = NULL;
+#if 0 if ((char *)base >= (char *)address_space_start) /* make sure the DOS area remains free */ status = map_view( &view, base, size, alloc_type & MEM_TOP_DOWN, vprot, zero_bits_64 ); +#endif
if (status) status = map_view( &view, NULL, size, alloc_type & MEM_TOP_DOWN, vprot, zero_bits_64 ); if (status) goto done; ---8<---
This seems to happen a lot on 32 bit arm builds (on Ubuntu 20.04), when the expected low addresses used as default load address of 0x400000 conflicts with e.g. /home/martin/wine32/share/wine/nls/sortdefault.nls which is mapped at 0x00230000-0x00564000.
https://bugs.winehq.org/show_bug.cgi?id=51539
--- Comment #1 from Martin Storsjö martin@martin.st --- I primarily debugged this on arm, but it does seem like the same modification (forcing loading modules at an address different from the default image base) breaks things on x86 too.
In this case, it seems like perform_relocations() gets an address different from where it actually ends up mapped. On x86_64, perform_relocations() gets both module and nt->OptionalHeader.ImageBase equal to the original image base address, while on ARM they end up with an entirely different address (not the original image base, nor the address where it actually ended up mapped).
https://bugs.winehq.org/show_bug.cgi?id=51539
--- Comment #2 from Martin Storsjö martin@martin.st --- Also to add more context...
Before 28fe84da45bea7de56539b50eac8ebcec54342de, "ntdll: Load the main image from the Unix side.", this was easy to fix by just using the old logic of "entry = (char *)peb->ImageBaseAddress + nt->OptionalHeader.AddressOfEntryPoint;" again, but after that, it seems like the actual address where the main exe was loaded is lost somehow, without doing the relevant relocations.
https://bugs.winehq.org/show_bug.cgi?id=51539
Austin English austinenglish@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Version|unspecified |6.2 Keywords| |regression
https://bugs.winehq.org/show_bug.cgi?id=51539
--- Comment #3 from Alexandre Julliard julliard@winehq.org --- I'm not sure how you are reproducing this since we should refuse to map executables to a different address, but in any case b08b4b8213949ecfc8eb449b5676552669ec3211 will hopefully help.
https://bugs.winehq.org/show_bug.cgi?id=51539
--- Comment #4 from Martin Storsjö martin@martin.st --- (In reply to Alexandre Julliard from comment #3)
I'm not sure how you are reproducing this since we should refuse to map executables to a different address
Oh, I see - I missed that this was an intended side effect of 28fe84da45bea7de56539b50eac8ebcec54342de (ntdll: Load the main image from the Unix side.) - previously this was implicitly allowed via the "if (status == STATUS_IMAGE_NOT_AT_BASE) status = STATUS_SUCCESS;" line, but now it errors out indeed.
I did most of my testing around these two commits, and you're right that I can't even get that far on any newer version, if unable to map the executable in the right spot.
So before a3c92a02cc7014cfdb1f90f1d070037868067097 (server: Get the process entry point from the exe image info.), mapping the executable at any address worked just fine, and after 28fe84da45bea7de56539b50eac8ebcec54342de it's explicitly disallowed.
but in any case b08b4b8213949ecfc8eb449b5676552669ec3211 will hopefully help.
Thanks - although as mapping the executable at a different address isn't allowed any longer I guess this doesn't really change anything...
I guess I should just try to implement the preloader for arm instead, to put it on par with the other architectures, which hopefully would let it map things at the desired addresses?
https://bugs.winehq.org/show_bug.cgi?id=51539
--- Comment #5 from Alexandre Julliard julliard@winehq.org --- Porting the preloader to ARM would definitely be a good idea.
The reason we now fail to load is precisely so that we can try again through start.exe, which will set WINEPRELOADRESERVE to have the preloader make sure that the memory range is free.
https://bugs.winehq.org/show_bug.cgi?id=51539
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Resolution|--- |FIXED Fixed by SHA1| |b08b4b8213949ecfc8eb449b567 | |6552669ec3211 Status|UNCONFIRMED |RESOLVED
--- Comment #6 from Alexandre Julliard julliard@winehq.org --- Marking fixed by b08b4b8213949ecfc8eb449b5676552669ec3211, even if the error should no longer happen thanks to the preloader.
https://bugs.winehq.org/show_bug.cgi?id=51539
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #7 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 7.0-rc2.