1c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//===-- esan_shadow.h -------------------------------------------*- C++ -*-===//
2c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
3c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//                     The LLVM Compiler Infrastructure
4c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
5c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source
6c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// License. See LICENSE.TXT for details.
7c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
8c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//===----------------------------------------------------------------------===//
9c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
10c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// This file is a part of EfficiencySanitizer, a family of performance tuners.
11c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
12c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Shadow memory mappings for the esan run-time.
13c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//===----------------------------------------------------------------------===//
14c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
15c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#ifndef ESAN_SHADOW_H
16c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#define ESAN_SHADOW_H
17c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
18c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include <sanitizer_common/sanitizer_platform.h>
19c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
20c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if SANITIZER_WORDSIZE != 64
21c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#error Only 64-bit is supported
22c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
23c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
24c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarnamespace __esan {
25c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
26c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if SANITIZER_LINUX && defined(__x86_64__)
27c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Linux x86_64
28c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
29c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Application memory falls into these 5 regions (ignoring the corner case
30c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// of PIE with a non-zero PT_LOAD base):
31c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
32c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x00000000'00000000, 0x00000100'00000000) non-PIE + heap
33c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x00005500'00000000, 0x00005700'00000000) PIE
34c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x00007e00'00000000, 0x00007fff'ff600000) libraries + stack, part 1
35c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x00007fff'ff601000, 0x00008000'00000000) libraries + stack, part 2
36c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0xffffffff'ff600000, 0xffffffff'ff601000) vsyscall
37c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
38c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Although we can ignore the vsyscall for the most part as there are few data
39c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// references there (other sanitizers ignore it), we enforce a gap inside the
40c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// library region to distinguish the vsyscall's shadow, considering this gap to
41c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// be an invalid app region.
42c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// We disallow application memory outside of those 5 regions.
43c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Our regions assume that the stack rlimit is less than a terabyte (otherwise
44c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// the Linux kernel's default mmap region drops below 0x7e00'), which we enforce
45c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// at init time (we can support larger and unlimited sizes for shadow
46c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// scaledowns, but it is difficult for 1:1 mappings).
47c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
48c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Our shadow memory is scaled from a 1:1 mapping and supports a scale
49c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// specified at library initialization time that can be any power-of-2
50c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// scaledown (1x, 2x, 4x, 8x, 16x, etc.).
51c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
52c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// We model our shadow memory after Umbra, a library used by the Dr. Memory
53c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// tool: https://github.com/DynamoRIO/drmemory/blob/master/umbra/umbra_x64.c.
54c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// We use Umbra's scheme as it was designed to support different
55c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// offsets, it supports two different shadow mappings (which we may want to
56c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// use for future tools), and it ensures that the shadow of a shadow will
57c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// not overlap either shadow memory or application memory.
58c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
59c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// This formula translates from application memory to shadow memory:
60c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
61c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//   shadow(app) = ((app & 0x00000fff'ffffffff) + offset) >> scale
62c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
63c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Where the offset for 1:1 is 0x00001300'00000000.  For other scales, the
64c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// offset is shifted left by the scale, except for scales of 1 and 2 where
65c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// it must be tweaked in order to pass the double-shadow test
66c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// (see the "shadow(shadow)" comments below):
67c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//   scale == 0: 0x00001300'000000000
68c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//   scale == 1: 0x00002200'000000000
69c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//   scale == 2: 0x00004400'000000000
70c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//   scale >= 3: (0x00001300'000000000 << scale)
71c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
72c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Do not pass in the open-ended end value to the formula as it will fail.
73c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
74c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// The resulting shadow memory regions for a 0 scaling are:
75c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
76c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x00001300'00000000, 0x00001400'00000000)
77c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x00001800'00000000, 0x00001a00'00000000)
78c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x00002100'00000000, 0x000022ff'ff600000)
79c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x000022ff'ff601000, 0x00002300'00000000)
80c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x000022ff'ff600000, 0x000022ff'ff601000]
81c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
82c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// We also want to ensure that a wild access by the application into the shadow
83c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// regions will not corrupt our own shadow memory.  shadow(shadow) ends up
84c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// disjoint from shadow(app):
85c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//
86c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x00001600'00000000, 0x00001700'00000000)
87c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x00001b00'00000000, 0x00001d00'00000000)
88c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x00001400'00000000, 0x000015ff'ff600000]
89c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x000015ff'ff601000, 0x00001600'00000000]
90c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// [0x000015ff'ff600000, 0x000015ff'ff601000]
91c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
92c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstruct ApplicationRegion {
93c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  uptr Start;
94c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  uptr End;
95c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  bool ShadowMergedWithPrev;
96c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar};
97c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
98c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstatic const struct ApplicationRegion AppRegions[] = {
99c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  {0x0000000000000000ull, 0x0000010000000000u, false},
100c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  {0x0000550000000000u,   0x0000570000000000u, false},
101c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // We make one shadow mapping to hold the shadow regions for all 3 of these
102c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // app regions, as the mappings interleave, and the gap between the 3rd and
103c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // 4th scales down below a page.
104c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  {0x00007e0000000000u,   0x00007fffff600000u, false},
105c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  {0x00007fffff601000u,   0x0000800000000000u, true},
106c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  {0xffffffffff600000u,   0xffffffffff601000u, true},
107c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar};
108c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstatic const u32 NumAppRegions = sizeof(AppRegions)/sizeof(AppRegions[0]);
109c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
110c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// See the comment above: we do not currently support a stack size rlimit
111c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// equal to or larger than 1TB.
112c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstatic const uptr MaxStackSize = (1ULL << 40) - 4096;
113c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
114c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarclass ShadowMapping {
115c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarpublic:
116c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  static const uptr Mask = 0x00000fffffffffffu;
117c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // The scale and offset vary by tool.
118c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  uptr Scale;
119c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  uptr Offset;
120c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  void initialize(uptr ShadowScale) {
121c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    static const uptr OffsetArray[3] = {
122c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar        0x0000130000000000u,
123c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar        0x0000220000000000u,
124c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar        0x0000440000000000u,
125c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    };
126c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    Scale = ShadowScale;
127c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (Scale <= 2)
128c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      Offset = OffsetArray[Scale];
129c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    else
130c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      Offset = OffsetArray[0] << Scale;
131c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
132c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar};
133c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarextern ShadowMapping Mapping;
134c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#else
135c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// We'll want to use templatized functions over the ShadowMapping once
136c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// we support more platforms.
137c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#error Platform not supported
138c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
139c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
140c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstatic inline bool getAppRegion(u32 i, uptr *Start, uptr *End) {
141c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (i >= NumAppRegions)
142c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    return false;
143c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  *Start = AppRegions[i].Start;
144c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  *End = AppRegions[i].End;
145c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return true;
146c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
147c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
148c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga NainarALWAYS_INLINE
149c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarbool isAppMem(uptr Mem) {
150c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  for (u32 i = 0; i < NumAppRegions; ++i) {
151c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (Mem >= AppRegions[i].Start && Mem < AppRegions[i].End)
152c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      return true;
153c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
154c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return false;
155c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
156c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
157c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga NainarALWAYS_INLINE
158c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainaruptr appToShadow(uptr App) {
159c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return (((App & ShadowMapping::Mask) + Mapping.Offset) >> Mapping.Scale);
160c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
161c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
162c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstatic inline bool getShadowRegion(u32 i, uptr *Start, uptr *End) {
163c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (i >= NumAppRegions)
164c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    return false;
165c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  u32 UnmergedShadowCount = 0;
166c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  u32 AppIdx;
167c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  for (AppIdx = 0; AppIdx < NumAppRegions; ++AppIdx) {
168c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (!AppRegions[AppIdx].ShadowMergedWithPrev) {
169c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      if (UnmergedShadowCount == i)
170c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar        break;
171c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      UnmergedShadowCount++;
172c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    }
173c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
174c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (AppIdx >= NumAppRegions || UnmergedShadowCount != i)
175c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    return false;
176c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  *Start = appToShadow(AppRegions[AppIdx].Start);
177c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // The formula fails for the end itself.
178c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  *End = appToShadow(AppRegions[AppIdx].End - 1) + 1;
179c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // Merge with adjacent shadow regions:
180c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  for (++AppIdx; AppIdx < NumAppRegions; ++AppIdx) {
181c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (!AppRegions[AppIdx].ShadowMergedWithPrev)
182c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      break;
183c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    *Start = Min(*Start, appToShadow(AppRegions[AppIdx].Start));
184c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    *End = Max(*End, appToShadow(AppRegions[AppIdx].End - 1) + 1);
185c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
186c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return true;
187c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
188c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
189c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga NainarALWAYS_INLINE
190c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarbool isShadowMem(uptr Mem) {
191c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // We assume this is not used on any critical performance path and so there's
192c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // no need to hardcode the mapping results.
193c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  for (uptr i = 0; i < NumAppRegions; ++i) {
194c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (Mem >= appToShadow(AppRegions[i].Start) &&
195c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar        Mem < appToShadow(AppRegions[i].End - 1) + 1)
196c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      return true;
197c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
198c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return false;
199c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
200c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
201c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar} // namespace __esan
202c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
203c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif /* ESAN_SHADOW_H */
204