Tags: dylib openssl
|So it's been brought to my attention that Scribe's self install of OpenSSL on Mac doesn't actually work in v2.0.x, so the last week I've been looking into what it takes to do that.|
The main issue is that load paths, are by default, absolute and hardcoded. Which works against you when you want a portable install of something. Secondly the OpenSSL .dylib is made of 2 libraries; libssl and libcrypt. And when you dlopen the first (libssl) the system needs to be able to find libcrypt. The link is embedded in the Mach-O image as a LC_LOAD_DYLIB segment. You can see that by issue the command:
otool -l ./libssl.1.0.0.dylib
Part of the output you'll get:
name /usr/lib/libcrypto.1.0.0.dylib (offset 24)
time stamp 2 Thu Jan 1 10:00:02 1970
That absolute path is what is causing the dlopen of libssl to fail. So we need to fix that. And the tool to do it 'install_name_tool', which is provided from Apple. Now I had two problems. Firstly what do you change the path to? And how do you actually get the tool to change the path?
Firstly Apple has several ways of locating shared libraries:
What I wanted is the path to be relative to the executable, so I want:
- @executable_path : relative to the main executable
- @loader_path : relative to the referring binary
- @rpath : relative to any of a list of paths.
But how to call install_name_tool to actually do that? Well to start with I tried:
install_name_tool -change /usr/lib/libcrypto.1.0.0.dylib @executable_path/libcrypto.1.0.0.dylib ./libssl.1.0.0.dylib
Which is actually the right command. But because the new string is longer than the old string the command fails (silently I might add). The trick to getting it to work is to add the linker command:
to the CFLAG variable in the OpenSSL root Makefile. This causes the load segments to have extra padding bytes so that you can change the paths as much as you want later. Now after rebuilding the OpenSSL dylibs you can reissue the install_name_tool command and the link path changes:
MacOS matthew$ otool -l ./libssl.1.0.0.dylib
name @executable_path/libcrypto.1.0.0.dylib (offset 24)
Then I could dlopen 'libssl.1.0.0.dylib' and it would pull in the right libcrypt file (both as sitting in the same folder as the executable).
I'm putting this here so I don't forget how to do this next time. Ha.
Thank you for sharing this solution. I trying to build OpenSSL 1.0.2a, but result libcrypto.1.0.0.dylib depends of /usr/lib/libcrypto.1.0.0.dylib, and libssl.1.0.0.dylib depends of both!
./Configure darwin64-x86_64-cc -shared
And after fix:
otool -L libssl.1.0.0.dylib
/usr/local/ssl/lib/libssl.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
@executable_path/libcrypto.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
otool -L libcrypto.1.0.0.dylib
/usr/local/ssl/lib/libcrypto.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
Have you any ideas how to avoid this situation?
|I'm apparently solve this problem:|
./Configure darwin64-x86_64-cc -shared --openssldir="@rpath"After building app I add result dylibs to Frameworks folder, and modify application binary via install_name_tool:
install_name_tool -change /usr/lib/libcrypto.0.9.8.dylib\
install_name_tool -change /usr/lib/libssl.0.9.8.dylib\