diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt index 4681d8c2bb73c..5c3f0342b9d9f 100644 --- a/libc/src/__support/OSUtil/linux/CMakeLists.txt +++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt @@ -9,6 +9,10 @@ add_object_library( SRCS exit.cpp fcntl.cpp + mmap.cpp + munmap.cpp + prctl.cpp + read.cpp HDRS io.h syscall.h @@ -22,6 +26,10 @@ add_object_library( libc.hdr.types.struct_f_owner_ex libc.hdr.types.off_t libc.include.sys_syscall + libc.src.__support.macros.sanitizer + libc.hdr.types.size_t + libc.hdr.types.ssize_t + libc.include.unistd ) add_header_library( diff --git a/libc/src/__support/OSUtil/linux/mmap.cpp b/libc/src/__support/OSUtil/linux/mmap.cpp new file mode 100644 index 0000000000000..05dc79c4662ab --- /dev/null +++ b/libc/src/__support/OSUtil/linux/mmap.cpp @@ -0,0 +1,66 @@ +//===------ Linux implementation of the POSIX mmap function -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/OSUtil/mmap.h" +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/__support/error_or.h" + +#include "src/__support/macros/config.h" +#include // For EXEC_PAGESIZE. +#include // For syscall numbers. +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + +// This function is currently linux only. It has to be refactored suitably if +// mmap is to be supported on non-linux operating systems also. +ErrorOr mmap(void *addr, size_t size, int prot, int flags, int fd, + off_t offset) { + // A lot of POSIX standard prescribed validation of the parameters is not + // done in this function as modern linux versions do it in the syscall. + // TODO: Perform argument validation not done by the linux syscall. + + // EXEC_PAGESIZE is used for the page size. While this is OK for x86_64, it + // might not be correct in general. + // TODO: Use pagesize read from the ELF aux vector instead of EXEC_PAGESIZE. + +#ifdef SYS_mmap2 + offset /= EXEC_PAGESIZE; + long syscall_number = SYS_mmap2; +#elif defined(SYS_mmap) + long syscall_number = SYS_mmap; +#else +#error "mmap or mmap2 syscalls not available." +#endif + + // We add an explicit cast to silence a "implicit conversion loses integer + // precision" warning when compiling for 32-bit systems. + long mmap_offset = static_cast(offset); + long ret = + LIBC_NAMESPACE::syscall_impl(syscall_number, reinterpret_cast(addr), + size, prot, flags, fd, mmap_offset); + + // The mmap/mmap2 syscalls return negative values on error. These negative + // values are actually the negative values of the error codes. So, fix them + // up in case an error code is detected. + // + // A point to keep in mind for the fix up is that a negative return value + // from the syscall can also be an error-free value returned by the syscall. + // However, since a valid return address cannot be within the last page, a + // return value corresponding to a location in the last page is an error + // value. + if (LIBC_UNLIKELY(ret < 0 && ret > -EXEC_PAGESIZE)) + return Error(static_cast(-ret)); + + return reinterpret_cast(ret); +} + +} // namespace internal +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/OSUtil/linux/munmap.cpp b/libc/src/__support/OSUtil/linux/munmap.cpp new file mode 100644 index 0000000000000..0c42a65a96c2f --- /dev/null +++ b/libc/src/__support/OSUtil/linux/munmap.cpp @@ -0,0 +1,35 @@ +//===---- Linux implementation of the POSIX munmap function -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/OSUtil/munmap.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" + +#include "src/__support/error_or.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include // For syscall numbers. + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + +// This function is currently linux only. It has to be refactored suitably if +// munmap is to be supported on non-linux operating systems also. +ErrorOr munmap(void *addr, size_t size) { + int ret = LIBC_NAMESPACE::syscall_impl( + SYS_munmap, reinterpret_cast(addr), size); + + if (LIBC_UNLIKELY(ret < 0)) + return Error(-ret); + + return 0; +} + +} // namespace internal +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/OSUtil/linux/prctl.cpp b/libc/src/__support/OSUtil/linux/prctl.cpp new file mode 100644 index 0000000000000..e701b531ca6fe --- /dev/null +++ b/libc/src/__support/OSUtil/linux/prctl.cpp @@ -0,0 +1,40 @@ +//===---- Linux implementation of the prctl function ------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/OSUtil/prctl.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. + +#include "src/__support/error_or.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include // For syscall numbers. + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + +ErrorOr prctl(int option, unsigned long arg2, unsigned long arg3, + unsigned long arg4, unsigned long arg5) { + long ret = + LIBC_NAMESPACE::syscall_impl(SYS_prctl, option, arg2, arg3, arg4, arg5); + + // The manpage states that "... return the nonnegative values described + // above. All other option values return 0 on success. On error, + // -1 is returned, and errno is set to indicate the error." + // According to the kernel implementation + // (https://github.com/torvalds/linux/blob/bee0e7762ad2c6025b9f5245c040fcc36ef2bde8/kernel/sys.c#L2442), + // return value from the syscall is set to 0 on default so we do not need to + // set the value on success manually. + if (LIBC_UNLIKELY(ret < 0)) + return Error(static_cast(-ret)); + + return static_cast(ret); +} + +} // namespace internal +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/OSUtil/linux/read.cpp b/libc/src/__support/OSUtil/linux/read.cpp new file mode 100644 index 0000000000000..23d7597da3740 --- /dev/null +++ b/libc/src/__support/OSUtil/linux/read.cpp @@ -0,0 +1,33 @@ +//===-- Linux implementation of read --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/OSUtil/read.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include "src/__support/macros/sanitizer.h" // for MSAN_UNPOISON +#include // For syscall numbers. + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + +ErrorOr read(int fd, void *buf, size_t count) { + ssize_t ret = LIBC_NAMESPACE::syscall_impl(SYS_read, fd, buf, count); + if (LIBC_UNLIKELY(ret < 0)) + return Error(static_cast(-ret)); + + // The cast is important since there is a check that dereferences the pointer + // which fails on void*. + MSAN_UNPOISON(reinterpret_cast(buf), count); + return ret; +} + +} // namespace internal +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/OSUtil/mmap.h b/libc/src/__support/OSUtil/mmap.h new file mode 100644 index 0000000000000..b884d0ece5ab4 --- /dev/null +++ b/libc/src/__support/OSUtil/mmap.h @@ -0,0 +1,26 @@ +//===----------- Implementation header of the mmap function -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_MMAP_H +#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_MMAP_H + +#include "hdr/types/off_t.h" +#include "hdr/types/size_t.h" +#include "src/__support/error_or.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + +ErrorOr mmap(void *addr, size_t size, int prot, int flags, int fd, + off_t offset); + +} // namespace internal +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_MMAP_H diff --git a/libc/src/__support/OSUtil/munmap.h b/libc/src/__support/OSUtil/munmap.h new file mode 100644 index 0000000000000..ed75c8178dfa1 --- /dev/null +++ b/libc/src/__support/OSUtil/munmap.h @@ -0,0 +1,25 @@ +//===--------- Implementation header of the munmap function -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_MUNMAP_H +#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_MUNMAP_H + +#include "hdr/types/off_t.h" +#include "hdr/types/size_t.h" +#include "src/__support/error_or.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + +ErrorOr munmap(void *addr, size_t size); + +} // namespace internal +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_MUNMAP_H diff --git a/libc/src/__support/OSUtil/prctl.h b/libc/src/__support/OSUtil/prctl.h new file mode 100644 index 0000000000000..fd8ddf0829985 --- /dev/null +++ b/libc/src/__support/OSUtil/prctl.h @@ -0,0 +1,26 @@ +//===--------- Implementation header of the prctl function -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_PRCTL_H +#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_PRCTL_H + +#include "src/__support/error_or.h" +#include "src/__support/libc_errno.h" +#include "src/__support/macros/config.h" +#include + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + +ErrorOr prctl(int option, unsigned long arg2, unsigned long arg3, + unsigned long arg4, unsigned long arg5); + +} // namespace internal +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_PRCTL_H diff --git a/libc/src/__support/OSUtil/read.h b/libc/src/__support/OSUtil/read.h new file mode 100644 index 0000000000000..16406e432a53b --- /dev/null +++ b/libc/src/__support/OSUtil/read.h @@ -0,0 +1,26 @@ +//===--------- Implementation header of the read function -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_READ_H +#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_READ_H + +#include "hdr/types/size_t.h" +#include "hdr/types/ssize_t.h" +#include "hdr/unistd_macros.h" +#include "src/__support/error_or.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + +ErrorOr read(int fd, void *buf, size_t count); + +} // namespace internal +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_READ_H diff --git a/libc/src/sys/auxv/linux/CMakeLists.txt b/libc/src/sys/auxv/linux/CMakeLists.txt index 4884184cc6053..d21754874830d 100644 --- a/libc/src/sys/auxv/linux/CMakeLists.txt +++ b/libc/src/sys/auxv/linux/CMakeLists.txt @@ -6,10 +6,9 @@ add_entrypoint_object( ../getauxval.h DEPENDS libc.src.sys.prctl.prctl - libc.src.sys.mman.mmap - libc.src.sys.mman.munmap libc.src.__support.threads.callonce libc.src.__support.common + libc.src.__support.OSUtil.osutil libc.src.errno.errno libc.config.app_h libc.src.fcntl.open diff --git a/libc/src/sys/auxv/linux/getauxval.cpp b/libc/src/sys/auxv/linux/getauxval.cpp index b50c5845bcc2b..113aeb500b73e 100644 --- a/libc/src/sys/auxv/linux/getauxval.cpp +++ b/libc/src/sys/auxv/linux/getauxval.cpp @@ -11,6 +11,7 @@ #include "hdr/fcntl_macros.h" #include "src/__support/OSUtil/fcntl.h" #include "src/__support/common.h" +#include "src/__support/error_or.h" #include "src/__support/libc_errno.h" #include "src/__support/macros/config.h" #include @@ -19,19 +20,13 @@ #include "src/__support/threads/callonce.h" #include "src/__support/threads/linux/futex_word.h" -// ----------------------------------------------------------------------------- -// TODO: This file should not include other public libc functions. Calling other -// public libc functions is an antipattern within LLVM-libc. This needs to be -// cleaned up. DO NOT COPY THIS. -// ----------------------------------------------------------------------------- - // for mallocing the global auxv -#include "src/sys/mman/mmap.h" -#include "src/sys/mman/munmap.h" +#include "src/__support/OSUtil/mmap.h" +#include "src/__support/OSUtil/munmap.h" // for reading /proc/self/auxv -#include "src/sys/prctl/prctl.h" -#include "src/unistd/read.h" +#include "src/__support/OSUtil/prctl.h" +#include "src/__support/OSUtil/read.h" // getauxval will work either with or without __cxa_atexit support. // In order to detect if __cxa_atexit is supported, we define a weak symbol. @@ -46,18 +41,6 @@ namespace LIBC_NAMESPACE_DECL { constexpr static size_t MAX_AUXV_ENTRIES = 64; -// Helper to recover or set errno -class AuxvErrnoGuard { -public: - AuxvErrnoGuard() : saved(libc_errno), failure(false) {} - ~AuxvErrnoGuard() { libc_errno = failure ? ENOENT : saved; } - void mark_failure() { failure = true; } - -private: - int saved; - bool failure; -}; - // Helper to manage the memory static AuxEntry *auxv = nullptr; @@ -66,18 +49,17 @@ class AuxvMMapGuard { constexpr static size_t AUXV_MMAP_SIZE = sizeof(AuxEntry) * MAX_AUXV_ENTRIES; AuxvMMapGuard() - : ptr(LIBC_NAMESPACE::mmap(nullptr, AUXV_MMAP_SIZE, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) {} + : ptr(internal::mmap(nullptr, AUXV_MMAP_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) {} ~AuxvMMapGuard() { - if (ptr != MAP_FAILED) - LIBC_NAMESPACE::munmap(ptr, AUXV_MMAP_SIZE); + if (ptr.has_value()) + internal::munmap(ptr.value(), AUXV_MMAP_SIZE); } void submit_to_global() { // atexit may fail, we do not set it to global in that case. int ret = __cxa_atexit( [](void *) { - LIBC_NAMESPACE::munmap(auxv, AUXV_MMAP_SIZE); + internal::munmap(auxv, AUXV_MMAP_SIZE); auxv = nullptr; }, nullptr, nullptr); @@ -85,14 +67,14 @@ class AuxvMMapGuard { if (ret != 0) return; - auxv = reinterpret_cast(ptr); - ptr = MAP_FAILED; + auxv = reinterpret_cast(ptr.value()); + ptr = Error(-1); } - bool allocated() const { return ptr != MAP_FAILED; } - void *get() const { return ptr; } + bool allocated() const { return ptr.has_value(); } + void *get() const { return ptr.value(); } private: - void *ptr; + ErrorOr ptr; }; class AuxvFdGuard { @@ -133,9 +115,9 @@ static void initialize_auxv_once(void) { // is compiled and run on separate kernels, we also check the return value of // prctl. #ifdef PR_GET_AUXV - int ret = prctl(PR_GET_AUXV, reinterpret_cast(ptr), - available_size, 0, 0); - if (ret >= 0) { + auto ret = internal::prctl(PR_GET_AUXV, reinterpret_cast(ptr), + available_size, 0, 0); + if (ret.has_value()) { mmap_guard.submit_to_global(); return; } @@ -144,23 +126,22 @@ static void initialize_auxv_once(void) { if (!fd_guard.valid()) return; auto *buf = reinterpret_cast(ptr); - libc_errno = 0; bool error_detected = false; // Read until we use up all the available space or we finish reading the file. while (available_size != 0) { - ssize_t bytes_read = - LIBC_NAMESPACE::read(fd_guard.get(), buf, available_size); - if (bytes_read <= 0) { - if (libc_errno == EINTR) + auto bytes_read = internal::read(fd_guard.get(), buf, available_size); + if (!bytes_read.has_value() || + (bytes_read.has_value() && bytes_read.value() == 0)) { + if (bytes_read.error() == EINTR) continue; // Now, we either have an non-recoverable error or we have reached the end // of the file. Mark `error_detected` accordingly. - if (bytes_read == -1) + if (!bytes_read.has_value()) error_detected = true; break; } - buf += bytes_read; - available_size -= bytes_read; + buf += bytes_read.value(); + available_size -= bytes_read.value(); } // If we get out of the loop without an error, the auxv is ready. if (!error_detected) @@ -172,17 +153,17 @@ static AuxEntry read_entry(int fd) { size_t size = sizeof(AuxEntry); char *ptr = reinterpret_cast(&buf); while (size > 0) { - ssize_t ret = LIBC_NAMESPACE::read(fd, ptr, size); - if (ret < 0) { - if (libc_errno == EINTR) + auto ret = internal::read(fd, ptr, size); + if (!ret.has_value()) { + if (ret.error() == EINTR) continue; // Error detected, return AT_NULL buf.id = AT_NULL; buf.value = AT_NULL; break; } - ptr += ret; - size -= ret; + ptr += ret.value(); + size -= ret.value(); } return buf; } @@ -191,15 +172,13 @@ LLVM_LIBC_FUNCTION(unsigned long, getauxval, (unsigned long id)) { // Fast path when libc is loaded by its own initialization code. In this case, // app.auxv_ptr is already set to the auxv passed on the initial stack of the // process. - AuxvErrnoGuard errno_guard; - auto search_auxv = [&errno_guard](AuxEntry *auxv, - unsigned long id) -> AuxEntryType { + auto search_auxv = [](AuxEntry *auxv, unsigned long id) -> AuxEntryType { for (auto *ptr = auxv; ptr->id != AT_NULL; ptr++) if (ptr->id == id) return ptr->value; - errno_guard.mark_failure(); + libc_errno = ENOENT; return AT_NULL; }; @@ -227,7 +206,7 @@ LLVM_LIBC_FUNCTION(unsigned long, getauxval, (unsigned long id)) { } // cannot find the entry after all methods, mark failure and return 0 - errno_guard.mark_failure(); + libc_errno = ENOENT; return AT_NULL; } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt index 89a0ad1527a06..60421c47c4053 100644 --- a/libc/src/sys/mman/linux/CMakeLists.txt +++ b/libc/src/sys/mman/linux/CMakeLists.txt @@ -18,8 +18,6 @@ add_entrypoint_object( HDRS ../mmap.h DEPENDS - libc.include.sys_mman - libc.include.sys_syscall libc.src.__support.OSUtil.osutil libc.src.errno.errno ) @@ -44,8 +42,6 @@ add_entrypoint_object( HDRS ../munmap.h DEPENDS - libc.include.sys_mman - libc.include.sys_syscall libc.src.__support.OSUtil.osutil libc.src.errno.errno ) diff --git a/libc/src/sys/mman/linux/mmap.cpp b/libc/src/sys/mman/linux/mmap.cpp index 33f9fe8ff3709..a0cb726132ed2 100644 --- a/libc/src/sys/mman/linux/mmap.cpp +++ b/libc/src/sys/mman/linux/mmap.cpp @@ -8,60 +8,24 @@ #include "src/sys/mman/mmap.h" -#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/OSUtil/mmap.h" #include "src/__support/common.h" - #include "src/__support/libc_errno.h" -#include "src/__support/macros/config.h" -#include // For EXEC_PAGESIZE. -#include // For syscall numbers. +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY namespace LIBC_NAMESPACE_DECL { -// This function is currently linux only. It has to be refactored suitably if -// mmap is to be supported on non-linux operating systems also. LLVM_LIBC_FUNCTION(void *, mmap, (void *addr, size_t size, int prot, int flags, int fd, off_t offset)) { - // A lot of POSIX standard prescribed validation of the parameters is not - // done in this function as modern linux versions do it in the syscall. - // TODO: Perform argument validation not done by the linux syscall. - - // EXEC_PAGESIZE is used for the page size. While this is OK for x86_64, it - // might not be correct in general. - // TODO: Use pagesize read from the ELF aux vector instead of EXEC_PAGESIZE. - -#ifdef SYS_mmap2 - offset /= EXEC_PAGESIZE; - long syscall_number = SYS_mmap2; -#elif defined(SYS_mmap) - long syscall_number = SYS_mmap; -#else -#error "mmap or mmap2 syscalls not available." -#endif - - // We add an explicit cast to silence a "implicit conversion loses integer - // precision" warning when compiling for 32-bit systems. - long mmap_offset = static_cast(offset); - long ret = - LIBC_NAMESPACE::syscall_impl(syscall_number, reinterpret_cast(addr), - size, prot, flags, fd, mmap_offset); + auto ptr = internal::mmap(addr, size, prot, flags, fd, offset); - // The mmap/mmap2 syscalls return negative values on error. These negative - // values are actually the negative values of the error codes. So, fix them - // up in case an error code is detected. - // - // A point to keep in mind for the fix up is that a negative return value - // from the syscall can also be an error-free value returned by the syscall. - // However, since a valid return address cannot be within the last page, a - // return value corresponding to a location in the last page is an error - // value. - if (ret < 0 && ret > -EXEC_PAGESIZE) { - libc_errno = static_cast(-ret); + if (LIBC_UNLIKELY(!ptr.has_value())) { + libc_errno = ptr.error(); return MAP_FAILED; } - return reinterpret_cast(ret); + return ptr.value(); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/mman/linux/munmap.cpp b/libc/src/sys/mman/linux/munmap.cpp index 61b1f1549dd18..d4613b5899503 100644 --- a/libc/src/sys/mman/linux/munmap.cpp +++ b/libc/src/sys/mman/linux/munmap.cpp @@ -8,29 +8,24 @@ #include "src/sys/mman/munmap.h" -#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/OSUtil/munmap.h" #include "src/__support/common.h" - #include "src/__support/libc_errno.h" -#include "src/__support/macros/config.h" -#include // For syscall numbers. +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY namespace LIBC_NAMESPACE_DECL { -// This function is currently linux only. It has to be refactored suitably if -// mmap is to be supported on non-linux operating systems also. LLVM_LIBC_FUNCTION(int, munmap, (void *addr, size_t size)) { - int ret = LIBC_NAMESPACE::syscall_impl( - SYS_munmap, reinterpret_cast(addr), size); + auto ret = internal::munmap(addr, size); // A negative return value indicates an error with the magnitude of the // value being the error code. - if (ret < 0) { - libc_errno = -ret; + if (LIBC_UNLIKELY(!ret.has_value())) { + libc_errno = ret.error(); return -1; } - return 0; + return ret.value(); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/prctl/linux/CMakeLists.txt b/libc/src/sys/prctl/linux/CMakeLists.txt index 05d336441f4d0..58a6410b5c583 100644 --- a/libc/src/sys/prctl/linux/CMakeLists.txt +++ b/libc/src/sys/prctl/linux/CMakeLists.txt @@ -6,7 +6,6 @@ add_entrypoint_object( ../prctl.h DEPENDS libc.include.sys_prctl - libc.include.sys_syscall libc.src.__support.OSUtil.osutil libc.src.errno.errno ) diff --git a/libc/src/sys/prctl/linux/prctl.cpp b/libc/src/sys/prctl/linux/prctl.cpp index c726b0a539591..2ee858df53f72 100644 --- a/libc/src/sys/prctl/linux/prctl.cpp +++ b/libc/src/sys/prctl/linux/prctl.cpp @@ -8,31 +8,23 @@ #include "src/sys/prctl/prctl.h" -#include "src/__support/OSUtil/syscall.h" // For internal syscall function. - +#include "src/__support/OSUtil/prctl.h" +#include "src/__support/common.h" #include "src/__support/libc_errno.h" -#include "src/__support/macros/config.h" -#include // For syscall numbers. namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(int, prctl, (int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)) { - long ret = - LIBC_NAMESPACE::syscall_impl(SYS_prctl, option, arg2, arg3, arg4, arg5); - // The manpage states that "... return the nonnegative values described - // above. All other option values return 0 on success. On error, - // -1 is returned, and errno is set to indicate the error." - // According to the kernel implementation - // (https://github.com/torvalds/linux/blob/bee0e7762ad2c6025b9f5245c040fcc36ef2bde8/kernel/sys.c#L2442), - // return value from the syscall is set to 0 on default so we do not need to - // set the value on success manually. - if (ret < 0) { - libc_errno = static_cast(-ret); + auto result = internal::prctl(option, arg2, arg3, arg4, arg5); + + if (!result.has_value()) { + libc_errno = result.error(); return -1; } - return static_cast(ret); + + return result.value(); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/unistd/linux/read.cpp b/libc/src/unistd/linux/read.cpp index 55676f3f7010a..79a78cdd714d7 100644 --- a/libc/src/unistd/linux/read.cpp +++ b/libc/src/unistd/linux/read.cpp @@ -8,25 +8,20 @@ #include "src/unistd/read.h" -#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/OSUtil/read.h" // For internal syscall function. #include "src/__support/common.h" #include "src/__support/libc_errno.h" -#include "src/__support/macros/config.h" -#include "src/__support/macros/sanitizer.h" // for MSAN_UNPOISON -#include // For syscall numbers. namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(ssize_t, read, (int fd, void *buf, size_t count)) { - ssize_t ret = LIBC_NAMESPACE::syscall_impl(SYS_read, fd, buf, count); - if (ret < 0) { - libc_errno = static_cast(-ret); + auto ret = internal::read(fd, buf, count); + if (!ret.has_value()) { + libc_errno = static_cast(ret.error()); return -1; } - // The cast is important since there is a check that dereferences the pointer - // which fails on void*. - MSAN_UNPOISON(reinterpret_cast(buf), count); - return ret; + + return ret.value(); } } // namespace LIBC_NAMESPACE_DECL