Path: blob/main/contrib/llvm-project/compiler-rt/lib/scudo/standalone/mem_map_linux.cpp
35292 views
//===-- mem_map_linux.cpp ---------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "platform.h"910#if SCUDO_LINUX1112#include "mem_map_linux.h"1314#include "common.h"15#include "internal_defs.h"16#include "linux.h"17#include "mutex.h"18#include "report_linux.h"19#include "string_utils.h"2021#include <errno.h>22#include <fcntl.h>23#include <linux/futex.h>24#include <sched.h>25#include <stdio.h>26#include <stdlib.h>27#include <string.h>28#include <sys/mman.h>29#include <sys/stat.h>30#include <sys/syscall.h>31#include <sys/time.h>32#include <time.h>33#include <unistd.h>3435#if SCUDO_ANDROID36// TODO(chiahungduan): Review if we still need the followings macros.37#include <sys/prctl.h>38// Definitions of prctl arguments to set a vma name in Android kernels.39#define ANDROID_PR_SET_VMA 0x53564d4140#define ANDROID_PR_SET_VMA_ANON_NAME 041#endif4243namespace scudo {4445static void *mmapWrapper(uptr Addr, uptr Size, const char *Name, uptr Flags) {46int MmapFlags = MAP_PRIVATE | MAP_ANONYMOUS;47int MmapProt;48if (Flags & MAP_NOACCESS) {49MmapFlags |= MAP_NORESERVE;50MmapProt = PROT_NONE;51} else {52MmapProt = PROT_READ | PROT_WRITE;53}54#if defined(__aarch64__)55#ifndef PROT_MTE56#define PROT_MTE 0x2057#endif58if (Flags & MAP_MEMTAG)59MmapProt |= PROT_MTE;60#endif61if (Addr)62MmapFlags |= MAP_FIXED;63void *P =64mmap(reinterpret_cast<void *>(Addr), Size, MmapProt, MmapFlags, -1, 0);65if (P == MAP_FAILED) {66if (!(Flags & MAP_ALLOWNOMEM) || errno != ENOMEM)67reportMapError(errno == ENOMEM ? Size : 0);68return nullptr;69}70#if SCUDO_ANDROID71if (Name)72prctl(ANDROID_PR_SET_VMA, ANDROID_PR_SET_VMA_ANON_NAME, P, Size, Name);73#else74(void)Name;75#endif7677return P;78}7980bool MemMapLinux::mapImpl(uptr Addr, uptr Size, const char *Name, uptr Flags) {81void *P = mmapWrapper(Addr, Size, Name, Flags);82if (P == nullptr)83return false;8485MapBase = reinterpret_cast<uptr>(P);86MapCapacity = Size;87return true;88}8990void MemMapLinux::unmapImpl(uptr Addr, uptr Size) {91// If we unmap all the pages, also mark `MapBase` to 0 to indicate invalid92// status.93if (Size == MapCapacity) {94MapBase = MapCapacity = 0;95} else {96// This is partial unmap and is unmapping the pages from the beginning,97// shift `MapBase` to the new base.98if (MapBase == Addr)99MapBase = Addr + Size;100MapCapacity -= Size;101}102103if (munmap(reinterpret_cast<void *>(Addr), Size) != 0)104reportUnmapError(Addr, Size);105}106107bool MemMapLinux::remapImpl(uptr Addr, uptr Size, const char *Name,108uptr Flags) {109void *P = mmapWrapper(Addr, Size, Name, Flags);110if (reinterpret_cast<uptr>(P) != Addr)111reportMapError();112return true;113}114115void MemMapLinux::setMemoryPermissionImpl(uptr Addr, uptr Size, uptr Flags) {116int Prot = (Flags & MAP_NOACCESS) ? PROT_NONE : (PROT_READ | PROT_WRITE);117if (mprotect(reinterpret_cast<void *>(Addr), Size, Prot) != 0)118reportProtectError(Addr, Size, Prot);119}120121void MemMapLinux::releaseAndZeroPagesToOSImpl(uptr From, uptr Size) {122void *Addr = reinterpret_cast<void *>(From);123124while (madvise(Addr, Size, MADV_DONTNEED) == -1 && errno == EAGAIN) {125}126}127128bool ReservedMemoryLinux::createImpl(uptr Addr, uptr Size, const char *Name,129uptr Flags) {130ReservedMemoryLinux::MemMapT MemMap;131if (!MemMap.map(Addr, Size, Name, Flags | MAP_NOACCESS))132return false;133134MapBase = MemMap.getBase();135MapCapacity = MemMap.getCapacity();136137return true;138}139140void ReservedMemoryLinux::releaseImpl() {141if (munmap(reinterpret_cast<void *>(getBase()), getCapacity()) != 0)142reportUnmapError(getBase(), getCapacity());143}144145ReservedMemoryLinux::MemMapT ReservedMemoryLinux::dispatchImpl(uptr Addr,146uptr Size) {147return ReservedMemoryLinux::MemMapT(Addr, Size);148}149150} // namespace scudo151152#endif // SCUDO_LINUX153154155