[libc] Move the implementation of mmap and munmap into a linux specific area.
authorSiva Chandra Reddy <sivachandra@google.com>
Tue, 7 Jan 2020 21:46:12 +0000 (13:46 -0800)
committerSiva Chandra Reddy <sivachandra@google.com>
Fri, 24 Jan 2020 23:42:28 +0000 (15:42 -0800)
This allows us to get rid of the PAGE_SIZE macro and use EXEC_PAGESIZE
from linux/param.h.

Few other points about this change:
1. The linux syscall functions have been moved into a linux specific area
instead of src/unistd/syscall.h. The Linux syscall function from unistd.h
is a public vararg function. What we have currently are linux speciif internal
overloaded C++ functions. So, moving them to a Linux only area is more
meaningful.
2. The implementations of mmap and munmap are now in a 'linux' directory
within src/sys/mman. The idea here is that platform specific
implementations will live in a platform specific subdirectories like these.
Infrastructure common to a platform will live in the platform's config
directory. For example, the linux syscall implementations live in
config/linux.

Reviewers: abrachet

Tags: #libc-project

Differential Revision: https://reviews.llvm.org/D73302

19 files changed:
libc/config/linux/CMakeLists.txt
libc/config/linux/platfrom_defs.h.inc
libc/config/linux/syscall.h.def [new file with mode: 0644]
libc/include/CMakeLists.txt
libc/src/CMakeLists.txt
libc/src/sys/mman/CMakeLists.txt
libc/src/sys/mman/linux/CMakeLists.txt [new file with mode: 0644]
libc/src/sys/mman/linux/mmap.cpp [new file with mode: 0644]
libc/src/sys/mman/linux/munmap.cpp [new file with mode: 0644]
libc/src/sys/mman/mmap.cpp [deleted file]
libc/src/sys/mman/munmap.cpp [deleted file]
libc/src/unistd/CMakeLists.txt [deleted file]
libc/src/unistd/syscall.h.def [deleted file]
libc/test/config/linux/x86_64/CMakeLists.txt
libc/test/config/linux/x86_64/syscall_test.cpp
libc/test/src/sys/mman/CMakeLists.txt
libc/test/src/sys/mman/linux/CMakeLists.txt [new file with mode: 0644]
libc/test/src/sys/mman/linux/mmap_test.cpp [new file with mode: 0644]
libc/test/src/sys/mman/mmap_test.cpp [deleted file]

index 7e2608e595f5b60bb51e4c1ef6dbbe7aca6912d2..86b178abb0dec8d06a7b346243c60898091a1f15 100644 (file)
@@ -1 +1,11 @@
+add_gen_header(
+  linux_syscall_h
+  DEF_FILE syscall.h.def
+  GEN_HDR syscall.h
+  PARAMS
+    inline_syscalls=${LIBC_TARGET_MACHINE}/syscall.h.inc
+  DATA_FILES
+    ${LIBC_TARGET_MACHINE}/syscall.h.inc
+)
+
 add_subdirectory(x86_64)
