[libc] add mremap (#112804)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -55,6 +55,16 @@ 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: '...'
|
||||
- name: mprotect
|
||||
standards:
|
||||
- POSIX
|
||||
|
||||
@@ -103,7 +103,7 @@ def Linux : StandardSpec<"Linux"> {
|
||||
ArgSpec<UnsignedIntType>,
|
||||
]
|
||||
>,
|
||||
FunctionSpec<
|
||||
FunctionSpec<
|
||||
"remap_file_pages",
|
||||
RetValSpec<IntType>,
|
||||
[
|
||||
@@ -114,6 +114,17 @@ def Linux : StandardSpec<"Linux"> {
|
||||
ArgSpec<IntType>,
|
||||
]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"mremap",
|
||||
RetValSpec<VoidPtr>,
|
||||
[
|
||||
ArgSpec<VoidPtr>,
|
||||
ArgSpec<SizeTType>,
|
||||
ArgSpec<SizeTType>,
|
||||
ArgSpec<IntType>,
|
||||
ArgSpec<VarArgType>,
|
||||
]
|
||||
>,
|
||||
] // Functions
|
||||
>;
|
||||
|
||||
|
||||
@@ -106,3 +106,10 @@ add_entrypoint_object(
|
||||
DEPENDS
|
||||
.${LIBC_TARGET_OS}.shm_unlink
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
mremap
|
||||
ALIAS
|
||||
DEPENDS
|
||||
.${LIBC_TARGET_OS}.mremap
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
45
libc/src/sys/mman/linux/mremap.cpp
Normal file
45
libc/src/sys/mman/linux/mremap.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
//===---------- 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 */)) {
|
||||
|
||||
long ret = 0;
|
||||
void *new_address = nullptr;
|
||||
if (flags & MREMAP_FIXED) {
|
||||
va_list varargs;
|
||||
va_start(varargs, flags);
|
||||
new_address = va_arg(varargs, void *);
|
||||
va_end(varargs);
|
||||
}
|
||||
ret = LIBC_NAMESPACE::syscall_impl<long>(SYS_mremap, old_address, old_size,
|
||||
new_size, flags, new_address);
|
||||
|
||||
if (ret < 0 && ret > -EXEC_PAGESIZE) {
|
||||
libc_errno = static_cast<int>(-ret);
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
return reinterpret_cast<void *>(ret);
|
||||
}
|
||||
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
22
libc/src/sys/mman/mremap.h
Normal file
22
libc/src/sys/mman/mremap.h
Normal file
@@ -0,0 +1,22 @@
|
||||
//===-- 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.
|
||||
// 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
|
||||
@@ -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
|
||||
|
||||
68
libc/test/src/sys/mman/linux/mremap_test.cpp
Normal file
68
libc/test/src/sys/mman/linux/mremap_test.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
//===-- 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/mremap.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());
|
||||
}
|
||||
Reference in New Issue
Block a user