Skip to content

Commit

Permalink
Depend on glibc 2.17 and use getauxval unconditionally.
Browse files Browse the repository at this point in the history
  • Loading branch information
sunfishcode committed May 17, 2024
1 parent b188a58 commit d8c14ad
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 85 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,14 @@ oldest Linux version supported by:
The specifics of this policy may change in the future, but we intend it to
always reflect “very old” Linux versions.

## Minimum glibc Version

On glibc platforms, rustix requires at least glibc 2.17. This is at most the
oldest glibc version supported by:
- [any current Rust target]
The specifics of this policy may change in the future, but we intend it to
always reflect “very old” glibc versions.

[MSRV]: #minimum-supported-rust-version-msrv
[Rust 1.63]: https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html
[any current Rust target]: https://doc.rust-lang.org/nightly/rustc/platform-support.html
Expand Down
27 changes: 8 additions & 19 deletions src/backend/libc/param/auxv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@ use crate::backend::c;
))]
use crate::ffi::CStr;

// `getauxval` wasn't supported in glibc until 2.16.
#[cfg(any(
all(target_os = "android", target_pointer_width = "64"),
target_os = "linux",
))]
weak!(fn getauxval(c::c_ulong) -> *mut c::c_void);
extern "C" {
fn getauxval(type_: c::c_ulong) -> *mut c::c_void;
}

