]>
Commit | Line | Data |
---|---|---|
f35db108 WM |
1 | //===-- asan_mapping.h ------------------------------------------*- C++ -*-===// |
2 | // | |
3 | // This file is distributed under the University of Illinois Open Source | |
4 | // License. See LICENSE.TXT for details. | |
5 | // | |
6 | //===----------------------------------------------------------------------===// | |
7 | // | |
8 | // This file is a part of AddressSanitizer, an address sanity checker. | |
9 | // | |
10 | // Defines ASan memory mapping. | |
11 | //===----------------------------------------------------------------------===// | |
12 | #ifndef ASAN_MAPPING_H | |
13 | #define ASAN_MAPPING_H | |
14 | ||
15 | #include "asan_internal.h" | |
16 | ||
17 | // The full explanation of the memory mapping could be found here: | |
18 | // http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm | |
7df59255 KS |
19 | // |
20 | // Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000: | |
21 | // || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || | |
22 | // || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow || | |
23 | // || `[0x00008fff7000, 0x02008fff6fff]` || ShadowGap || | |
24 | // || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow || | |
25 | // || `[0x000000000000, 0x00007fff7fff]` || LowMem || | |
26 | // | |
27 | // When SHADOW_OFFSET is zero (-pie): | |
28 | // || `[0x100000000000, 0x7fffffffffff]` || HighMem || | |
29 | // || `[0x020000000000, 0x0fffffffffff]` || HighShadow || | |
30 | // || `[0x000000040000, 0x01ffffffffff]` || ShadowGap || | |
31 | // | |
32 | // Special case when something is already mapped between | |
4c376126 | 33 | // 0x003000000000 and 0x005000000000 (e.g. when prelink is installed): |
7df59255 KS |
34 | // || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || |
35 | // || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow || | |
4c376126 JJ |
36 | // || `[0x005000000000, 0x02008fff6fff]` || ShadowGap3 || |
37 | // || `[0x003000000000, 0x004fffffffff]` || MidMem || | |
38 | // || `[0x000a7fff8000, 0x002fffffffff]` || ShadowGap2 || | |
39 | // || `[0x00067fff8000, 0x000a7fff7fff]` || MidShadow || | |
7df59255 KS |
40 | // || `[0x00008fff7000, 0x00067fff7fff]` || ShadowGap || |
41 | // || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow || | |
42 | // || `[0x000000000000, 0x00007fff7fff]` || LowMem || | |
43 | // | |
dee5ea7a | 44 | // Default Linux/i386 mapping on x86_64 machine: |
7df59255 KS |
45 | // || `[0x40000000, 0xffffffff]` || HighMem || |
46 | // || `[0x28000000, 0x3fffffff]` || HighShadow || | |
47 | // || `[0x24000000, 0x27ffffff]` || ShadowGap || | |
48 | // || `[0x20000000, 0x23ffffff]` || LowShadow || | |
49 | // || `[0x00000000, 0x1fffffff]` || LowMem || | |
ef1b3fda | 50 | // |
dee5ea7a KS |
51 | // Default Linux/i386 mapping on i386 machine |
52 | // (addresses starting with 0xc0000000 are reserved | |
53 | // for kernel and thus not sanitized): | |
54 | // || `[0x38000000, 0xbfffffff]` || HighMem || | |
55 | // || `[0x27000000, 0x37ffffff]` || HighShadow || | |
56 | // || `[0x24000000, 0x26ffffff]` || ShadowGap || | |
57 | // || `[0x20000000, 0x23ffffff]` || LowShadow || | |
58 | // || `[0x00000000, 0x1fffffff]` || LowMem || | |
59 | // | |
696d846a | 60 | // Default Linux/MIPS32 mapping: |
c5be964a KS |
61 | // || `[0x2aaa0000, 0xffffffff]` || HighMem || |
62 | // || `[0x0fff4000, 0x2aa9ffff]` || HighShadow || | |
63 | // || `[0x0bff4000, 0x0fff3fff]` || ShadowGap || | |
64 | // || `[0x0aaa0000, 0x0bff3fff]` || LowShadow || | |
65 | // || `[0x00000000, 0x0aa9ffff]` || LowMem || | |
dee5ea7a | 66 | // |
696d846a MO |
67 | // Default Linux/MIPS64 mapping: |
68 | // || `[0x4000000000, 0xffffffffff]` || HighMem || | |
69 | // || `[0x2800000000, 0x3fffffffff]` || HighShadow || | |
70 | // || `[0x2400000000, 0x27ffffffff]` || ShadowGap || | |
71 | // || `[0x2000000000, 0x23ffffffff]` || LowShadow || | |
72 | // || `[0x0000000000, 0x1fffffffff]` || LowMem || | |
73 | // | |
74 | // Default Linux/AArch64 (39-bit VMA) mapping: | |
75 | // || `[0x2000000000, 0x7fffffffff]` || highmem || | |
76 | // || `[0x1400000000, 0x1fffffffff]` || highshadow || | |
77 | // || `[0x1200000000, 0x13ffffffff]` || shadowgap || | |
78 | // || `[0x1000000000, 0x11ffffffff]` || lowshadow || | |
79 | // || `[0x0000000000, 0x0fffffffff]` || lowmem || | |
80 | // | |
81 | // Default Linux/AArch64 (42-bit VMA) mapping: | |
82 | // || `[0x10000000000, 0x3ffffffffff]` || highmem || | |
83 | // || `[0x0a000000000, 0x0ffffffffff]` || highshadow || | |
84 | // || `[0x09000000000, 0x09fffffffff]` || shadowgap || | |
85 | // || `[0x08000000000, 0x08fffffffff]` || lowshadow || | |
86 | // || `[0x00000000000, 0x07fffffffff]` || lowmem || | |
87 | // | |
dee5ea7a KS |
88 | // Shadow mapping on FreeBSD/x86-64 with SHADOW_OFFSET == 0x400000000000: |
89 | // || `[0x500000000000, 0x7fffffffffff]` || HighMem || | |
90 | // || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow || | |
91 | // || `[0x480000000000, 0x49ffffffffff]` || ShadowGap || | |
92 | // || `[0x400000000000, 0x47ffffffffff]` || LowShadow || | |
93 | // || `[0x000000000000, 0x3fffffffffff]` || LowMem || | |
94 | // | |
95 | // Shadow mapping on FreeBSD/i386 with SHADOW_OFFSET == 0x40000000: | |
96 | // || `[0x60000000, 0xffffffff]` || HighMem || | |
97 | // || `[0x4c000000, 0x5fffffff]` || HighShadow || | |
98 | // || `[0x48000000, 0x4bffffff]` || ShadowGap || | |
99 | // || `[0x40000000, 0x47ffffff]` || LowShadow || | |
100 | // || `[0x00000000, 0x3fffffff]` || LowMem || | |
696d846a MO |
101 | // |
102 | // Default Windows/i386 mapping: | |
103 | // (the exact location of HighShadow/HighMem may vary depending | |
104 | // on WoW64, /LARGEADDRESSAWARE, etc). | |
105 | // || `[0x50000000, 0xffffffff]` || HighMem || | |
106 | // || `[0x3a000000, 0x4fffffff]` || HighShadow || | |
107 | // || `[0x36000000, 0x39ffffff]` || ShadowGap || | |
108 | // || `[0x30000000, 0x35ffffff]` || LowShadow || | |
109 | // || `[0x00000000, 0x2fffffff]` || LowMem || | |
ef1b3fda KS |
110 | |
111 | static const u64 kDefaultShadowScale = 3; | |
dee5ea7a | 112 | static const u64 kDefaultShadowOffset32 = 1ULL << 29; // 0x20000000 |
ef1b3fda KS |
113 | static const u64 kDefaultShadowOffset64 = 1ULL << 44; |
114 | static const u64 kDefaultShort64bitShadowOffset = 0x7FFF8000; // < 2G. | |
696d846a MO |
115 | static const u64 kIosShadowOffset32 = 1ULL << 30; // 0x40000000 |
116 | static const u64 kIosShadowOffset64 = 0x130000000; | |
117 | static const u64 kIosSimShadowOffset32 = 1ULL << 30; | |
118 | static const u64 kIosSimShadowOffset64 = kDefaultShadowOffset64; | |
dee5ea7a | 119 | static const u64 kAArch64_ShadowOffset64 = 1ULL << 36; |
c5be964a | 120 | static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000; |
696d846a | 121 | static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37; |
ecd5543f | 122 | static const u64 kPPC64_ShadowOffset64 = 1ULL << 41; |
dee5ea7a KS |
123 | static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000 |
124 | static const u64 kFreeBSD_ShadowOffset64 = 1ULL << 46; // 0x400000000000 | |
696d846a | 125 | static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000 |
f35db108 | 126 | |
dee5ea7a | 127 | #define SHADOW_SCALE kDefaultShadowScale |
696d846a MO |
128 | |
129 | ||
130 | #if SANITIZER_WORDSIZE == 32 | |
131 | # if SANITIZER_ANDROID | |
132 | # define SHADOW_OFFSET (0) | |
133 | # elif defined(__mips__) | |
dee5ea7a KS |
134 | # define SHADOW_OFFSET kMIPS32_ShadowOffset32 |
135 | # elif SANITIZER_FREEBSD | |
136 | # define SHADOW_OFFSET kFreeBSD_ShadowOffset32 | |
696d846a MO |
137 | # elif SANITIZER_WINDOWS |
138 | # define SHADOW_OFFSET kWindowsShadowOffset32 | |
139 | # elif SANITIZER_IOSSIM | |
140 | # define SHADOW_OFFSET kIosSimShadowOffset32 | |
141 | # elif SANITIZER_IOS | |
142 | # define SHADOW_OFFSET kIosShadowOffset32 | |
dee5ea7a | 143 | # else |
696d846a | 144 | # define SHADOW_OFFSET kDefaultShadowOffset32 |
dee5ea7a | 145 | # endif |
696d846a | 146 | #else |
dee5ea7a KS |
147 | # if defined(__aarch64__) |
148 | # define SHADOW_OFFSET kAArch64_ShadowOffset64 | |
ecd5543f JJ |
149 | # elif defined(__powerpc64__) |
150 | # define SHADOW_OFFSET kPPC64_ShadowOffset64 | |
dee5ea7a KS |
151 | # elif SANITIZER_FREEBSD |
152 | # define SHADOW_OFFSET kFreeBSD_ShadowOffset64 | |
153 | # elif SANITIZER_MAC | |
154 | # define SHADOW_OFFSET kDefaultShadowOffset64 | |
c5be964a KS |
155 | # elif defined(__mips64) |
156 | # define SHADOW_OFFSET kMIPS64_ShadowOffset64 | |
696d846a MO |
157 | # elif SANITIZER_IOSSIM |
158 | # define SHADOW_OFFSET kIosSimShadowOffset64 | |
159 | # elif SANITIZER_IOS | |
160 | # define SHADOW_OFFSET kIosShadowOffset64 | |
f35db108 | 161 | # else |
dee5ea7a | 162 | # define SHADOW_OFFSET kDefaultShort64bitShadowOffset |
f35db108 | 163 | # endif |
dee5ea7a | 164 | #endif |
f35db108 WM |
165 | |
166 | #define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE) | |
b4ab7d34 | 167 | #define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) + (SHADOW_OFFSET)) |
f35db108 WM |
168 | #define SHADOW_TO_MEM(shadow) (((shadow) - SHADOW_OFFSET) << SHADOW_SCALE) |
169 | ||
f35db108 WM |
170 | #define kLowMemBeg 0 |
171 | #define kLowMemEnd (SHADOW_OFFSET ? SHADOW_OFFSET - 1 : 0) | |
172 | ||
173 | #define kLowShadowBeg SHADOW_OFFSET | |
174 | #define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd) | |
175 | ||
176 | #define kHighMemBeg (MEM_TO_SHADOW(kHighMemEnd) + 1) | |
177 | ||
178 | #define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) | |
179 | #define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd) | |
180 | ||
7df59255 KS |
181 | # define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg) |
182 | # define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd) | |
183 | ||
4ba5ca46 KS |
184 | // With the zero shadow base we can not actually map pages starting from 0. |
185 | // This constant is somewhat arbitrary. | |
696d846a MO |
186 | #define kZeroBaseShadowStart 0 |
187 | #define kZeroBaseMaxShadowStart (1 << 18) | |
4ba5ca46 KS |
188 | |
189 | #define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \ | |
190 | : kZeroBaseShadowStart) | |
7df59255 KS |
191 | #define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1) |
192 | ||
193 | #define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0) | |
194 | #define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0) | |
195 | ||
196 | #define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0) | |
197 | #define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0) | |
198 | ||
199 | #define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below. | |
200 | ||
201 | #if DO_ASAN_MAPPING_PROFILE | |
202 | # define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++; | |
203 | #else | |
204 | # define PROFILE_ASAN_MAPPING() | |
205 | #endif | |
206 | ||
207 | // If 1, all shadow boundaries are constants. | |
208 | // Don't set to 1 other than for testing. | |
209 | #define ASAN_FIXED_MAPPING 0 | |
f35db108 | 210 | |
f35db108 WM |
211 | namespace __asan { |
212 | ||
7df59255 KS |
213 | extern uptr AsanMappingProfile[]; |
214 | ||
215 | #if ASAN_FIXED_MAPPING | |
216 | // Fixed mapping for 64-bit Linux. Mostly used for performance comparison | |
217 | // with non-fixed mapping. As of r175253 (Feb 2013) the performance | |
218 | // difference between fixed and non-fixed mapping is below the noise level. | |
219 | static uptr kHighMemEnd = 0x7fffffffffffULL; | |
220 | static uptr kMidMemBeg = 0x3000000000ULL; | |
4c376126 | 221 | static uptr kMidMemEnd = 0x4fffffffffULL; |
7df59255 | 222 | #else |
7df59255 KS |
223 | extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init. |
224 | #endif | |
b4ab7d34 | 225 | |
f35db108 | 226 | static inline bool AddrIsInLowMem(uptr a) { |
7df59255 | 227 | PROFILE_ASAN_MAPPING(); |
f35db108 WM |
228 | return a < kLowMemEnd; |
229 | } | |
230 | ||
231 | static inline bool AddrIsInLowShadow(uptr a) { | |
7df59255 | 232 | PROFILE_ASAN_MAPPING(); |
f35db108 WM |
233 | return a >= kLowShadowBeg && a <= kLowShadowEnd; |
234 | } | |
235 | ||
236 | static inline bool AddrIsInHighMem(uptr a) { | |
7df59255 | 237 | PROFILE_ASAN_MAPPING(); |
f35db108 WM |
238 | return a >= kHighMemBeg && a <= kHighMemEnd; |
239 | } | |
240 | ||
7df59255 KS |
241 | static inline bool AddrIsInMidMem(uptr a) { |
242 | PROFILE_ASAN_MAPPING(); | |
243 | return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd; | |
244 | } | |
245 | ||
f35db108 | 246 | static inline bool AddrIsInMem(uptr a) { |
7df59255 KS |
247 | PROFILE_ASAN_MAPPING(); |
248 | return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a); | |
f35db108 WM |
249 | } |
250 | ||
251 | static inline uptr MemToShadow(uptr p) { | |
7df59255 | 252 | PROFILE_ASAN_MAPPING(); |
f35db108 WM |
253 | CHECK(AddrIsInMem(p)); |
254 | return MEM_TO_SHADOW(p); | |
255 | } | |
256 | ||
257 | static inline bool AddrIsInHighShadow(uptr a) { | |
7df59255 KS |
258 | PROFILE_ASAN_MAPPING(); |
259 | return a >= kHighShadowBeg && a <= kHighMemEnd; | |
260 | } | |
261 | ||
262 | static inline bool AddrIsInMidShadow(uptr a) { | |
263 | PROFILE_ASAN_MAPPING(); | |
264 | return kMidMemBeg && a >= kMidShadowBeg && a <= kMidMemEnd; | |
f35db108 WM |
265 | } |
266 | ||
267 | static inline bool AddrIsInShadow(uptr a) { | |
7df59255 KS |
268 | PROFILE_ASAN_MAPPING(); |
269 | return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a); | |
f35db108 WM |
270 | } |
271 | ||
272 | static inline bool AddrIsInShadowGap(uptr a) { | |
7df59255 KS |
273 | PROFILE_ASAN_MAPPING(); |
274 | if (kMidMemBeg) { | |
275 | if (a <= kShadowGapEnd) | |
276 | return SHADOW_OFFSET == 0 || a >= kShadowGapBeg; | |
277 | return (a >= kShadowGap2Beg && a <= kShadowGap2End) || | |
278 | (a >= kShadowGap3Beg && a <= kShadowGap3End); | |
279 | } | |
2660d12d KS |
280 | // In zero-based shadow mode we treat addresses near zero as addresses |
281 | // in shadow gap as well. | |
282 | if (SHADOW_OFFSET == 0) | |
283 | return a <= kShadowGapEnd; | |
f35db108 WM |
284 | return a >= kShadowGapBeg && a <= kShadowGapEnd; |
285 | } | |
286 | ||
287 | static inline bool AddrIsAlignedByGranularity(uptr a) { | |
7df59255 | 288 | PROFILE_ASAN_MAPPING(); |
f35db108 WM |
289 | return (a & (SHADOW_GRANULARITY - 1)) == 0; |
290 | } | |
291 | ||
292 | static inline bool AddressIsPoisoned(uptr a) { | |
7df59255 | 293 | PROFILE_ASAN_MAPPING(); |
f35db108 | 294 | const uptr kAccessSize = 1; |
7df59255 | 295 | u8 *shadow_address = (u8*)MEM_TO_SHADOW(a); |
f35db108 WM |
296 | s8 shadow_value = *shadow_address; |
297 | if (shadow_value) { | |
298 | u8 last_accessed_byte = (a & (SHADOW_GRANULARITY - 1)) | |
299 | + kAccessSize - 1; | |
300 | return (last_accessed_byte >= shadow_value); | |
301 | } | |
302 | return false; | |
303 | } | |
304 | ||
7df59255 KS |
305 | // Must be after all calls to PROFILE_ASAN_MAPPING(). |
306 | static const uptr kAsanMappingProfileSize = __LINE__; | |
307 | ||
f35db108 WM |
308 | } // namespace __asan |
309 | ||
310 | #endif // ASAN_MAPPING_H |