Index: lib/dfsan/dfsan.h =================================================================== --- lib/dfsan/dfsan.h +++ lib/dfsan/dfsan.h @@ -16,6 +16,7 @@ #define DFSAN_H #include "sanitizer_common/sanitizer_internal_defs.h" +#include "dfsan_platform.h" // Copy declarations from public sanitizer/dfsan_interface.h header here. typedef u16 dfsan_label; @@ -44,17 +45,7 @@ void InitializeInterceptors(); inline dfsan_label *shadow_for(void *ptr) { -#if defined(__x86_64__) - return (dfsan_label *) ((((uptr) ptr) & ~0x700000000000) << 1); -#elif defined(__mips64) - return (dfsan_label *) ((((uptr) ptr) & ~0xF000000000) << 1); -#elif defined(__aarch64__) -# if SANITIZER_AARCH64_VMA == 39 - return (dfsan_label *) ((((uptr) ptr) & ~0x7800000000) << 1); -# elif SANITIZER_AARCH64_VMA == 42 - return (dfsan_label *) ((((uptr) ptr) & ~0x3c000000000) << 1); -# endif -#endif + return (dfsan_label *) ((((uptr) ptr) & ShadowMask()) << 1); } inline const dfsan_label *shadow_for(const void *ptr) { Index: lib/dfsan/dfsan.cc =================================================================== --- lib/dfsan/dfsan.cc +++ lib/dfsan/dfsan.cc @@ -42,6 +42,8 @@ SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL dfsan_label __dfsan_retval_tls; SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL dfsan_label __dfsan_arg_tls[64]; +SANITIZER_INTERFACE_ATTRIBUTE uptr __dfsan_shadow_ptr_mask; + // On Linux/x86_64, memory is laid out as follows: // // +--------------------+ 0x800000000000 (top of memory) @@ -114,35 +116,18 @@ typedef atomic_dfsan_label dfsan_union_table_t[kNumLabels][kNumLabels]; -#if defined(__x86_64__) -static const uptr kShadowAddr = 0x10000; -static const uptr kUnionTableAddr = 0x200000000000; -static const uptr kUnusedAddr = kUnionTableAddr + sizeof(dfsan_union_table_t); -static const uptr kAppAddr = 0x700000008000; -#elif defined(__mips64) -static const uptr kShadowAddr = 0x10000; -static const uptr kUnionTableAddr = 0x2000000000; -static const uptr kUnusedAddr = kUnionTableAddr + sizeof(dfsan_union_table_t); -static const uptr kAppAddr = 0xF000008000; -#elif defined(__aarch64__) -static const uptr kShadowAddr = 0x10000; -# if SANITIZER_AARCH64_VMA == 39 -static const uptr kUnionTableAddr = 0x1000000000; -# elif SANITIZER_AARCH64_VMA == 42 -static const uptr kUnionTableAddr = 0x8000000000; -# endif -static const uptr kUnusedAddr = kUnionTableAddr + sizeof(dfsan_union_table_t); -# if SANITIZER_AARCH64_VMA == 39 -static const uptr kAppAddr = 0x7000008000; -# elif SANITIZER_AARCH64_VMA == 42 -static const uptr kAppAddr = 0x3ff00008000; -# endif -#else -# error "DFSan not supported for this platform!" +#ifdef DFSAN_RUNTIME_VMA +// Runtime detected VMA size. +int __dfsan::vmaSize; #endif +static uptr UnusedAddr() { + return MappingArchImpl() + + sizeof(dfsan_union_table_t); +} + static atomic_dfsan_label *union_table(dfsan_label l1, dfsan_label l2) { - return &(*(dfsan_union_table_t *) kUnionTableAddr)[l1][l2]; + return &(*(dfsan_union_table_t *) UnionTableAddr())[l1][l2]; } // Checks we do not run out of labels. @@ -382,6 +367,22 @@ if (common_flags()->help) parser.PrintFlagDescriptions(); } +static void InitializePlatformEarly() { +#ifdef DFSAN_RUNTIME_VMA +# ifdef __aarch64__ + __dfsan::vmaSize = + (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); + if (__dfsan::vmaSize == 39 || __dfsan::vmaSize == 42) { + __dfsan_shadow_ptr_mask = ShadowMask(); + } else { + Printf("FATAL: ThreadSanitizer: unsupported VMA range\n"); + Printf("FATAL: Found %d - Supported 39 and 42\n", __dfsan::vmaSize); + Die(); + } +# endif +#endif +} + static void dfsan_fini() { if (internal_strcmp(flags().dump_labels_at_exit, "") != 0) { fd_t fd = OpenFile(flags().dump_labels_at_exit, WrOnly); @@ -401,9 +402,9 @@ static void dfsan_init(int argc, char **argv, char **envp) { InitializeFlags(); - CheckVMASize(); + InitializePlatformEarly(); - MmapFixedNoReserve(kShadowAddr, kUnusedAddr - kShadowAddr); + MmapFixedNoReserve(ShadowAddr(), UnusedAddr() - ShadowAddr()); // Protect the region of memory we don't use, to preserve the one-to-one // mapping from application to shadow memory. But if ASLR is disabled, Linux @@ -411,8 +412,8 @@ // works so long as the program doesn't use too much memory. We support this // case by disabling memory protection when ASLR is disabled. uptr init_addr = (uptr)&dfsan_init; - if (!(init_addr >= kUnusedAddr && init_addr < kAppAddr)) - MmapNoAccess(kUnusedAddr, kAppAddr - kUnusedAddr); + if (!(init_addr >= UnusedAddr() && init_addr < AppAddr())) + MmapNoAccess(UnusedAddr(), AppAddr() - UnusedAddr()); InitializeInterceptors(); Index: lib/dfsan/dfsan_platform.h =================================================================== --- /dev/null +++ lib/dfsan/dfsan_platform.h @@ -0,0 +1,107 @@ +//===-- dfsan_platform.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of DataFlowSanitizer. +// +// Platform specific information for DFSan. +//===----------------------------------------------------------------------===// + +#ifndef DFSAN_PLATFORM_H +#define DFSAN_PLATFORM_H + +namespace __dfsan { + +#if defined(__x86_64__) +struct Mapping { + static const uptr kShadowAddr = 0x10000; + static const uptr kUnionTableAddr = 0x200000000000; + static const uptr kAppAddr = 0x700000008000; + static const uptr kShadowMask = ~0x700000000000; +}; +#elif defined(__mips64) +struct Mapping { + static const uptr kShadowAddr = 0x10000; + static const uptr kUnionTableAddr = 0x2000000000; + static const uptr kAppAddr = 0xF000008000; + static const uptr kShadowMask = ~0xF000000000; +}; +#elif defined(__aarch64__) +struct Mapping39 { + static const uptr kShadowAddr = 0x10000; + static const uptr kUnionTableAddr = 0x1000000000; + static const uptr kAppAddr = 0x7000008000; + static const uptr kShadowMask = ~0x7800000000; +}; + +struct Mapping42 { + static const uptr kShadowAddr = 0x10000; + static const uptr kUnionTableAddr = 0x8000000000; + static const uptr kAppAddr = 0x3ff00008000; + static const uptr kShadowMask = ~0x3c000000000; +}; + +extern int vmaSize; +# define DFSAN_RUNTIME_VMA 1 +#else +# error "DFSan not supported for this platform!" +#endif + +enum MappingType { + MAPPING_SHADOW_ADDR, + MAPPING_UNION_TABLE_ADDR, + MAPPING_APP_ADDR, + MAPPING_SHADOW_MASK +}; + +template +uptr MappingImpl(void) { + switch (Type) { + case MAPPING_SHADOW_ADDR: return Mapping::kShadowAddr; + case MAPPING_UNION_TABLE_ADDR: return Mapping::kUnionTableAddr; + case MAPPING_APP_ADDR: return Mapping::kAppAddr; + case MAPPING_SHADOW_MASK: return Mapping::kShadowMask; + } +} + +template +uptr MappingArchImpl(void) { +#ifdef __aarch64__ + if (vmaSize == 39) + return MappingImpl(); + else + return MappingImpl(); + DCHECK(0); +#else + return MappingImpl(); +#endif +} + +ALWAYS_INLINE +uptr ShadowAddr() { + return MappingArchImpl(); +} + +ALWAYS_INLINE +uptr UnionTableAddr() { + return MappingArchImpl(); +} + +ALWAYS_INLINE +uptr AppAddr() { + return MappingArchImpl(); +} + +ALWAYS_INLINE +uptr ShadowMask() { + return MappingArchImpl(); +} + +} // namespace __dfsan + +#endif