Skip to content

Change the syntax of the internal weak! macro #138988

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

Merged
merged 1 commit into from
Mar 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions library/std/src/sys/fs/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,15 @@ cfg_has_statx! {{
enum STATX_STATE{ Unknown = 0, Present, Unavailable }
static STATX_SAVED_STATE: AtomicU8 = AtomicU8::new(STATX_STATE::Unknown as u8);

syscall! {
syscall!(
fn statx(
fd: c_int,
pathname: *const c_char,
flags: c_int,
mask: libc::c_uint,
statxbuf: *mut libc::statx
) -> c_int
}
statxbuf: *mut libc::statx,
) -> c_int;
);

let statx_availability = STATX_SAVED_STATE.load(Ordering::Relaxed);
if statx_availability == STATX_STATE::Unavailable as u8 {
Expand Down Expand Up @@ -1540,7 +1540,9 @@ impl File {
let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?];
// futimens requires Android API level 19
cvt(unsafe {
weak!(fn futimens(c_int, *const libc::timespec) -> c_int);
weak!(
fn futimens(fd: c_int, times: *const libc::timespec) -> c_int;
);
match futimens.get() {
Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()),
None => return Err(io::const_error!(
Expand All @@ -1556,7 +1558,9 @@ impl File {
use crate::sys::{time::__timespec64, weak::weak};

// Added in glibc 2.34
weak!(fn __futimens64(libc::c_int, *const __timespec64) -> libc::c_int);
weak!(
fn __futimens64(fd: c_int, times: *const __timespec64) -> c_int;
);

if let Some(futimens64) = __futimens64.get() {
let to_timespec = |time: Option<SystemTime>| time.map(|time| time.t.to_timespec64())
Expand Down
52 changes: 40 additions & 12 deletions library/std/src/sys/pal/unix/fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,14 @@ impl FileDesc {
// implementation if `preadv` is not available.
#[cfg(all(target_os = "android", target_pointer_width = "64"))]
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
super::weak::syscall! {
super::weak::syscall!(
fn preadv(
fd: libc::c_int,
iovec: *const libc::iovec,
n_iovec: libc::c_int,
offset: off64_t
) -> isize
}
offset: off64_t,
) -> isize;
);

let ret = cvt(unsafe {
preadv(
Expand All @@ -257,7 +257,14 @@ impl FileDesc {
// and its metadata from LLVM IR.
#[no_sanitize(cfi)]
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
super::weak::weak!(
fn preadv64(
fd: libc::c_int,
iovec: *const libc::iovec,
n_iovec: libc::c_int,
offset: off64_t,
) -> isize;
);

match preadv64.get() {
Some(preadv) => {
Expand Down Expand Up @@ -286,7 +293,14 @@ impl FileDesc {
// use "weak" linking.
#[cfg(target_vendor = "apple")]
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
super::weak::weak!(fn preadv(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
super::weak::weak!(
fn preadv(
fd: libc::c_int,
iovec: *const libc::iovec,
n_iovec: libc::c_int,
offset: off64_t,
) -> isize;
);

match preadv.get() {
Some(preadv) => {
Expand Down Expand Up @@ -428,14 +442,14 @@ impl FileDesc {
// implementation if `pwritev` is not available.
#[cfg(all(target_os = "android", target_pointer_width = "64"))]
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
super::weak::syscall! {
super::weak::syscall!(
fn pwritev(
fd: libc::c_int,
iovec: *const libc::iovec,
n_iovec: libc::c_int,
offset: off64_t
) -> isize
}
offset: off64_t,
) -> isize;
);

let ret = cvt(unsafe {
pwritev(
Expand All @@ -450,7 +464,14 @@ impl FileDesc {

#[cfg(all(target_os = "android", target_pointer_width = "32"))]
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
super::weak::weak!(
fn pwritev64(
fd: libc::c_int,
iovec: *const libc::iovec,
n_iovec: libc::c_int,
offset: off64_t,
) -> isize;
);

match pwritev64.get() {
Some(pwritev) => {
Expand Down Expand Up @@ -479,7 +500,14 @@ impl FileDesc {
// use "weak" linking.
#[cfg(target_vendor = "apple")]
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
super::weak::weak!(fn pwritev(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
super::weak::weak!(
fn pwritev(
fd: libc::c_int,
iovec: *const libc::iovec,
n_iovec: libc::c_int,
offset: off64_t,
) -> isize;
);

match pwritev.get() {
Some(pwritev) => {
Expand Down
16 changes: 8 additions & 8 deletions library/std/src/sys/pal/unix/kernel_copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,16 +604,16 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
_ => true,
};

syscall! {
syscall!(
fn copy_file_range(
fd_in: libc::c_int,
off_in: *mut libc::loff_t,
fd_out: libc::c_int,
off_out: *mut libc::loff_t,
len: libc::size_t,
flags: libc::c_uint
) -> libc::ssize_t
}
flags: libc::c_uint,
) -> libc::ssize_t;
);

fn probe_copy_file_range_support() -> u8 {
// In some cases, we cannot determine availability from the first
Expand Down Expand Up @@ -727,16 +727,16 @@ fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) ->
// Android builds use feature level 14, but the libc wrapper for splice is
// gated on feature level 21+, so we have to invoke the syscall directly.
#[cfg(target_os = "android")]
syscall! {
syscall!(
fn splice(
srcfd: libc::c_int,
src_offset: *const i64,
dstfd: libc::c_int,
dst_offset: *const i64,
len: libc::size_t,
flags: libc::c_int
) -> libc::ssize_t
}
flags: libc::c_int,
) -> libc::ssize_t;
);

#[cfg(target_os = "linux")]
use libc::splice;
Expand Down
30 changes: 22 additions & 8 deletions library/std/src/sys/pal/unix/stack_overflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,18 +424,32 @@ mod imp {

let pages = PAGES.get_or_init(|| {
use crate::sys::weak::dlsym;
dlsym!(fn sysctlbyname(*const libc::c_char, *mut libc::c_void, *mut libc::size_t, *const libc::c_void, libc::size_t) -> libc::c_int);
dlsym!(
fn sysctlbyname(
name: *const libc::c_char,
oldp: *mut libc::c_void,
oldlenp: *mut libc::size_t,
newp: *const libc::c_void,
newlen: libc::size_t,
) -> libc::c_int;
);
let mut guard: usize = 0;
let mut size = size_of_val(&guard);
let oid = c"security.bsd.stack_guard_page";
match sysctlbyname.get() {
Some(fcn) if unsafe {
fcn(oid.as_ptr(),
(&raw mut guard).cast(),
&raw mut size,
ptr::null_mut(),
0) == 0
} => guard,
Some(fcn)
if unsafe {
fcn(
oid.as_ptr(),
(&raw mut guard).cast(),
&raw mut size,
ptr::null_mut(),
0,
) == 0
} =>
{
guard
}
_ => 1,
}
});
Expand Down
13 changes: 8 additions & 5 deletions library/std/src/sys/pal/unix/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,12 @@ impl Thread {
// and its metadata from LLVM IR.
#[no_sanitize(cfi)]
pub fn set_name(name: &CStr) {
weak! {
weak!(
fn pthread_setname_np(
libc::pthread_t, *const libc::c_char
) -> libc::c_int
}
thread: libc::pthread_t,
name: *const libc::c_char,
) -> libc::c_int;
);

if let Some(f) = pthread_setname_np.get() {
#[cfg(target_os = "nto")]
Expand Down Expand Up @@ -762,7 +763,9 @@ unsafe fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
// We use dlsym to avoid an ELF version dependency on GLIBC_PRIVATE. (#23628)
// We shouldn't really be using such an internal symbol, but there's currently
// no other way to account for the TLS size.
dlsym!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t);
dlsym!(
fn __pthread_get_minstack(attr: *const libc::pthread_attr_t) -> libc::size_t;
);

match __pthread_get_minstack.get() {
None => libc::PTHREAD_STACK_MIN,
Expand Down
7 changes: 6 additions & 1 deletion library/std/src/sys/pal/unix/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,12 @@ impl Timespec {

// __clock_gettime64 was added to 32-bit arches in glibc 2.34,
// and it handles both vDSO calls and ENOSYS fallbacks itself.
weak!(fn __clock_gettime64(libc::clockid_t, *mut __timespec64) -> libc::c_int);
weak!(
fn __clock_gettime64(
clockid: libc::clockid_t,
tp: *mut __timespec64,
) -> libc::c_int;
);

if let Some(clock_gettime64) = __clock_gettime64.get() {
let mut t = MaybeUninit::uninit();
Expand Down
40 changes: 24 additions & 16 deletions library/std/src/sys/pal/unix/weak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::{mem, ptr};
// We can use true weak linkage on ELF targets.
#[cfg(all(unix, not(target_vendor = "apple")))]
pub(crate) macro weak {
(fn $name:ident($($t:ty),*) -> $ret:ty) => (
(fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
unsafe extern "C" {
#[linkage = "extern_weak"]
Expand Down Expand Up @@ -62,10 +62,16 @@ impl<F: Copy> ExternWeak<F> {
}

pub(crate) macro dlsym {
(fn $name:ident($($t:ty),*) -> $ret:ty) => (
dlsym!(fn $name($($t),*) -> $ret, stringify!($name));
(fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
dlsym!(
#[link_name = stringify!($name)]
fn $name($($param : $t),*) -> $ret;
);
),
(fn $name:ident($($t:ty),*) -> $ret:ty, $sym:expr) => (
(
#[link_name = $sym:expr]
fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;
) => (
static DLSYM: DlsymWeak<unsafe extern "C" fn($($t),*) -> $ret> =
DlsymWeak::new(concat!($sym, '\0'));
let $name = &DLSYM;
Expand Down Expand Up @@ -143,15 +149,15 @@ unsafe fn fetch(name: &str) -> *mut libc::c_void {

#[cfg(not(any(target_os = "linux", target_os = "android")))]
pub(crate) macro syscall {
(fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
(fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
// FIXME(#115199): Rust currently omits weak function definitions
// and its metadata from LLVM IR.
#[no_sanitize(cfi)]
unsafe fn $name($($arg_name: $t),*) -> $ret {
weak! { fn $name($($t),*) -> $ret }
unsafe fn $name($($param: $t),*) -> $ret {
weak!(fn $name($($param: $t),*) -> $ret;);

if let Some(fun) = $name.get() {
fun($($arg_name),*)
fun($($param),*)
} else {
super::os::set_errno(libc::ENOSYS);
-1
Expand All @@ -162,26 +168,28 @@ pub(crate) macro syscall {

#[cfg(any(target_os = "linux", target_os = "android"))]
pub(crate) macro syscall {
(fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
unsafe fn $name($($arg_name:$t),*) -> $ret {
weak! { fn $name($($t),*) -> $ret }
(
fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;
) => (
unsafe fn $name($($param: $t),*) -> $ret {
weak!(fn $name($($param: $t),*) -> $ret;);

// Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
// interposition, but if it's not found just use a raw syscall.
if let Some(fun) = $name.get() {
fun($($arg_name),*)
fun($($param),*)
} else {
libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret
libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret
}
}
)
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub(crate) macro raw_syscall {
(fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
unsafe fn $name($($arg_name:$t),*) -> $ret {
libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret
(fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
unsafe fn $name($($param: $t),*) -> $ret {
libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret
}
)
}
Loading
Loading