forked from OSchip/llvm-project
[asan] make asan work with 7fff8000 offset and prelink
When prelink is installed in the system, prelink-ed libraries map between 0x003000000000 and 0x004000000000 thus occupying the shadow Gap, so we need so split the address space even further, like this: || [0x10007fff8000, 0x7fffffffffff] || HighMem || || [0x02008fff7000, 0x10007fff7fff] || HighShadow || || [0x004000000000, 0x02008fff6fff] || ShadowGap3 || || [0x003000000000, 0x003fffffffff] || MidMem || || [0x00087fff8000, 0x002fffffffff] || ShadowGap2 || || [0x00067fff8000, 0x00087fff7fff] || MidShadow || || [0x00008fff7000, 0x00067fff7fff] || ShadowGap || || [0x00007fff8000, 0x00008fff6fff] || LowShadow || || [0x000000000000, 0x00007fff7fff] || LowMem || Do it only if necessary. Also added a bit of profiling code to make sure that the mapping code is efficient. Added a lit test to simulate prelink-ed libraries. Unfortunately, this test does not work with binutils-gold linker. If gold is the default linker the test silently passes. Also replaced __has_feature(address_sanitizer) with __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) in two places. Patch partially by Jakub Jelinek. llvm-svn: 175263
This commit is contained in:
parent
54a8602aef
commit
fd61b6f0c8
|
|
@ -37,8 +37,8 @@ extern "C" {
|
|||
// (un)poison memory in the same memory region simultaneously.
|
||||
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
|
||||
|
||||
// User code should use macro instead of functions.
|
||||
#if __has_feature(address_sanitizer)
|
||||
// User code should use macros instead of functions.
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
#define ASAN_POISON_MEMORY_REGION(addr, size) \
|
||||
__asan_poison_memory_region((addr), (size))
|
||||
#define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
|
||||
|
|
|
|||
|
|
@ -16,6 +16,11 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// GCC does not understand __has_feature.
|
||||
#if !defined(__has_feature)
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
|
||||
#define ASAN_POSIX (ASAN_LINUX || ASAN_MAC)
|
||||
|
||||
#if __has_feature(address_sanitizer)
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
# error "The AddressSanitizer run-time should not be"
|
||||
" instrumented by AddressSanitizer"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -18,6 +18,37 @@
|
|||
|
||||
// The full explanation of the memory mapping could be found here:
|
||||
// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm
|
||||
//
|
||||
// Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000:
|
||||
// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem ||
|
||||
// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow ||
|
||||
// || `[0x00008fff7000, 0x02008fff6fff]` || ShadowGap ||
|
||||
// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow ||
|
||||
// || `[0x000000000000, 0x00007fff7fff]` || LowMem ||
|
||||
//
|
||||
// When SHADOW_OFFSET is zero (-pie):
|
||||
// || `[0x100000000000, 0x7fffffffffff]` || HighMem ||
|
||||
// || `[0x020000000000, 0x0fffffffffff]` || HighShadow ||
|
||||
// || `[0x000000040000, 0x01ffffffffff]` || ShadowGap ||
|
||||
//
|
||||
// Special case when something is already mapped between
|
||||
// 0x003000000000 and 0x004000000000 (e.g. when prelink is installed):
|
||||
// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem ||
|
||||
// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow ||
|
||||
// || `[0x004000000000, 0x02008fff6fff]` || ShadowGap3 ||
|
||||
// || `[0x003000000000, 0x003fffffffff]` || MidMem ||
|
||||
// || `[0x00087fff8000, 0x002fffffffff]` || ShadowGap2 ||
|
||||
// || `[0x00067fff8000, 0x00087fff7fff]` || MidShadow ||
|
||||
// || `[0x00008fff7000, 0x00067fff7fff]` || ShadowGap ||
|
||||
// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow ||
|
||||
// || `[0x000000000000, 0x00007fff7fff]` || LowMem ||
|
||||
//
|
||||
// Default Linux/i386 mapping:
|
||||
// || `[0x40000000, 0xffffffff]` || HighMem ||
|
||||
// || `[0x28000000, 0x3fffffff]` || HighShadow ||
|
||||
// || `[0x24000000, 0x27ffffff]` || ShadowGap ||
|
||||
// || `[0x20000000, 0x23ffffff]` || LowShadow ||
|
||||
// || `[0x00000000, 0x1fffffff]` || LowMem ||
|
||||
|
||||
#if ASAN_FLEXIBLE_MAPPING_AND_OFFSET == 1
|
||||
extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_scale;
|
||||
|
|
@ -61,49 +92,105 @@ extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset;
|
|||
#define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg)
|
||||
#define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd)
|
||||
|
||||
# define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg)
|
||||
# define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd)
|
||||
|
||||
// With the zero shadow base we can not actually map pages starting from 0.
|
||||
// This constant is somewhat arbitrary.
|
||||
#define kZeroBaseShadowStart (1 << 18)
|
||||
|
||||
#define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \
|
||||
: kZeroBaseShadowStart)
|
||||
#define kShadowGapEnd (kHighShadowBeg - 1)
|
||||
#define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1)
|
||||
|
||||
#define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0)
|
||||
#define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0)
|
||||
|
||||
#define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0)
|
||||
#define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0)
|
||||
|
||||
#define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below.
|
||||
|
||||
#if DO_ASAN_MAPPING_PROFILE
|
||||
# define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++;
|
||||
#else
|
||||
# define PROFILE_ASAN_MAPPING()
|
||||
#endif
|
||||
|
||||
// If 1, all shadow boundaries are constants.
|
||||
// Don't set to 1 other than for testing.
|
||||
#define ASAN_FIXED_MAPPING 0
|
||||
|
||||
namespace __asan {
|
||||
|
||||
extern uptr AsanMappingProfile[];
|
||||
|
||||
#if ASAN_FIXED_MAPPING
|
||||
// Fixed mapping for 64-bit Linux. Mostly used for performance comparison
|
||||
// with non-fixed mapping. As of r175253 (Feb 2013) the performance
|
||||
// difference between fixed and non-fixed mapping is below the noise level.
|
||||
static uptr kHighMemEnd = 0x7fffffffffffULL;
|
||||
static uptr kMidMemBeg = 0x3000000000ULL;
|
||||
static uptr kMidMemEnd = 0x3fffffffffULL;
|
||||
#else
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
extern uptr kHighMemEnd; // Initialized in __asan_init.
|
||||
extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init.
|
||||
#endif
|
||||
|
||||
static inline bool AddrIsInLowMem(uptr a) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
return a < kLowMemEnd;
|
||||
}
|
||||
|
||||
static inline bool AddrIsInLowShadow(uptr a) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
return a >= kLowShadowBeg && a <= kLowShadowEnd;
|
||||
}
|
||||
|
||||
static inline bool AddrIsInHighMem(uptr a) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
return a >= kHighMemBeg && a <= kHighMemEnd;
|
||||
}
|
||||
|
||||
static inline bool AddrIsInMidMem(uptr a) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd;
|
||||
}
|
||||
|
||||
static inline bool AddrIsInMem(uptr a) {
|
||||
return AddrIsInLowMem(a) || AddrIsInHighMem(a);
|
||||
PROFILE_ASAN_MAPPING();
|
||||
return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a);
|
||||
}
|
||||
|
||||
static inline uptr MemToShadow(uptr p) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
CHECK(AddrIsInMem(p));
|
||||
return MEM_TO_SHADOW(p);
|
||||
}
|
||||
|
||||
static inline bool AddrIsInHighShadow(uptr a) {
|
||||
return a >= kHighShadowBeg && a <= kHighMemEnd;
|
||||
PROFILE_ASAN_MAPPING();
|
||||
return a >= kHighShadowBeg && a <= kHighMemEnd;
|
||||
}
|
||||
|
||||
static inline bool AddrIsInMidShadow(uptr a) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
return kMidMemBeg && a >= kMidShadowBeg && a <= kMidMemEnd;
|
||||
}
|
||||
|
||||
static inline bool AddrIsInShadow(uptr a) {
|
||||
return AddrIsInLowShadow(a) || AddrIsInHighShadow(a);
|
||||
PROFILE_ASAN_MAPPING();
|
||||
return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a);
|
||||
}
|
||||
|
||||
static inline bool AddrIsInShadowGap(uptr a) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
if (kMidMemBeg) {
|
||||
if (a <= kShadowGapEnd)
|
||||
return SHADOW_OFFSET == 0 || a >= kShadowGapBeg;
|
||||
return (a >= kShadowGap2Beg && a <= kShadowGap2End) ||
|
||||
(a >= kShadowGap3Beg && a <= kShadowGap3End);
|
||||
}
|
||||
// In zero-based shadow mode we treat addresses near zero as addresses
|
||||
// in shadow gap as well.
|
||||
if (SHADOW_OFFSET == 0)
|
||||
|
|
@ -112,10 +199,12 @@ static inline bool AddrIsInShadowGap(uptr a) {
|
|||
}
|
||||
|
||||
static inline bool AddrIsAlignedByGranularity(uptr a) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
return (a & (SHADOW_GRANULARITY - 1)) == 0;
|
||||
}
|
||||
|
||||
static inline bool AddressIsPoisoned(uptr a) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
const uptr kAccessSize = 1;
|
||||
u8 *shadow_address = (u8*)MemToShadow(a);
|
||||
s8 shadow_value = *shadow_address;
|
||||
|
|
@ -127,6 +216,9 @@ static inline bool AddressIsPoisoned(uptr a) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Must be after all calls to PROFILE_ASAN_MAPPING().
|
||||
static const uptr kAsanMappingProfileSize = __LINE__;
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
#endif // ASAN_MAPPING_H
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
namespace __asan {
|
||||
|
||||
uptr AsanMappingProfile[kAsanMappingProfileSize];
|
||||
|
||||
static void AsanDie() {
|
||||
static atomic_uint32_t num_calls;
|
||||
if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
|
||||
|
|
@ -37,8 +39,14 @@ static void AsanDie() {
|
|||
Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying);
|
||||
SleepForSeconds(flags()->sleep_before_dying);
|
||||
}
|
||||
if (flags()->unmap_shadow_on_exit)
|
||||
UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
|
||||
if (flags()->unmap_shadow_on_exit) {
|
||||
if (kMidMemBeg) {
|
||||
UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg);
|
||||
UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd);
|
||||
} else {
|
||||
UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
|
||||
}
|
||||
}
|
||||
if (death_callback)
|
||||
death_callback();
|
||||
if (flags()->abort_on_error)
|
||||
|
|
@ -163,7 +171,10 @@ void InitializeFlags(Flags *f, const char *env) {
|
|||
int asan_inited;
|
||||
bool asan_init_is_running;
|
||||
void (*death_callback)(void);
|
||||
uptr kHighMemEnd;
|
||||
|
||||
#if !ASAN_FIXED_MAPPING
|
||||
uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;
|
||||
#endif
|
||||
|
||||
// -------------------------- Misc ---------------- {{{1
|
||||
void ShowStatsAndAbort() {
|
||||
|
|
@ -261,9 +272,15 @@ static NOINLINE void force_interface_symbols() {
|
|||
static void asan_atexit() {
|
||||
Printf("AddressSanitizer exit stats:\n");
|
||||
__asan_print_accumulated_stats();
|
||||
// Print AsanMappingProfile.
|
||||
for (uptr i = 0; i < kAsanMappingProfileSize; i++) {
|
||||
if (AsanMappingProfile[i] == 0) continue;
|
||||
Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void InitializeHighMemEnd() {
|
||||
#if !ASAN_FIXED_MAPPING
|
||||
#if SANITIZER_WORDSIZE == 64
|
||||
# if defined(__powerpc64__)
|
||||
// FIXME:
|
||||
|
|
@ -279,6 +296,58 @@ static void InitializeHighMemEnd() {
|
|||
#else // SANITIZER_WORDSIZE == 32
|
||||
kHighMemEnd = (1ULL << 32) - 1; // 0xffffffff;
|
||||
#endif // SANITIZER_WORDSIZE
|
||||
#endif // !ASAN_FIXED_MAPPING
|
||||
}
|
||||
|
||||
static void ProtectGap(uptr a, uptr size) {
|
||||
CHECK_EQ(a, (uptr)Mprotect(a, size));
|
||||
}
|
||||
|
||||
static void PrintAddressSpaceLayout() {
|
||||
Printf("|| `[%p, %p]` || HighMem ||\n",
|
||||
(void*)kHighMemBeg, (void*)kHighMemEnd);
|
||||
Printf("|| `[%p, %p]` || HighShadow ||\n",
|
||||
(void*)kHighShadowBeg, (void*)kHighShadowEnd);
|
||||
if (kMidMemBeg) {
|
||||
Printf("|| `[%p, %p]` || ShadowGap3 ||\n",
|
||||
(void*)kShadowGap3Beg, (void*)kShadowGap3End);
|
||||
Printf("|| `[%p, %p]` || MidMem ||\n",
|
||||
(void*)kMidMemBeg, (void*)kMidMemEnd);
|
||||
Printf("|| `[%p, %p]` || ShadowGap2 ||\n",
|
||||
(void*)kShadowGap2Beg, (void*)kShadowGap2End);
|
||||
Printf("|| `[%p, %p]` || MidShadow ||\n",
|
||||
(void*)kMidShadowBeg, (void*)kMidShadowEnd);
|
||||
}
|
||||
Printf("|| `[%p, %p]` || ShadowGap ||\n",
|
||||
(void*)kShadowGapBeg, (void*)kShadowGapEnd);
|
||||
if (kLowShadowBeg) {
|
||||
Printf("|| `[%p, %p]` || LowShadow ||\n",
|
||||
(void*)kLowShadowBeg, (void*)kLowShadowEnd);
|
||||
Printf("|| `[%p, %p]` || LowMem ||\n",
|
||||
(void*)kLowMemBeg, (void*)kLowMemEnd);
|
||||
}
|
||||
Printf("MemToShadow(shadow): %p %p %p %p",
|
||||
(void*)MEM_TO_SHADOW(kLowShadowBeg),
|
||||
(void*)MEM_TO_SHADOW(kLowShadowEnd),
|
||||
(void*)MEM_TO_SHADOW(kHighShadowBeg),
|
||||
(void*)MEM_TO_SHADOW(kHighShadowEnd));
|
||||
if (kMidMemBeg) {
|
||||
Printf(" %p %p",
|
||||
(void*)MEM_TO_SHADOW(kMidShadowBeg),
|
||||
(void*)MEM_TO_SHADOW(kMidShadowEnd));
|
||||
}
|
||||
Printf("\n");
|
||||
Printf("red_zone=%zu\n", (uptr)flags()->redzone);
|
||||
Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size);
|
||||
|
||||
Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE);
|
||||
Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY);
|
||||
Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET);
|
||||
CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
|
||||
if (kMidMemBeg)
|
||||
CHECK(kMidShadowBeg > kLowShadowEnd &&
|
||||
kMidMemBeg > kMidShadowEnd &&
|
||||
kHighShadowBeg > kMidMemEnd);
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
|
|
@ -354,49 +423,48 @@ void __asan_init() {
|
|||
ReplaceSystemMalloc();
|
||||
ReplaceOperatorsNewAndDelete();
|
||||
|
||||
if (flags()->verbosity) {
|
||||
Printf("|| `[%p, %p]` || HighMem ||\n",
|
||||
(void*)kHighMemBeg, (void*)kHighMemEnd);
|
||||
Printf("|| `[%p, %p]` || HighShadow ||\n",
|
||||
(void*)kHighShadowBeg, (void*)kHighShadowEnd);
|
||||
Printf("|| `[%p, %p]` || ShadowGap ||\n",
|
||||
(void*)kShadowGapBeg, (void*)kShadowGapEnd);
|
||||
Printf("|| `[%p, %p]` || LowShadow ||\n",
|
||||
(void*)kLowShadowBeg, (void*)kLowShadowEnd);
|
||||
Printf("|| `[%p, %p]` || LowMem ||\n",
|
||||
(void*)kLowMemBeg, (void*)kLowMemEnd);
|
||||
Printf("MemToShadow(shadow): %p %p %p %p\n",
|
||||
(void*)MEM_TO_SHADOW(kLowShadowBeg),
|
||||
(void*)MEM_TO_SHADOW(kLowShadowEnd),
|
||||
(void*)MEM_TO_SHADOW(kHighShadowBeg),
|
||||
(void*)MEM_TO_SHADOW(kHighShadowEnd));
|
||||
Printf("red_zone=%zu\n", (uptr)flags()->redzone);
|
||||
Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size);
|
||||
uptr shadow_start = kLowShadowBeg;
|
||||
if (kLowShadowBeg) shadow_start -= GetMmapGranularity();
|
||||
uptr shadow_end = kHighShadowEnd;
|
||||
bool full_shadow_is_available =
|
||||
MemoryRangeIsAvailable(shadow_start, shadow_end);
|
||||
|
||||
Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE);
|
||||
Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY);
|
||||
Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET);
|
||||
CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
|
||||
#if ASAN_LINUX && defined(__x86_64__) && !ASAN_FIXED_MAPPING
|
||||
if (!full_shadow_is_available) {
|
||||
kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
|
||||
kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x3fffffffffULL : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (flags()->verbosity)
|
||||
PrintAddressSpaceLayout();
|
||||
|
||||
if (flags()->disable_core) {
|
||||
DisableCoreDumper();
|
||||
}
|
||||
|
||||
uptr shadow_start = kLowShadowBeg;
|
||||
if (kLowShadowBeg > 0) shadow_start -= GetMmapGranularity();
|
||||
uptr shadow_end = kHighShadowEnd;
|
||||
if (MemoryRangeIsAvailable(shadow_start, shadow_end)) {
|
||||
if (kLowShadowBeg != kLowShadowEnd) {
|
||||
// mmap the low shadow plus at least one page.
|
||||
ReserveShadowMemoryRange(kLowShadowBeg - GetMmapGranularity(),
|
||||
kLowShadowEnd);
|
||||
}
|
||||
if (full_shadow_is_available) {
|
||||
// mmap the low shadow plus at least one page at the left.
|
||||
if (kLowShadowBeg)
|
||||
ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
|
||||
// mmap the high shadow.
|
||||
ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
|
||||
// protect the gap
|
||||
void *prot = Mprotect(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
|
||||
CHECK(prot == (void*)kShadowGapBeg);
|
||||
// protect the gap.
|
||||
ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
|
||||
} else if (kMidMemBeg &&
|
||||
MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
|
||||
MemoryRangeIsAvailable(kMidMemEnd + 1, shadow_end)) {
|
||||
CHECK(kLowShadowBeg != kLowShadowEnd);
|
||||
// mmap the low shadow plus at least one page at the left.
|
||||
ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
|
||||
// mmap the mid shadow.
|
||||
ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd);
|
||||
// mmap the high shadow.
|
||||
ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
|
||||
// protect the gaps.
|
||||
ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
|
||||
ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
|
||||
ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);
|
||||
} else {
|
||||
Report("Shadow memory range interleaves with an existing memory mapping. "
|
||||
"ASan cannot proceed correctly. ABORTING.\n");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
// Test if asan works with prelink.
|
||||
// It does not actually use prelink, but relies on ld's flag -Ttext-segment.
|
||||
// This flag is not present in GNU gold, so if the link command line fails
|
||||
// we just exit 0.
|
||||
//
|
||||
// RUN: %clangxx_asan -m64 -c %s -o %t.o
|
||||
// RUN: %clangxx_asan -m64 -DBUILD_SO=1 -fPIC -shared %s -o %t.so -Wl,-Ttext-segment=0x3600000000 || exit 0
|
||||
// RUN: %clangxx_asan -m64 %t.o %t.so -Wl,-R. -o %t
|
||||
// RUN: ASAN_OPTIONS=verbosity=1 %t 2>&1 | FileCheck %s
|
||||
#if BUILD_SO
|
||||
int G;
|
||||
int *getG() {
|
||||
return &G;
|
||||
}
|
||||
#else
|
||||
#include <stdio.h>
|
||||
extern int *getG();
|
||||
int main(int argc, char **argv) {
|
||||
long p = (long)getG();
|
||||
printf("SO mapped at %lx\n", p & ~0xffffffffUL);
|
||||
*getG() = 0;
|
||||
}
|
||||
#endif
|
||||
// CHECK: 0x003000000000, 0x003fffffffff{{.*}} MidMem
|
||||
// CHECK: SO mapped at 3600000000
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
# define SANITIZER_SUPPORTS_WEAK_HOOKS 0
|
||||
#endif
|
||||
|
||||
// __has_feature
|
||||
// GCC does not understand __has_feature
|
||||
#if !defined(__has_feature)
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue