| 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/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs |
| index a9cd509..92dd6b9 100644 |
| --- a/src/libstd/sys/unix/os.rs |
| +++ b/src/libstd/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) |
| + } |
| } |
| } |
| |