dyld linking to the wrong dylib

We have encountered a problem where the dyld ends up using the incorrect dylib.

Here's the use case:

Plugin A (a bundle) depends on Dynamic Library A - referenced with "@loader_path". Plugin B (a bundle) depends on Dynamic Library B - referenced with "@loader_path".

Relevant File (binaries) layout is like this:

MyPluginA.bundle/Contents/MacOS/MyPluginA
[depends on @loader_path/../../../MyLibraryA.framework/MyLibrary]
MyLibraryA.framework/MyLibrary
MyPluginB.bundle/Contents/MacOS/MyPluginB
[depends on @loader_path/../../../MyLibraryB.framework/MyLibrary]
MyLibraryB.framework/MyLibrary

This scheme works fine on most machines.

But on some Macs, dyld tries to link MyPluginB with the library in MyLibraryA - which causes the plugin not to be loaded because it cannot find the required symbols in the library.

If we try to print dyld debug information, it shows that MyLibraryB is loaded and then unloaded, without showing any reason. And following that, the MyPluginB tries to look for MyLibraryB's symbols in MyLibraryA.

Can this be due to some kind of caching done by dyld?

Why is the @loader_path not being used to refer to the actual library being used?

Answered by DTS Engineer in 747086022

All the exported symbols however are prepended with a version specific identifier.

Hmmm. Have you consider embedding the version number in the framework name? That seems like the easiest way out of this conundrum, in that the dynamic linker will consider them to be two completely different frameworks.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

What program is loading these plug-ins?

Can this be due to some kind of caching done by dyld?

Probably not. Something else is going on here.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

What program is loading these plug-ins?

This is our own program which is loading the plugins - using bundle APIs.

I’d like to clarify the names in play here. You wrote MyLibraryA.framework/MyLibrary and MyLibraryB.framework/MyLibrary, which would be weird because normally the framework’s main executable name matches the overall framework name. In reality, are these actually both called MyLibrary.framework/MyLibrary? That is, you have two separate copies of the MyLibrary framework?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

That's right - this setup has two separate libraries, both of them have the same binary name "MyLibrary". [The exported symbols are all different because the symbols contain the version "A" or "B" in the symbol names.]

I was surprised that this could even work, but my coworkers told me that they have been using this scheme for some time, and it seems to work fine on most other Macs.

Thanks. Devendra.

You are certainly exploring the edges of what the dynamic linker is capable of handling. Honestly, I’m not sure what’s going on here. Before we go further, I’d like to understand more about why you’ve set things up this way.

Are these two copies of the MyLibrary framework different versions of the same code? Or are they completely different codebases?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Yes, these are different versions of the same basic code, but with some additions, changes, etc.

All the exported symbols however are prepended with a version specific identifier.

For example, MyLibraryA would have A::SomeFunc(), while MyLibraryB would have B::SomeFunc().

Accepted Answer

All the exported symbols however are prepended with a version specific identifier.

Hmmm. Have you consider embedding the version number in the framework name? That seems like the easiest way out of this conundrum, in that the dynamic linker will consider them to be two completely different frameworks.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I think that's what we'll just do - no need to live in the ambiguity!

Thank you Quinn for your help - as always!

Devendra.

dyld linking to the wrong dylib
 
 
Q