Skip to content

Commit

Permalink
Rollup merge of #124089 - simlay:fix-preadv64-and-pwritev64-link-for-…
Browse files Browse the repository at this point in the history
…watchos-and-visionos, r=workingjubilee

Fix watchOS and visionOS for pread64 and pwrite64 calls

In #122880, links to `preadv64` and `pwritev64` were added for `watchOS` however the underlying [`weak!` macro did not include `target_os = "watchos"`](https://github.com/rust-lang/rust/blob/c45dee5efd0c042e9d1e24559ebd0d6424d8aa70/library/std/src/sys/pal/unix/weak.rs#L30-L74).

This resulted in an `xcodebuild` error when targeting `watchOS`:
```
Undefined symbols for architecture arm64:
  "_preadv64", referenced from:
      __rust_extern_with_linkage_preadv64 in libliveview_native_core.a[274](std-324fdd8d31e8eaa2.std.e18cf7e8d0336778-cgu.08.rcgu.o)
  "_pwritev64", referenced from:
      __rust_extern_with_linkage_pwritev64 in libliveview_native_core.a[274](std-324fdd8d31e8eaa2.std.e18cf7e8d0336778-cgu.08.rcgu.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
```

So I added them. I also went ahead and added the same for visionOS because it's bound to create the same issue.
  • Loading branch information
GuillaumeGomez authored Apr 21, 2024
2 parents f122a51 + fa53b9f commit 9efd147
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 38 deletions.
100 changes: 64 additions & 36 deletions library/std/src/sys/pal/unix/fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,9 @@ const READ_LIMIT: usize = libc::ssize_t::MAX as usize;
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "tvos",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "watchos",
target_os = "visionos",
target_vendor = "apple",
))]
const fn max_iov() -> usize {
libc::IOV_MAX as usize
Expand All @@ -72,17 +68,13 @@ const fn max_iov() -> usize {
target_os = "dragonfly",
target_os = "emscripten",
target_os = "freebsd",
target_os = "ios",
target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "nto",
target_os = "openbsd",
target_os = "horizon",
target_os = "vita",
target_os = "watchos",
target_os = "visionos",
target_vendor = "apple",
)))]
const fn max_iov() -> usize {
16 // The minimum value required by POSIX.
Expand Down Expand Up @@ -201,13 +193,10 @@ impl FileDesc {
target_os = "fuchsia",
target_os = "hurd",
target_os = "illumos",
target_os = "ios",
target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "watchos",
target_vendor = "apple",
)))]
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
io::default_read_vectored(|b| self.read_at(b, offset), bufs)
Expand Down Expand Up @@ -241,15 +230,7 @@ impl FileDesc {
Ok(ret as usize)
}

// We support old MacOS and iOS versions that do not have `preadv`. There is
// no `syscall` possible in these platform.
#[cfg(any(
all(target_os = "android", target_pointer_width = "32"),
target_os = "ios", // ios 14.0
target_os = "tvos", // tvos 14.0
target_os = "macos", // macos 11.0
target_os = "watchos", // watchos 7.0
))]
#[cfg(all(target_os = "android", target_pointer_width = "32"))]
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);

Expand All @@ -269,6 +250,35 @@ impl FileDesc {
}
}

// We support old MacOS, iOS, watchOS, tvOS and visionOS. `preadv` was added in the following
// Apple OS versions:
// ios 14.0
// tvos 14.0
// macos 11.0
// watchos 7.0
//
// These versions may be newer than the minimum supported versions of OS's we support so we must
// 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);

match preadv.get() {
Some(preadv) => {
let ret = cvt(unsafe {
preadv(
self.as_raw_fd(),
bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
cmp::min(bufs.len(), max_iov()) as libc::c_int,
offset as _,
)
})?;
Ok(ret as usize)
}
None => io::default_read_vectored(|b| self.read_at(b, offset), bufs),
}
}

pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
let ret = cvt(unsafe {
libc::write(
Expand Down Expand Up @@ -360,13 +370,10 @@ impl FileDesc {
target_os = "fuchsia",
target_os = "hurd",
target_os = "illumos",
target_os = "ios",
target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "watchos",
target_vendor = "apple",
)))]
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
io::default_write_vectored(|b| self.write_at(b, offset), bufs)
Expand Down Expand Up @@ -400,15 +407,7 @@ impl FileDesc {
Ok(ret as usize)
}

// We support old MacOS and iOS versions that do not have `pwritev`. There is
// no `syscall` possible in these platform.
#[cfg(any(
all(target_os = "android", target_pointer_width = "32"),
target_os = "ios", // ios 14.0
target_os = "tvos", // tvos 14.0
target_os = "macos", // macos 11.0
target_os = "watchos", // watchos 7.0
))]
#[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);

Expand All @@ -428,6 +427,35 @@ impl FileDesc {
}
}

// We support old MacOS, iOS, watchOS, tvOS and visionOS. `pwritev` was added in the following
// Apple OS versions:
// ios 14.0
// tvos 14.0
// macos 11.0
// watchos 7.0
//
// These versions may be newer than the minimum supported versions of OS's we support so we must
// 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);

match pwritev.get() {
Some(pwritev) => {
let ret = cvt(unsafe {
pwritev(
self.as_raw_fd(),
bufs.as_ptr() as *const libc::iovec,
cmp::min(bufs.len(), max_iov()) as libc::c_int,
offset as _,
)
})?;
Ok(ret as usize)
}
None => io::default_write_vectored(|b| self.write_at(b, offset), bufs),
}
}

#[cfg(not(any(
target_env = "newlib",
target_os = "solaris",
Expand Down
4 changes: 2 additions & 2 deletions library/std/src/sys/pal/unix/weak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use crate::ptr;
use crate::sync::atomic::{self, AtomicPtr, Ordering};

// We can use true weak linkage on ELF targets.
#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "tvos")))]
#[cfg(all(unix, not(target_vendor = "apple")))]
pub(crate) macro weak {
(fn $name:ident($($t:ty),*) -> $ret:ty) => (
let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
Expand All @@ -43,7 +43,7 @@ pub(crate) macro weak {
}

// On non-ELF targets, use the dlsym approximation of weak linkage.
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))]
#[cfg(target_vendor = "apple")]
pub(crate) use self::dlsym as weak;

pub(crate) struct ExternWeak<F: Copy> {
Expand Down

0 comments on commit 9efd147

Please sign in to comment.