Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions libc/newhdrgen/yaml/sys/mman.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 12 additions & 1 deletion libc/spec/linux.td
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def Linux : StandardSpec<"Linux"> {
ArgSpec<UnsignedIntType>,
]
>,
FunctionSpec<
FunctionSpec<
"remap_file_pages",
RetValSpec<IntType>,
[
Expand All @@ -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
>;

Expand Down
7 changes: 7 additions & 0 deletions libc/src/sys/mman/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,10 @@ add_entrypoint_object(
DEPENDS
.${LIBC_TARGET_OS}.shm_unlink
)

add_entrypoint_object(
mremap
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.mremap
)
13 changes: 13 additions & 0 deletions libc/src/sys/mman/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
45 changes: 45 additions & 0 deletions libc/src/sys/mman/linux/mremap.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 22 additions & 0 deletions libc/src/sys/mman/mremap.h
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions libc/test/src/sys/mman/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
68 changes: 68 additions & 0 deletions libc/test/src/sys/mman/linux/mremap_test.cpp
Original file line number Diff line number Diff line change
@@ -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());
}
Loading