#[inline]
pub(crate) fn page_size() -> usize {
Expand All @@ -29,14 +26,10 @@ pub(crate) fn clock_ticks_per_second() -> u64 {
))]
#[inline]
pub(crate) fn linux_hwcap() -> (usize, usize) {
if let Some(libc_getauxval) = getauxval.get() {
unsafe {
let hwcap = libc_getauxval(c::AT_HWCAP) as usize;
let hwcap2 = libc_getauxval(c::AT_HWCAP2) as usize;
(hwcap, hwcap2)
}
} else {
(0, 0)
unsafe {
let hwcap = getauxval(c::AT_HWCAP) as usize;
let hwcap2 = getauxval(c::AT_HWCAP2) as usize;
(hwcap, hwcap2)
}
}

Expand All @@ -61,9 +54,5 @@ pub(crate) fn linux_minsigstksz() -> usize {
))]
#[inline]
pub(crate) fn linux_execfn() -> &'static CStr {
if let Some(libc_getauxval) = getauxval.get() {
unsafe { CStr::from_ptr(libc_getauxval(c::AT_EXECFN).cast()) }
} else {
cstr!("")
}
unsafe { CStr::from_ptr(getauxval(c::AT_EXECFN).cast()) }
}
4 changes: 2 additions & 2 deletions src/backend/linux_raw/param/auxv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ pub(crate) fn vsyscall() -> *const c::c_void {

if vsyscall.is_null() {
#[cold]
fn compute_vsyscall() -> *const c::c_void {
fn compute_vsyscall() -> *mut c::c_void {
init_auxv();
VSYSCALL.load(Relaxed)
}
Expand Down Expand Up @@ -253,7 +253,7 @@ static PHNUM: AtomicUsize = AtomicUsize::new(0);
static ENTRY: AtomicUsize = AtomicUsize::new(0);
#[cfg(feature = "runtime")]
static RANDOM: AtomicPtr<[u8; 16]> = AtomicPtr::new(null_mut());
#[cfg(feature = "x86")]
#[cfg(target_arch = "x86")]
static VSYSCALL: AtomicPtr<c::c_void> = AtomicPtr::new(null_mut());

const PR_GET_AUXV: c::c_int = 0x4155_5856;
Expand Down
50 changes: 3 additions & 47 deletions src/backend/linux_raw/param/libc_auxv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@ use {
core::sync::atomic::Ordering::Relaxed,
};

// `getauxval` wasn't supported in glibc until 2.16. Also this lets us use
// `*mut` as the return type to preserve strict provenance.
#[cfg(not(feature = "runtime"))]
weak!(fn getauxval(c::c_ulong) -> *mut c::c_void);

// With the "runtime" feature, go ahead and depend on `getauxval` existing so
// that we never fail.
#[cfg(feature = "runtime")]
extern "C" {
fn getauxval(type_: c::c_ulong) -> *mut c::c_void;
}
Expand Down Expand Up @@ -99,18 +91,6 @@ pub(crate) fn clock_ticks_per_second() -> u64 {
#[cfg(feature = "param")]
#[inline]
pub(crate) fn linux_hwcap() -> (usize, usize) {
#[cfg(not(feature = "runtime"))]
unsafe {
if let Some(libc_getauxval) = getauxval.get() {
let hwcap = libc_getauxval(AT_HWCAP) as usize;
let hwcap2 = libc_getauxval(AT_HWCAP2) as usize;
(hwcap, hwcap2)
} else {
(0, 0)
}
}

#[cfg(feature = "runtime")]
unsafe {
let hwcap = getauxval(AT_HWCAP) as usize;
let hwcap2 = getauxval(AT_HWCAP2) as usize;
Expand Down Expand Up @@ -140,19 +120,7 @@ pub(crate) fn linux_minsigstksz() -> usize {
#[cfg(feature = "param")]
#[inline]
pub(crate) fn linux_execfn() -> &'static CStr {
#[cfg(not(feature = "runtime"))]
unsafe {
if let Some(libc_getauxval) = getauxval.get() {
CStr::from_ptr(libc_getauxval(AT_EXECFN).cast())
} else {
cstr!("")
}
}

#[cfg(feature = "runtime")]
unsafe {
CStr::from_ptr(getauxval(AT_EXECFN).cast())
}
unsafe { CStr::from_ptr(getauxval(AT_EXECFN).cast()) }
}

#[cfg(feature = "runtime")]
Expand All @@ -176,19 +144,7 @@ pub(crate) fn exe_phdrs() -> (*const c::c_void, usize, usize) {
/// if we don't see it, this function returns a null pointer.
#[inline]
pub(in super::super) fn sysinfo_ehdr() -> *const Elf_Ehdr {
#[cfg(not(feature = "runtime"))]
unsafe {
if let Some(libc_getauxval) = getauxval.get() {
libc_getauxval(AT_SYSINFO_EHDR) as *const Elf_Ehdr
} else {
null()
}
}

#[cfg(feature = "runtime")]
unsafe {
getauxval(AT_SYSINFO_EHDR) as *const Elf_Ehdr
}
unsafe { getauxval(AT_SYSINFO_EHDR) as *const Elf_Ehdr }
}

#[cfg(feature = "runtime")]
Expand All @@ -214,7 +170,7 @@ pub(crate) fn vsyscall() -> *const c_void {
if vsyscall.is_null() {
#[cold]
fn compute_vsyscall() -> *mut c_void {
let vsyscall = unsafe { getauxval(AT_SYSINFO) } as *mut c_void;
let vsyscall = unsafe { getauxval(AT_SYSINFO) as *mut c_void };
VSYSCALL.store(vsyscall, Relaxed);
vsyscall
}
Expand Down
12 changes: 3 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,15 +157,9 @@ pub(crate) mod check_types;
#[macro_use]
pub(crate) mod bitcast;

// linux_raw: Weak symbols are used by the use-libc-auxv feature for
// glibc 2.15 support.
//
// libc: Weak symbols are used to call various functions available in some
// versions of libc and not others.
#[cfg(any(
all(linux_raw, feature = "use-libc-auxv"),
all(libc, not(any(windows, target_os = "espidf", target_os = "wasi")))
))]
// Weak symbols are used to call various functions available in some versions
// of libc and not others.
#[cfg(all(libc, not(any(windows, target_os = "espidf", target_os = "wasi"))))]
#[macro_use]
mod weak;

Expand Down
16 changes: 8 additions & 8 deletions tests/param/auxv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ fn test_clock_ticks_per_second() {
))]
#[test]
fn test_linux_hwcap() {
weak!(fn getauxval(libc::c_ulong) -> libc::c_ulong);
extern "C" {
fn getauxval(type_: c::c_ulong) -> *mut c::c_void;
}

if let Some(libc_getauxval) = getauxval.get() {
let (_hwcap, hwcap2) = linux_hwcap();
let (_hwcap, hwcap2) = linux_hwcap();

// glibc seems to return a different value than `LD_SHOW_AUXV=1` reports.
#[cfg(not(target_env = "gnu"))]
assert_eq!(_hwcap, unsafe { libc_getauxval(libc::AT_HWCAP) } as usize);
// glibc seems to return a different value than `LD_SHOW_AUXV=1` reports.
#[cfg(not(target_env = "gnu"))]
assert_eq!(_hwcap, unsafe { getauxval(libc::AT_HWCAP) } as usize);

assert_eq!(hwcap2, unsafe { libc_getauxval(libc::AT_HWCAP2) } as usize);
}
assert_eq!(hwcap2, unsafe { getauxval(libc::AT_HWCAP2) } as usize);
}

#[cfg(any(
Expand Down

0 comments on commit d8c14ad

Please sign in to comment.