[libc-commits] [libc] Add Linux sys call wrapper in LibC [ Issue #110122 ] (PR #110307)

Aly ElAshram via libc-commits libc-commits at lists.llvm.org
Fri Sep 27 11:06:30 PDT 2024


https://github.com/AlyElashram created https://github.com/llvm/llvm-project/pull/110307

- Create remap_file_pages.h/.cpp wrapper for the linux sys call.
- Add UnitTests for remap_file_pages
- Add function to libc/spec/linux.td
- Add Function spec to mman.yaml

>From 50bf5e92716bfca96c311da021dace6688f98fcd Mon Sep 17 00:00:00 2001
From: Aly Elashram <alyahelashram at gmail.com>
Date: Fri, 27 Sep 2024 20:46:11 +0300
Subject: [PATCH] - Create remap_file_pages wrapper for the linux sys call. -
 Add UnitTest for remap_file_pages - Add function to libc/spec/linux.td - Add
 Function spec to mman.yaml

---
 libc/newhdrgen/yaml/sys/mman.yaml             | 10 +++
 libc/spec/linux.td                            | 11 +++
 libc/src/sys/mman/CMakeLists.txt              |  7 ++
 libc/src/sys/mman/linux/CMakeLists.txt        | 13 ++++
 libc/src/sys/mman/linux/remap_file_pages.cpp  | 44 +++++++++++
 libc/src/sys/mman/remap_file_pages.h          | 21 ++++++
 libc/test/src/sys/mman/linux/CMakeLists.txt   | 17 +++++
 .../sys/mman/linux/remap_file_pages_test.cpp  | 74 +++++++++++++++++++
 8 files changed, 197 insertions(+)
 create mode 100644 libc/src/sys/mman/linux/remap_file_pages.cpp
 create mode 100644 libc/src/sys/mman/remap_file_pages.h
 create mode 100644 libc/test/src/sys/mman/linux/remap_file_pages_test.cpp

diff --git a/libc/newhdrgen/yaml/sys/mman.yaml b/libc/newhdrgen/yaml/sys/mman.yaml
index 272e7e2af16aaf..2f5f199bddec83 100644
--- a/libc/newhdrgen/yaml/sys/mman.yaml
+++ b/libc/newhdrgen/yaml/sys/mman.yaml
@@ -98,6 +98,16 @@ functions:
       - type: void *
       - type: size_t
       - type: int
+  - name: remap_file_pages
+    standards:
+      - LINUX
+    return_type: int
+    arguments:
+      - type: void *
+      - type: size_t
+      - type: int
+      - type: size_t
+      - type: int
   - name: shm_open
     standards:
       - POSIX
diff --git a/libc/spec/linux.td b/libc/spec/linux.td
index 395c2a6fe853a7..4aaf18b0803f3d 100644
--- a/libc/spec/linux.td
+++ b/libc/spec/linux.td
@@ -103,6 +103,17 @@ def Linux : StandardSpec<"Linux"> {
             ArgSpec<UnsignedIntType>,
           ]
         >,
+         FunctionSpec<
+          "remap_file_pages",
+          RetValSpec<IntType>,
+          [
+            ArgSpec<VoidPtr>,
+            ArgSpec<SizeTType>,
+            ArgSpec<IntType>,
+            ArgSpec<SizeTType>,
+            ArgSpec<IntType>,
+          ]
+        >,
       ]  // Functions
   >;
 
diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt
index 9c74202a09f035..4ea43e14be0297 100644
--- a/libc/src/sys/mman/CMakeLists.txt
+++ b/libc/src/sys/mman/CMakeLists.txt
@@ -86,6 +86,13 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.msync
 )
 
