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 <stdint.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_t 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_t 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_t marker) // NOLINT
169 E : : value(static_cast<ShadowMarker>(marker)) {}
170 E : ShadowMarkerValue(const ShadowMarkerValue& rhs) // NOLINT
171 E : : value(rhs.value) {
172 E : }
173 : ShadowMarker value;
174 : };
175 :
176 : // A simple helper for querying and building ShadowMarker values.
177 : struct ShadowMarkerHelper {
178 : // @name For querying shadow markers.
179 : // @{
180 :
181 : // @param marker The shadow marker to query.
182 : // @returns true if the marker is a redzone (inaccessible) marker, false
183 : // otherwise.
184 : static bool IsRedzone(ShadowMarkerValue marker);
185 :
186 : // @param marker The shadow marker to query.
187 : // @returns true if the marker describes an active block.
188 : static bool IsActiveBlock(ShadowMarkerValue marker);
189 :
190 : // @param marker The shadow marker to query.
191 : // @returns true if the marker describes a historic block.
192 : static bool IsHistoricBlock(ShadowMarkerValue marker);
193 :
194 : // @param marker The shadow marker to query.
195 : // @returns true if the marker describes memory pertaining to a block,
196 : // historic or otherwise.
197 : static bool IsBlock(ShadowMarkerValue marker);
198 :
199 : // @param marker The shadow marker to query.
200 : // @returns true if the marker describes an active block start marker.
201 : static bool IsActiveBlockStart(ShadowMarkerValue marker);
202 :
203 : // @param marker The shadow marker to query.
204 : // @returns true if the marker describes a historic block start marker.
205 : static bool IsHistoricBlockStart(ShadowMarkerValue marker);
206 :
207 : // @param marker The shadow marker to query.
208 : // @returns true if the marker describes a block header marker, historic or
209 : // active.
210 : static bool IsBlockStart(ShadowMarkerValue marker);
211 :
212 : // @param marker The shadow marker to query.
213 : // @returns true if the markers describes a nested block start marker,
214 : // historic or active.
215 : static bool IsNestedBlockStart(ShadowMarkerValue marker);
216 :
217 : // @param marker The shadow marker to query.
218 : // @returns the extra data encoded in a block start marker.
219 : // @note This should only be called for block start markers.
220 : static uint8_t GetBlockStartData(ShadowMarkerValue marker);
221 :
222 : // @param marker The shadow marker to query.
223 : // @returns true if the marker describes an active block start marker.
224 : static bool IsActiveBlockEnd(ShadowMarkerValue marker);
225 :
226 : // @param marker The shadow marker to query.
227 : // @returns true if the marker describes a historic block start marker.
228 : static bool IsHistoricBlockEnd(ShadowMarkerValue marker);
229 :
230 : // @param marker The shadow marker to query.
231 : // @returns true if the marker describes a block header marker, historic or
232 : // active.
233 : static bool IsBlockEnd(ShadowMarkerValue marker);
234 :
235 : // @param marker The shadow marker to query.
236 : // @returns true if the markers describes a nested block end marker,
237 : // historic or active.
238 : static bool IsNestedBlockEnd(ShadowMarkerValue marker);
239 :
240 : // @param marker The shadow marker to query.
241 : // @returns true if the marker describes a historic left redzone.
242 : // Note that block start markers are part of a left redzone.
243 : static bool IsHistoricLeftRedzone(ShadowMarkerValue marker);
244 :
245 : // @param marker The shadow marker to query.
246 : // @returns true if the marker describes an active left redzone.
247 : // Note that block start markers are part of a left redzone.
248 : static bool IsActiveLeftRedzone(ShadowMarkerValue marker);
249 :
250 : // @param marker The shadow marker to query.
251 : // @returns true if the marker describes a left redzone, historic or active.
252 : // Note that block start markers are part of a left redzone.
253 : static bool IsLeftRedzone(ShadowMarkerValue marker);
254 :
255 : // @param marker The shadow marker to query.
256 : // @returns true if the marker describes a historic right redzone.
257 : // Note that block end markers are part of a right redzone.
258 : static bool IsHistoricRightRedzone(ShadowMarkerValue marker);
259 :
260 : // @param marker The shadow marker to query.
261 : // @returns true if the marker describes an active right redzone.
262 : // Note that block end markers are part of a right redzone.
263 : static bool IsActiveRightRedzone(ShadowMarkerValue marker);
264 :
265 : // @param marker The shadow marker to query.
266 : // @returns true if the marker describes a right redzone, historic or active.
267 : // Note that block end markers are part of a left redzone.
268 : static bool IsRightRedzone(ShadowMarkerValue marker);
269 :
270 : // @}
271 :
272 : // @name For modifying shadow markers.
273 : // @{
274 :
275 : // @param marker The shadow marker to modify.
276 : // @returns the historic version of the input marker.
277 : // @note The input marker must be an active block marker that has an
278 : // equivalent historic type.
279 : static ShadowMarker ToHistoric(ShadowMarkerValue marker);
280 :
281 : // @}
282 :
283 : // @name For building shadow markers.
284 : // @{
285 :
286 : // Builds a block start marker.
287 : // @param active True if the block is active, false if its historic.
288 : // @param nested True if the block is nested, false otherwise.
289 : // @param data The data to be appended to the marker. This can only consist
290 : // of 3 bits of data.
291 : // @returns the generated block start marker.
292 : static ShadowMarker BuildBlockStart(bool active, bool nested, uint8_t data);
293 :
294 : // Builds a block end marker.
295 : // @param active True if the block is active, false if its historic.
296 : // @param nested True if the block is nested, false otherwise.
297 : // @returns the generated block end marker.
298 : static ShadowMarker BuildBlockEnd(bool active, bool nested);
299 :
300 : // @}
301 : };
302 :
303 : } // namespace asan
304 : } // namespace agent
305 :
306 : #endif // SYZYGY_AGENT_ASAN_SHADOW_MARKER_H_
|