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