+add_entrypoint_object(
+  remap_file_pages
+  ALIAS
+  DEPENDS
+  .${LIBC_TARGET_OS}.remap_file_pages
+)
+
 add_entrypoint_object(
   shm_open
   ALIAS
diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt
index 00f4f0e64ec06b..f673d47ba96aef 100644
--- a/libc/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/src/sys/mman/linux/CMakeLists.txt
@@ -153,6 +153,19 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  remap_file_pages
+  SRCS
+    remap_file_pages.cpp.cpp
+  HDRS
+    ../remap_file_pages.h.h
+  DEPENDS
+    libc.include.sys_mman
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+)
+
 add_header_library(
   shm_common
   HDRS
diff --git a/libc/src/sys/mman/linux/remap_file_pages.cpp b/libc/src/sys/mman/linux/remap_file_pages.cpp
new file mode 100644
index 00000000000000..074d24d7c9b435
--- /dev/null
+++ b/libc/src/sys/mman/linux/remap_file_pages.cpp
@@ -0,0 +1,44 @@
+//===----- Linux implementation of the POSIX remap_file_pages 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/remap_file_pages.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 <sys/syscall.h>          // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+
+// This function is currently linux only. It has to be refactored suitably if
+// remap_file_pages is to be supported on non-linux operating systems also.
+LLVM_LIBC_FUNCTION(int, remap_file_pages,
+                   (void *addr, size_t size, int prot, size_t pgoff, int flags))
+                    {
+#ifdef SYS_remap_file_pages
+  long syscall_number = SYS_remap_file_pages;
+#else
+#error "remap_file_pages syscall is not available."
+#endif
+
+
+  int ret = LIBC_NAMESPACE::syscall_impl<int>(
+  syscall_number, reinterpret_cast<long>(addr), size, prot, pgoff, flags);
+
+  // 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
\ No newline at end of file
diff --git a/libc/src/sys/mman/remap_file_pages.h b/libc/src/sys/mman/remap_file_pages.h
new file mode 100644
index 00000000000000..cfb540fd904140
--- /dev/null
+++ b/libc/src/sys/mman/remap_file_pages.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for remap_file_pages 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_REMAP_FILE_PAGES_H
+#define LLVM_LIBC_SRC_SYS_MMAN_REMAP_FILE_PAGES_H
+
+#include "src/__support/macros/config.h"
+#include <sys/mman.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+int remap_file_pages(void *addr, size_t size, int prot, size_t pgoff, int flags);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif //LLVM_LIBC_SRC_SYS_MMAN_REMAP_FILE_PAGES_H
diff --git a/libc/test/src/sys/mman/linux/CMakeLists.txt b/libc/test/src/sys/mman/linux/CMakeLists.txt
index b63c76f4306fac..3718f732b425f6 100644
--- a/libc/test/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/test/src/sys/mman/linux/CMakeLists.txt
@@ -128,6 +128,23 @@ add_libc_unittest(
     libc.test.UnitTest.ErrnoSetterMatcher
 )
 
+add_libc_unittest(
+  remap_file_pages_test
+  SUITE
+    libc_sys_mman_unittests
+  SRCS
+    remap_file_pages_test.cpp
+  DEPENDS
+    libc.include.sys_mman
+    libc.src.unistd.sysconf
+    libc.test.UnitTest.Test
+    libc.test.UnitTest.ErrnoSetterMatcher
+    libc.src.sys.mman.remap_file_pages
+    libc.src.errno.errno
+    libc.src.sys.mman.mmap
+    libc.src.sys.mman.munmap
+)
+
 add_libc_unittest(
   shm_test
   SUITE
diff --git a/libc/test/src/sys/mman/linux/remap_file_pages_test.cpp b/libc/test/src/sys/mman/linux/remap_file_pages_test.cpp
new file mode 100644
index 00000000000000..270ae4b6701e97
--- /dev/null
+++ b/libc/test/src/sys/mman/linux/remap_file_pages_test.cpp
@@ -0,0 +1,74 @@
+//===-- Unittests for remap_file_pages ------------------------------------===//
+//
+// 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 "src/sys/mman/remap_file_pages.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "src/unistd/sysconf.h"
+
+#include <sys/mman.h>
+
+
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+
+TEST(LlvmLibcRemapFilePagesTest, NoError) {
+  size_t page_size = sysconf(_SC_PAGE_SIZE);
+  ASSERT_GT(page_size, size_t(0));
+
+  // First, allocate some memory using mmap
+  size_t alloc_size = 2 * page_size;
+  LIBC_NAMESPACE::libc_errno = 0;
+  void *addr = LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ | PROT_WRITE,
+                                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  ASSERT_ERRNO_SUCCESS();
+  EXPECT_NE(addr, MAP_FAILED);
+
+  // Reset error number for the new function
+  LIBC_NAMESPACE::libc_errno = 0;
+
+  // Now try to remap the pages
+  EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(addr, page_size, PROT_READ, page_size, 0),
+              Succeeds());
+
+  // Reset error number for the new function
+  LIBC_NAMESPACE::libc_errno = 0;
+
+  // Clean up
+  EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, alloc_size), Succeeds());
+}
+
+TEST(LlvmLibcRemapFilePagesTest, ErrorInvalidFlags) {
+  size_t page_size = sysconf(_SC_PAGESIZE);
+  ASSERT_GT(page_size, size_t(0));
+
+  void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ | PROT_WRITE,
+                                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  ASSERT_NE(addr, MAP_FAILED);
+
+  // Try to remap pages with an invalid flag MAP_PRIVATE
+  EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(addr, page_size, PROT_READ, 0, MAP_PRIVATE),
+              Fails(EINVAL));
+
+  // Clean up
+  EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds());
+}
+
+TEST(LlvmLibcRemapFilePagesTest, ErrorInvalidAddress) {
+  size_t page_size = sysconf(_SC_PAGESIZE);
+  ASSERT_GT(page_size, size_t(0));
+
+  // Use an address that we haven't mapped
+  void *invalid_addr = reinterpret_cast<void*>(0x12345000);
+
+  EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(invalid_addr, page_size, PROT_READ, 0, 0),
+              Fails(EINVAL));
+}
\ No newline at end of file



More information about the libc-commits mailing list