blob: ac9005b34e65b9eadeac378a72344ce0b68a0740 [file] [log] [blame]
Our cross-compilers and related tooling are executed via ld.so trickery, which
makes /proc/self/exe not point to the right place. If we detect that we're in
that situation in `current_exe()`, we _should_ have `LD_ARGV0_REL` in an env
var. This is the path to the _original_ binary, relative to ld.so.
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index a9cd509..92dd6b9 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -327,12 +327,45 @@ pub fn current_exe() -> io::Result<PathBuf> {
#[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))]
pub fn current_exe() -> io::Result<PathBuf> {
+ let is_ld_so = |p: &crate::path::Path| -> Option<bool> {
+ let parent_dir_name = p.parent()?.file_name()?;
+ if parent_dir_name != OsStr::new("lib") {
+ return Some(false);
+ }
+ // We assume that the `ld.so` path is always valid unicode, since there's... no reason for
+ // it not to be. :)
+ let file_name = p.file_name()?.to_str()?;
+ Some(
+ file_name.starts_with("ld-linux-")
+ && (file_name.ends_with(".so") || file_name.contains(".so.")),
+ )
+ };
+
match crate::fs::read_link("/proc/self/exe") {
Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new(
io::ErrorKind::Other,
"no /proc/self/exe available. Is /proc mounted?",
)),
- other => other,
+ Err(x) => Err(x),
+ Ok(p) => {
+ // Chrome OS-specific: in some configurations, Rust binaries are invoked through
+ // `ld.so`. In these cases, we want to present the user with the path to the Rust
+ // binary that was invoked.
+ //
+ // Because the ld.so wrappers _generally_ don't want to invoke things with absolute
+ // paths, this is _generally_ a path relative to dirname(ld.so).
+ if is_ld_so(&p) == Some(true) {
+ if let Some(relative_to_ld) = crate::env::var_os("LD_ARGV0_REL") {
+ let relative_to_ld = PathBuf::from(relative_to_ld);
+ if relative_to_ld.is_absolute() {
+ return Ok(relative_to_ld);
+ }
+ // safety: is_ld_so checks the parent directory of `p`.
+ return Ok(p.parent().unwrap().join(relative_to_ld));
+ }
+ }
+ Ok(p)
+ }
}
}