[compiler-rt] [dfsan] Unify aarch64 mapping

This patch reorganize the platform specific mapping information to
export the application mask on a external variable. This exported
variable will be used by intrumentation phase to create code to be
used on architecture with multiple VMA range.
    
The patch creates a new header, dfsan_platform.h, and move all the
mapping information and also create function accessors to the
mapping value.

Also for aarch64 it initialize application exported mask to the 
value based on runtime VMA detection.

llvm-svn: 254197
This commit is contained in:
Adhemerval Zanella 2015-11-27 12:43:33 +00:00
parent d93c0c4dc4
commit f2d3dbfaca
3 changed files with 138 additions and 41 deletions

View File

@ -42,6 +42,8 @@ Flags __dfsan::flags_data;
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 @@ SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL dfsan_label __dfsan_arg_tls[64];
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<MAPPING_UNION_TABLE_ADDR>()
+ 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,20 @@ static void InitializeFlags() {
if (common_flags()->help) parser.PrintFlagDescriptions();
}
static void InitializePlatformEarly() {
#ifdef DFSAN_RUNTIME_VMA
__dfsan::vmaSize =
(MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);
if (__dfsan::vmaSize == 39 || __dfsan::vmaSize == 42) {
__dfsan_shadow_ptr_mask = ShadowMask();
} else {
Printf("FATAL: DataFlowSanitizer: unsupported VMA range\n");
Printf("FATAL: Found %d - Supported 39 and 42\n", __dfsan::vmaSize);
Die();
}
#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 +400,9 @@ static void dfsan_fini() {
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 +410,8 @@ static void dfsan_init(int argc, char **argv, char **envp) {
// 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();

View File

@ -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 @@ namespace __dfsan {
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) {

View File

@ -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<typename Mapping, int Type>
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<int Type>
uptr MappingArchImpl(void) {
#ifdef __aarch64__
if (vmaSize == 39)
return MappingImpl<Mapping39, Type>();
else
return MappingImpl<Mapping42, Type>();
DCHECK(0);
#else
return MappingImpl<Mapping, Type>();
#endif
}
ALWAYS_INLINE
uptr ShadowAddr() {
return MappingArchImpl<MAPPING_SHADOW_ADDR>();
}
ALWAYS_INLINE
uptr UnionTableAddr() {
return MappingArchImpl<MAPPING_UNION_TABLE_ADDR>();
}
ALWAYS_INLINE
uptr AppAddr() {
return MappingArchImpl<MAPPING_APP_ADDR>();
}
ALWAYS_INLINE
uptr ShadowMask() {
return MappingArchImpl<MAPPING_SHADOW_MASK>();
}
} // namespace __dfsan
#endif