From c0cb968758f6eb58b255aaddd503473bbe51b51a Mon Sep 17 00:00:00 2001 From: Uzair Nawaz Date: Mon, 16 Jun 2025 16:53:04 +0000 Subject: [PATCH 01/11] made mmap an internal function; called internal function in getauxval --- .../src/__support/OSUtil/linux/CMakeLists.txt | 1 + libc/src/__support/OSUtil/linux/mmap.cpp | 66 +++++++++++++++++++ libc/src/__support/OSUtil/mmap.h | 23 +++++++ libc/src/sys/auxv/linux/CMakeLists.txt | 2 +- libc/src/sys/auxv/linux/getauxval.cpp | 6 +- libc/src/sys/mman/linux/CMakeLists.txt | 3 - libc/src/sys/mman/linux/mmap.cpp | 50 +------------- 7 files changed, 97 insertions(+), 54 deletions(-) create mode 100644 libc/src/__support/OSUtil/linux/mmap.cpp create mode 100644 libc/src/__support/OSUtil/mmap.h diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt index b9704d42cd33b..9ff47eab858de 100644 --- a/libc/src/__support/OSUtil/linux/CMakeLists.txt +++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt @@ -9,6 +9,7 @@ add_object_library( SRCS exit.cpp fcntl.cpp + mmap.cpp HDRS io.h syscall.h diff --git a/libc/src/__support/OSUtil/linux/mmap.cpp b/libc/src/__support/OSUtil/linux/mmap.cpp new file mode 100644 index 0000000000000..81b4457812785 --- /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/libc_errno.h" +#include "src/__support/macros/config.h" +#include // For EXEC_PAGESIZE. +#include // For syscall numbers. + +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. +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); + + // 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); + return MAP_FAILED; + } + + return reinterpret_cast(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..45bbab22f4cda --- /dev/null +++ b/libc/src/__support/OSUtil/mmap.h @@ -0,0 +1,23 @@ +//===----------- 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 "src/__support/macros/config.h" +#include // For size_t and off_t + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + +void *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/sys/auxv/linux/CMakeLists.txt b/libc/src/sys/auxv/linux/CMakeLists.txt index 4884184cc6053..072b00f80b54d 100644 --- a/libc/src/sys/auxv/linux/CMakeLists.txt +++ b/libc/src/sys/auxv/linux/CMakeLists.txt @@ -6,10 +6,10 @@ 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 f3ae7c5c4e07a..41b46e20587b6 100644 --- a/libc/src/sys/auxv/linux/getauxval.cpp +++ b/libc/src/sys/auxv/linux/getauxval.cpp @@ -18,7 +18,7 @@ #include "src/__support/threads/linux/futex_word.h" // for mallocing the global auxv -#include "src/sys/mman/mmap.h" +#include "src/__support/OSUtil/mmap.h" #include "src/sys/mman/munmap.h" // for reading /proc/self/auxv @@ -60,8 +60,8 @@ class AuxvMMapGuard { constexpr static size_t AUXV_MMAP_SIZE = sizeof(AuxEntry) * MAX_AUXV_ENTRIES; AuxvMMapGuard() - : ptr(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) munmap(ptr, AUXV_MMAP_SIZE); diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt index 89a0ad1527a06..affb3c672a460 100644 --- a/libc/src/sys/mman/linux/CMakeLists.txt +++ b/libc/src/sys/mman/linux/CMakeLists.txt @@ -18,10 +18,7 @@ add_entrypoint_object( HDRS ../mmap.h DEPENDS - libc.include.sys_mman - libc.include.sys_syscall libc.src.__support.OSUtil.osutil - libc.src.errno.errno ) add_entrypoint_object( diff --git a/libc/src/sys/mman/linux/mmap.cpp b/libc/src/sys/mman/linux/mmap.cpp index 33f9fe8ff3709..811c3541768e0 100644 --- a/libc/src/sys/mman/linux/mmap.cpp +++ b/libc/src/sys/mman/linux/mmap.cpp @@ -8,60 +8,16 @@ #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. - 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); - - // 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); - return MAP_FAILED; - } - - return reinterpret_cast(ret); + return internal::mmap(addr, size, prot, flags, fd, offset); } } // namespace LIBC_NAMESPACE_DECL From d110ef55afc414929327ef44fd55f09d356e1761 Mon Sep 17 00:00:00 2001 From: Uzair Nawaz Date: Mon, 16 Jun 2025 17:11:44 +0000 Subject: [PATCH 02/11] refactored to make munmap an internal function --- .../src/__support/OSUtil/linux/CMakeLists.txt | 1 + libc/src/__support/OSUtil/linux/munmap.cpp | 37 +++++++++++++++++++ libc/src/__support/OSUtil/munmap.h | 23 ++++++++++++ libc/src/sys/auxv/linux/CMakeLists.txt | 1 - libc/src/sys/auxv/linux/getauxval.cpp | 6 +-- libc/src/sys/mman/linux/CMakeLists.txt | 3 -- libc/src/sys/mman/linux/munmap.cpp | 20 +--------- 7 files changed, 66 insertions(+), 25 deletions(-) create mode 100644 libc/src/__support/OSUtil/linux/munmap.cpp create mode 100644 libc/src/__support/OSUtil/munmap.h diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt index 9ff47eab858de..a7af63e4aa7c3 100644 --- a/libc/src/__support/OSUtil/linux/CMakeLists.txt +++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt @@ -10,6 +10,7 @@ add_object_library( exit.cpp fcntl.cpp mmap.cpp + munmap.cpp HDRS io.h syscall.h diff --git a/libc/src/__support/OSUtil/linux/munmap.cpp b/libc/src/__support/OSUtil/linux/munmap.cpp new file mode 100644 index 0000000000000..15bfc514b493e --- /dev/null +++ b/libc/src/__support/OSUtil/linux/munmap.cpp @@ -0,0 +1,37 @@ +//===---- 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/libc_errno.h" +#include "src/__support/macros/config.h" +#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. +int munmap(void *addr, size_t size) { + int ret = LIBC_NAMESPACE::syscall_impl( + SYS_munmap, reinterpret_cast(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; + return -1; + } + + return 0; +} +} // namespace internal +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/OSUtil/munmap.h b/libc/src/__support/OSUtil/munmap.h new file mode 100644 index 0000000000000..b279ecfcb49d3 --- /dev/null +++ b/libc/src/__support/OSUtil/munmap.h @@ -0,0 +1,23 @@ +//===--------- 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 "src/__support/macros/config.h" +#include // For size_t and off_t + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + +int 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/sys/auxv/linux/CMakeLists.txt b/libc/src/sys/auxv/linux/CMakeLists.txt index 072b00f80b54d..d21754874830d 100644 --- a/libc/src/sys/auxv/linux/CMakeLists.txt +++ b/libc/src/sys/auxv/linux/CMakeLists.txt @@ -6,7 +6,6 @@ add_entrypoint_object( ../getauxval.h DEPENDS libc.src.sys.prctl.prctl - libc.src.sys.mman.munmap libc.src.__support.threads.callonce libc.src.__support.common libc.src.__support.OSUtil.osutil diff --git a/libc/src/sys/auxv/linux/getauxval.cpp b/libc/src/sys/auxv/linux/getauxval.cpp index 41b46e20587b6..44ac4d041c19a 100644 --- a/libc/src/sys/auxv/linux/getauxval.cpp +++ b/libc/src/sys/auxv/linux/getauxval.cpp @@ -19,7 +19,7 @@ // for mallocing the global auxv #include "src/__support/OSUtil/mmap.h" -#include "src/sys/mman/munmap.h" +#include "src/__support/OSUtil/munmap.h" // for reading /proc/self/auxv #include "src/fcntl/open.h" @@ -64,13 +64,13 @@ class AuxvMMapGuard { MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) {} ~AuxvMMapGuard() { if (ptr != MAP_FAILED) - munmap(ptr, AUXV_MMAP_SIZE); + internal::munmap(ptr, 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 *) { - munmap(auxv, AUXV_MMAP_SIZE); + internal::munmap(auxv, AUXV_MMAP_SIZE); auxv = nullptr; }, nullptr, nullptr); diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt index affb3c672a460..6447af9a3ff8a 100644 --- a/libc/src/sys/mman/linux/CMakeLists.txt +++ b/libc/src/sys/mman/linux/CMakeLists.txt @@ -41,10 +41,7 @@ add_entrypoint_object( HDRS ../munmap.h DEPENDS - libc.include.sys_mman - libc.include.sys_syscall libc.src.__support.OSUtil.osutil - libc.src.errno.errno ) add_entrypoint_object( diff --git a/libc/src/sys/mman/linux/munmap.cpp b/libc/src/sys/mman/linux/munmap.cpp index 61b1f1549dd18..ec9558855a83a 100644 --- a/libc/src/sys/mman/linux/munmap.cpp +++ b/libc/src/sys/mman/linux/munmap.cpp @@ -8,29 +8,13 @@ #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. - 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); - - // A negative return value indicates an error with the magnitude of the - // value being the error code. - if (ret < 0) { - libc_errno = -ret; - return -1; - } - - return 0; + return internal::munmap(addr, size); } } // namespace LIBC_NAMESPACE_DECL From 192eadf5a735a766f2dadebcb3fe36c771bbc811 Mon Sep 17 00:00:00 2001 From: Uzair Nawaz Date: Mon, 16 Jun 2025 18:29:00 +0000 Subject: [PATCH 03/11] switching to erroror for internal functions, not complete --- .../src/__support/OSUtil/linux/CMakeLists.txt | 1 + libc/src/__support/OSUtil/linux/mmap.cpp | 13 +++---- libc/src/__support/OSUtil/linux/munmap.cpp | 14 ++----- libc/src/__support/OSUtil/linux/prctl.cpp | 39 +++++++++++++++++++ libc/src/__support/OSUtil/mmap.h | 3 +- libc/src/__support/OSUtil/prctl.h | 25 ++++++++++++ libc/src/sys/auxv/linux/getauxval.cpp | 15 +++---- libc/src/sys/mman/linux/CMakeLists.txt | 2 + libc/src/sys/mman/linux/mmap.cpp | 10 ++++- libc/src/sys/mman/linux/munmap.cpp | 12 +++++- libc/src/sys/prctl/linux/prctl.cpp | 24 ++++-------- 11 files changed, 113 insertions(+), 45 deletions(-) create mode 100644 libc/src/__support/OSUtil/linux/prctl.cpp create mode 100644 libc/src/__support/OSUtil/prctl.h diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt index 498efb08c67ab..4be990a2b029a 100644 --- a/libc/src/__support/OSUtil/linux/CMakeLists.txt +++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt @@ -11,6 +11,7 @@ add_object_library( fcntl.cpp mmap.cpp munmap.cpp + prctl.cpp HDRS io.h syscall.h diff --git a/libc/src/__support/OSUtil/linux/mmap.cpp b/libc/src/__support/OSUtil/linux/mmap.cpp index 81b4457812785..9e27701e73572 100644 --- a/libc/src/__support/OSUtil/linux/mmap.cpp +++ b/libc/src/__support/OSUtil/linux/mmap.cpp @@ -9,18 +9,19 @@ #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/libc_errno.h" #include "src/__support/macros/config.h" #include // For EXEC_PAGESIZE. #include // For syscall numbers. 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. -void *mmap(void *addr, size_t size, int prot, int flags, int fd, off_t offset) { +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. @@ -54,10 +55,8 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, off_t offset) { // 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); - return MAP_FAILED; - } + if (ret < 0 && ret > -EXEC_PAGESIZE) + return Error(static_cast(-ret)); return reinterpret_cast(ret); } diff --git a/libc/src/__support/OSUtil/linux/munmap.cpp b/libc/src/__support/OSUtil/linux/munmap.cpp index 15bfc514b493e..199467c93c48e 100644 --- a/libc/src/__support/OSUtil/linux/munmap.cpp +++ b/libc/src/__support/OSUtil/linux/munmap.cpp @@ -21,17 +21,9 @@ 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. int munmap(void *addr, size_t size) { - int ret = LIBC_NAMESPACE::syscall_impl( - SYS_munmap, reinterpret_cast(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; - return -1; - } - - return 0; + return LIBC_NAMESPACE::syscall_impl(SYS_munmap, + reinterpret_cast(addr), size); } + } // 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..1610fcbf2c402 --- /dev/null +++ b/libc/src/__support/OSUtil/linux/prctl.cpp @@ -0,0 +1,39 @@ +//===---- 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 // 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 (ret < 0) + return Error(-ret); + + return static_cast(ret); +} + +} // namespace internal +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/OSUtil/mmap.h b/libc/src/__support/OSUtil/mmap.h index 45bbab22f4cda..6d91bd5477f95 100644 --- a/libc/src/__support/OSUtil/mmap.h +++ b/libc/src/__support/OSUtil/mmap.h @@ -10,12 +10,13 @@ #define LLVM_LIBC_SRC___SUPPORT_OSUTIL_MMAP_H #include "src/__support/macros/config.h" +#include "src/__support/error_or.h" #include // For size_t and off_t namespace LIBC_NAMESPACE_DECL { namespace internal { -void *mmap(void *addr, size_t size, int prot, int flags, int fd, off_t offset); +ErrorOr mmap(void *addr, size_t size, int prot, int flags, int fd, off_t offset); } // namespace internal } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/OSUtil/prctl.h b/libc/src/__support/OSUtil/prctl.h new file mode 100644 index 0000000000000..bbfe6323548e1 --- /dev/null +++ b/libc/src/__support/OSUtil/prctl.h @@ -0,0 +1,25 @@ +//===--------- 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/macros/config.h" +#include "src/__support/error_or.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/sys/auxv/linux/getauxval.cpp b/libc/src/sys/auxv/linux/getauxval.cpp index 9d214f8ee576b..024642bb4fc67 100644 --- a/libc/src/sys/auxv/linux/getauxval.cpp +++ b/libc/src/sys/auxv/linux/getauxval.cpp @@ -12,6 +12,7 @@ #include "src/__support/OSUtil/fcntl.h" #include "src/__support/common.h" #include "src/__support/libc_errno.h" +#include "src/__support/error_or.h" #include "src/__support/macros/config.h" #include @@ -69,8 +70,8 @@ class AuxvMMapGuard { : ptr(internal::mmap(nullptr, AUXV_MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) {} ~AuxvMMapGuard() { - if (ptr != MAP_FAILED) - internal::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. @@ -84,14 +85,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 { diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt index 6447af9a3ff8a..60421c47c4053 100644 --- a/libc/src/sys/mman/linux/CMakeLists.txt +++ b/libc/src/sys/mman/linux/CMakeLists.txt @@ -19,6 +19,7 @@ add_entrypoint_object( ../mmap.h DEPENDS libc.src.__support.OSUtil.osutil + libc.src.errno.errno ) add_entrypoint_object( @@ -42,6 +43,7 @@ add_entrypoint_object( ../munmap.h DEPENDS libc.src.__support.OSUtil.osutil + libc.src.errno.errno ) add_entrypoint_object( diff --git a/libc/src/sys/mman/linux/mmap.cpp b/libc/src/sys/mman/linux/mmap.cpp index 811c3541768e0..e149a787fd67b 100644 --- a/libc/src/sys/mman/linux/mmap.cpp +++ b/libc/src/sys/mman/linux/mmap.cpp @@ -10,14 +10,20 @@ #include "src/__support/OSUtil/mmap.h" #include "src/__support/common.h" +#include "src/__support/libc_errno.h" namespace LIBC_NAMESPACE_DECL { - LLVM_LIBC_FUNCTION(void *, mmap, (void *addr, size_t size, int prot, int flags, int fd, off_t offset)) { - return internal::mmap(addr, size, prot, flags, fd, offset); + auto ptr = internal::mmap(addr, size, prot, flags, fd, offset); + + if (ptr.has_value()) + return ptr.value(); + + libc_errno = ptr.error(); + return MAP_FAILED; } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/mman/linux/munmap.cpp b/libc/src/sys/mman/linux/munmap.cpp index ec9558855a83a..c801989b9cdf6 100644 --- a/libc/src/sys/mman/linux/munmap.cpp +++ b/libc/src/sys/mman/linux/munmap.cpp @@ -10,11 +10,21 @@ #include "src/__support/OSUtil/munmap.h" #include "src/__support/common.h" +#include "src/__support/libc_errno.h" namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(int, munmap, (void *addr, size_t size)) { - return internal::munmap(addr, size); + int 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; + return -1; + } + + return 0; } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/prctl/linux/prctl.cpp b/libc/src/sys/prctl/linux/prctl.cpp index c726b0a539591..ca38a99923bbb 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/libc_errno.h" -#include "src/__support/macros/config.h" -#include // For syscall numbers. +#include "src/__support/common.h" 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 From 09363d4840910002dd0d6db1fdf691403cb6e715 Mon Sep 17 00:00:00 2001 From: Uzair Nawaz Date: Mon, 16 Jun 2025 20:17:45 +0000 Subject: [PATCH 04/11] switching to erroror for internal functions, not complete --- libc/src/__support/OSUtil/linux/prctl.cpp | 2 +- libc/src/__support/OSUtil/prctl.h | 1 + libc/src/__support/wchar/wcrtomb.cpp | 37 +++++++++++++++++++++++ libc/src/sys/auxv/linux/getauxval.cpp | 6 ++-- libc/src/sys/prctl/linux/CMakeLists.txt | 1 - 5 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 libc/src/__support/wchar/wcrtomb.cpp diff --git a/libc/src/__support/OSUtil/linux/prctl.cpp b/libc/src/__support/OSUtil/linux/prctl.cpp index 1610fcbf2c402..9f5f2d719c7f4 100644 --- a/libc/src/__support/OSUtil/linux/prctl.cpp +++ b/libc/src/__support/OSUtil/linux/prctl.cpp @@ -30,7 +30,7 @@ ErrorOr prctl(int option, unsigned long arg2, unsigned long arg3, // 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) - return Error(-ret); + return Error(static_cast(-ret)); return static_cast(ret); } diff --git a/libc/src/__support/OSUtil/prctl.h b/libc/src/__support/OSUtil/prctl.h index bbfe6323548e1..cc0c85fa8fce7 100644 --- a/libc/src/__support/OSUtil/prctl.h +++ b/libc/src/__support/OSUtil/prctl.h @@ -12,6 +12,7 @@ #include "src/__support/macros/config.h" #include "src/__support/error_or.h" #include +#include "src/__support/libc_errno.h" namespace LIBC_NAMESPACE_DECL { namespace internal { diff --git a/libc/src/__support/wchar/wcrtomb.cpp b/libc/src/__support/wchar/wcrtomb.cpp new file mode 100644 index 0000000000000..d7a1b3738a6ef --- /dev/null +++ b/libc/src/__support/wchar/wcrtomb.cpp @@ -0,0 +1,37 @@ + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + void utf32to8(char* out, wchar_t src) { + char u, v, w, x, y, z; + u = (src & (0xf << 20)) >> 20; + v = (src & (0xf << 16)) >> 16; + w = (src & (0xf << 12)) >> 12; + x = (src & (0xf << 8)) >> 8; + y = (src & (0xf << 4)) >> 4; + z = (src & (0xf << 0)) >> 0; + + if (src <= 0x7f) { + // 0yyyzzzz + out[0] = src; + } + else if (src <= 0x7ff) { + // 110xxxyy 10yyzzzz + out[0] = 0xC0 | (x << 2) | (y >> 2); + out[1] = 0x80 | ((y & 0x3) << 4) | z; + } + else if (src <= 0xffff) { + // 1110wwww 10xxxxyy 10yyzzzz + out[0] = 0xE0 | w; + out[1] = 0x80 | (x << 2) | (y >> 2); + out[2] = 0x80 | ((y & 0x3) << 4) | z; + } + else if (src <= 0x10ffff) { + // 11110uvv 10vvwwww 10xxxxyy 10yyzzzz + out[0] = 0xF0 | (u << 2) | (v >> 2); + out[1] = 0x80 | ((v & 0x3) << 4) | w; + out[2] = 0x80 | (x << 2) | (y >> 2); + out[3] = 0x80 | ((y & 0x3) << 4) | z; + } + } +} +} diff --git a/libc/src/sys/auxv/linux/getauxval.cpp b/libc/src/sys/auxv/linux/getauxval.cpp index 024642bb4fc67..da92cc1962c34 100644 --- a/libc/src/sys/auxv/linux/getauxval.cpp +++ b/libc/src/sys/auxv/linux/getauxval.cpp @@ -31,7 +31,7 @@ #include "src/__support/OSUtil/munmap.h" // for reading /proc/self/auxv -#include "src/sys/prctl/prctl.h" +#include "src/__support/OSUtil/prctl.h" #include "src/unistd/read.h" // getauxval will work either with or without __cxa_atexit support. @@ -133,9 +133,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), + auto ret = internal::prctl(PR_GET_AUXV, reinterpret_cast(ptr), available_size, 0, 0); - if (ret >= 0) { + if (ret.has_value()) { mmap_guard.submit_to_global(); return; } 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 ) From f2fa63950207cb27eab57bc11b5f1fbcb092cbff Mon Sep 17 00:00:00 2001 From: Uzair Nawaz Date: Mon, 16 Jun 2025 22:36:12 +0000 Subject: [PATCH 05/11] made internal function for read; removed errno guard class in getauxval --- .../src/__support/OSUtil/linux/CMakeLists.txt | 5 ++ libc/src/__support/OSUtil/linux/read.cpp | 32 ++++++++++ libc/src/__support/OSUtil/read.h | 26 ++++++++ libc/src/sys/auxv/linux/getauxval.cpp | 59 ++++++------------- libc/src/unistd/linux/read.cpp | 19 +++--- 5 files changed, 89 insertions(+), 52 deletions(-) create mode 100644 libc/src/__support/OSUtil/linux/read.cpp create mode 100644 libc/src/__support/OSUtil/read.h diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt index 4be990a2b029a..5c3f0342b9d9f 100644 --- a/libc/src/__support/OSUtil/linux/CMakeLists.txt +++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt @@ -12,6 +12,7 @@ add_object_library( mmap.cpp munmap.cpp prctl.cpp + read.cpp HDRS io.h syscall.h @@ -25,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/read.cpp b/libc/src/__support/OSUtil/linux/read.cpp new file mode 100644 index 0000000000000..88b6c9c754f68 --- /dev/null +++ b/libc/src/__support/OSUtil/linux/read.cpp @@ -0,0 +1,32 @@ +//===-- 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/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 (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/read.h b/libc/src/__support/OSUtil/read.h new file mode 100644 index 0000000000000..0e29fc36cfa24 --- /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/macros/config.h" +#include "src/__support/error_or.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/getauxval.cpp b/libc/src/sys/auxv/linux/getauxval.cpp index da92cc1962c34..113aeb500b73e 100644 --- a/libc/src/sys/auxv/linux/getauxval.cpp +++ b/libc/src/sys/auxv/linux/getauxval.cpp @@ -11,8 +11,8 @@ #include "hdr/fcntl_macros.h" #include "src/__support/OSUtil/fcntl.h" #include "src/__support/common.h" -#include "src/__support/libc_errno.h" #include "src/__support/error_or.h" +#include "src/__support/libc_errno.h" #include "src/__support/macros/config.h" #include @@ -20,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/__support/OSUtil/mmap.h" #include "src/__support/OSUtil/munmap.h" // for reading /proc/self/auxv #include "src/__support/OSUtil/prctl.h" -#include "src/unistd/read.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. @@ -47,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; @@ -92,7 +74,7 @@ class AuxvMMapGuard { void *get() const { return ptr.value(); } private: - ErrorOr ptr; + ErrorOr ptr; }; class AuxvFdGuard { @@ -134,7 +116,7 @@ static void initialize_auxv_once(void) { // prctl. #ifdef PR_GET_AUXV auto ret = internal::prctl(PR_GET_AUXV, reinterpret_cast(ptr), - available_size, 0, 0); + 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/unistd/linux/read.cpp b/libc/src/unistd/linux/read.cpp index 55676f3f7010a..2f8a991e5558c 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/common.h" +#include "src/__support/OSUtil/read.h" // For internal syscall function. #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. +#include "src/__support/common.h" 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 From 30af3b2327031b4d03795d6c20e39c96116c6c23 Mon Sep 17 00:00:00 2001 From: Uzair Nawaz Date: Mon, 16 Jun 2025 22:40:22 +0000 Subject: [PATCH 06/11] accidentally commited file previously --- libc/src/__support/wchar/wcrtomb.cpp | 37 ---------------------------- 1 file changed, 37 deletions(-) delete mode 100644 libc/src/__support/wchar/wcrtomb.cpp diff --git a/libc/src/__support/wchar/wcrtomb.cpp b/libc/src/__support/wchar/wcrtomb.cpp deleted file mode 100644 index d7a1b3738a6ef..0000000000000 --- a/libc/src/__support/wchar/wcrtomb.cpp +++ /dev/null @@ -1,37 +0,0 @@ - -namespace LIBC_NAMESPACE_DECL { -namespace internal { - void utf32to8(char* out, wchar_t src) { - char u, v, w, x, y, z; - u = (src & (0xf << 20)) >> 20; - v = (src & (0xf << 16)) >> 16; - w = (src & (0xf << 12)) >> 12; - x = (src & (0xf << 8)) >> 8; - y = (src & (0xf << 4)) >> 4; - z = (src & (0xf << 0)) >> 0; - - if (src <= 0x7f) { - // 0yyyzzzz - out[0] = src; - } - else if (src <= 0x7ff) { - // 110xxxyy 10yyzzzz - out[0] = 0xC0 | (x << 2) | (y >> 2); - out[1] = 0x80 | ((y & 0x3) << 4) | z; - } - else if (src <= 0xffff) { - // 1110wwww 10xxxxyy 10yyzzzz - out[0] = 0xE0 | w; - out[1] = 0x80 | (x << 2) | (y >> 2); - out[2] = 0x80 | ((y & 0x3) << 4) | z; - } - else if (src <= 0x10ffff) { - // 11110uvv 10vvwwww 10xxxxyy 10yyzzzz - out[0] = 0xF0 | (u << 2) | (v >> 2); - out[1] = 0x80 | ((v & 0x3) << 4) | w; - out[2] = 0x80 | (x << 2) | (y >> 2); - out[3] = 0x80 | ((y & 0x3) << 4) | z; - } - } -} -} From 172dcd74e1b7fd62cebd58f5d3547d0dfa61bc6b Mon Sep 17 00:00:00 2001 From: Uzair Nawaz Date: Mon, 16 Jun 2025 22:55:29 +0000 Subject: [PATCH 07/11] changed munmap to return an ErrorOr --- libc/src/__support/OSUtil/linux/munmap.cpp | 13 +++++++++---- libc/src/__support/OSUtil/munmap.h | 3 ++- libc/src/__support/OSUtil/prctl.h | 6 +++--- libc/src/sys/auxv/linux/CMakeLists.txt | 2 +- libc/src/sys/mman/linux/munmap.cpp | 8 ++++---- libc/src/sys/prctl/linux/prctl.cpp | 2 +- 6 files changed, 20 insertions(+), 14 deletions(-) diff --git a/libc/src/__support/OSUtil/linux/munmap.cpp b/libc/src/__support/OSUtil/linux/munmap.cpp index 199467c93c48e..6a11bae263f13 100644 --- a/libc/src/__support/OSUtil/linux/munmap.cpp +++ b/libc/src/__support/OSUtil/linux/munmap.cpp @@ -11,7 +11,7 @@ #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/__support/common.h" -#include "src/__support/libc_errno.h" +#include "src/__support/error_or.h" #include "src/__support/macros/config.h" #include // For syscall numbers. @@ -20,9 +20,14 @@ 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. -int munmap(void *addr, size_t size) { - return LIBC_NAMESPACE::syscall_impl(SYS_munmap, - reinterpret_cast(addr), size); +ErrorOr munmap(void *addr, size_t size) { + int ret = LIBC_NAMESPACE::syscall_impl( + SYS_munmap, reinterpret_cast(addr), size); + + if (ret < 0) + return Error(-ret); + + return 0; } } // namespace internal diff --git a/libc/src/__support/OSUtil/munmap.h b/libc/src/__support/OSUtil/munmap.h index b279ecfcb49d3..5e1a961f4d654 100644 --- a/libc/src/__support/OSUtil/munmap.h +++ b/libc/src/__support/OSUtil/munmap.h @@ -9,13 +9,14 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_MUNMAP_H #define LLVM_LIBC_SRC___SUPPORT_OSUTIL_MUNMAP_H +#include "src/__support/error_or.h" #include "src/__support/macros/config.h" #include // For size_t and off_t namespace LIBC_NAMESPACE_DECL { namespace internal { -int munmap(void *addr, size_t size); +ErrorOr munmap(void *addr, size_t size); } // namespace internal } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/OSUtil/prctl.h b/libc/src/__support/OSUtil/prctl.h index cc0c85fa8fce7..fd8ddf0829985 100644 --- a/libc/src/__support/OSUtil/prctl.h +++ b/libc/src/__support/OSUtil/prctl.h @@ -9,16 +9,16 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_PRCTL_H #define LLVM_LIBC_SRC___SUPPORT_OSUTIL_PRCTL_H -#include "src/__support/macros/config.h" #include "src/__support/error_or.h" -#include #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); + unsigned long arg4, unsigned long arg5); } // namespace internal } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/auxv/linux/CMakeLists.txt b/libc/src/sys/auxv/linux/CMakeLists.txt index d21754874830d..ab6f01a314f0e 100644 --- a/libc/src/sys/auxv/linux/CMakeLists.txt +++ b/libc/src/sys/auxv/linux/CMakeLists.txt @@ -15,4 +15,4 @@ add_entrypoint_object( libc.src.unistd.read libc.src.unistd.close libc.include.sys_auxv -) +) \ No newline at end of file diff --git a/libc/src/sys/mman/linux/munmap.cpp b/libc/src/sys/mman/linux/munmap.cpp index c801989b9cdf6..34bbca3231f9c 100644 --- a/libc/src/sys/mman/linux/munmap.cpp +++ b/libc/src/sys/mman/linux/munmap.cpp @@ -15,16 +15,16 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(int, munmap, (void *addr, size_t size)) { - int ret = internal::munmap(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 (!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/prctl.cpp b/libc/src/sys/prctl/linux/prctl.cpp index ca38a99923bbb..2ee858df53f72 100644 --- a/libc/src/sys/prctl/linux/prctl.cpp +++ b/libc/src/sys/prctl/linux/prctl.cpp @@ -9,8 +9,8 @@ #include "src/sys/prctl/prctl.h" #include "src/__support/OSUtil/prctl.h" -#include "src/__support/libc_errno.h" #include "src/__support/common.h" +#include "src/__support/libc_errno.h" namespace LIBC_NAMESPACE_DECL { From 55b32ce6bf19d0bf932f13cb2c79cb76eeb3e1ba Mon Sep 17 00:00:00 2001 From: Uzair Nawaz Date: Mon, 16 Jun 2025 22:58:34 +0000 Subject: [PATCH 08/11] style --- libc/src/sys/auxv/linux/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/src/sys/auxv/linux/CMakeLists.txt b/libc/src/sys/auxv/linux/CMakeLists.txt index ab6f01a314f0e..d21754874830d 100644 --- a/libc/src/sys/auxv/linux/CMakeLists.txt +++ b/libc/src/sys/auxv/linux/CMakeLists.txt @@ -15,4 +15,4 @@ add_entrypoint_object( libc.src.unistd.read libc.src.unistd.close libc.include.sys_auxv -) \ No newline at end of file +) From 11f29fe1309e8e2c8132c27f7a3383eec0b03a9a Mon Sep 17 00:00:00 2001 From: Uzair Nawaz Date: Mon, 16 Jun 2025 23:05:52 +0000 Subject: [PATCH 09/11] format fix --- libc/src/__support/OSUtil/linux/prctl.cpp | 2 +- libc/src/__support/OSUtil/mmap.h | 5 +++-- libc/src/__support/OSUtil/read.h | 2 +- libc/src/unistd/linux/read.cpp | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libc/src/__support/OSUtil/linux/prctl.cpp b/libc/src/__support/OSUtil/linux/prctl.cpp index 9f5f2d719c7f4..42370ed4d4abb 100644 --- a/libc/src/__support/OSUtil/linux/prctl.cpp +++ b/libc/src/__support/OSUtil/linux/prctl.cpp @@ -18,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL { namespace internal { ErrorOr prctl(int option, unsigned long arg2, unsigned long arg3, - unsigned long arg4, unsigned long arg5) { + unsigned long arg4, unsigned long arg5) { long ret = LIBC_NAMESPACE::syscall_impl(SYS_prctl, option, arg2, arg3, arg4, arg5); diff --git a/libc/src/__support/OSUtil/mmap.h b/libc/src/__support/OSUtil/mmap.h index 6d91bd5477f95..891c52593362e 100644 --- a/libc/src/__support/OSUtil/mmap.h +++ b/libc/src/__support/OSUtil/mmap.h @@ -9,14 +9,15 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_MMAP_H #define LLVM_LIBC_SRC___SUPPORT_OSUTIL_MMAP_H -#include "src/__support/macros/config.h" #include "src/__support/error_or.h" +#include "src/__support/macros/config.h" #include // For size_t and off_t namespace LIBC_NAMESPACE_DECL { namespace internal { -ErrorOr mmap(void *addr, size_t size, int prot, int flags, int fd, off_t offset); +ErrorOr mmap(void *addr, size_t size, int prot, int flags, int fd, + off_t offset); } // namespace internal } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/OSUtil/read.h b/libc/src/__support/OSUtil/read.h index 0e29fc36cfa24..16406e432a53b 100644 --- a/libc/src/__support/OSUtil/read.h +++ b/libc/src/__support/OSUtil/read.h @@ -12,8 +12,8 @@ #include "hdr/types/size_t.h" #include "hdr/types/ssize_t.h" #include "hdr/unistd_macros.h" -#include "src/__support/macros/config.h" #include "src/__support/error_or.h" +#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE_DECL { namespace internal { diff --git a/libc/src/unistd/linux/read.cpp b/libc/src/unistd/linux/read.cpp index 2f8a991e5558c..79a78cdd714d7 100644 --- a/libc/src/unistd/linux/read.cpp +++ b/libc/src/unistd/linux/read.cpp @@ -9,8 +9,8 @@ #include "src/unistd/read.h" #include "src/__support/OSUtil/read.h" // For internal syscall function. -#include "src/__support/libc_errno.h" #include "src/__support/common.h" +#include "src/__support/libc_errno.h" namespace LIBC_NAMESPACE_DECL { From cab7ffe167249d5aad0d68b72509761594f03482 Mon Sep 17 00:00:00 2001 From: Uzair Nawaz Date: Mon, 16 Jun 2025 23:27:32 +0000 Subject: [PATCH 10/11] use proxy headers for size_t/ssize_t --- libc/src/__support/OSUtil/mmap.h | 3 ++- libc/src/__support/OSUtil/munmap.h | 3 ++- libc/src/sys/mman/linux/mmap.cpp | 11 ++++++----- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/libc/src/__support/OSUtil/mmap.h b/libc/src/__support/OSUtil/mmap.h index 891c52593362e..b884d0ece5ab4 100644 --- a/libc/src/__support/OSUtil/mmap.h +++ b/libc/src/__support/OSUtil/mmap.h @@ -9,9 +9,10 @@ #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" -#include // For size_t and off_t namespace LIBC_NAMESPACE_DECL { namespace internal { diff --git a/libc/src/__support/OSUtil/munmap.h b/libc/src/__support/OSUtil/munmap.h index 5e1a961f4d654..ed75c8178dfa1 100644 --- a/libc/src/__support/OSUtil/munmap.h +++ b/libc/src/__support/OSUtil/munmap.h @@ -9,9 +9,10 @@ #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" -#include // For size_t and off_t namespace LIBC_NAMESPACE_DECL { namespace internal { diff --git a/libc/src/sys/mman/linux/mmap.cpp b/libc/src/sys/mman/linux/mmap.cpp index e149a787fd67b..27df12719e096 100644 --- a/libc/src/sys/mman/linux/mmap.cpp +++ b/libc/src/sys/mman/linux/mmap.cpp @@ -19,11 +19,12 @@ LLVM_LIBC_FUNCTION(void *, mmap, off_t offset)) { auto ptr = internal::mmap(addr, size, prot, flags, fd, offset); - if (ptr.has_value()) - return ptr.value(); - - libc_errno = ptr.error(); - return MAP_FAILED; + if (!ptr.has_value()) { + libc_errno = ptr.error(); + return MAP_FAILED; + } + + return ptr.value(); } } // namespace LIBC_NAMESPACE_DECL From d68d0f90d20ddf5dd21741dbe0e18c5d8a8d27d9 Mon Sep 17 00:00:00 2001 From: Uzair Nawaz Date: Tue, 17 Jun 2025 20:29:50 +0000 Subject: [PATCH 11/11] added LIBC_UNLIKELY to optimize for non-error cases --- libc/src/__support/OSUtil/linux/mmap.cpp | 3 ++- libc/src/__support/OSUtil/linux/munmap.cpp | 5 +++-- libc/src/__support/OSUtil/linux/prctl.cpp | 3 ++- libc/src/__support/OSUtil/linux/read.cpp | 7 ++++--- libc/src/sys/mman/linux/mmap.cpp | 5 +++-- libc/src/sys/mman/linux/munmap.cpp | 3 ++- 6 files changed, 16 insertions(+), 10 deletions(-) diff --git a/libc/src/__support/OSUtil/linux/mmap.cpp b/libc/src/__support/OSUtil/linux/mmap.cpp index 9e27701e73572..05dc79c4662ab 100644 --- a/libc/src/__support/OSUtil/linux/mmap.cpp +++ b/libc/src/__support/OSUtil/linux/mmap.cpp @@ -14,6 +14,7 @@ #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 { @@ -55,7 +56,7 @@ ErrorOr mmap(void *addr, size_t size, int prot, int flags, int fd, // 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) + if (LIBC_UNLIKELY(ret < 0 && ret > -EXEC_PAGESIZE)) return Error(static_cast(-ret)); return reinterpret_cast(ret); diff --git a/libc/src/__support/OSUtil/linux/munmap.cpp b/libc/src/__support/OSUtil/linux/munmap.cpp index 6a11bae263f13..0c42a65a96c2f 100644 --- a/libc/src/__support/OSUtil/linux/munmap.cpp +++ b/libc/src/__support/OSUtil/linux/munmap.cpp @@ -13,7 +13,8 @@ #include "src/__support/error_or.h" #include "src/__support/macros/config.h" -#include // For syscall numbers. +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include // For syscall numbers. namespace LIBC_NAMESPACE_DECL { namespace internal { @@ -24,7 +25,7 @@ ErrorOr munmap(void *addr, size_t size) { int ret = LIBC_NAMESPACE::syscall_impl( SYS_munmap, reinterpret_cast(addr), size); - if (ret < 0) + if (LIBC_UNLIKELY(ret < 0)) return Error(-ret); return 0; diff --git a/libc/src/__support/OSUtil/linux/prctl.cpp b/libc/src/__support/OSUtil/linux/prctl.cpp index 42370ed4d4abb..e701b531ca6fe 100644 --- a/libc/src/__support/OSUtil/linux/prctl.cpp +++ b/libc/src/__support/OSUtil/linux/prctl.cpp @@ -12,6 +12,7 @@ #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 { @@ -29,7 +30,7 @@ ErrorOr prctl(int option, unsigned long arg2, unsigned long arg3, // (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) + if (LIBC_UNLIKELY(ret < 0)) return Error(static_cast(-ret)); return static_cast(ret); diff --git a/libc/src/__support/OSUtil/linux/read.cpp b/libc/src/__support/OSUtil/linux/read.cpp index 88b6c9c754f68..23d7597da3740 100644 --- a/libc/src/__support/OSUtil/linux/read.cpp +++ b/libc/src/__support/OSUtil/linux/read.cpp @@ -11,15 +11,16 @@ #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/sanitizer.h" // for MSAN_UNPOISON -#include // For syscall numbers. +#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 (ret < 0) + if (LIBC_UNLIKELY(ret < 0)) return Error(static_cast(-ret)); // The cast is important since there is a check that dereferences the pointer diff --git a/libc/src/sys/mman/linux/mmap.cpp b/libc/src/sys/mman/linux/mmap.cpp index 27df12719e096..a0cb726132ed2 100644 --- a/libc/src/sys/mman/linux/mmap.cpp +++ b/libc/src/sys/mman/linux/mmap.cpp @@ -11,6 +11,7 @@ #include "src/__support/OSUtil/mmap.h" #include "src/__support/common.h" #include "src/__support/libc_errno.h" +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY namespace LIBC_NAMESPACE_DECL { @@ -19,11 +20,11 @@ LLVM_LIBC_FUNCTION(void *, mmap, off_t offset)) { auto ptr = internal::mmap(addr, size, prot, flags, fd, offset); - if (!ptr.has_value()) { + if (LIBC_UNLIKELY(!ptr.has_value())) { libc_errno = ptr.error(); return MAP_FAILED; } - + return ptr.value(); } diff --git a/libc/src/sys/mman/linux/munmap.cpp b/libc/src/sys/mman/linux/munmap.cpp index 34bbca3231f9c..d4613b5899503 100644 --- a/libc/src/sys/mman/linux/munmap.cpp +++ b/libc/src/sys/mman/linux/munmap.cpp @@ -11,6 +11,7 @@ #include "src/__support/OSUtil/munmap.h" #include "src/__support/common.h" #include "src/__support/libc_errno.h" +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY namespace LIBC_NAMESPACE_DECL { @@ -19,7 +20,7 @@ LLVM_LIBC_FUNCTION(int, munmap, (void *addr, size_t size)) { // A negative return value indicates an error with the magnitude of the // value being the error code. - if (!ret.has_value()) { + if (LIBC_UNLIKELY(!ret.has_value())) { libc_errno = ret.error(); return -1; }