Skip to content

Commit ce26498

Browse files
committedMay 18, 2018
[asan] Add support for Myriad RTEMS memory map
The Myriad RTEMS memory system has a few unique aspects that require support in the ASan run-time. - A limited amount of memory (currently 512M). - No virtual memory, no memory protection. - DRAM starts at address 0x80000000. Other parts of memory may be used for MMIO, etc. - The second highest address bit is the "cache" bit, and 0x80000000 and 0x84000000 alias to the same memory. To support the above, we make the following changes: - Use a ShadowScale of 5, to reduce shadow memory overhead. - Adjust some existing macros to remove assumption that the lowest memory address is 0. - add a RawAddr macro that on Myriad strips the cache bit from the input address, before using the address for shadow memory (for other archs this does nothing). - We must check that an address is in DRAM range before using it to index into shadow memory. Differential Revision: https://reviews.llvm.org/D46456 llvm-svn: 332690
1 parent 68f2218 commit ce26498

File tree

4 files changed

+187
-52
lines changed

4 files changed

+187
-52
lines changed
 

‎compiler-rt/lib/asan/asan_mapping.h

+73-40
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,17 @@
137137
// || `[0x36000000, 0x39ffffff]` || ShadowGap ||
138138
// || `[0x30000000, 0x35ffffff]` || LowShadow ||
139139
// || `[0x00000000, 0x2fffffff]` || LowMem ||
140+
//
141+
// Shadow mapping on Myriad2 (for shadow scale 5):
142+
// || `[0x9ff80000, 0x9fffffff]` || ShadowGap ||
143+
// || `[0x9f000000, 0x9ff7ffff]` || LowShadow ||
144+
// || `[0x80000000, 0x9effffff]` || LowMem ||
145+
// || `[0x00000000, 0x7fffffff]` || Ignored ||
140146

141147
#if defined(ASAN_SHADOW_SCALE)
142148
static const u64 kDefaultShadowScale = ASAN_SHADOW_SCALE;
143149
#else
144-
static const u64 kDefaultShadowScale = 3;
150+
static const u64 kDefaultShadowScale = SANITIZER_MYRIAD2 ? 5 : 3;
145151
#endif
146152
static const u64 kDefaultShadowSentinel = ~(uptr)0;
147153
static const u64 kDefaultShadowOffset32 = 1ULL << 29; // 0x20000000
@@ -163,6 +169,15 @@ static const u64 kNetBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000
163169
static const u64 kNetBSD_ShadowOffset64 = 1ULL << 46; // 0x400000000000
164170
static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
165171

172+
static const u64 kMyriadMemoryOffset32 = 0x80000000ULL;
173+
static const u64 kMyriadMemorySize32 = 0x20000000ULL;
174+
static const u64 kMyriadMemoryEnd32 =
175+
kMyriadMemoryOffset32 + kMyriadMemorySize32 - 1;
176+
static const u64 kMyriadShadowOffset32 =
177+
(kMyriadMemoryOffset32 + kMyriadMemorySize32 -
178+
(kMyriadMemorySize32 >> kDefaultShadowScale));
179+
static const u64 kMyriadCacheBitMask32 = 0x40000000ULL;
180+
166181
#define SHADOW_SCALE kDefaultShadowScale
167182

168183
#if SANITIZER_FUCHSIA
@@ -184,6 +199,8 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
184199
# else
185200
# define SHADOW_OFFSET kIosShadowOffset32
186201
# endif
202+
# elif SANITIZER_MYRIAD2
203+
# define SHADOW_OFFSET kMyriadShadowOffset32
187204
# else
188205
# define SHADOW_OFFSET kDefaultShadowOffset32
189206
# endif
@@ -222,6 +239,39 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
222239
#endif
223240

224241
#define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE)
242+
243+
#define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below.
244+
245+
#if DO_ASAN_MAPPING_PROFILE
246+
# define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++;
247+
#else
248+
# define PROFILE_ASAN_MAPPING()
249+
#endif
250+
251+
// If 1, all shadow boundaries are constants.
252+
// Don't set to 1 other than for testing.
253+
#define ASAN_FIXED_MAPPING 0
254+
255+
namespace __asan {
256+
257+
extern uptr AsanMappingProfile[];
258+
259+
#if ASAN_FIXED_MAPPING
260+
// Fixed mapping for 64-bit Linux. Mostly used for performance comparison
261+
// with non-fixed mapping. As of r175253 (Feb 2013) the performance
262+
// difference between fixed and non-fixed mapping is below the noise level.
263+
static uptr kHighMemEnd = 0x7fffffffffffULL;
264+
static uptr kMidMemBeg = 0x3000000000ULL;
265+
static uptr kMidMemEnd = 0x4fffffffffULL;
266+
#else
267+
extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init.
268+
#endif
269+
270+
} // namespace __asan
271+
272+
#if SANITIZER_MYRIAD2
273+
#include "asan_mapping_myriad.h"
274+
#else
225275
#define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) + (SHADOW_OFFSET))
226276

227277
#define kLowMemBeg 0
@@ -253,51 +303,36 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
253303
#define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0)
254304
#define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0)
255305

256-
#define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below.
257-
258-
#if DO_ASAN_MAPPING_PROFILE
259-
# define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++;
260-
#else
261-
# define PROFILE_ASAN_MAPPING()
262-
#endif
263-
264-
// If 1, all shadow boundaries are constants.
265-
// Don't set to 1 other than for testing.
266-
#define ASAN_FIXED_MAPPING 0
267-
268306
namespace __asan {
269307

270-
extern uptr AsanMappingProfile[];
271-
272-
#if ASAN_FIXED_MAPPING
273-
// Fixed mapping for 64-bit Linux. Mostly used for performance comparison
274-
// with non-fixed mapping. As of r175253 (Feb 2013) the performance
275-
// difference between fixed and non-fixed mapping is below the noise level.
276-
static uptr kHighMemEnd = 0x7fffffffffffULL;
277-
static uptr kMidMemBeg = 0x3000000000ULL;
278-
static uptr kMidMemEnd = 0x4fffffffffULL;
279-
#else
280-
extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init.
281-
#endif
282-
283308
static inline bool AddrIsInLowMem(uptr a) {
284309
PROFILE_ASAN_MAPPING();
285-
return a < kLowMemEnd;
310+
return a >= kLowMemBeg && a <= kLowMemEnd;
286311
}
287312

288313
static inline bool AddrIsInLowShadow(uptr a) {
289314
PROFILE_ASAN_MAPPING();
290315
return a >= kLowShadowBeg && a <= kLowShadowEnd;
291316
}
292317

318+
static inline bool AddrIsInMidMem(uptr a) {
319+
PROFILE_ASAN_MAPPING();
320+
return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd;
321+
}
322+
323+
static inline bool AddrIsInMidShadow(uptr a) {
324+
PROFILE_ASAN_MAPPING();
325+
return kMidMemBeg && a >= kMidShadowBeg && a <= kMidShadowEnd;
326+
}
327+
293328
static inline bool AddrIsInHighMem(uptr a) {
294329
PROFILE_ASAN_MAPPING();
295-
return a >= kHighMemBeg && a <= kHighMemEnd;
330+
return kHighMemBeg && a >= kHighMemBeg && a <= kHighMemEnd;
296331
}
297332

298-
static inline bool AddrIsInMidMem(uptr a) {
333+
static inline bool AddrIsInHighShadow(uptr a) {
299334
PROFILE_ASAN_MAPPING();
300-
return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd;
335+
return kHighMemBeg && a >= kHighShadowBeg && a <= kHighShadowEnd;
301336
}
302337

303338
static inline bool AddrIsInShadowGap(uptr a) {
@@ -315,6 +350,12 @@ static inline bool AddrIsInShadowGap(uptr a) {
315350
return a >= kShadowGapBeg && a <= kShadowGapEnd;
316351
}
317352

353+
} // namespace __asan
354+
355+
#endif // SANITIZER_MYRIAD2
356+
357+
namespace __asan {
358+
318359
static inline bool AddrIsInMem(uptr a) {
319360
PROFILE_ASAN_MAPPING();
320361
return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a) ||
@@ -327,16 +368,6 @@ static inline uptr MemToShadow(uptr p) {
327368
return MEM_TO_SHADOW(p);
328369
}
329370

330-
static inline bool AddrIsInHighShadow(uptr a) {
331-
PROFILE_ASAN_MAPPING();
332-
return a >= kHighShadowBeg && a <= kHighShadowEnd;
333-
}
334-
335-
static inline bool AddrIsInMidShadow(uptr a) {
336-
PROFILE_ASAN_MAPPING();
337-
return kMidMemBeg && a >= kMidShadowBeg && a <= kMidShadowEnd;
338-
}
339-
340371
static inline bool AddrIsInShadow(uptr a) {
341372
PROFILE_ASAN_MAPPING();
342373
return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a);
@@ -349,6 +380,8 @@ static inline bool AddrIsAlignedByGranularity(uptr a) {
349380

350381
static inline bool AddressIsPoisoned(uptr a) {
351382
PROFILE_ASAN_MAPPING();
383+
if (SANITIZER_MYRIAD2 && !AddrIsInMem(a) && !AddrIsInShadow(a))
384+
return false;
352385
const uptr kAccessSize = 1;
353386
u8 *shadow_address = (u8*)MEM_TO_SHADOW(a);
354387
s8 shadow_value = *shadow_address;
+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//===-- asan_mapping_myriad.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+
// Myriad-specific definitions for ASan memory mapping.
13+
//===----------------------------------------------------------------------===//
14+
#ifndef ASAN_MAPPING_MYRIAD_H
15+
#define ASAN_MAPPING_MYRIAD_H
16+
17+
#define RAW_ADDR(mem) ((mem) & ~kMyriadCacheBitMask32)
18+
#define MEM_TO_SHADOW(mem) \
19+
(((RAW_ADDR(mem) - kLowMemBeg) >> SHADOW_SCALE) + (SHADOW_OFFSET))
20+
21+
#define kLowMemBeg kMyriadMemoryOffset32
22+
#define kLowMemEnd (SHADOW_OFFSET - 1)
23+
24+
#define kLowShadowBeg SHADOW_OFFSET
25+
#define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd)
26+
27+
#define kHighMemBeg 0
28+
29+
#define kHighShadowBeg 0
30+
#define kHighShadowEnd 0
31+
32+
#define kMidShadowBeg 0
33+
#define kMidShadowEnd 0
34+
35+
#define kShadowGapBeg (kLowShadowEnd + 1)
36+
#define kShadowGapEnd kMyriadMemoryEnd32
37+
38+
#define kShadowGap2Beg 0
39+
#define kShadowGap2End 0
40+
41+
#define kShadowGap3Beg 0
42+
#define kShadowGap3End 0
43+
44+
namespace __asan {
45+
46+
static inline bool AddrIsInLowMem(uptr a) {
47+
PROFILE_ASAN_MAPPING();
48+
a = RAW_ADDR(a);
49+
return a >= kLowMemBeg && a <= kLowMemEnd;
50+
}
51+
52+
static inline bool AddrIsInLowShadow(uptr a) {
53+
PROFILE_ASAN_MAPPING();
54+
a = RAW_ADDR(a);
55+
return a >= kLowShadowBeg && a <= kLowShadowEnd;
56+
}
57+
58+
static inline bool AddrIsInMidMem(uptr a) {
59+
PROFILE_ASAN_MAPPING();
60+
return false;
61+
}
62+
63+
static inline bool AddrIsInMidShadow(uptr a) {
64+
PROFILE_ASAN_MAPPING();
65+
return false;
66+
}
67+
68+
static inline bool AddrIsInHighMem(uptr a) {
69+
PROFILE_ASAN_MAPPING();
70+
return false;
71+
}
72+
73+
static inline bool AddrIsInHighShadow(uptr a) {
74+
PROFILE_ASAN_MAPPING();
75+
return false;
76+
}
77+
78+
static inline bool AddrIsInShadowGap(uptr a) {
79+
PROFILE_ASAN_MAPPING();
80+
a = RAW_ADDR(a);
81+
return a >= kShadowGapBeg && a <= kShadowGapEnd;
82+
}
83+
84+
} // namespace __asan
85+
86+
#endif // ASAN_MAPPING_MYRIAD_H

‎compiler-rt/lib/asan/asan_poisoning.cc

+9-3
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,15 @@ int __asan_address_is_poisoned(void const volatile *addr) {
182182
uptr __asan_region_is_poisoned(uptr beg, uptr size) {
183183
if (!size) return 0;
184184
uptr end = beg + size;
185-
if (!AddrIsInMem(beg)) return beg;
186-
if (!AddrIsInMem(end)) return end;
185+
if (SANITIZER_MYRIAD2) {
186+
// On Myriad, address not in DRAM range need to be treated as
187+
// unpoisoned.
188+
if (!AddrIsInMem(beg) && !AddrIsInShadow(beg)) return 0;
189+
if (!AddrIsInMem(end) && !AddrIsInShadow(end)) return 0;
190+
} else {
191+
if (!AddrIsInMem(beg)) return beg;
192+
if (!AddrIsInMem(end)) return end;
193+
}
187194
CHECK_LT(beg, end);
188195
uptr aligned_b = RoundUpTo(beg, SHADOW_GRANULARITY);
189196
uptr aligned_e = RoundDownTo(end, SHADOW_GRANULARITY);
@@ -452,4 +459,3 @@ bool WordIsPoisoned(uptr addr) {
452459
return (__asan_region_is_poisoned(addr, sizeof(uptr)) != 0);
453460
}
454461
}
455-

‎compiler-rt/lib/asan/asan_rtl.cc

+19-9
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ static void AsanDie() {
5656
UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg);
5757
UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd);
5858
} else {
59-
UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
59+
if (kHighShadowEnd)
60+
UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
6061
}
6162
}
6263
}
@@ -140,6 +141,8 @@ ASAN_REPORT_ERROR_N(load, false)
140141
ASAN_REPORT_ERROR_N(store, true)
141142

142143
#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg, fatal) \
144+
if (SANITIZER_MYRIAD2 && !AddrIsInMem(addr) && !AddrIsInShadow(addr)) \
145+
return; \
143146
uptr sp = MEM_TO_SHADOW(addr); \
144147
uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \
145148
: *reinterpret_cast<u16 *>(sp); \
@@ -306,20 +309,24 @@ static void asan_atexit() {
306309
}
307310

308311
static void InitializeHighMemEnd() {
312+
#if !SANITIZER_MYRIAD2
309313
#if !ASAN_FIXED_MAPPING
310314
kHighMemEnd = GetMaxUserVirtualAddress();
311315
// Increase kHighMemEnd to make sure it's properly
312316
// aligned together with kHighMemBeg:
313317
kHighMemEnd |= SHADOW_GRANULARITY * GetMmapGranularity() - 1;
314318
#endif // !ASAN_FIXED_MAPPING
315319
CHECK_EQ((kHighMemBeg % GetMmapGranularity()), 0);
320+
#endif // !SANITIZER_MYRIAD2
316321
}
317322

318323
void PrintAddressSpaceLayout() {
319-
Printf("|| `[%p, %p]` || HighMem ||\n",
320-
(void*)kHighMemBeg, (void*)kHighMemEnd);
321-
Printf("|| `[%p, %p]` || HighShadow ||\n",
322-
(void*)kHighShadowBeg, (void*)kHighShadowEnd);
324+
if (kHighMemBeg) {
325+
Printf("|| `[%p, %p]` || HighMem ||\n",
326+
(void*)kHighMemBeg, (void*)kHighMemEnd);
327+
Printf("|| `[%p, %p]` || HighShadow ||\n",
328+
(void*)kHighShadowBeg, (void*)kHighShadowEnd);
329+
}
323330
if (kMidMemBeg) {
324331
Printf("|| `[%p, %p]` || ShadowGap3 ||\n",
325332
(void*)kShadowGap3Beg, (void*)kShadowGap3End);
@@ -338,11 +345,14 @@ void PrintAddressSpaceLayout() {
338345
Printf("|| `[%p, %p]` || LowMem ||\n",
339346
(void*)kLowMemBeg, (void*)kLowMemEnd);
340347
}
341-
Printf("MemToShadow(shadow): %p %p %p %p",
348+
Printf("MemToShadow(shadow): %p %p",
342349
(void*)MEM_TO_SHADOW(kLowShadowBeg),
343-
(void*)MEM_TO_SHADOW(kLowShadowEnd),
344-
(void*)MEM_TO_SHADOW(kHighShadowBeg),
345-
(void*)MEM_TO_SHADOW(kHighShadowEnd));
350+
(void*)MEM_TO_SHADOW(kLowShadowEnd));
351+
if (kHighMemBeg) {
352+
Printf(" %p %p",
353+
(void*)MEM_TO_SHADOW(kHighShadowBeg),
354+
(void*)MEM_TO_SHADOW(kHighShadowEnd));
355+
}
346356
if (kMidMemBeg) {
347357
Printf(" %p %p",
348358
(void*)MEM_TO_SHADOW(kMidShadowBeg),

0 commit comments

Comments
 (0)
Please sign in to comment.