123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- //===-- mem_map_linux.cpp ---------------------------------------*- 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 "platform.h"
- #if SCUDO_LINUX
- #include "mem_map_linux.h"
- #include "common.h"
- #include "internal_defs.h"
- #include "linux.h"
- #include "mutex.h"
- #include "report_linux.h"
- #include "string_utils.h"
- #include <errno.h>
- #include <fcntl.h>
- #include <linux/futex.h>
- #include <sched.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/mman.h>
- #include <sys/stat.h>
- #include <sys/syscall.h>
- #include <sys/time.h>
- #include <time.h>
- #include <unistd.h>
- #if SCUDO_ANDROID
- // TODO(chiahungduan): Review if we still need the followings macros.
- #include <sys/prctl.h>
- // Definitions of prctl arguments to set a vma name in Android kernels.
- #define ANDROID_PR_SET_VMA 0x53564d41
- #define ANDROID_PR_SET_VMA_ANON_NAME 0
- #endif
- namespace scudo {
- static void *mmapWrapper(uptr Addr, uptr Size, const char *Name, uptr Flags) {
- int MmapFlags = MAP_PRIVATE | MAP_ANONYMOUS;
- int MmapProt;
- if (Flags & MAP_NOACCESS) {
- MmapFlags |= MAP_NORESERVE;
- MmapProt = PROT_NONE;
- } else {
- MmapProt = PROT_READ | PROT_WRITE;
- }
- #if defined(__aarch64__)
- #ifndef PROT_MTE
- #define PROT_MTE 0x20
- #endif
- if (Flags & MAP_MEMTAG)
- MmapProt |= PROT_MTE;
- #endif
- if (Addr)
- MmapFlags |= MAP_FIXED;
- void *P =
- mmap(reinterpret_cast<void *>(Addr), Size, MmapProt, MmapFlags, -1, 0);
- if (P == MAP_FAILED) {
- if (!(Flags & MAP_ALLOWNOMEM) || errno != ENOMEM)
- reportMapError(errno == ENOMEM ? Size : 0);
- return nullptr;
- }
- #if SCUDO_ANDROID
- if (Name)
- prctl(ANDROID_PR_SET_VMA, ANDROID_PR_SET_VMA_ANON_NAME, P, Size, Name);
- #else
- (void)Name;
- #endif
- return P;
- }
- bool MemMapLinux::mapImpl(uptr Addr, uptr Size, const char *Name, uptr Flags) {
- void *P = mmapWrapper(Addr, Size, Name, Flags);
- if (P == nullptr)
- return false;
- MapBase = reinterpret_cast<uptr>(P);
- MapCapacity = Size;
- return true;
- }
- void MemMapLinux::unmapImpl(uptr Addr, uptr Size) {
- // If we unmap all the pages, also mark `MapBase` to 0 to indicate invalid
- // status.
- if (Size == MapCapacity) {
- MapBase = MapCapacity = 0;
- } else {
- // This is partial unmap and is unmapping the pages from the beginning,
- // shift `MapBase` to the new base.
- if (MapBase == Addr)
- MapBase = Addr + Size;
- MapCapacity -= Size;
- }
- if (munmap(reinterpret_cast<void *>(Addr), Size) != 0)
- reportUnmapError(Addr, Size);
- }
- bool MemMapLinux::remapImpl(uptr Addr, uptr Size, const char *Name,
- uptr Flags) {
- void *P = mmapWrapper(Addr, Size, Name, Flags);
- if (reinterpret_cast<uptr>(P) != Addr)
- reportMapError();
- return true;
- }
- void MemMapLinux::setMemoryPermissionImpl(uptr Addr, uptr Size, uptr Flags) {
- int Prot = (Flags & MAP_NOACCESS) ? PROT_NONE : (PROT_READ | PROT_WRITE);
- if (mprotect(reinterpret_cast<void *>(Addr), Size, Prot) != 0)
- reportProtectError(Addr, Size, Prot);
- }
- void MemMapLinux::releaseAndZeroPagesToOSImpl(uptr From, uptr Size) {
- void *Addr = reinterpret_cast<void *>(From);
- while (madvise(Addr, Size, MADV_DONTNEED) == -1 && errno == EAGAIN) {
- }
- }
- bool ReservedMemoryLinux::createImpl(uptr Addr, uptr Size, const char *Name,
- uptr Flags) {
- ReservedMemoryLinux::MemMapT MemMap;
- if (!MemMap.map(Addr, Size, Name, Flags | MAP_NOACCESS))
- return false;
- MapBase = MemMap.getBase();
- MapCapacity = MemMap.getCapacity();
- return true;
- }
- void ReservedMemoryLinux::releaseImpl() {
- if (munmap(reinterpret_cast<void *>(getBase()), getCapacity()) != 0)
- reportUnmapError(getBase(), getCapacity());
- }
- ReservedMemoryLinux::MemMapT ReservedMemoryLinux::dispatchImpl(uptr Addr,
- uptr Size) {
- return ReservedMemoryLinux::MemMapT(Addr, Size);
- }
- } // namespace scudo
- #endif // SCUDO_LINUX
|