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