From dc4e93d4698e8d363ead3580621034c4dd953a3e Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 29 Sep 2021 15:26:44 -0700 Subject: [PATCH] Implement `linux_execfn`, exposing `AT_EXECFN`. --- examples/process.rs | 2 ++ src/imp/libc/process/auxv.rs | 11 +++++++++++ src/imp/libc/process/mod.rs | 4 ++-- src/imp/linux_raw/process/auxv.rs | 11 ++++++++++- src/imp/linux_raw/process/mod.rs | 2 +- src/process/auxv.rs | 17 +++++++++++++++++ src/process/mod.rs | 2 +- 7 files changed, 44 insertions(+), 5 deletions(-) diff --git a/examples/process.rs b/examples/process.rs index e877609e..700b0750 100644 --- a/examples/process.rs +++ b/examples/process.rs @@ -80,5 +80,7 @@ fn main() -> io::Result<()> { target_os = "openbsd", )))] println!("Rttime Limit: {:?}", getrlimit(Resource::Rttime)); + #[cfg(any(target_os = "android", target_os = "linux"))] + println!("Execfn: {:?}", linux_execfn()); Ok(()) } diff --git a/src/imp/libc/process/auxv.rs b/src/imp/libc/process/auxv.rs index 12781bb7..c87a6b6d 100644 --- a/src/imp/libc/process/auxv.rs +++ b/src/imp/libc/process/auxv.rs @@ -1,3 +1,8 @@ +#[cfg(any(target_os = "android", target_os = "linux"))] +use libc::c_char; +#[cfg(any(target_os = "android", target_os = "linux"))] +use std::ffi::CStr; + #[inline] pub(crate) fn page_size() -> usize { unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize } @@ -12,3 +17,9 @@ pub(crate) fn linux_hwcap() -> (usize, usize) { (hwcap, hwcap2) } } + +#[cfg(any(target_os = "android", target_os = "linux"))] +#[inline] +pub(crate) fn linux_execfn() -> &'static CStr { + unsafe { CStr::from_ptr(libc::getauxval(libc::AT_EXECFN) as *const c_char) } +} diff --git a/src/imp/libc/process/mod.rs b/src/imp/libc/process/mod.rs index c59c6359..c650a692 100644 --- a/src/imp/libc/process/mod.rs +++ b/src/imp/libc/process/mod.rs @@ -1,9 +1,9 @@ mod auxv; mod types; -#[cfg(any(target_os = "android", target_os = "linux"))] -pub(crate) use auxv::linux_hwcap; pub(crate) use auxv::page_size; +#[cfg(any(target_os = "android", target_os = "linux"))] +pub(crate) use auxv::{linux_execfn, linux_hwcap}; #[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] pub use types::Resource; #[cfg(any(target_os = "android", target_os = "linux"))] diff --git a/src/imp/linux_raw/process/auxv.rs b/src/imp/linux_raw/process/auxv.rs index b147f640..0327ae2a 100644 --- a/src/imp/linux_raw/process/auxv.rs +++ b/src/imp/linux_raw/process/auxv.rs @@ -6,13 +6,14 @@ #![allow(unsafe_code)] use super::super::elf::Elf_Phdr; -use linux_raw_sys::general::{AT_HWCAP, AT_NULL, AT_PAGESZ, AT_PHDR, AT_PHENT, AT_PHNUM}; +use linux_raw_sys::general::{AT_HWCAP, AT_NULL, AT_PAGESZ, AT_PHDR, AT_PHENT, AT_PHNUM, AT_EXECFN}; use linux_raw_sys::v5_4::general::{AT_HWCAP2, AT_SYSINFO_EHDR}; use std::mem::size_of; use std::os::raw::c_char; #[cfg(target_env = "gnu")] use std::os::raw::c_int; use std::slice; +use std::ffi::CStr; #[inline] pub(crate) fn page_size() -> usize { @@ -25,6 +26,11 @@ pub(crate) fn linux_hwcap() -> (usize, usize) { (auxv.hwcap, auxv.hwcap2) } +#[inline] +pub(crate) fn linux_execfn() -> &'static CStr { + unsafe { CStr::from_ptr(auxv().execfn as *const c_char) } +} + #[inline] pub(in super::super) fn exe_phdrs() -> &'static [Elf_Phdr] { unsafe { slice::from_raw_parts(AUXV.phdr as *const Elf_Phdr, AUXV.phnum) } @@ -50,6 +56,7 @@ struct Auxv { sysinfo_ehdr: usize, phdr: usize, phnum: usize, + execfn: usize, } /// Data obtained from the kernel-provided auxv array. This is initialized at @@ -61,6 +68,7 @@ static mut AUXV: Auxv = Auxv { sysinfo_ehdr: 0, phdr: 0, phnum: 0, + execfn: 0, }; /// GLIBC passes argc, argv, and envp to functions in .init_array, as a @@ -121,6 +129,7 @@ unsafe fn init_from_auxp(mut auxp: *const Elf_auxv_t) { AT_PHDR => AUXV.phdr = a_val, AT_PHNUM => AUXV.phnum = a_val, AT_PHENT => assert_eq!(a_val, size_of::()), + AT_EXECFN => AUXV.execfn = a_val, AT_NULL => break, _ => (), } diff --git a/src/imp/linux_raw/process/mod.rs b/src/imp/linux_raw/process/mod.rs index 196e45af..6fd65d2d 100644 --- a/src/imp/linux_raw/process/mod.rs +++ b/src/imp/linux_raw/process/mod.rs @@ -2,7 +2,7 @@ mod auxv; mod types; pub(super) use auxv::{exe_phdrs, sysinfo_ehdr}; -pub(crate) use auxv::{linux_hwcap, page_size}; +pub(crate) use auxv::{linux_hwcap, page_size, linux_execfn}; pub use types::{ MembarrierCommand, RawCpuid, RawGid, RawPid, RawUid, RawUname, Resource, EXIT_FAILURE, EXIT_SIGNALED_SIGABRT, EXIT_SUCCESS, diff --git a/src/process/auxv.rs b/src/process/auxv.rs index e14f7b4c..bfd20bf8 100644 --- a/src/process/auxv.rs +++ b/src/process/auxv.rs @@ -1,4 +1,6 @@ use crate::imp; +#[cfg(any(linux_raw, all(libc, any(target_os = "android", target_os = "linux"))))] +use std::ffi::CStr; /// `getpagesize()`—Returns the process' page size. #[inline] @@ -22,3 +24,18 @@ pub fn page_size() -> usize { pub fn linux_hwcap() -> (usize, usize) { imp::process::linux_hwcap() } + +/// `getauxval(AT_EXECFN)`—Returns the Linux "execfn" string. +/// +/// Return the string that Linux has recorded as the filesystem path to the +/// executable. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man3/getauxval.3.html +#[cfg(any(linux_raw, all(libc, any(target_os = "android", target_os = "linux"))))] +#[inline] +pub fn linux_execfn() -> &'static CStr { + imp::process::linux_execfn() +} diff --git a/src/process/mod.rs b/src/process/mod.rs index d4f6ac0c..181d52db 100644 --- a/src/process/mod.rs +++ b/src/process/mod.rs @@ -19,7 +19,7 @@ mod sched; mod uname; #[cfg(any(linux_raw, all(libc, any(target_os = "android", target_os = "linux"))))] -pub use auxv::linux_hwcap; +pub use auxv::{linux_hwcap, linux_execfn}; pub use auxv::page_size; #[cfg(not(target_os = "wasi"))] pub use chdir::chdir;