1*d89ec533Spatrick //===-- memprof_mapping.h --------------------------------------*- C++ -*-===// 2*d89ec533Spatrick // 3*d89ec533Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*d89ec533Spatrick // See https://llvm.org/LICENSE.txt for license information. 5*d89ec533Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*d89ec533Spatrick // 7*d89ec533Spatrick //===----------------------------------------------------------------------===// 8*d89ec533Spatrick // 9*d89ec533Spatrick // This file is a part of MemProfiler, a memory profiler. 10*d89ec533Spatrick // 11*d89ec533Spatrick // Defines MemProf memory mapping. 12*d89ec533Spatrick //===----------------------------------------------------------------------===// 13*d89ec533Spatrick #ifndef MEMPROF_MAPPING_H 14*d89ec533Spatrick #define MEMPROF_MAPPING_H 15*d89ec533Spatrick 16*d89ec533Spatrick #include "memprof_internal.h" 17*d89ec533Spatrick 18*d89ec533Spatrick static const u64 kDefaultShadowScale = 3; 19*d89ec533Spatrick #define SHADOW_SCALE kDefaultShadowScale 20*d89ec533Spatrick 21*d89ec533Spatrick #define SHADOW_OFFSET __memprof_shadow_memory_dynamic_address 22*d89ec533Spatrick 23*d89ec533Spatrick #define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE) 24*d89ec533Spatrick #define MEMPROF_ALIGNMENT 32 25*d89ec533Spatrick 26*d89ec533Spatrick namespace __memprof { 27*d89ec533Spatrick 28*d89ec533Spatrick extern uptr kHighMemEnd; // Initialized in __memprof_init. 29*d89ec533Spatrick 30*d89ec533Spatrick } // namespace __memprof 31*d89ec533Spatrick 32*d89ec533Spatrick #define SHADOW_ENTRY_SIZE 8 33*d89ec533Spatrick 34*d89ec533Spatrick // Size of memory block mapped to a single shadow location 35*d89ec533Spatrick #define MEM_GRANULARITY 64ULL 36*d89ec533Spatrick 37*d89ec533Spatrick #define SHADOW_MASK ~(MEM_GRANULARITY - 1) 38*d89ec533Spatrick 39*d89ec533Spatrick #define MEM_TO_SHADOW(mem) \ 40*d89ec533Spatrick ((((mem) & SHADOW_MASK) >> SHADOW_SCALE) + (SHADOW_OFFSET)) 41*d89ec533Spatrick 42*d89ec533Spatrick #define kLowMemBeg 0 43*d89ec533Spatrick #define kLowMemEnd (SHADOW_OFFSET ? SHADOW_OFFSET - 1 : 0) 44*d89ec533Spatrick 45*d89ec533Spatrick #define kLowShadowBeg SHADOW_OFFSET 46*d89ec533Spatrick #define kLowShadowEnd (MEM_TO_SHADOW(kLowMemEnd) + SHADOW_ENTRY_SIZE - 1) 47*d89ec533Spatrick 48*d89ec533Spatrick #define kHighMemBeg (MEM_TO_SHADOW(kHighMemEnd) + 1 + SHADOW_ENTRY_SIZE - 1) 49*d89ec533Spatrick 50*d89ec533Spatrick #define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) 51*d89ec533Spatrick #define kHighShadowEnd (MEM_TO_SHADOW(kHighMemEnd) + SHADOW_ENTRY_SIZE - 1) 52*d89ec533Spatrick 53*d89ec533Spatrick // With the zero shadow base we can not actually map pages starting from 0. 54*d89ec533Spatrick // This constant is somewhat arbitrary. 55*d89ec533Spatrick #define kZeroBaseShadowStart 0 56*d89ec533Spatrick #define kZeroBaseMaxShadowStart (1 << 18) 57*d89ec533Spatrick 58*d89ec533Spatrick #define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 : kZeroBaseShadowStart) 59*d89ec533Spatrick #define kShadowGapEnd (kHighShadowBeg - 1) 60*d89ec533Spatrick 61*d89ec533Spatrick namespace __memprof { 62*d89ec533Spatrick MemToShadowSize(uptr size)63*d89ec533Spatrickinline uptr MemToShadowSize(uptr size) { return size >> SHADOW_SCALE; } AddrIsInLowMem(uptr a)64*d89ec533Spatrickinline bool AddrIsInLowMem(uptr a) { return a <= kLowMemEnd; } 65*d89ec533Spatrick AddrIsInLowShadow(uptr a)66*d89ec533Spatrickinline bool AddrIsInLowShadow(uptr a) { 67*d89ec533Spatrick return a >= kLowShadowBeg && a <= kLowShadowEnd; 68*d89ec533Spatrick } 69*d89ec533Spatrick AddrIsInHighMem(uptr a)70*d89ec533Spatrickinline bool AddrIsInHighMem(uptr a) { 71*d89ec533Spatrick return kHighMemBeg && a >= kHighMemBeg && a <= kHighMemEnd; 72*d89ec533Spatrick } 73*d89ec533Spatrick AddrIsInHighShadow(uptr a)74*d89ec533Spatrickinline bool AddrIsInHighShadow(uptr a) { 75*d89ec533Spatrick return kHighMemBeg && a >= kHighShadowBeg && a <= kHighShadowEnd; 76*d89ec533Spatrick } 77*d89ec533Spatrick AddrIsInShadowGap(uptr a)78*d89ec533Spatrickinline bool AddrIsInShadowGap(uptr a) { 79*d89ec533Spatrick // In zero-based shadow mode we treat addresses near zero as addresses 80*d89ec533Spatrick // in shadow gap as well. 81*d89ec533Spatrick if (SHADOW_OFFSET == 0) 82*d89ec533Spatrick return a <= kShadowGapEnd; 83*d89ec533Spatrick return a >= kShadowGapBeg && a <= kShadowGapEnd; 84*d89ec533Spatrick } 85*d89ec533Spatrick AddrIsInMem(uptr a)86*d89ec533Spatrickinline bool AddrIsInMem(uptr a) { 87*d89ec533Spatrick return AddrIsInLowMem(a) || AddrIsInHighMem(a) || 88*d89ec533Spatrick (flags()->protect_shadow_gap == 0 && AddrIsInShadowGap(a)); 89*d89ec533Spatrick } 90*d89ec533Spatrick MemToShadow(uptr p)91*d89ec533Spatrickinline uptr MemToShadow(uptr p) { 92*d89ec533Spatrick CHECK(AddrIsInMem(p)); 93*d89ec533Spatrick return MEM_TO_SHADOW(p); 94*d89ec533Spatrick } 95*d89ec533Spatrick AddrIsInShadow(uptr a)96*d89ec533Spatrickinline bool AddrIsInShadow(uptr a) { 97*d89ec533Spatrick return AddrIsInLowShadow(a) || AddrIsInHighShadow(a); 98*d89ec533Spatrick } 99*d89ec533Spatrick AddrIsAlignedByGranularity(uptr a)100*d89ec533Spatrickinline bool AddrIsAlignedByGranularity(uptr a) { 101*d89ec533Spatrick return (a & (SHADOW_GRANULARITY - 1)) == 0; 102*d89ec533Spatrick } 103*d89ec533Spatrick RecordAccess(uptr a)104*d89ec533Spatrickinline void RecordAccess(uptr a) { 105*d89ec533Spatrick // If we use a different shadow size then the type below needs adjustment. 106*d89ec533Spatrick CHECK_EQ(SHADOW_ENTRY_SIZE, 8); 107*d89ec533Spatrick u64 *shadow_address = (u64 *)MEM_TO_SHADOW(a); 108*d89ec533Spatrick (*shadow_address)++; 109*d89ec533Spatrick } 110*d89ec533Spatrick 111*d89ec533Spatrick } // namespace __memprof 112*d89ec533Spatrick 113*d89ec533Spatrick #endif // MEMPROF_MAPPING_H 114