Skip to content
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

New load commands: LC_DYLD_EXPORTS_TRIE and LC_DYLD_CHAINED_FIXUPS #261

Closed
woodruffw opened this issue Sep 29, 2020 · 2 comments
Closed

Comments

@woodruffw
Copy link
Member

Apple snuck these in on us at some point. They're 0x33 and 0x34 (masked with LC_REQ_DYLD), respectively, and should be mapped to LinkeditDataCommand

#define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD) /* used with linkedit_data_command, payload is trie */
#define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD) /* used with linkedit_data_command */
ilammy added a commit to ilammy/openssl-apple that referenced this issue Nov 22, 2020
arm64e builds are included to test the pointer authentication feature of
iOS devices. We have to include it in binary CLOpenSSL builds so that
upstream users of CLOpenSSL might enable it themselves for testing.

However, inclusion of this architecture slice causes issues with
CocoaPods handling of vendored binary frameworks. arm64e builds include
a certain linker command -- LC_DYLD_CHAINED_FIXUPS (0x80000034) -- which
confuses CocoaPods' detector of dynamic binaries, making it believe that
the vendored framework in a static one, not dynamic. This in turn causes
issues when using CLOpenSSL as CocoaPods refuses to link "static" binary
without "static_framework = true".

This is a know issue in CocoaPods, stemming from the missing features in
Homebrew's Mach-O parser [1][2].

[1]: Homebrew/brew#7857
[2]: Homebrew/ruby-macho#261

There is nothing we can do about it right now, other than disable
"arm64e" builds for the time being. This does not affect deployment to
App Store, but will break dependencies of CLOpenSSL which expect this
architecture to be present. The dependencies will have to disable arm64e
in their projects, if they have it explicitly enabled. (Considering that
CocoaPods packaging of CLOpenSSL was never in good shape, the actual
impact of this change should be minimal.)
ilammy pushed a commit to cossacklabs/openssl-apple that referenced this issue Nov 22, 2020
* Automatically enable Apple Silicon support

Since Xcode 12.2 (stable) is out, Apple Silicon support can be enabled
automatically there. Check the version of the command-line tools and
set APPLE_SILICON_SUPPORT value automatically if possible.

After a while, once Xcode 12.0.1 and earlier are not longer supported
and widely used, this variable can be removed completely. Right now
it won't be really necessary to set it explicitly, unless you want
something strange.

* Revert "Use static frameworks for CocoaPods (#13)"

This reverts commit d21e3b7.

We can't just migrate CLOpenSSL to static frameworks as that requires
all upstream dependencies to migrate to static frameworks too, and
that breaks builds left, right, and center.

Instead, we have figured out what has been breaking dynamic linkage
with CocoaPods, and now we're coming back to using dynamic linkage.

If static versions of CLOpenSSL are published, they will be published
in a separate podspec.

* Drop arm64e to work around CocoaPods issues

arm64e builds are included to test the pointer authentication feature of
iOS devices. We have to include it in binary CLOpenSSL builds so that
upstream users of CLOpenSSL might enable it themselves for testing.

However, inclusion of this architecture slice causes issues with
CocoaPods handling of vendored binary frameworks. arm64e builds include
a certain linker command -- LC_DYLD_CHAINED_FIXUPS (0x80000034) -- which
confuses CocoaPods' detector of dynamic binaries, making it believe that
the vendored framework in a static one, not dynamic. This in turn causes
issues when using CLOpenSSL as CocoaPods refuses to link "static" binary
without "static_framework = true".

This is a know issue in CocoaPods, stemming from the missing features in
Homebrew's Mach-O parser [1][2].

[1]: Homebrew/brew#7857
[2]: Homebrew/ruby-macho#261

There is nothing we can do about it right now, other than disable
"arm64e" builds for the time being. This does not affect deployment to
App Store, but will break dependencies of CLOpenSSL which expect this
architecture to be present. The dependencies will have to disable arm64e
in their projects, if they have it explicitly enabled. (Considering that
CocoaPods packaging of CLOpenSSL was never in good shape, the actual
impact of this change should be minimal.)

* Set install name during linkage

Instead of using "install_name_tool" to fix the LC_ID_DYLIB value of the
dylib, pass the "-install_name" parameter to the linker directly. This
doesn't change anything in the resulting binary but looks a bit cleaner.

* Use ABI-correct install name on macOS

On macOS -- contrary to iOS, watchOS, and tvOS -- it is customary for
frameworks to provide additional internal structure which helps with
binary compatibility. For example, on iOS/watchOS/tvOS a framework
typically has flat structure:

    openssl.framework
    ├── Headers
    ├── Info.plist
    └── openssl

while on macOS it's a bit more involved:

    frameworks/MacOSX/openssl.framework
    ├── Headers -> Versions/Current/Headers
    ├── Resources -> Versions/Current/Resources
    ├── Versions
    │   ├── A
    │   └── Current -> A
    └── openssl -> Versions/Current/openssl

Note that the top-level files are actually symlinks to the
"Versions/Current" which in turn is a symlink to the "A" version,
which actually contains the framework content:

    openssl.framework/Versions/A
    ├── Headers
    ├── Resources
    │   └── Info.plist
    └── openssl

Currently, the 'install name' of all "openssl" binaries is set to
"@rpath/openssl.framework/openssl", which makes the linked binaries
remember and use this path when loading OpenSSL. On macOS this will
involve two additional symlink resolutions. Another thing here is that
if we will need to introduce a different version of OpenSSL framework
on macOS, existing applications will still look up the current one,
instead of using the A version that they should.

Update the install name computation to use

    @rpath/openssl.framework/openssl

for iOS, watchOS, tvOS while using more explicit

    @rpath/openssl.framework/Versions/A/openssl

for macOS.

This is how Apple's system frameworks do it. Though they have a pressing
issue of supporting multiple possible ABIs and it's not that important
in our case, you never know when this turns out to be necessary or
whether some weird tool might choke on the symlinks.
@BrewTestBot
Copy link
Member

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@woodruffw
Copy link
Member Author

#264.

@Homebrew Homebrew locked as resolved and limited conversation to collaborators Jan 15, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants