From 525ae42da8f940c8792426b0b4743cc9148eb9f0 Mon Sep 17 00:00:00 2001 From: Jingyu Qiu <118010248@link.cuhk.edu.cn> Date: Wed, 9 Oct 2024 17:53:47 -0400 Subject: [PATCH 1/4] add mremap --- libc/newhdrgen/yaml/sys/mman.yaml | 11 ++++ libc/spec/linux.td | 13 +++- libc/src/sys/mman/CMakeLists.txt | 7 ++ libc/src/sys/mman/linux/CMakeLists.txt | 13 ++++ libc/src/sys/mman/linux/mremap.cpp | 53 ++++++++++++++++ libc/src/sys/mman/mremap.h | 23 +++++++ libc/test/src/sys/mman/linux/CMakeLists.txt | 15 +++++ libc/test/src/sys/mman/linux/mremap_test.cpp | 67 ++++++++++++++++++++ 8 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 libc/src/sys/mman/linux/mremap.cpp create mode 100644 libc/src/sys/mman/mremap.h create mode 100644 libc/test/src/sys/mman/linux/mremap_test.cpp diff --git a/libc/newhdrgen/yaml/sys/mman.yaml b/libc/newhdrgen/yaml/sys/mman.yaml index 7c4fb1ef09e79..4b062f7202053 100644 --- a/libc/newhdrgen/yaml/sys/mman.yaml +++ b/libc/newhdrgen/yaml/sys/mman.yaml @@ -55,6 +55,17 @@ functions: - type: int - type: int - type: off_t + - name: mremap + standards: + - POSIX + return_type: void * + arguments: + - type: void * + - type: size_t + - type: size_t + - type: int + - type: void * + description: "This argument is optional." - name: mprotect standards: - POSIX diff --git a/libc/spec/linux.td b/libc/spec/linux.td index 4aaf18b0803f3..6dda2c03213e4 100644 --- a/libc/spec/linux.td +++ b/libc/spec/linux.td @@ -103,7 +103,7 @@ def Linux : StandardSpec<"Linux"> { ArgSpec, ] >, - FunctionSpec< + FunctionSpec< "remap_file_pages", RetValSpec, [ @@ -114,6 +114,17 @@ def Linux : StandardSpec<"Linux"> { ArgSpec, ] >, + FunctionSpec< + "mremap", + RetValSpec, + [ + ArgSpec, + ArgSpec, + ArgSpec, + ArgSpec, + ArgSpec, + ] + >, ] // Functions >; diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt index 4ea43e14be029..8126d6205c9a1 100644 --- a/libc/src/sys/mman/CMakeLists.txt +++ b/libc/src/sys/mman/CMakeLists.txt @@ -106,3 +106,10 @@ add_entrypoint_object( DEPENDS .${LIBC_TARGET_OS}.shm_unlink ) + +add_entrypoint_object( + mremap, + ALIAS, + DEPENDS + .${LIBC_TARGET_OS}.mremap +) diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt index 11188254cfbd4..50c75179095a4 100644 --- a/libc/src/sys/mman/linux/CMakeLists.txt +++ b/libc/src/sys/mman/linux/CMakeLists.txt @@ -24,6 +24,19 @@ add_entrypoint_object( libc.src.errno.errno ) +add_entrypoint_object( + mremap + SRCS + mremap.cpp + HDRS + ../mremap.h + DEPENDS + libc.include.sys_mman + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + add_entrypoint_object( munmap SRCS diff --git a/libc/src/sys/mman/linux/mremap.cpp b/libc/src/sys/mman/linux/mremap.cpp new file mode 100644 index 0000000000000..182d1c2482935 --- /dev/null +++ b/libc/src/sys/mman/linux/mremap.cpp @@ -0,0 +1,53 @@ +//===---------- Linux implementation of the POSIX mremap function +//-----------===// +// +// 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/sys/mman/mremap.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" + +#include "src/__support/macros/config.h" +#include "src/errno/libc_errno.h" +#include // For EXEC_PAGESIZE. +#include +#include // For syscall numbers. + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(void *, mremap, + (void *old_address, size_t old_size, size_t new_size, + int flags, ... /* void *new_address */)) { + +#ifdef SYS_mremap + long syscall_number = SYS_mremap; +#else +#error "mremap syscalls not available." +#endif + long ret = 0; + if (flags & MREMAP_FIXED) { + void *arg; + va_list varargs; + va_start(varargs, flags); + arg = va_arg(varargs, void *); + va_end(varargs); + ret = LIBC_NAMESPACE::syscall_impl(syscall_number, old_address, old_size, + new_size, flags, arg); + } else { + ret = LIBC_NAMESPACE::syscall_impl(syscall_number, old_address, old_size, + new_size, flags); + } + if (ret < 0 && ret > -EXEC_PAGESIZE) { + libc_errno = static_cast(-ret); + return MAP_FAILED; + } + + return reinterpret_cast(ret); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/mman/mremap.h b/libc/src/sys/mman/mremap.h new file mode 100644 index 0000000000000..5287658089dd5 --- /dev/null +++ b/libc/src/sys/mman/mremap.h @@ -0,0 +1,23 @@ +//===-- Implementation header for mremap 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_SYS_MMAN_MREMAP_H +#define LLVM_LIBC_SRC_SYS_MMAN_MREMAP_H + +#include "src/__support/macros/config.h" +#include // For size_t and off_t + +namespace LIBC_NAMESPACE_DECL { + +void *mremap(void *old_address, size_t old_size, size_t new_size, int flags, + ... /* void *new_address */); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_SYS_MMAN_MREMAP_H diff --git a/libc/test/src/sys/mman/linux/CMakeLists.txt b/libc/test/src/sys/mman/linux/CMakeLists.txt index a432d88ffb90c..cf8e4f41d9441 100644 --- a/libc/test/src/sys/mman/linux/CMakeLists.txt +++ b/libc/test/src/sys/mman/linux/CMakeLists.txt @@ -14,6 +14,21 @@ add_libc_unittest( libc.test.UnitTest.ErrnoSetterMatcher ) +add_libc_unittest( + mremap_test + SUITE + libc_sys_mman_unittests + SRCS + mremap_test.cpp + DEPENDS + libc.include.sys_mman + libc.src.errno.errno + libc.src.sys.mman.mmap + libc.src.sys.mman.mremap + libc.src.sys.mman.munmap + libc.test.UnitTest.ErrnoSetterMatcher +) + if (NOT LLVM_USE_SANITIZER) add_libc_unittest( mprotect_test diff --git a/libc/test/src/sys/mman/linux/mremap_test.cpp b/libc/test/src/sys/mman/linux/mremap_test.cpp new file mode 100644 index 0000000000000..36f606386467d --- /dev/null +++ b/libc/test/src/sys/mman/linux/mremap_test.cpp @@ -0,0 +1,67 @@ +//===-- Unittests for mremap ----------------------------------------------===// +// +// 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/errno/libc_errno.h" +#include "src/sys/mman/mmap.h" +#include "src/sys/mman/munmap.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/Test.h" + +#include + +using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; +using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; + +TEST(LlvmLibcMremapTest, NoError) { + size_t initial_size = 128; + size_t new_size = 256; + LIBC_NAMESPACE::libc_errno = 0; + + // Allocate memory using mmap. + void *addr = + LIBC_NAMESPACE::mmap(nullptr, initial_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + ASSERT_ERRNO_SUCCESS(); + EXPECT_NE(addr, MAP_FAILED); + + int *array = reinterpret_cast(addr); + // Writing to the memory should not crash the test. + array[0] = 123; + EXPECT_EQ(array[0], 123); + + // Re-map the memory using mremap with an increased size. + void *new_addr = + LIBC_NAMESPACE::mremap(addr, initial_size, new_size, MREMAP_MAYMOVE); + ASSERT_ERRNO_SUCCESS(); + EXPECT_NE(new_addr, MAP_FAILED); + EXPECT_EQ(reinterpret_cast(new_addr)[0], + 123); // Verify data is preserved. + + // Clean up memory by unmapping it. + EXPECT_THAT(LIBC_NAMESPACE::munmap(new_addr, new_size), Succeeds()); +} + +TEST(LlvmLibcMremapTest, Error_InvalidSize) { + size_t initial_size = 128; + LIBC_NAMESPACE::libc_errno = 0; + + // Allocate memory using mmap. + void *addr = + LIBC_NAMESPACE::mmap(nullptr, initial_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + ASSERT_ERRNO_SUCCESS(); + EXPECT_NE(addr, MAP_FAILED); + + // Attempt to re-map the memory with an invalid new size (0). + void *new_addr = + LIBC_NAMESPACE::mremap(addr, initial_size, 0, MREMAP_MAYMOVE); + EXPECT_THAT(new_addr, Fails(EINVAL, MAP_FAILED)); + + // Clean up the original mapping. + EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, initial_size), Succeeds()); +} From 9f34176a0cc42afce265531affbbd5c441e866f6 Mon Sep 17 00:00:00 2001 From: Jingyu Qiu <118010248@link.cuhk.edu.cn> Date: Thu, 31 Oct 2024 15:12:02 -0400 Subject: [PATCH 2/4] add entry point of test --- libc/config/linux/aarch64/entrypoints.txt | 1 + libc/config/linux/x86_64/entrypoints.txt | 1 + libc/src/sys/mman/CMakeLists.txt | 4 ++-- libc/src/sys/mman/linux/mremap.cpp | 17 ++++++----------- libc/src/sys/mman/mremap.h | 3 +-- libc/test/src/sys/mman/linux/mremap_test.cpp | 1 + 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 885827d304efe..d511c4bb3bc11 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -245,6 +245,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.mlock2 libc.src.sys.mman.mlockall libc.src.sys.mman.mmap + libc.src.sys.mman.mremap libc.src.sys.mman.mprotect libc.src.sys.mman.msync libc.src.sys.mman.munlock diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 39f451d6b5fc0..eefd6b7b9af9c 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -244,6 +244,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.mlock2 libc.src.sys.mman.mlockall libc.src.sys.mman.mmap + libc.src.sys.mman.mremap libc.src.sys.mman.mprotect libc.src.sys.mman.msync libc.src.sys.mman.munlock diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt index 8126d6205c9a1..4d4c2ad376050 100644 --- a/libc/src/sys/mman/CMakeLists.txt +++ b/libc/src/sys/mman/CMakeLists.txt @@ -108,8 +108,8 @@ add_entrypoint_object( ) add_entrypoint_object( - mremap, - ALIAS, + mremap + ALIAS DEPENDS .${LIBC_TARGET_OS}.mremap ) diff --git a/libc/src/sys/mman/linux/mremap.cpp b/libc/src/sys/mman/linux/mremap.cpp index 182d1c2482935..e91a77aab230c 100644 --- a/libc/src/sys/mman/linux/mremap.cpp +++ b/libc/src/sys/mman/linux/mremap.cpp @@ -24,23 +24,18 @@ LLVM_LIBC_FUNCTION(void *, mremap, (void *old_address, size_t old_size, size_t new_size, int flags, ... /* void *new_address */)) { -#ifdef SYS_mremap - long syscall_number = SYS_mremap; -#else -#error "mremap syscalls not available." -#endif long ret = 0; + void *new_address = nullptr; if (flags & MREMAP_FIXED) { - void *arg; va_list varargs; va_start(varargs, flags); - arg = va_arg(varargs, void *); + new_address = va_arg(varargs, void *); va_end(varargs); - ret = LIBC_NAMESPACE::syscall_impl(syscall_number, old_address, old_size, - new_size, flags, arg); + ret = LIBC_NAMESPACE::syscall_impl(SYS_mremap, old_address, old_size, + new_size, flags, new_address); } else { - ret = LIBC_NAMESPACE::syscall_impl(syscall_number, old_address, old_size, - new_size, flags); + ret = LIBC_NAMESPACE::syscall_impl(SYS_mremap, old_address, old_size, + new_size, flags); } if (ret < 0 && ret > -EXEC_PAGESIZE) { libc_errno = static_cast(-ret); diff --git a/libc/src/sys/mman/mremap.h b/libc/src/sys/mman/mremap.h index 5287658089dd5..208946bc58a2e 100644 --- a/libc/src/sys/mman/mremap.h +++ b/libc/src/sys/mman/mremap.h @@ -1,5 +1,4 @@ -//===-- Implementation header for mremap function -----------------*- C++ -//-*-===// +//===-- Implementation header for mremap function -------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libc/test/src/sys/mman/linux/mremap_test.cpp b/libc/test/src/sys/mman/linux/mremap_test.cpp index 36f606386467d..12e4485588421 100644 --- a/libc/test/src/sys/mman/linux/mremap_test.cpp +++ b/libc/test/src/sys/mman/linux/mremap_test.cpp @@ -8,6 +8,7 @@ #include "src/errno/libc_errno.h" #include "src/sys/mman/mmap.h" +#include "src/sys/mman/mremap.h" #include "src/sys/mman/munmap.h" #include "test/UnitTest/ErrnoSetterMatcher.h" #include "test/UnitTest/Test.h" From 380d36ea00209b0c84d42028c7eb55dc1b27ce9c Mon Sep 17 00:00:00 2001 From: Jingyu Qiu <118010248@link.cuhk.edu.cn> Date: Fri, 1 Nov 2024 17:52:41 -0400 Subject: [PATCH 3/4] format --- libc/src/sys/mman/linux/mremap.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/libc/src/sys/mman/linux/mremap.cpp b/libc/src/sys/mman/linux/mremap.cpp index e91a77aab230c..38bcfce833d3d 100644 --- a/libc/src/sys/mman/linux/mremap.cpp +++ b/libc/src/sys/mman/linux/mremap.cpp @@ -1,5 +1,4 @@ -//===---------- Linux implementation of the POSIX mremap function -//-----------===// +//===---------- Linux implementation of the POSIX mremap function----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -31,12 +30,10 @@ LLVM_LIBC_FUNCTION(void *, mremap, va_start(varargs, flags); new_address = va_arg(varargs, void *); va_end(varargs); - ret = LIBC_NAMESPACE::syscall_impl(SYS_mremap, old_address, old_size, - new_size, flags, new_address); - } else { - ret = LIBC_NAMESPACE::syscall_impl(SYS_mremap, old_address, old_size, - new_size, flags); } + ret = LIBC_NAMESPACE::syscall_impl(SYS_mremap, old_address, old_size, + new_size, flags, new_address); + if (ret < 0 && ret > -EXEC_PAGESIZE) { libc_errno = static_cast(-ret); return MAP_FAILED; From 4eb09f0d160dc720b42e6310a262cee5a00e87c2 Mon Sep 17 00:00:00 2001 From: Jingyu Qiu <118010248@link.cuhk.edu.cn> Date: Tue, 5 Nov 2024 16:49:28 -0500 Subject: [PATCH 4/4] fix type spec --- libc/newhdrgen/yaml/sys/mman.yaml | 3 +-- libc/spec/linux.td | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libc/newhdrgen/yaml/sys/mman.yaml b/libc/newhdrgen/yaml/sys/mman.yaml index 4b062f7202053..962ca3591917f 100644 --- a/libc/newhdrgen/yaml/sys/mman.yaml +++ b/libc/newhdrgen/yaml/sys/mman.yaml @@ -64,8 +64,7 @@ functions: - type: size_t - type: size_t - type: int - - type: void * - description: "This argument is optional." + - type: '...' - name: mprotect standards: - POSIX diff --git a/libc/spec/linux.td b/libc/spec/linux.td index 6dda2c03213e4..0ac1d3d8730a8 100644 --- a/libc/spec/linux.td +++ b/libc/spec/linux.td @@ -122,7 +122,7 @@ def Linux : StandardSpec<"Linux"> { ArgSpec, ArgSpec, ArgSpec, - ArgSpec, + ArgSpec, ] >, ] // Functions