1 : // Copyright 2014 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Declares the ShadowMarker enumeration, and a utility class for querying the
16 : // component parts of a shadow byte.
17 :
18 : #ifndef SYZYGY_AGENT_ASAN_SHADOW_MARKER_H_
19 : #define SYZYGY_AGENT_ASAN_SHADOW_MARKER_H_
20 :
21 : #include "base/basictypes.h"
22 :
23 : namespace agent {
24 : namespace asan {
25 :
26 : // Defines the various distinct values that are used to mark shadow memory. At
27 : // the highest level this is split into 2 classes: accessible memory (leading
28 : // bit is 0), and inaccessible, or redzoned, memory (leading bit is 1). The
29 : // fast path Asan error checking code relies on the fact that the leading bit
30 : // is 1 for redzoned memory.
31 : //
32 : // The redzoned memory is broken into various distinct types. A lot of the
33 : // codespace of this enum is dedicated to describing blocks, with sufficient
34 : // detail to reconstruct the layout of the block from an inspection of shadow
35 : // memory alone.
36 : //
37 : // All block markers have 'historic' variants which are used for marking old
38 : // blocks that have since fallen out of the quarantine. This serves as a
39 : // persistent record of the block that *used* to be located at a specific spot
40 : // in memory, at least until the owning heap reuses the memory.
41 : //
42 : // Since the code space is quite convoluted (it has strictly been added to, and
43 : // was initially a clone of Asan's far simpler marker types) a helper class
44 : // (ShadowMarkerHelper) has been defined for making queries about marker
45 : // properties.
46 : //
47 : // NOTE: If this grows any more complex then it would be relatively simple to
48 : // define a 32-bit 'ShadowMarkerProperties' struct, and simply map each
49 : // marker type to its properties. The properties could then be trivially
50 : // inspected via masks.
51 : #define SHADOW_MARKER_GENERATOR(F) \
52 : /* ADDRESSABLE BYTES. */ \
53 : /* This is either a range of bytes that we know nothing about, or is */ \
54 : /* an allocated byte that is explicitly accessible. */ \
55 : F(kHeapAddressableMarker, 0x00) \
56 : /* Values 0x01 through 0x07 indicate that a range of bytes is */ \
57 : /* partially accessible, and partially inaccessible. */ \
58 : F(kHeapPartiallyAddressableByte1, 0x01) \
59 : F(kHeapPartiallyAddressableByte2, 0x02) \
60 : F(kHeapPartiallyAddressableByte3, 0x03) \
61 : F(kHeapPartiallyAddressableByte4, 0x04) \
62 : F(kHeapPartiallyAddressableByte5, 0x05) \
63 : F(kHeapPartiallyAddressableByte6, 0x06) \
64 : F(kHeapPartiallyAddressableByte7, 0x07) \
65 : /* NON-ADDRESSABLE BYTES. */ \
66 : /* These are 'historic' block start bytes. They are equivalent to */ \
67 : /* other block markers, but mark blocks that have since fallen out of */ \
68 : /* the quarantine. They are kept around to provide extra data, but */ \
69 : /* through memory reuse may end up being incomplete. The values are */ \
70 : /* the same as 'active' block markers, but with the 'active' bit */ \
71 : /* (0x20) disabled. Thus any marker starting with 0xc0 is a historic */ \
72 : /* block start marker. */ \
73 : F(kHeapHistoricBlockStartMarker0, 0xC0) \
74 : F(kHeapHistoricBlockStartMarker1, 0xC1) \
75 : F(kHeapHistoricBlockStartMarker2, 0xC2) \
76 : F(kHeapHistoricBlockStartMarker3, 0xC3) \
77 : F(kHeapHistoricBlockStartMarker4, 0xC4) \
78 : F(kHeapHistoricBlockStartMarker5, 0xC5) \
79 : F(kHeapHistoricBlockStartMarker6, 0xC6) \
80 : F(kHeapHistoricBlockStartMarker7, 0xC7) \
81 : /* Nested block start bytes have the bit 0x80 set. */ \
82 : F(kHeapHistoricNestedBlockStartMarker0, 0xC8) \
83 : F(kHeapHistoricNestedBlockStartMarker1, 0xC9) \
84 : F(kHeapHistoricNestedBlockStartMarker2, 0xCA) \
85 : F(kHeapHistoricNestedBlockStartMarker3, 0xCB) \
86 : F(kHeapHistoricNestedBlockStartMarker4, 0xCC) \
87 : F(kHeapHistoricNestedBlockStartMarker5, 0xCD) \
88 : F(kHeapHistoricNestedBlockStartMarker6, 0xCE) \
89 : F(kHeapHistoricNestedBlockStartMarker7, 0xCF) \
90 : /* These are 'historic' markers associated with block left/right */ \
91 : /* redzones and freed data. They consist of the same values as the */ \
92 : /* active markers, minus the active block bit. */ \
93 : F(kHeapHistoricBlockEndMarker, 0xD4) \
94 : F(kHeapHistoricNestedBlockEndMarker, 0xD5) \
95 : F(kHeapHistoricLeftPaddingMarker, 0xDA) \
96 : F(kHeapHistoricRightPaddingMarker, 0xDB) \
97 : F(kHeapHistoricFreedMarker, 0xDD) \
98 : /* Any marker starting with 0xe0 marks the beginning of a block. The */ \
99 : /* trailing 4 bits of the marker are used to encode additional */ \
100 : /* metadata about the block itself. This is necessary to allow */ \
101 : /* full introspection of blocks via the shadow. All 'active' block */ \
102 : /* start bytes have the bit 0x20 set. */ \
103 : F(kHeapBlockStartMarker0, 0xE0) \
104 : F(kHeapBlockStartMarker1, 0xE1) \
105 : F(kHeapBlockStartMarker2, 0xE2) \
106 : F(kHeapBlockStartMarker3, 0xE3) \
107 : F(kHeapBlockStartMarker4, 0xE4) \
108 : F(kHeapBlockStartMarker5, 0xE5) \
109 : F(kHeapBlockStartMarker6, 0xE6) \
110 : F(kHeapBlockStartMarker7, 0xE7) \
111 : /* Nested block start bytes have the bit 0x80 set. */ \
112 : F(kHeapNestedBlockStartMarker0, 0xE8) \
113 : F(kHeapNestedBlockStartMarker1, 0xE9) \
114 : F(kHeapNestedBlockStartMarker2, 0xEA) \
115 : F(kHeapNestedBlockStartMarker3, 0xEB) \
116 : F(kHeapNestedBlockStartMarker4, 0xEC) \
117 : F(kHeapNestedBlockStartMarker5, 0xED) \
118 : F(kHeapNestedBlockStartMarker6, 0xEE) \
119 : F(kHeapNestedBlockStartMarker7, 0xEF) \
120 : /* The data in this block maps to internal memory structures. */ \
121 : F(kAsanMemoryMarker, 0xF1) \
122 : /* The address covered by this byte are simply invalid and unable to */ \
123 : /* be accessed by user code. */ \
124 : F(kInvalidAddressMarker, 0xF2) \
125 : /* The bytes are part of a block that has been allocated by the */ \
126 : /* instrumented code, but subsequently redzoned via the runtime API. */ \
127 : F(kUserRedzoneMarker, 0xF3) \
128 : /* This marker marks the end of a block in memory, and is part of a */ \
129 : /* right redzone. */ \
130 : F(kHeapBlockEndMarker, 0xF4) \
131 : F(kHeapNestedBlockEndMarker, 0xF5) \
132 : /* The bytes are part of a left redzone (block header padding). */ \
133 : /* This is the same value as used by Asan itself. */ \
134 : F(kHeapLeftPaddingMarker, 0xFA) \
135 : /* The bytes are part of a right redzone (block trailer and padding). */ \
136 : /* This is the same value as used by Asan itself. */ \
137 : F(kHeapRightPaddingMarker, 0xFB) \
138 : /* These bytes are part of memory that is destined to be used by the */ \
139 : /* heap, has been reserved from the OS, but not yet handed out to */ \
140 : /* the code under test. */ \
141 : F(kAsanReservedMarker, 0xFC) \
142 : /* The bytes are part of the body of a block that has been allocated */ \
143 : /* and subsequently freed by instrumented code. */ \
144 : /* This is the same value as used by Asan itself. */ \
145 : F(kHeapFreedMarker, 0xFD)
146 :
147 : // Any non-accessible marker will have these bits set.
148 : static const uint8 kHeapNonAccessibleMarkerMask = 0x80;
149 :
150 : // Generate the enum using the generator. This keeps it such that we only need
151 : // to maintain a single list.
152 : #define SHADOW_MARKER_ENUM_FUNCTION(x, y) x = y,
153 : enum ShadowMarker {
154 : SHADOW_MARKER_GENERATOR(SHADOW_MARKER_ENUM_FUNCTION)
155 : };
156 : #undef SHADOW_MARKER_ENUM_FUNCTION
157 :
158 : // Maps from a shadow marker ID to its name. Invalid enumeration values are
159 : // mapped to a NULL string.
160 : extern const char* kShadowMarkerNames[256];
161 :
162 : // A convenience class that automatically accepts either a uint8 or a
163 : // ShadowMarker enum.
164 : struct ShadowMarkerValue {
165 : // These are deliberately left as implicit typecasts.
166 E : ShadowMarkerValue(ShadowMarker marker) : value(marker) { // NOLINT
167 E : }
168 E : ShadowMarkerValue(uint8 marker) // NOLINT
169 : : value(static_cast<ShadowMarker>(marker)) {
170 E : }
171 E : ShadowMarkerValue(const ShadowMarkerValue& rhs) // NOLINT
172 : : value(rhs.value) {
173 E : }
174 : ShadowMarker value;
175 : };
176 :
177 : // A simple helper for querying and building ShadowMarker values.
178 : struct ShadowMarkerHelper {
179 : // @name For querying shadow markers.
180 : // @{
181 :
182 : // @param marker The shadow marker to query.
183 : // @returns true if the marker is a redzone (inaccessible) marker, false
184 : // otherwise.
185 : static bool IsRedzone(ShadowMarkerValue marker);
186 :
187 : // @param marker The shadow marker to query.
188 : // @returns true if the marker describes an active block.
189 : static bool IsActiveBlock(ShadowMarkerValue marker);
190 :
191 : // @param marker The shadow marker to query.
192 : // @returns true if the marker describes a historic block.
193 : static bool IsHistoricBlock(ShadowMarkerValue marker);
194 :
195 : // @param marker The shadow marker to query.
196 : // @returns true if the marker describes memory pertaining to a block,
197 : // historic or otherwise.
198 : static bool IsBlock(ShadowMarkerValue marker);
199 :
200 : // @param marker The shadow marker to query.
201 : // @returns true if the marker describes an active block start marker.
202 : static bool IsActiveBlockStart(ShadowMarkerValue marker);
203 :
204 : // @param marker The shadow marker to query.
205 : // @returns true if the marker describes a historic block start marker.
206 : static bool IsHistoricBlockStart(ShadowMarkerValue marker);
207 :
208 : // @param marker The shadow marker to query.
209 : // @returns true if the marker describes a block header marker, historic or
210 : // active.
211 : static bool IsBlockStart(ShadowMarkerValue marker);
212 :
213 : // @param marker The shadow marker to query.
214 : // @returns true if the markers describes a nested block start marker,
215 : // historic or active.
216 : static bool IsNestedBlockStart(ShadowMarkerValue marker);
217 :
218 : // @param marker The shadow marker to query.
219 : // @returns the extra data encoded in a block start marker.
220 : // @note This should only be called for block start markers.
221 : static uint8 GetBlockStartData(ShadowMarkerValue marker);
222 :
223 : // @param marker The shadow marker to query.
224 : // @returns true if the marker describes an active block start marker.
225 : static bool IsActiveBlockEnd(ShadowMarkerValue marker);
226 :
227 : // @param marker The shadow marker to query.
228 : // @returns true if the marker describes a historic block start marker.
229 : static bool IsHistoricBlockEnd(ShadowMarkerValue marker);
230 :
231 : // @param marker The shadow marker to query.
232 : // @returns true if the marker describes a block header marker, historic or
233 : // active.
234 : static bool IsBlockEnd(ShadowMarkerValue marker);
235 :
236 : // @param marker The shadow marker to query.
237 : // @returns true if the markers describes a nested block end marker,
238 : // historic or active.
239 : static bool IsNestedBlockEnd(ShadowMarkerValue marker);
240 :
241 : // @param marker The shadow marker to query.
242 : // @returns true if the marker describes a historic left redzone.
243 : // Note that block start markers are part of a left redzone.
244 : static bool IsHistoricLeftRedzone(ShadowMarkerValue marker);
245 :
246 : // @param marker The shadow marker to query.
247 : // @returns true if the marker describes an active left redzone.
248 : // Note that block start markers are part of a left redzone.
249 : static bool IsActiveLeftRedzone(ShadowMarkerValue marker);
250 :
251 : // @param marker The shadow marker to query.
252 : // @returns true if the marker describes a left redzone, historic or active.
253 : // Note that block start markers are part of a left redzone.
254 : static bool IsLeftRedzone(ShadowMarkerValue marker);
255 :
256 : // @param marker The shadow marker to query.
257 : // @returns true if the marker describes a historic right redzone.
258 : // Note that block end markers are part of a right redzone.
259 : static bool IsHistoricRightRedzone(ShadowMarkerValue marker);
260 :
261 : // @param marker The shadow marker to query.
262 : // @returns true if the marker describes an active right redzone.
263 : // Note that block end markers are part of a right redzone.
264 : static bool IsActiveRightRedzone(ShadowMarkerValue marker);
265 :
266 : // @param marker The shadow marker to query.
267 : // @returns true if the marker describes a right redzone, historic or active.
268 : // Note that block end markers are part of a left redzone.
269 : static bool IsRightRedzone(ShadowMarkerValue marker);
270 :
271 : // @}
272 :
273 : // @name For modifying shadow markers.
274 : // @{
275 :
276 : // @param marker The shadow marker to modify.
277 : // @returns the historic version of the input marker.
278 : // @note The input marker must be an active block marker that has an
279 : // equivalent historic type.
280 : static ShadowMarker ToHistoric(ShadowMarkerValue marker);
281 :
282 : // @}
283 :
284 : // @name For building shadow markers.
285 : // @{
286 :
287 : // Builds a block start marker.
288 : // @param active True if the block is active, false if its historic.
289 : // @param nested True if the block is nested, false otherwise.
290 : // @param data The data to be appended to the marker. This can only consist
291 : // of 3 bits of data.
292 : // @returns the generated block start marker.
293 : static ShadowMarker BuildBlockStart(bool active, bool nested, uint8 data);
294 :
295 : // Builds a block end marker.
296 : // @param active True if the block is active, false if its historic.
297 : // @param nested True if the block is nested, false otherwise.
298 : // @returns the generated block end marker.
299 : static ShadowMarker BuildBlockEnd(bool active, bool nested);
300 :
301 : // @}
302 : };
303 :
304 : } // namespace asan
305 : } // namespace agent
306 :
307 : #endif // SYZYGY_AGENT_ASAN_SHADOW_MARKER_H_
|