summaryrefslogtreecommitdiff
path: root/libsanitizer/asan/asan_mapping.h
blob: 85d1129dea8d1cc7843fa85c2c53eca6618166d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//===-- asan_mapping.h ------------------------------------------*- C++ -*-===//
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// Defines ASan memory mapping.
//===----------------------------------------------------------------------===//
#ifndef ASAN_MAPPING_H
#define ASAN_MAPPING_H

#include "asan_internal.h"

// The full explanation of the memory mapping could be found here:
// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm

#if ASAN_FLEXIBLE_MAPPING_AND_OFFSET == 1
extern __attribute__((visibility("default"))) uptr __asan_mapping_scale;
extern __attribute__((visibility("default"))) uptr __asan_mapping_offset;
# define SHADOW_SCALE (__asan_mapping_scale)
# define SHADOW_OFFSET (__asan_mapping_offset)
#else
# if ASAN_ANDROID
#  define SHADOW_SCALE (3)
#  define SHADOW_OFFSET (0)
# else
#  define SHADOW_SCALE (3)
#  if SANITIZER_WORDSIZE == 32
#   define SHADOW_OFFSET (1 << 29)
#  else
#   if defined(__powerpc64__)
#    define SHADOW_OFFSET (1ULL << 41)
#   else
#    define SHADOW_OFFSET (1ULL << 44)
#   endif
#  endif
# endif
#endif  // ASAN_FLEXIBLE_MAPPING_AND_OFFSET

#define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE)
#define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) | (SHADOW_OFFSET))
#define SHADOW_TO_MEM(shadow) (((shadow) - SHADOW_OFFSET) << SHADOW_SCALE)

#if SANITIZER_WORDSIZE == 64
# if defined(__powerpc64__)
  static const uptr kHighMemEnd = 0x00000fffffffffffUL;
# else
  static const uptr kHighMemEnd = 0x00007fffffffffffUL;
# endif
#else  // SANITIZER_WORDSIZE == 32
  static const uptr kHighMemEnd = 0xffffffff;
#endif  // SANITIZER_WORDSIZE


#define kLowMemBeg      0
#define kLowMemEnd      (SHADOW_OFFSET ? SHADOW_OFFSET - 1 : 0)

#define kLowShadowBeg   SHADOW_OFFSET
#define kLowShadowEnd   MEM_TO_SHADOW(kLowMemEnd)

#define kHighMemBeg     (MEM_TO_SHADOW(kHighMemEnd) + 1)

#define kHighShadowBeg  MEM_TO_SHADOW(kHighMemBeg)
#define kHighShadowEnd  MEM_TO_SHADOW(kHighMemEnd)

// 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 kGlobalAndStackRedzone \
      (SHADOW_GRANULARITY < 32 ? 32 : SHADOW_GRANULARITY)

namespace __asan {

static inline bool AddrIsInLowMem(uptr a) {
  return a < kLowMemEnd;
}

static inline bool AddrIsInLowShadow(uptr a) {
  return a >= kLowShadowBeg && a <= kLowShadowEnd;
}

static inline bool AddrIsInHighMem(uptr a) {
  return a >= kHighMemBeg && a <= kHighMemEnd;
}

static inline bool AddrIsInMem(uptr a) {
  return AddrIsInLowMem(a) || AddrIsInHighMem(a);
}

static inline uptr MemToShadow(uptr p) {
  CHECK(AddrIsInMem(p));
  return MEM_TO_SHADOW(p);
}

static inline bool AddrIsInHighShadow(uptr a) {
  return a >= kHighShadowBeg && a <=  kHighMemEnd;
}

static inline bool AddrIsInShadow(uptr a) {
  return AddrIsInLowShadow(a) || AddrIsInHighShadow(a);
}

static inline bool AddrIsInShadowGap(uptr a) {
  return a >= kShadowGapBeg && a <= kShadowGapEnd;
}

static inline bool AddrIsAlignedByGranularity(uptr a) {
  return (a & (SHADOW_GRANULARITY - 1)) == 0;
}

static inline bool AddressIsPoisoned(uptr a) {
  const uptr kAccessSize = 1;
  u8 *shadow_address = (u8*)MemToShadow(a);
  s8 shadow_value = *shadow_address;
  if (shadow_value) {
    u8 last_accessed_byte = (a & (SHADOW_GRANULARITY - 1))
                                 + kAccessSize - 1;
    return (last_accessed_byte >= shadow_value);
  }
  return false;
}

}  // namespace __asan

#endif  // ASAN_MAPPING_H