1 //===-- bytemap.h -----------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef SCUDO_BYTEMAP_H_
10 #define SCUDO_BYTEMAP_H_
12 #include "atomic_helpers.h"
18 template <uptr Size> class FlatByteMap {
20 void initLinkerInitialized() {
21 Map = reinterpret_cast<u8 *>(map(nullptr, Size, "scudo:bytemap"));
23 void init() { initLinkerInitialized(); }
25 void unmapTestOnly() { unmap(reinterpret_cast<void *>(Map), Size); }
27 void set(uptr Index, u8 Value) {
28 DCHECK_LT(Index, Size);
29 DCHECK_EQ(0U, Map[Index]);
32 u8 operator[](uptr Index) {
33 DCHECK_LT(Index, Size);
44 template <uptr Level1Size, uptr Level2Size> class TwoLevelByteMap {
46 void initLinkerInitialized() {
47 Level1Map = reinterpret_cast<atomic_uptr *>(
48 map(nullptr, sizeof(atomic_uptr) * Level1Size, "scudo:bytemap"));
52 initLinkerInitialized();
56 for (uptr I = 0; I < Level1Size; I++) {
62 memset(Level1Map, 0, sizeof(atomic_uptr) * Level1Size);
65 void unmapTestOnly() {
67 unmap(reinterpret_cast<void *>(Level1Map),
68 sizeof(atomic_uptr) * Level1Size);
71 uptr size() const { return Level1Size * Level2Size; }
73 void set(uptr Index, u8 Value) {
74 DCHECK_LT(Index, Level1Size * Level2Size);
75 u8 *Level2Map = getOrCreate(Index / Level2Size);
76 DCHECK_EQ(0U, Level2Map[Index % Level2Size]);
77 Level2Map[Index % Level2Size] = Value;
80 u8 operator[](uptr Index) const {
81 DCHECK_LT(Index, Level1Size * Level2Size);
82 u8 *Level2Map = get(Index / Level2Size);
85 return Level2Map[Index % Level2Size];
88 void disable() { Mutex.lock(); }
89 void enable() { Mutex.unlock(); }
92 u8 *get(uptr Index) const {
93 DCHECK_LT(Index, Level1Size);
94 return reinterpret_cast<u8 *>(
95 atomic_load(&Level1Map[Index], memory_order_acquire));
98 u8 *getOrCreate(uptr Index) {
102 if (!(Res = get(Index))) {
103 Res = reinterpret_cast<u8 *>(map(nullptr, Level2Size, "scudo:bytemap"));
104 atomic_store(&Level1Map[Index], reinterpret_cast<uptr>(Res),
105 memory_order_release);
111 atomic_uptr *Level1Map;
117 #endif // SCUDO_BYTEMAP_H_