haampie / libtree

ldd as a tree
MIT License
2.67k stars 60 forks source link

macOS support #22

Open haampie opened 4 years ago

haampie commented 4 years ago

It would be nice to have the same tool on the mac for locating dylibs.

haampie commented 4 years ago

Turns out parsing mach-o files for mac is incredibly easy. Should not be hard to get this in :)

haampie commented 4 years ago

Just some notes on getting started. macOS has imho a very awkard alternative to rpath and $ORIGIN. If you want to mimick that on the mac, it would go like this:

Suppose your executable lives in usr/bin/app and your dylib in usr/lib/my_lib.dylib; first compile my_lib.dylib with an install name @rpath/my_lib.dylib. Then compile your executable and link against my_lib.dylib s.t. the install name is copied over as a load command in the mach-o file, then add an rpath in app to @loader_path/../lib/ or @executable_path/../lib.

When resolving dependencies of app, first substitute all occurrences of @loader_path and @executable_path in the list of rpaths and the list of to-be-loaded dylibs with the absolute path of app, then loop over the to-be-loaded dylibs, and whenever you see @rpath, try to substitute it with all possible rpaths.

So basically:

  1. read the dylib deps and rpaths of app: dylds = ['@rpath/my_lib.dylib'] rpaths = [@loader_path/../lib/']
  2. substitute all occurrences of @loader_path and @executable_path with the path of app dylds = ['@rpath/my_lib.dylib'] rpaths = [/path/to/usr/bin/../lib/']
  3. for every dyld, if the name starts with/contains @rpath, loop over all the rpaths and substitute, in this case leading to dylds = ['/path/to/usr/bin/../lib/my_lib.dylib'].

So it's awkward because both the executable and the dependent dylib has to be configured to support rpath :|. In any case, it should be straightforward to implement this strategy.

--

Another issue is fat mach-o files that support multiple architectures. Not sure how to handle them