[libc-commits] [libc] add mremap (PR #112804)
via libc-commits
libc-commits at lists.llvm.org
Thu Oct 17 17:54:51 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Jingyu Qiu (SoftJing1)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/112804.diff
8 Files Affected:
- (modified) libc/newhdrgen/yaml/sys/mman.yaml (+11)
- (modified) libc/spec/linux.td (+11)
- (modified) libc/src/sys/mman/CMakeLists.txt (+7)
- (modified) libc/src/sys/mman/linux/CMakeLists.txt (+13)
- (added) libc/src/sys/mman/linux/mremap.cpp (+53)
- (added) libc/src/sys/mman/mremap.h (+23)
- (modified) libc/test/src/sys/mman/linux/CMakeLists.txt (+15)
- (added) libc/test/src/sys/mman/linux/mremap_test.cpp (+67)
``````````diff
diff --git a/libc/newhdrgen/yaml/sys/mman.yaml b/libc/newhdrgen/yaml/sys/mman.yaml
index 272e7e2af16aaf..23637f733a2b8d 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 395c2a6fe853a7..3b4fff383472ec 100644
--- a/libc/spec/linux.td
+++ b/libc/spec/linux.td
@@ -103,6 +103,17 @@ def Linux : StandardSpec<"Linux"> {
ArgSpec<UnsignedIntType>,
]
>,
+ FunctionSpec<
+ "mremap",
+ RetValSpec<VoidPtr>,
+ [
+ ArgSpec<VoidPtr>,
+ ArgSpec<SizeTType>,
+ ArgSpec<SizeTType>,
+ ArgSpec<IntType>,
+ ArgSpec<VoidPtr>,
+ ]
+ >,
] // Functions
>;
diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt
index 9c74202a09f035..246460bab7a824 100644
--- a/libc/src/sys/mman/CMakeLists.txt
+++ b/libc/src/sys/mman/CMakeLists.txt
@@ -99,3 +99,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 00f4f0e64ec06b..740316b763dfa1 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 00000000000000..182d1c24829358
--- /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 <linux/param.h> // For EXEC_PAGESIZE.
+#include <stdarg.h>
+#include <sys/syscall.h> // 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<int>(-ret);
+ return MAP_FAILED;
+ }
+
+ return reinterpret_cast<void *>(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 00000000000000..5287658089dd54
--- /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 <sys/mman.h> // 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 b63c76f4306fac..dcc2045250a4c9 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 00000000000000..36f606386467db
--- /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 <sys/mman.h>
+
+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<int *>(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<int *>(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());
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/112804
More information about the libc-commits
mailing list