-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
rustc OSX LC_LOAD_DYLIB paths are broken #28640
Comments
This is actually largely all expected behavior depending on how you look at it! For the first part, it looks like the entry in
So to "fix" this we'd want to pass Do you know if there's a benefit (beyond looking nicer) to doing this? It looks like we wouldn't necessarily get any concrete benefit, but I'm certainly no expert in this area! For the second part, this is actually a little subtle with dylib generation and how we call the linker. Due to the way linkage in Rust work we continually link dylibs downstream instead of just linking them once, so when the Now we also pass the
The clause there about no initialization side effects makes me wary that we'd want to start passing it because a statically linked native library may have side effects (even though no Rust code does). Like the previous point, though, do you know of any concrete benefits of enabling dead stripping of dylibs? Everything will eventually be transitively needed anyway, so I'd expect it to not buy us too much beyond aesthetics of course. |
Point 1Good call checking the So I would suggest using the As for benefits of using this, honestly the aesthetic argument is enough for me, as the current setup looks strange and non-standard. I would argue when in Rome, do as the Romans do in this case. A second reason is again, the dynamic lib calls are only accidentally working, because of the default search paths of Lastly, and this may or may not be a security issue, but again, the dylib's name ( To illustrate this, in a directory, say
Now cp
and you should see that Again, this may or may not be a security issue; it doesn't look like the libraries are signed, so I could in principle alter any symbol's assembly in the tmp Point 2Again, for me the aesthetic argument is sufficient, in addition to if they are serving no purpose, then remove them. As for side-effects, that is definitely a legitimate concern; given this condition, then since the majority of the dead libraries are rust libraries (which as you say have no side-effects), I'd suggest marking them as dead libraries at the very least. It cleans up the binary, and makes it clearer what exactly this binary depends on, say for static analysis tools, someone looking at the binary, someone computing the transitive closure of symbols against a library ;), etc. As for the other two native libraries, which could be side-effecting, I only see:
As for the side-effect concern itself, I believe that warning only applies to loading a library purely for it's initialization side-effect, and no other reason. I'm not sure how common this is, and I suspect not at all. If Of course don't take my word, absolutely test, but I believe all of the above caveats would also apply to the GNU/Linux version of rustc, which has the exact minimal dependencies I listed above. So if the worry is not including That being said, and given the above, I'd suggest the following as a conservative library declaration:
Although again, I really don't think the latter two are needed at all, and only clutter things. |
On a related note, I've also noticed that executables or dynamic libraries import the technically incorrect rust dynamic libraries if you go by those libraries's E.g. compiling the following: fn main (){
println!("{}", 5);
} with
NOTE the stage2 in the install_name path for the rust libs. As stated above,
NOTE the stage1.
|
I think it'd be fine to start passing At the very least we could pass For the For the running against the "wrong libraries", this is actually somewhat intentional behavior in the sense that it's fine and it happens on all other systems as well. |
I would suggest default prefixing with I've noticed #17219 has other issues with the library install name paths, so it might be something you just want to set to It will also prevent a library with the same name if a path exists during execution time from being used, which I mentioned above as well, and after thinking about it more, it is probably pretty serious and can be entirely avoided by using absolute install_names. |
As for the wrong libraries, I can't understand how this is intentional or fine. To be blunt, it's just incorrect. Generated binaries library dependencies should be referencing the exact same name in For example, scanning the dynamic libraries in /usr/local/lib with something like:
The only offenders are rust libraries with non-absolute paths. SImilarly for the binaries in
The only offenders seem to be rust generated binaries. As such I'm not sure what you mean when you say it's fine or happens all other systems as well? On linux you have soname's, so it's a different system, and what's occurring here can't come up. In fact, this is the purpose of |
Currently there's a number of methods by which you can install rust on OSX:
Unfortunately we can't just assume that When I say we're mixing up libraries what I mean is that the ones in And don't get me wrong, it definitely looks like there's something to do here! I'm not sure how much of it should be in the compiler vs as part of an installation, but it sounds like at least some change needs to be made! |
cc @brson |
It seems like this problem affects more than just the libs we distribute, but also all OS X libs that rustc generates. It's baffling that dynamic linkers all seem to expect you to magically know features of your runtime environment from your build environment. Linux has a similar problem that the path to the dynamic linker is embedded in the binary. Dynamic linkers are such a nightmare. |
I think this is fixed. I now get
with rustc installed via rustup. |
@comex can you update with output for the LC_RPATH value? |
Oh, yeah. Actually,
The first one is right, although I'm about to file another issue about the nonsensicality of using a relative path in this instance. The second one is wrong, as |
Triage: i don't have a mac, so I can't re-try this. The original report was in 2015, a couple of comments in 2017. Lots has changed. Can anyone reproduce this? |
In my previous post here (from 2017), I think I pasted the rpath not of a toolchain dylib but of a binary compiled with
Here is the rpath for a dylib from the toolchain:
No However, when compiling a binary: If I only pass
This has a separate report: #50001 (Cannot execute Hello World on macOS with prefer-dynamic) If I pass
The first rpath is similar to before: a relative path from the directory containing the binary to the dylib, even though in this case that means backing all the way out to the root directory. It works but will stop working if the binary is moved. I'm not sure if I ever filed an issue for it, but #58343 seems to be about the same issue on Linux. The second rpath is broken... differently from before. For some reason, rustc has appended |
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: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, becausedyld
's default library search path(s) are:and when interpreting a binary if
dyld
fails to find a library at the specifiedLC_LOAD_DYLIB
path, it then takes the basename of the library with the bad path, e.g.: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: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 therustc
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 outputtingLC_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 inrustc
are:Hence, the minimal set of dynamic libraries required is:
which I believe closely matches the library dependencies for the GNU/Linux
rustc
distribution.The text was updated successfully, but these errors were encountered: