[compiler-rt] f5fffbe - [scudo] Implement and enable MemMapLinux

Chia-hung Duan via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 7 09:03:49 PDT 2023


Author: Chia-hung Duan
Date: 2023-08-07T16:03:25Z
New Revision: f5fffbe2a587a8ac39b98448a9fb3b552543464f

URL: https://github.com/llvm/llvm-project/commit/f5fffbe2a587a8ac39b98448a9fb3b552543464f
DIFF: https://github.com/llvm/llvm-project/commit/f5fffbe2a587a8ac39b98448a9fb3b552543464f.diff

LOG: [scudo] Implement and enable MemMapLinux

Most of the implementations are copied from linux.cpp and we will be
keeping those memory functions in linux.cpp for a while until we are
able to switch to use MemMap completely.

The remaining part is SizeClassAllocator32 which hasn't been switched to
use MemMap interface

Reviewed By: cferris

Differential Revision: https://reviews.llvm.org/D146453

Added: 
    compiler-rt/lib/scudo/standalone/mem_map_linux.cpp
    compiler-rt/lib/scudo/standalone/mem_map_linux.h

Modified: 
    compiler-rt/lib/scudo/standalone/CMakeLists.txt
    compiler-rt/lib/scudo/standalone/linux.cpp
    compiler-rt/lib/scudo/standalone/mem_map.h

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/scudo/standalone/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/CMakeLists.txt
index 094c23a73f36bf..a5d9a4651c2039 100644
--- a/compiler-rt/lib/scudo/standalone/CMakeLists.txt
+++ b/compiler-rt/lib/scudo/standalone/CMakeLists.txt
@@ -74,6 +74,7 @@ set(SCUDO_HEADERS
   mem_map.h
   mem_map_base.h
   mem_map_fuchsia.h
+  mem_map_linux.h
   mutex.h
   options.h
   platform.h
@@ -109,6 +110,7 @@ set(SCUDO_SOURCES
   linux.cpp
   mem_map.cpp
   mem_map_fuchsia.cpp
+  mem_map_linux.cpp
   release.cpp
   report.cpp
   rss_limit_checker.cpp

diff  --git a/compiler-rt/lib/scudo/standalone/linux.cpp b/compiler-rt/lib/scudo/standalone/linux.cpp
index cb746b8eb04f89..54d0461bb4fa0b 100644
--- a/compiler-rt/lib/scudo/standalone/linux.cpp
+++ b/compiler-rt/lib/scudo/standalone/linux.cpp
@@ -43,6 +43,7 @@ uptr getPageSize() { return static_cast<uptr>(sysconf(_SC_PAGESIZE)); }
 
 void NORETURN die() { abort(); }
 
+// TODO: Will be deprecated. Use the interfaces in MemMapLinux instead.
 void *map(void *Addr, uptr Size, UNUSED const char *Name, uptr Flags,
           UNUSED MapPlatformData *Data) {
   int MmapFlags = MAP_PRIVATE | MAP_ANONYMOUS;
@@ -75,12 +76,14 @@ void *map(void *Addr, uptr Size, UNUSED const char *Name, uptr Flags,
   return P;
 }
 
+// TODO: Will be deprecated. Use the interfaces in MemMapLinux instead.
 void unmap(void *Addr, uptr Size, UNUSED uptr Flags,
            UNUSED MapPlatformData *Data) {
   if (munmap(Addr, Size) != 0)
     dieOnMapUnmapError();
 }
 
+// TODO: Will be deprecated. Use the interfaces in MemMapLinux instead.
 void setMemoryPermission(uptr Addr, uptr Size, uptr Flags,
                          UNUSED MapPlatformData *Data) {
   int Prot = (Flags & MAP_NOACCESS) ? PROT_NONE : (PROT_READ | PROT_WRITE);
@@ -88,6 +91,7 @@ void setMemoryPermission(uptr Addr, uptr Size, uptr Flags,
     dieOnMapUnmapError();
 }
 
+// TODO: Will be deprecated. Use the interfaces in MemMapLinux instead.
 void releasePagesToOS(uptr BaseAddress, uptr Offset, uptr Size,
                       UNUSED MapPlatformData *Data) {
   void *Addr = reinterpret_cast<void *>(BaseAddress + Offset);

diff  --git a/compiler-rt/lib/scudo/standalone/mem_map.h b/compiler-rt/lib/scudo/standalone/mem_map.h
index 23d0ab61774567..b92216cf271de8 100644
--- a/compiler-rt/lib/scudo/standalone/mem_map.h
+++ b/compiler-rt/lib/scudo/standalone/mem_map.h
@@ -22,6 +22,7 @@
 #include "trusty.h"
 
 #include "mem_map_fuchsia.h"
+#include "mem_map_linux.h"
 
 namespace scudo {
 
@@ -73,7 +74,7 @@ class ReservedMemoryDefault final
 };
 
 #if SCUDO_LINUX
-using ReservedMemoryT = ReservedMemoryDefault;
+using ReservedMemoryT = ReservedMemoryLinux;
 using MemMapT = ReservedMemoryT::MemMapT;
 #elif SCUDO_FUCHSIA
 using ReservedMemoryT = ReservedMemoryFuchsia;

diff  --git a/compiler-rt/lib/scudo/standalone/mem_map_linux.cpp b/compiler-rt/lib/scudo/standalone/mem_map_linux.cpp
new file mode 100644
index 00000000000000..f377d105894db7
--- /dev/null
+++ b/compiler-rt/lib/scudo/standalone/mem_map_linux.cpp
@@ -0,0 +1,152 @@
+//===-- 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 "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)
+      dieOnMapUnmapError(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)
+    dieOnMapUnmapError();
+}
+
+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)
+    dieOnMapUnmapError();
+  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)
+    dieOnMapUnmapError();
+}
+
+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)
+    dieOnMapUnmapError();
+}
+
+ReservedMemoryLinux::MemMapT ReservedMemoryLinux::dispatchImpl(uptr Addr,
+                                                               uptr Size) {
+  return ReservedMemoryLinux::MemMapT(Addr, Size);
+}
+
+} // namespace scudo
+
+#endif // SCUDO_LINUX

diff  --git a/compiler-rt/lib/scudo/standalone/mem_map_linux.h b/compiler-rt/lib/scudo/standalone/mem_map_linux.h
new file mode 100644
index 00000000000000..7a89b3bff5ed19
--- /dev/null
+++ b/compiler-rt/lib/scudo/standalone/mem_map_linux.h
@@ -0,0 +1,67 @@
+//===-- mem_map_linux.h -----------------------------------------*- 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 SCUDO_MEM_MAP_LINUX_H_
+#define SCUDO_MEM_MAP_LINUX_H_
+
+#include "platform.h"
+
+#if SCUDO_LINUX
+
+#include "common.h"
+#include "mem_map_base.h"
+
+namespace scudo {
+
+class MemMapLinux final : public MemMapBase<MemMapLinux> {
+public:
+  constexpr MemMapLinux() = default;
+  MemMapLinux(uptr Base, uptr Capacity)
+      : MapBase(Base), MapCapacity(Capacity) {}
+
+  // Impls for base functions.
+  bool mapImpl(uptr Addr, uptr Size, const char *Name, uptr Flags = 0);
+  void unmapImpl(uptr Addr, uptr Size);
+  bool remapImpl(uptr Addr, uptr Size, const char *Name, uptr Flags = 0);
+  void setMemoryPermissionImpl(uptr Addr, uptr Size, uptr Flags);
+  void releasePagesToOSImpl(uptr From, uptr Size) {
+    return releaseAndZeroPagesToOSImpl(From, Size);
+  }
+  void releaseAndZeroPagesToOSImpl(uptr From, uptr Size);
+  uptr getBaseImpl() { return MapBase; }
+  uptr getCapacityImpl() { return MapCapacity; }
+
+private:
+  uptr MapBase = 0;
+  uptr MapCapacity = 0;
+};
+
+// This will be deprecated when every allocator has been supported by each
+// platform's `MemMap` implementation.
+class ReservedMemoryLinux final
+    : public ReservedMemory<ReservedMemoryLinux, MemMapLinux> {
+public:
+  // The following two are the Impls for function in `MemMapBase`.
+  uptr getBaseImpl() { return MapBase; }
+  uptr getCapacityImpl() { return MapCapacity; }
+
+  // These threes are specific to `ReservedMemory`.
+  bool createImpl(uptr Addr, uptr Size, const char *Name, uptr Flags);
+  void releaseImpl();
+  MemMapT dispatchImpl(uptr Addr, uptr Size);
+
+private:
+  uptr MapBase = 0;
+  uptr MapCapacity = 0;
+};
+
+} // namespace scudo
+
+#endif // SCUDO_LINUX
+
+#endif // SCUDO_MEM_MAP_LINUX_H_


        


More information about the llvm-commits mailing list