summaryrefslogtreecommitdiffstats
path: root/libc/src/sys
diff options
context:
space:
mode:
authorSiva Chandra Reddy <sivachandra@google.com>2019-12-04 23:17:14 -0800
committerSiva Chandra Reddy <sivachandra@google.com>2019-12-23 14:04:02 -0800
commite5a743c4f6e3639ba3bee778c894a996ef96391a (patch)
tree3e0d71a35f51bef145cb95f010707a6d2a4ac58e /libc/src/sys
parent187f66bcac668dd2ea25244ed7d7711551275f9d (diff)
downloadbcm5719-llvm-e5a743c4f6e3639ba3bee778c894a996ef96391a.tar.gz
bcm5719-llvm-e5a743c4f6e3639ba3bee778c894a996ef96391a.zip
Add implementations of POSIX mmap and munmap functions.
Summary: A set of of linux x86_64 internal syscall helpers have also been added. This change does not try to be perfect with respect to OS and machine abstractions. A TODO note has been added at places where such abstractions would help and make the arrangement scalable and cleaner. Addressing the TODOs and building such abstractions is not in the scope of this change. It is hoped that follow up changes cleaning up the problem areas and addressing the TODOs will better illustrate the need for the changes. This change also does not try to imitate mmap and munmap implementations of other libcs. The idea here is to put in the bare minimum required to obtain a working mmap and munmap, and then add the rest of the functionality on an as needed basis. Reviewers: abrachet, phosek, stanshebs, theraven Subscribers: mgorny, MaskRay, jfb, libc-commits Tags: #libc-project Differential Revision: https://reviews.llvm.org/D71634
Diffstat (limited to 'libc/src/sys')
-rw-r--r--libc/src/sys/CMakeLists.txt1
-rw-r--r--libc/src/sys/mman/CMakeLists.txt41
-rw-r--r--libc/src/sys/mman/mmap.cpp57
-rw-r--r--libc/src/sys/mman/mmap.h20
-rw-r--r--libc/src/sys/mman/mmap_test.cpp48
-rw-r--r--libc/src/sys/mman/munmap.cpp35
-rw-r--r--libc/src/sys/mman/munmap.h20
7 files changed, 222 insertions, 0 deletions
diff --git a/libc/src/sys/CMakeLists.txt b/libc/src/sys/CMakeLists.txt
new file mode 100644
index 00000000000..03c59bfc4a0
--- /dev/null
+++ b/libc/src/sys/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(mman)
diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt
new file mode 100644
index 00000000000..f2d98a45518
--- /dev/null
+++ b/libc/src/sys/mman/CMakeLists.txt
@@ -0,0 +1,41 @@
+#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
+)
+
+add_custom_target(libc_sys_mman_unittests)
+
+add_libc_unittest(
+ mmap_test
+ SUITE
+ libc_sys_mman_unittests
+ SRCS
+ mmap_test.cpp
+ DEPENDS
+ mmap
+ munmap
+ __errno_location
+)
diff --git a/libc/src/sys/mman/mmap.cpp b/libc/src/sys/mman/mmap.cpp
new file mode 100644
index 00000000000..bcf65314176
--- /dev/null
+++ b/libc/src/sys/mman/mmap.cpp
@@ -0,0 +1,57 @@
+//===-------------- 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 "src/__support/common.h"
+#include "src/errno/llvmlibc_errno.h"
+
+#include "src/unistd/syscall.h" // For internal syscall function.
+
+#include <sys/syscall.h> // For syscall numbers.
+
+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/mmap.h b/libc/src/sys/mman/mmap.h
new file mode 100644
index 00000000000..f34a5ab7615
--- /dev/null
+++ b/libc/src/sys/mman/mmap.h
@@ -0,0 +1,20 @@
+//===-------------- Implementation header for mmap 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_MMAP_H
+#define LLVM_LIBC_SRC_SYS_MMAN_MMAP_H
+
+#include <sys/mman.h> // For size_t and off_t
+
+namespace __llvm_libc {
+
+void *mmap(void *addr, size_t size, int prot, int flags, int fd, off_t offset);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SYS_MMAN_MMAP_H
diff --git a/libc/src/sys/mman/mmap_test.cpp b/libc/src/sys/mman/mmap_test.cpp
new file mode 100644
index 00000000000..ab2e6ceb4a9
--- /dev/null
+++ b/libc/src/sys/mman/mmap_test.cpp
@@ -0,0 +1,48 @@
+//===------------------ 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 "src/errno/llvmlibc_errno.h"
+#include "src/sys/mman/mmap.h"
+#include "src/sys/mman/munmap.h"
+
+#include "gtest/gtest.h"
+
+#include "errno.h"
+#include "sys/mman.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/src/sys/mman/munmap.cpp b/libc/src/sys/mman/munmap.cpp
new file mode 100644
index 00000000000..6a8b4f77769
--- /dev/null
+++ b/libc/src/sys/mman/munmap.cpp
@@ -0,0 +1,35 @@
+//===------------- 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 "src/__support/common.h"
+#include "src/errno/llvmlibc_errno.h"
+
+#include "src/unistd/syscall.h" // For internal syscall function.
+
+#include <sys/syscall.h> // For syscall numbers.
+
+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/munmap.h b/libc/src/sys/mman/munmap.h
new file mode 100644
index 00000000000..2c01cbd87cd
--- /dev/null
+++ b/libc/src/sys/mman/munmap.h
@@ -0,0 +1,20 @@
+//===-------------- Implementation header for mumap 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_MUNMAP_H
+#define LLVM_LIBC_SRC_SYS_MMAN_MUNMAP_H
+
+#include <sys/mman.h> // For size_t
+
+namespace __llvm_libc {
+
+int munmap(void *addr, size_t size);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SYS_MMAN_MUNMAP_H
OpenPOWER on IntegriCloud