1//===---------- Linux implementation of the POSIX mmap function -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "src/sys/mman/mmap.h"
10
11#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
12#include "src/__support/common.h"
13
14#include "src/errno/libc_errno.h"
15#include <linux/param.h> // For EXEC_PAGESIZE.
16#include <sys/syscall.h> // For syscall numbers.
17
18namespace LIBC_NAMESPACE {
19
20// This function is currently linux only. It has to be refactored suitably if
21// mmap is to be supported on non-linux operating systems also.
22LLVM_LIBC_FUNCTION(void *, mmap,
23 (void *addr, size_t size, int prot, int flags, int fd,
24 off_t offset)) {
25 // A lot of POSIX standard prescribed validation of the parameters is not
26 // done in this function as modern linux versions do it in the syscall.
27 // TODO: Perform argument validation not done by the linux syscall.
28
29 // EXEC_PAGESIZE is used for the page size. While this is OK for x86_64, it
30 // might not be correct in general.
31 // TODO: Use pagesize read from the ELF aux vector instead of EXEC_PAGESIZE.
32
33#ifdef SYS_mmap2
34 offset /= EXEC_PAGESIZE;
35 long syscall_number = SYS_mmap2;
36#elif defined(SYS_mmap)
37 long syscall_number = SYS_mmap;
38#else
39#error "mmap or mmap2 syscalls not available."
40#endif
41
42 long ret =
43 LIBC_NAMESPACE::syscall_impl(number: syscall_number, arg1: reinterpret_cast<long>(addr),
44 arg2: size, arg3: prot, arg4: flags, arg5: fd, arg6: offset);
45
46 // The mmap/mmap2 syscalls return negative values on error. These negative
47 // values are actually the negative values of the error codes. So, fix them
48 // up in case an error code is detected.
49 //
50 // A point to keep in mind for the fix up is that a negative return value
51 // from the syscall can also be an error-free value returned by the syscall.
52 // However, since a valid return address cannot be within the last page, a
53 // return value corresponding to a location in the last page is an error
54 // value.
55 if (ret < 0 && ret > -EXEC_PAGESIZE) {
56 libc_errno = static_cast<int>(-ret);
57 return MAP_FAILED;
58 }
59
60 return reinterpret_cast<void *>(ret);
61}
62
63} // namespace LIBC_NAMESPACE
64

source code of libc/src/sys/mman/linux/mmap.cpp