Skip to content

rustc OSX LC_LOAD_DYLIB paths are broken #28640

Open
@m4b

Description

@m4b

I've noticed that the /usr/local/bin/rustc has several dylib load commands for various rust libraries which have incorrect/nonexistent paths prefixed to them.

There are two points I'd like to bring up, the first being much more serious.

Bad Paths

In my setup various tools all report that /usr/local/bin/rustc loads/requires the following dynamic libraries:

x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/librustc_driver-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/librustc_trans-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/librustc_privacy-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/librustc_borrowck-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/librustc_resolve-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/librustc_lint-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/librustc_typeck-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/librustc-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libflate-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/librustc_data_structures-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libarena-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libgraphviz-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libgetopts-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/librbml-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/librustc_back-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libsyntax-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libserialize-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libterm-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/liblog-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libfmt_macros-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/librustc_llvm-198068b3.dylib
x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libstd-198068b3.dylib
/usr/lib/libSystem.B.dylib
/usr/lib/libedit.3.dylib
/usr/lib/libc++.1.dylib

However, most of these (the rust libs) appear to be an artifact from the initial compilation build (on a side note, non-absolute paths in OSX typically should have an @rpath or @install_path prefixed to the path, etc.) . If you run:

DYLD_PRINT_LIBRARIES=true /usr/local/bin/rustc --version

you will notice all of the libraries actually get bound to /usr/local/lib/<name of dylib>. This only accidentally works, because dyld's default library search path(s) are:

$(HOME)/lib:/usr/local/lib:/lib:/usr/lib

and when interpreting a binary if dyld fails to find a library at the specified LC_LOAD_DYLIB path, it then takes the basename of the library with the bad path, e.g.:

x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libstd-198068b3.dylib -> libstd-198068b3.dylib

and looks for that dynamic library in the default path list; in our case it just so happens the libraries were installed to /usr/local/lib, so it finds them and runs as normal. If they were installed to a nonstandard path, /usr/local/bin/rustc would fail to run with something like:

dyld: Library not loaded: x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libstd-198068b3.dylib
  Referenced from: /usr/local/bin/rustc
  Reason: image not found
Trace/BPT trap: 5

You can verify this by moving /usr/local/lib/libstd-198068b3.dylib somewhere else (don't do this unless you know how to undue it), or by manually editing the basename of the imported libraries in the rustc binary (don't do this either unless you know how to undo it); either case will fail with an error similar to the above.

Therefore /usr/local/bin/rustc is only accidentally running correctly on OSX as of this writing.

If /usr/local/lib/ is the preferred location for rust libraries (and why not), then I highly suggest outputting LC_LOAD_DYLIB paths like /usr/local/lib/libstd-198068b3.dylib, etc.

If you want this dynamic or configurable, then I suggest using @rpath although this adds more complexity; more information can be found at the Apple official documentation.

Too Many Libraries

This is a less serious issue, but I believe most of the libraries printed above are actually not required to run rustc on OSX. Please correct me if I'm wrong, but it looks like the only imports in rustc are:

2038 __ZN4main20h62bf81b281987584efdE (8) ~> x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/librustc_driver-198068b3.dylib
2040 __ZN2rt10lang_start20hd654f015947477d622wE (8) ~> x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libstd-198068b3.dylib
2048 _rust_stack_exhausted (8) ~> x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libstd-198068b3.dylib
2050 _exit (8) ~> /usr/lib/libSystem.B.dylib
2028 dyld_stub_binder (8) -> /usr/lib/libSystem.B.dylib

Hence, the minimal set of dynamic libraries required is:

/usr/local/lib/librustc_driver-198068b3.dylib
/usr/local/lib/libstd-198068b3.dylib
/usr/lib/libSystem.B.dylib

which I believe closely matches the library dependencies for the GNU/Linux rustc distribution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-linkageArea: linking into static, shared libraries and binariesC-bugCategory: This is a bug.O-macosOperating system: macOS

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions