Skip to content

cygwin: give cygperl*.dll an explicit base address #22853

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 24, 2025

Conversation

tonycoz
Copy link
Contributor

@tonycoz tonycoz commented Dec 9, 2024

Cygwin's fork emulation doesn't handle overlapping addresses between different DLLs, since it tries to lay out the address space of the child process to match the parent process, but if there's an address conflict between DLLs, Windows may load those DLLs at different addresses.

To avoid having to manually assign addresses to each DLL, since around 5.10 we've used --enable-auto-image-base to assign load addresses for cygperl*.dll and dynamic extension DLLs and this has mostly worked well, but as perl has gotten larger and cygperl*.dll has grown, we've had two cases where there's overlap between the address space for cygperl*.dll and some extension DLL, see #22695 and #22104.

This problem occurs because:

  • cygperl*.dll is large, and with -DDEBUGGING or some other option that increases binary size, even large, occupying more than one of the "slots" that the automatic image base code in ld can assign the DLL to.
  • unlike the extension DLLs, the name of cygperl*.dll changes with every release, so we roll the dice each release on whether there will be a conflict between cygperl*.dll and some other DLL.

Previously I've added an entry to perldelta and updated the CI workflow to workaround the conflict, this change should prevent that particular conflict.

The addresses I've chosen here are "just" (for large values of "just") below the base address range used by automatic address space selection.

For 64-bit this was done by inspection, examing the output of "rebase -i" on the extension DLLs and looking at the source of ld, in particular:

https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=ld/emultempl/pep.em;h=00c4ea9e15a765c29b15b621f53d6bfcb499e5ed;hb=HEAD#l144

Note cygwin builds set move_default_addr_high=1 if you read that code.

For 32-bit I just looked at the source:

https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=ld/emultempl/pe.em;h=52f59b8b#l173

since I don't have a 32-bit cygwin install any more, since cygwin no longer ship it and it commonly had the fork address conflicts discussed above.

I would have liked to make the load address configurable via -Dcygperl_base or similar, but I didn't see a way to get the base address to pass from Configure through to Makefile.SH.

Fixes #22695

Also reverts the workflow workaround added for the previous release.


  • This set of changes requires a perldelta entry, and it is included.

@jkeenan
Copy link
Contributor

jkeenan commented Mar 19, 2025

Is there anyone running Cygwin who can review this pull request? Thanks.

@sisyphus
Copy link
Contributor

sisyphus commented Mar 20, 2025

I build perl on Cygwin regularly (at every devel release), so I gave this PR a run with blead at commit 1fb05c6.
But it built a perl executable and dll that named themselves as being version 5.41.7. (I expected 5.41.10.)
The config args I used were:

-des -Dusethreads -Dusemultiplicity -Dprefix=/cygdrive/d/cygperl-5.41.91-d -Dlibpth=/lib/gcc/x86_64-pc-cygwin/11 -Uversiononly -Dusedevel

And @INC is confusingly:

$ perl -le 'print for @INC;'
/cygdrive/d/cygperl-5.41.91-d/lib/site_perl/5.41.7/cygwin-thread-multi
/cygdrive/d/cygperl-5.41.91-d/lib/site_perl/5.41.7
/cygdrive/d/cygperl-5.41.91-d/lib/5.41.7/cygwin-thread-multi
/cygdrive/d/cygperl-5.41.91-d/lib/5.41.7

I feel that this PR is not yet ready for merging.

Other than that, everything seems pretty normal.
As per usual, I get a couple of failing tests:

Failed 2 tests out of 2737, 99.93% okay.
        ../dist/Net-Ping/t/450_service.t
        ../lib/File/Copy.t

I normally do -Duselongdouble and -Dusequadmath builds, too - but I don't see much point in trying them at the moment.

tonycoz added 3 commits April 24, 2025 17:55
Cygwin's fork emulation doesn't handle overlapping addresses
between different DLLs, since it tries to lay out the address space
of the child process to match the parent process, but if there's an
address conflict between DLLs, Windows may load those DLLs at
different addresses.

To avoid having to manually assign addresses to each DLL, since
around 5.10 we've used --enable-auto-image-base to assign load
addresses for cygperl*.dll and dynamic extension DLLs and this
has mostly worked well, but as perl has gotten larger and
cygperl*.dll has grown, we've had two cases where there's overlap
between the address space for cygperl*.dll and some extension
DLL, see Perl#22695 and Perl#22104.

This problem occurs because:

- cygperl*.dll is large, and with -DDEBUGGING or some other option
  that increases binary size, even large, occupying more than one of
  the "slots" that the automatic image base code in ld can assign
  the DLL to.

- unlike the extension DLLs, the name of cygperl*.dll changes with
  every release, so we roll the dice each release on whether there
  will be a conflict between cygperl*.dll and some other DLL.

Previously I've added an entry to perldelta and updated the CI
workflow to workaround the conflict, this change should prevent
that particular conflict.

The addresses I've chosen here are "just" (for large values of
"just") below the base address range used by automatic address
space selection.

For 64-bit this was done by inspection, examing the output of
"rebase -i" on the extension DLLs and looking at the source of ld,
in particular:

  https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=ld/emultempl/pep.em;h=00c4ea9e15a765c29b15b621f53d6bfcb499e5ed;hb=HEAD#l144

Note cygwin builds set move_default_addr_high=1 if you read that code.

For 32-bit I just looked at the source:

  https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=ld/emultempl/pe.em;h=52f59b8b#l173

since I don't have a 32-bit cygwin install any more, since cygwin
no longer ship it and it commonly had the fork address conflicts
discussed above.

I would have liked to make the load address configurable via
-Dcygperl_base or similar, but I didn't see a way to get the
base address to pass from Configure through to Makefile.SH.

Fixes Perl#22695
@haarg haarg force-pushed the 22695-cygwin-less-dll-conflict branch from 4f3b845 to a2cf1d5 Compare April 24, 2025 15:55
@haarg haarg merged commit 3c2aa9f into Perl:blead Apr 24, 2025
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

cygwin DLL address conflict with version 5.41.6
4 participants