[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
Mon Sep 30 15:04:51 PDT 2024


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

>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 1/3] - 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

>From 5a8891ad6dbd23317f226a2995230f6c8011b674 Mon Sep 17 00:00:00 2001
From: Aly Elashram <alyahelashram at gmail.com>
Date: Sat, 28 Sep 2024 02:43:14 +0300
Subject: [PATCH 2/3] fixup! - 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             |  2 +-
 libc/src/sys/mman/linux/remap_file_pages.cpp  | 22 ++++++++-----------
 libc/src/sys/mman/remap_file_pages.h          |  7 +++---
 .../sys/mman/linux/remap_file_pages_test.cpp  | 16 ++++++++------
 4 files changed, 23 insertions(+), 24 deletions(-)

diff --git a/libc/newhdrgen/yaml/sys/mman.yaml b/libc/newhdrgen/yaml/sys/mman.yaml
index 2f5f199bddec83..7c4fb1ef09e791 100644
--- a/libc/newhdrgen/yaml/sys/mman.yaml
+++ b/libc/newhdrgen/yaml/sys/mman.yaml
@@ -100,7 +100,7 @@ functions:
       - type: int
   - name: remap_file_pages
     standards:
-      - LINUX
+      - Linux
     return_type: int
     arguments:
       - type: void *
diff --git a/libc/src/sys/mman/linux/remap_file_pages.cpp b/libc/src/sys/mman/linux/remap_file_pages.cpp
index 074d24d7c9b435..46e0f8b150ae51 100644
--- a/libc/src/sys/mman/linux/remap_file_pages.cpp
+++ b/libc/src/sys/mman/linux/remap_file_pages.cpp
@@ -1,4 +1,4 @@
-//===----- Linux implementation of the POSIX remap_file_pages function ----===//
+//===------- Linux implementation of the 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.
@@ -6,31 +6,27 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <src/sys/mman/remap_file_pages.h>
+#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.
+#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))
-                    {
+                   (void *addr, size_t size, int prot, size_t pgoff,
+                    int flags)) {
 #ifdef SYS_remap_file_pages
-  long syscall_number = SYS_remap_file_pages;
+  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_remap_file_pages,
+                                              reinterpret_cast<long>(addr),
+                                              size, prot, pgoff, flags);
 #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) {
@@ -41,4 +37,4 @@ LLVM_LIBC_FUNCTION(int, remap_file_pages,
   return 0;
 }
 
-} // namespace LIBC_NAMESPACE_DECL
\ No newline at end of file
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/mman/remap_file_pages.h b/libc/src/sys/mman/remap_file_pages.h
index cfb540fd904140..518502960d5cf1 100644
--- a/libc/src/sys/mman/remap_file_pages.h
+++ b/libc/src/sys/mman/remap_file_pages.h
@@ -10,12 +10,13 @@
 #define LLVM_LIBC_SRC_SYS_MMAN_REMAP_FILE_PAGES_H
 
 #include "src/__support/macros/config.h"
-#include <sys/mman.h>
+#include <stddef.h>
 
 namespace LIBC_NAMESPACE_DECL {
 
-int remap_file_pages(void *addr, size_t size, int prot, size_t pgoff, int flags);
+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
+#endif // LLVM_LIBC_SRC_SYS_MMAN_REMAP_FILE_PAGES_H
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
index 270ae4b6701e97..069303232d0b9d 100644
--- a/libc/test/src/sys/mman/linux/remap_file_pages_test.cpp
+++ b/libc/test/src/sys/mman/linux/remap_file_pages_test.cpp
@@ -10,13 +10,12 @@
 #include "src/sys/mman/mmap.h"
 #include "src/sys/mman/munmap.h"
 #include "src/sys/mman/remap_file_pages.h"
+#include "src/unistd/sysconf.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;
 
@@ -36,7 +35,8 @@ TEST(LlvmLibcRemapFilePagesTest, NoError) {
   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),
+  EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(addr, page_size, PROT_READ,
+                                               page_size, 0),
               Succeeds());
 
   // Reset error number for the new function
@@ -55,7 +55,8 @@ TEST(LlvmLibcRemapFilePagesTest, ErrorInvalidFlags) {
   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),
+  EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(addr, page_size, PROT_READ, 0,
+                                               MAP_PRIVATE),
               Fails(EINVAL));
 
   // Clean up
@@ -67,8 +68,9 @@ TEST(LlvmLibcRemapFilePagesTest, ErrorInvalidAddress) {
   ASSERT_GT(page_size, size_t(0));
 
   // Use an address that we haven't mapped
-  void *invalid_addr = reinterpret_cast<void*>(0x12345000);
+  void *invalid_addr = reinterpret_cast<void *>(0x12345000);
 
-  EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(invalid_addr, page_size, PROT_READ, 0, 0),
+  EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(invalid_addr, page_size,
+                                               PROT_READ, 0, 0),
               Fails(EINVAL));
-}
\ No newline at end of file
+}

>From 17d7626ae3b3a2f1d49fa9f6e63ba263982bcd4f Mon Sep 17 00:00:00 2001
From: Aly Elashram <alyahelashram at gmail.com>
Date: Tue, 1 Oct 2024 01:04:25 +0300
Subject: [PATCH 3/3] fixup! - 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/config/linux/aarch64/entrypoints.txt | 1 +
 libc/config/linux/riscv/entrypoints.txt   | 1 +
 libc/config/linux/x86_64/entrypoints.txt  | 1 +
 3 files changed, 3 insertions(+)

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 64fbe1a250c0ba..0031883c98ac83 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -250,6 +250,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.mman.munlock
     libc.src.sys.mman.munlockall
     libc.src.sys.mman.munmap
+    libc.src.sys.mman.remap_file_pages
     libc.src.sys.mman.posix_madvise
     libc.src.sys.mman.shm_open
     libc.src.sys.mman.shm_unlink
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index ff3d821c664c5b..8a32407b3c6dc7 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -249,6 +249,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.mman.munlock
     libc.src.sys.mman.munlockall
     libc.src.sys.mman.munmap
+    libc.src.sys.mman.remap_file_pages
     libc.src.sys.mman.posix_madvise
     libc.src.sys.mman.shm_open
     libc.src.sys.mman.shm_unlink
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index dd658af3bfb674..4de278f07b6afe 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -249,6 +249,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.mman.munlock
     libc.src.sys.mman.munlockall
     libc.src.sys.mman.munmap
+    libc.src.sys.mman.remap_file_pages
     libc.src.sys.mman.posix_madvise
     libc.src.sys.mman.shm_open
     libc.src.sys.mman.shm_unlink



More information about the libc-commits mailing list