index 19bf3f7593c19996cc0626e92345a9903a0a7baa..495d07c80cf29483024adfe4f81c4278713f8eb4 100644 (file)
@@ -11,9 +11,3 @@
 #define ENTRYPOINT_SECTION_ATTRIBUTE(name) \
     __attribute__((section(".llvm.libc.entrypoint."#name)))
 #define LLVM_LIBC_ENTRYPOINT(name) ENTRYPOINT_SECTION_ATTRIBUTE(name) name
-
-// TODO: Get rid of the PAGE_SIZE macro. It is present only as an interim
-// measure until we can move the implementations of mmap and munmap to under
-// the config/linux directory. After that, the implementations can use
-// EXEC_PAGESIZE until page size can be read from the aux vector. 
-#define PAGE_SIZE 4096
diff --git a/libc/config/linux/syscall.h.def b/libc/config/linux/syscall.h.def
new file mode 100644 (file)
index 0000000..7f52a26
--- /dev/null
@@ -0,0 +1,9 @@
+//===--------------- Internal syscall declarations --------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+%%include_file(${inline_syscalls})
index 7773be6227a320dc88cc6d0bbf41a9d4a6fa7009..8558d7586b57a299c1ddcfecaf0f25405483f894 100644 (file)
@@ -56,6 +56,7 @@ add_gen_header(
   GEN_HDR sys/mman.h
   DEPENDS
     libc_posix_types_h
+    llvm_libc_common_h
 )
 
 add_gen_header(
index 28084cd9a9be86d8804b0df76de0a88449d0c8a0..b416e83934d6cb814fd25e5624d85c7e43abf84f 100644 (file)
@@ -3,6 +3,5 @@ add_subdirectory(math)
 add_subdirectory(string)
 # TODO: Add this target conditional to the target OS.
 add_subdirectory(sys)
-add_subdirectory(unistd)
 
 add_subdirectory(__support)
index 9b8cc66299a6cb54099fb87d7b45391052834df0..b4bbe81c92ff2ebe511e5102fe9f9f56f8f0093b 100644 (file)
@@ -1,27 +1,3 @@
-#TODO: The sources and target listed here should ideally live in config/linux.
-
-add_entrypoint_object(
-  mmap
-  SRCS
-    mmap.cpp
-  HDRS
-    mmap.h
-  DEPENDS
-    sys_mman_h
-    sys_syscall_h
-    syscall_impl_h
-    __errno_location
-)
-
-add_entrypoint_object(
-  munmap
-  SRCS
-    munmap.cpp
-  HDRS
-    munmap.h
-  DEPENDS
-    sys_mman_h
-    sys_syscall_h
-    syscall_impl_h
-    __errno_location
-)
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${LIBC_TARGET_OS})
+endif()
diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt
new file mode 100644 (file)
index 0000000..527da64
--- /dev/null
@@ -0,0 +1,25 @@
+add_entrypoint_object(
+  mmap
+  SRCS
+    mmap.cpp
+  HDRS
+    ../mmap.h
+  DEPENDS
+    sys_mman_h
+    sys_syscall_h
+    linux_syscall_h
+    __errno_location
+)
+
+add_entrypoint_object(
+  munmap
+  SRCS
+    munmap.cpp
+  HDRS
+    ../munmap.h
+  DEPENDS
+    sys_mman_h
+    sys_syscall_h
+    linux_syscall_h
+    __errno_location
+)
diff --git a/libc/src/sys/mman/linux/mmap.cpp b/libc/src/sys/mman/linux/mmap.cpp
new file mode 100644 (file)
index 0000000..616cd98
--- /dev/null
@@ -0,0 +1,62 @@
+//===---------- Linux implementation of the POSIX mmap 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/mmap.h"
+
+#include "config/linux/syscall.h" // For internal syscall function.
+#include "include/sys/syscall.h"  // For syscall numbers.
+#include "src/__support/common.h"
+#include "src/errno/llvmlibc_errno.h"
+
+#include <linux/param.h> // For EXEC_PAGESIZE.
+
+namespace __llvm_libc {
+
+// This function is currently linux only. It has to be refactored suitably if
+// mmap is to be supported on non-linux operating systems also.
+void *LLVM_LIBC_ENTRYPOINT(mmap)(void *addr, size_t size, int prot, int flags,
+                                 int fd, off_t offset) {
+  // A lot of POSIX standard prescribed validation of the parameters is not
+  // done in this function as modern linux versions do it in the syscall.
+  // TODO: Perform argument validation not done by the linux syscall.
+
+  // EXEC_PAGESIZE is used for the page size. While this is OK for x86_64, it
+  // might not be correct in general.
+  // TODO: Use pagesize read from the ELF aux vector instead of EXEC_PAGESIZE.
+
+#ifdef SYS_mmap2
+  offset /= EXEC_PAGESIZE;
+  long syscall_number = SYS_mmap2;
+#elif SYS_mmap
+  long syscall_number = SYS_mmap;
+#else
+#error "Target platform does not have SYS_mmap or SYS_mmap2 defined"
+#endif
+
+  long ret_val =
+      __llvm_libc::syscall(syscall_number, reinterpret_cast<long>(addr), size,
+                           prot, flags, fd, offset);
+
+  // The mmap/mmap2 syscalls return negative values on error. These negative
+  // values are actually the negative values of the error codes. So, fix them
+  // up in case an error code is detected.
+  //
+  // A point to keep in mind for the fix up is that a negative return value
+  // from the syscall can also be an error-free value returned by the syscall.
+  // However, since a valid return address cannot be within the last page, a
+  // return value corresponding to a location in the last page is an error
+  // value.
+  if (ret_val < 0 && ret_val > -EXEC_PAGESIZE) {
+    llvmlibc_errno = -ret_val;
+    return MAP_FAILED;
+  }
+
+  return reinterpret_cast<void *>(ret_val);
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/sys/mman/linux/munmap.cpp b/libc/src/sys/mman/linux/munmap.cpp
new file mode 100644 (file)
index 0000000..1f112f8
--- /dev/null
@@ -0,0 +1,34 @@
+//===---------- Linux implementation of the POSIX munmap 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/munmap.h"
+
+#include "config/linux/syscall.h" // For internal syscall function.
+#include "include/sys/syscall.h"  // For syscall numbers.
+#include "src/__support/common.h"
+#include "src/errno/llvmlibc_errno.h"
+
+namespace __llvm_libc {
+
+// This function is currently linux only. It has to be refactored suitably if
+// mmap is to be supported on non-linux operating systems also.
+int LLVM_LIBC_ENTRYPOINT(munmap)(void *addr, size_t size) {
+  long ret_val =
+      __llvm_libc::syscall(SYS_munmap, reinterpret_cast<long>(addr), size);
+
+  // A negative return value indicates an error with the magnitude of the
+  // value being the error code.
+  if (ret_val < 0) {
+    llvmlibc_errno = -ret_val;
+    return -1;
+  }
+
+  return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/sys/mman/mmap.cpp b/libc/src/sys/mman/mmap.cpp
deleted file mode 100644 (file)
index 10ae0c7..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-//===-------------- Implementation of the POSIX mmap 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/mmap.h"
-#include "include/sys/syscall.h" // For syscall numbers.
-#include "src/__support/common.h"
-#include "src/errno/llvmlibc_errno.h"
-#include "src/unistd/syscall.h" // For internal syscall function.
-
-namespace __llvm_libc {
-
-// This function is currently linux only. It has to be refactored suitably if
-// mmap is to be supported on non-linux operating systems also.
-void *LLVM_LIBC_ENTRYPOINT(mmap)(void *addr, size_t size, int prot, int flags,
-                                 int fd, off_t offset) {
-  // A lot of POSIX standard prescribed validation of the parameters is not
-  // done in this function as modern linux versions do it in the syscall.
-  // TODO: Perform argument validation not done by the linux syscall.
-
-#ifdef SYS_mmap2
-  offset /= PAGE_SIZE;
-  long syscall_number = SYS_mmap2;
-#elif SYS_mmap
-  long syscall_number = SYS_mmap;
-#else
-#error "Target platform does not have SYS_mmap or SYS_mmap2 defined"
-#endif
-
-  long ret_val =
-      __llvm_libc::syscall(syscall_number, reinterpret_cast<long>(addr), size,
-                           prot, flags, fd, offset);
-
-  // The mmap/mmap2 syscalls return negative values on error. These negative
-  // values are actually the negative values of the error codes. So, fix them
-  // up in case an error code is detected.
-  //
-  // A point to keep in mind for the fix up is that a negative return value
-  // from the syscall can also be an error-free value returned by the syscall.
-  // However, since a valid return address cannot be within the last page, a
-  // return value corresponding to a location in the last page is an error
-  // value.
-  if (ret_val < 0 && ret_val > -PAGE_SIZE) {
-    llvmlibc_errno = -ret_val;
-    return MAP_FAILED;
-  }
-
-  return reinterpret_cast<void *>(ret_val);
-}
-
-} // namespace __llvm_libc
diff --git a/libc/src/sys/mman/munmap.cpp b/libc/src/sys/mman/munmap.cpp
deleted file mode 100644 (file)
index d11f53a..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-//===------------- Implementation of the POSIX munmap 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/munmap.h"
-#include "include/sys/syscall.h" // For syscall numbers.
-#include "src/__support/common.h"
-#include "src/errno/llvmlibc_errno.h"
-#include "src/unistd/syscall.h" // For internal syscall function.
-
-namespace __llvm_libc {
-
-// This function is currently linux only. It has to be refactored suitably if
-// mmap is to be supported on non-linux operating systems also.
-int LLVM_LIBC_ENTRYPOINT(munmap)(void *addr, size_t size) {
-  long ret_val =
-      __llvm_libc::syscall(SYS_munmap, reinterpret_cast<long>(addr), size);
-
-  // A negative return value indicates an error with the magnitude of the
-  // value being the error code.
-  if (ret_val < 0) {
-    llvmlibc_errno = -ret_val;
-    return -1;
-  }
-
-  return 0;
-}
-
-} // namespace __llvm_libc
diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt
deleted file mode 100644 (file)
index ed23b70..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-add_gen_header(
-  syscall_impl_h
-  DEF_FILE syscall.h.def
-  GEN_HDR syscall.h
-  PARAMS
-    inline_syscalls=../../config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/syscall.h.inc
-  DATA_FILES
-    ../../config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/syscall.h.inc
-)
diff --git a/libc/src/unistd/syscall.h.def b/libc/src/unistd/syscall.h.def
deleted file mode 100644 (file)
index 7f52a26..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-//===--------------- Internal syscall declarations --------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-%%include_file(${inline_syscalls})
index 9f9d21251c6f4d5ebb7431b77794146548fcbacf..23f82b27c9bd95b65cb536330774311115ba1244 100644 (file)
@@ -3,6 +3,6 @@ add_libc_unittest(
   SUITE libc_linux_tests
   SRCS syscall_test.cpp
   DEPENDS
-   syscall_impl_h
+   linux_syscall_h
    support_common_h
 )
index 27628be6a4cde4073350b24e3aa7c701e663a1f8..efab1444d35cae623e1bfa45a9f149ab2936d263 100644 (file)
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "src/unistd/syscall.h"
+#include "config/linux/syscall.h"
 #include "utils/UnitTest/Test.h"
 
 #include <functional>
index 3fcc8fff3c290d7bd4c23587f5037ce675d51e8b..b4bbe81c92ff2ebe511e5102fe9f9f56f8f0093b 100644 (file)
@@ -1,15 +1,3 @@
-add_libc_testsuite(libc_sys_mman_unittests)
-
-add_libc_unittest(
-  mmap_test
-  SUITE
-    libc_sys_mman_unittests
-  SRCS
-    mmap_test.cpp
-  DEPENDS
-    errno_h
-    sys_mman_h
-    mmap
-    munmap
-    __errno_location
-)
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${LIBC_TARGET_OS})
+endif()
diff --git a/libc/test/src/sys/mman/linux/CMakeLists.txt b/libc/test/src/sys/mman/linux/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3fcc8ff
--- /dev/null
@@ -0,0 +1,15 @@
+add_libc_testsuite(libc_sys_mman_unittests)
+
+add_libc_unittest(
+  mmap_test
+  SUITE
+    libc_sys_mman_unittests
+  SRCS
+    mmap_test.cpp
+  DEPENDS
+    errno_h
+    sys_mman_h
+    mmap
+    munmap
+    __errno_location
+)
diff --git a/libc/test/src/sys/mman/linux/mmap_test.cpp b/libc/test/src/sys/mman/linux/mmap_test.cpp
new file mode 100644 (file)
index 0000000..9cc3abc
--- /dev/null
@@ -0,0 +1,46 @@
+//===------------------ Unittests for mmap and munmap ---------------------===//
+//
+// 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 "include/errno.h"
+#include "include/sys/mman.h"
+#include "src/errno/llvmlibc_errno.h"
+#include "src/sys/mman/mmap.h"
+#include "src/sys/mman/munmap.h"
+#include "utils/UnitTest/Test.h"
+
+TEST(MMapTest, NoError) {
+  size_t alloc_size = 128;
+  llvmlibc_errno = 0;
+  void *addr = __llvm_libc::mmap(nullptr, alloc_size, PROT_READ,
+                                 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  EXPECT_EQ(0, llvmlibc_errno);
+  EXPECT_NE(addr, MAP_FAILED);
+
+  int *array = reinterpret_cast<int *>(addr);
+  // Reading from the memory should not crash the test.
+  // Since we used the MAP_ANONYMOUS flag, the contents of the newly
+  // allocated memory should be initialized to zero.
+  EXPECT_EQ(array[0], 0);
+
+  int ret_val = __llvm_libc::munmap(addr, alloc_size);
+  EXPECT_EQ(0, ret_val);
+  EXPECT_EQ(0, llvmlibc_errno);
+}
+
+TEST(MMapTest, Error_InvalidSize) {
+  llvmlibc_errno = 0;
+  void *addr = __llvm_libc::mmap(nullptr, 0, PROT_READ,
+                                 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  EXPECT_EQ(EINVAL, llvmlibc_errno);
+  EXPECT_EQ(addr, MAP_FAILED);
+
+  llvmlibc_errno = 0;
+  int ret_val = __llvm_libc::munmap(0, 0);
+  EXPECT_EQ(-1, ret_val);
+  EXPECT_EQ(EINVAL, llvmlibc_errno);
+}
diff --git a/libc/test/src/sys/mman/mmap_test.cpp b/libc/test/src/sys/mman/mmap_test.cpp
deleted file mode 100644 (file)
index 9cc3abc..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-//===------------------ Unittests for mmap and munmap ---------------------===//
-//
-// 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 "include/errno.h"
-#include "include/sys/mman.h"
-#include "src/errno/llvmlibc_errno.h"
-#include "src/sys/mman/mmap.h"
-#include "src/sys/mman/munmap.h"
-#include "utils/UnitTest/Test.h"
-
-TEST(MMapTest, NoError) {
-  size_t alloc_size = 128;
-  llvmlibc_errno = 0;
-  void *addr = __llvm_libc::mmap(nullptr, alloc_size, PROT_READ,
-                                 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-  EXPECT_EQ(0, llvmlibc_errno);
-  EXPECT_NE(addr, MAP_FAILED);
-
-  int *array = reinterpret_cast<int *>(addr);
-  // Reading from the memory should not crash the test.
-  // Since we used the MAP_ANONYMOUS flag, the contents of the newly
-  // allocated memory should be initialized to zero.
-  EXPECT_EQ(array[0], 0);
-
-  int ret_val = __llvm_libc::munmap(addr, alloc_size);
-  EXPECT_EQ(0, ret_val);
-  EXPECT_EQ(0, llvmlibc_errno);
-}
-
-TEST(MMapTest, Error_InvalidSize) {
-  llvmlibc_errno = 0;
-  void *addr = __llvm_libc::mmap(nullptr, 0, PROT_READ,
-                                 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-  EXPECT_EQ(EINVAL, llvmlibc_errno);
-  EXPECT_EQ(addr, MAP_FAILED);
-
-  llvmlibc_errno = 0;
-  int ret_val = __llvm_libc::munmap(0, 0);
-  EXPECT_EQ(-1, ret_val);
-  EXPECT_EQ(EINVAL, llvmlibc_errno);
-}