1e8d8bef9SDimitry Andric //===-- memprof_mapping.h --------------------------------------*- C++ -*-===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric // 9e8d8bef9SDimitry Andric // This file is a part of MemProfiler, a memory profiler. 10e8d8bef9SDimitry Andric // 11e8d8bef9SDimitry Andric // Defines MemProf memory mapping. 12e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 13e8d8bef9SDimitry Andric #ifndef MEMPROF_MAPPING_H 14e8d8bef9SDimitry Andric #define MEMPROF_MAPPING_H 15e8d8bef9SDimitry Andric 16e8d8bef9SDimitry Andric #include "memprof_internal.h" 17e8d8bef9SDimitry Andric 18e8d8bef9SDimitry Andric static const u64 kDefaultShadowScale = 3; 19e8d8bef9SDimitry Andric #define SHADOW_SCALE kDefaultShadowScale 20e8d8bef9SDimitry Andric 21e8d8bef9SDimitry Andric #define SHADOW_OFFSET __memprof_shadow_memory_dynamic_address 22e8d8bef9SDimitry Andric 23e8d8bef9SDimitry Andric #define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE) 24e8d8bef9SDimitry Andric #define MEMPROF_ALIGNMENT 32 25e8d8bef9SDimitry Andric namespace __memprof { 26e8d8bef9SDimitry Andric 27e8d8bef9SDimitry Andric extern uptr kHighMemEnd; // Initialized in __memprof_init. 28e8d8bef9SDimitry Andric 29e8d8bef9SDimitry Andric } // namespace __memprof 30e8d8bef9SDimitry Andric 31e8d8bef9SDimitry Andric // Size of memory block mapped to a single shadow location 32e8d8bef9SDimitry Andric #define MEM_GRANULARITY 64ULL 33e8d8bef9SDimitry Andric 34e8d8bef9SDimitry Andric #define SHADOW_MASK ~(MEM_GRANULARITY - 1) 35e8d8bef9SDimitry Andric 36e8d8bef9SDimitry Andric #define MEM_TO_SHADOW(mem) \ 37e8d8bef9SDimitry Andric ((((mem) & SHADOW_MASK) >> SHADOW_SCALE) + (SHADOW_OFFSET)) 38e8d8bef9SDimitry Andric 39*0fca6ea1SDimitry Andric // Histogram shadow memory is laid different to the standard configuration: 40*0fca6ea1SDimitry Andric 41*0fca6ea1SDimitry Andric // 8 bytes 42*0fca6ea1SDimitry Andric // +---+---+---+ +---+---+---+ +---+---+---+ 43*0fca6ea1SDimitry Andric // Memory | a | | b | | c | 44*0fca6ea1SDimitry Andric // +---+---+---+ +---+---+---+ +---+---+---+ 45*0fca6ea1SDimitry Andric 46*0fca6ea1SDimitry Andric // +---+ +---+ +---+ 47*0fca6ea1SDimitry Andric // Shadow | a | | b | | c | 48*0fca6ea1SDimitry Andric // +---+ +---+ +---+ 49*0fca6ea1SDimitry Andric // 1 byte 50*0fca6ea1SDimitry Andric // 51*0fca6ea1SDimitry Andric // Where we have a 1 byte counter for each 8 bytes. HISTOGRAM_MEM_TO_SHADOW 52*0fca6ea1SDimitry Andric // translates a memory address to the address of its corresponding shadow 53*0fca6ea1SDimitry Andric // counter memory address. The same data is still provided in MIB whether 54*0fca6ea1SDimitry Andric // histograms are used or not. Total access counts per allocations are 55*0fca6ea1SDimitry Andric // computed by summing up all individual 1 byte counters. This can incur an 56*0fca6ea1SDimitry Andric // accuracy penalty. 57*0fca6ea1SDimitry Andric 58*0fca6ea1SDimitry Andric #define HISTOGRAM_GRANULARITY 8U 59*0fca6ea1SDimitry Andric 60*0fca6ea1SDimitry Andric #define HISTOGRAM_MAX_COUNTER 255U 61*0fca6ea1SDimitry Andric 62*0fca6ea1SDimitry Andric #define HISTOGRAM_SHADOW_MASK ~(HISTOGRAM_GRANULARITY - 1) 63*0fca6ea1SDimitry Andric 64*0fca6ea1SDimitry Andric #define HISTOGRAM_MEM_TO_SHADOW(mem) \ 65*0fca6ea1SDimitry Andric ((((mem) & HISTOGRAM_SHADOW_MASK) >> SHADOW_SCALE) + (SHADOW_OFFSET)) 66*0fca6ea1SDimitry Andric 67*0fca6ea1SDimitry Andric #define SHADOW_ENTRY_SIZE (MEM_GRANULARITY >> SHADOW_SCALE) 68*0fca6ea1SDimitry Andric 69e8d8bef9SDimitry Andric #define kLowMemBeg 0 70e8d8bef9SDimitry Andric #define kLowMemEnd (SHADOW_OFFSET ? SHADOW_OFFSET - 1 : 0) 71e8d8bef9SDimitry Andric 72e8d8bef9SDimitry Andric #define kLowShadowBeg SHADOW_OFFSET 73e8d8bef9SDimitry Andric #define kLowShadowEnd (MEM_TO_SHADOW(kLowMemEnd) + SHADOW_ENTRY_SIZE - 1) 74e8d8bef9SDimitry Andric 75e8d8bef9SDimitry Andric #define kHighMemBeg (MEM_TO_SHADOW(kHighMemEnd) + 1 + SHADOW_ENTRY_SIZE - 1) 76e8d8bef9SDimitry Andric 77e8d8bef9SDimitry Andric #define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) 78e8d8bef9SDimitry Andric #define kHighShadowEnd (MEM_TO_SHADOW(kHighMemEnd) + SHADOW_ENTRY_SIZE - 1) 79e8d8bef9SDimitry Andric 80e8d8bef9SDimitry Andric // With the zero shadow base we can not actually map pages starting from 0. 81e8d8bef9SDimitry Andric // This constant is somewhat arbitrary. 82e8d8bef9SDimitry Andric #define kZeroBaseShadowStart 0 83e8d8bef9SDimitry Andric #define kZeroBaseMaxShadowStart (1 << 18) 84e8d8bef9SDimitry Andric 85e8d8bef9SDimitry Andric #define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 : kZeroBaseShadowStart) 86e8d8bef9SDimitry Andric #define kShadowGapEnd (kHighShadowBeg - 1) 87e8d8bef9SDimitry Andric 88e8d8bef9SDimitry Andric namespace __memprof { 89e8d8bef9SDimitry Andric 90e8d8bef9SDimitry Andric inline uptr MemToShadowSize(uptr size) { return size >> SHADOW_SCALE; } 91e8d8bef9SDimitry Andric inline bool AddrIsInLowMem(uptr a) { return a <= kLowMemEnd; } 92e8d8bef9SDimitry Andric 93e8d8bef9SDimitry Andric inline bool AddrIsInLowShadow(uptr a) { 94e8d8bef9SDimitry Andric return a >= kLowShadowBeg && a <= kLowShadowEnd; 95e8d8bef9SDimitry Andric } 96e8d8bef9SDimitry Andric 97e8d8bef9SDimitry Andric inline bool AddrIsInHighMem(uptr a) { 98e8d8bef9SDimitry Andric return kHighMemBeg && a >= kHighMemBeg && a <= kHighMemEnd; 99e8d8bef9SDimitry Andric } 100e8d8bef9SDimitry Andric 101e8d8bef9SDimitry Andric inline bool AddrIsInHighShadow(uptr a) { 102e8d8bef9SDimitry Andric return kHighMemBeg && a >= kHighShadowBeg && a <= kHighShadowEnd; 103e8d8bef9SDimitry Andric } 104e8d8bef9SDimitry Andric 105e8d8bef9SDimitry Andric inline bool AddrIsInShadowGap(uptr a) { 106e8d8bef9SDimitry Andric // In zero-based shadow mode we treat addresses near zero as addresses 107e8d8bef9SDimitry Andric // in shadow gap as well. 108e8d8bef9SDimitry Andric if (SHADOW_OFFSET == 0) 109e8d8bef9SDimitry Andric return a <= kShadowGapEnd; 110e8d8bef9SDimitry Andric return a >= kShadowGapBeg && a <= kShadowGapEnd; 111e8d8bef9SDimitry Andric } 112e8d8bef9SDimitry Andric 113e8d8bef9SDimitry Andric inline bool AddrIsInMem(uptr a) { 114e8d8bef9SDimitry Andric return AddrIsInLowMem(a) || AddrIsInHighMem(a) || 115e8d8bef9SDimitry Andric (flags()->protect_shadow_gap == 0 && AddrIsInShadowGap(a)); 116e8d8bef9SDimitry Andric } 117e8d8bef9SDimitry Andric 118e8d8bef9SDimitry Andric inline uptr MemToShadow(uptr p) { 119e8d8bef9SDimitry Andric CHECK(AddrIsInMem(p)); 120e8d8bef9SDimitry Andric return MEM_TO_SHADOW(p); 121e8d8bef9SDimitry Andric } 122e8d8bef9SDimitry Andric 123e8d8bef9SDimitry Andric inline bool AddrIsInShadow(uptr a) { 124e8d8bef9SDimitry Andric return AddrIsInLowShadow(a) || AddrIsInHighShadow(a); 125e8d8bef9SDimitry Andric } 126e8d8bef9SDimitry Andric 127e8d8bef9SDimitry Andric inline bool AddrIsAlignedByGranularity(uptr a) { 128e8d8bef9SDimitry Andric return (a & (SHADOW_GRANULARITY - 1)) == 0; 129e8d8bef9SDimitry Andric } 130e8d8bef9SDimitry Andric 131e8d8bef9SDimitry Andric inline void RecordAccess(uptr a) { 132e8d8bef9SDimitry Andric // If we use a different shadow size then the type below needs adjustment. 133e8d8bef9SDimitry Andric CHECK_EQ(SHADOW_ENTRY_SIZE, 8); 134e8d8bef9SDimitry Andric u64 *shadow_address = (u64 *)MEM_TO_SHADOW(a); 135e8d8bef9SDimitry Andric (*shadow_address)++; 136e8d8bef9SDimitry Andric } 137e8d8bef9SDimitry Andric 138*0fca6ea1SDimitry Andric inline void RecordAccessHistogram(uptr a) { 139*0fca6ea1SDimitry Andric CHECK_EQ(SHADOW_ENTRY_SIZE, 8); 140*0fca6ea1SDimitry Andric u8 *shadow_address = (u8 *)HISTOGRAM_MEM_TO_SHADOW(a); 141*0fca6ea1SDimitry Andric if (*shadow_address < HISTOGRAM_MAX_COUNTER) { 142*0fca6ea1SDimitry Andric (*shadow_address)++; 143*0fca6ea1SDimitry Andric } 144*0fca6ea1SDimitry Andric } 145*0fca6ea1SDimitry Andric 146e8d8bef9SDimitry Andric } // namespace __memprof 147e8d8bef9SDimitry Andric 148e8d8bef9SDimitry Andric #endif // MEMPROF_MAPPING_H 149