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 some structure and some utility functions used to get some
16 : // information about an Asan error.
17 :
18 : #ifndef SYZYGY_AGENT_ASAN_ERROR_INFO_H_
19 : #define SYZYGY_AGENT_ASAN_ERROR_INFO_H_
20 :
21 : #include "base/callback.h"
22 : #include "syzygy/agent/asan/block.h"
23 : #include "syzygy/agent/asan/heap.h"
24 : #include "syzygy/agent/common/stack_capture.h"
25 :
26 : // Forward declaration.
27 m : namespace crashdata {
28 m : class Value;
29 m : } // namespace crashdata
30 :
31 m : namespace agent {
32 m : namespace asan {
33 :
34 : // Forward declarations.
35 m : class StackCaptureCache;
36 m : struct BlockHeader;
37 :
38 : // The different memory access modes that we can encounter.
39 m : enum AccessMode {
40 m : ASAN_READ_ACCESS,
41 m : ASAN_WRITE_ACCESS,
42 m : ASAN_UNKNOWN_ACCESS
43 m : };
44 :
45 : // Enumeration of the different kinds of bad heap accesses that we can
46 : // encounter.
47 m : enum BadAccessKind {
48 : // This enum should start with bad access type that are not relative to a
49 : // heap block.
50 : // @note The ordering is important because those labels are used in
51 : // numeric inequalities.
52 m : UNKNOWN_BAD_ACCESS,
53 m : WILD_ACCESS,
54 m : INVALID_ADDRESS,
55 m : CORRUPT_BLOCK,
56 m : CORRUPT_HEAP,
57 :
58 : // This enum should end with bad access types that are relative to heap
59 : // blocks.
60 m : USE_AFTER_FREE,
61 m : HEAP_BUFFER_OVERFLOW,
62 m : HEAP_BUFFER_UNDERFLOW,
63 m : DOUBLE_FREE
64 m : };
65 :
66 : // The different types of errors we can encounter.
67 m : extern const char kHeapUseAfterFree[];
68 m : extern const char kHeapBufferUnderFlow[];
69 m : extern const char kHeapBufferOverFlow[];
70 m : extern const char kAttemptingDoubleFree[];
71 m : extern const char kInvalidAddress[];
72 m : extern const char kWildAccess[];
73 m : extern const char kHeapUnknownError[];
74 m : extern const char kHeapCorruptBlock[];
75 m : extern const char kCorruptHeap[];
76 :
77 : // Store the information that we want to report about a block.
78 : // TODO(sebmarchand): Rename this to avoid the confusion with the BlockInfo
79 : // structure?
80 m : struct AsanBlockInfo {
81 : // The address of the header for this block.
82 m : const void* header;
83 : // The user size of the block.
84 m : size_t user_size : 30;
85 : // This is implicitly a BlockState value.
86 m : size_t state : 2;
87 : // The ID of the allocation thread.
88 m : DWORD alloc_tid;
89 : // The ID of the free thread.
90 m : DWORD free_tid;
91 : // The result of a block analysis on this block.
92 m : BlockAnalysisResult analysis;
93 : // The allocation stack trace.
94 m : void* alloc_stack[agent::common::StackCapture::kMaxNumFrames];
95 : // The free stack trace.
96 m : void* free_stack[agent::common::StackCapture::kMaxNumFrames];
97 : // The size of the allocation stack trace.
98 m : uint8 alloc_stack_size;
99 : // The size of the free stack trace.
100 m : uint8 free_stack_size;
101 : // The type of heap that made the allocation.
102 m : HeapType heap_type;
103 : // The time since this block has been freed. This would be equal to zero if
104 : // the block is still allocated.
105 : // TODO(chrisha): We actually keep track of this in ticks. Rename this?
106 m : uint32 milliseconds_since_free;
107 m : };
108 :
109 m : struct AsanCorruptBlockRange {
110 : // The beginning address of the range.
111 m : const void* address;
112 : // The length of the range.
113 m : size_t length;
114 : // The number of blocks in this range.
115 m : size_t block_count;
116 : // The number of blocks in the |block_info| array.
117 m : size_t block_info_count;
118 : // The information about the blocks in this range. This may include one or
119 : // more of the corrupt blocks and/or the valid blocks surrounding them; at the
120 : // very least it will contain the first corrupt block in the range. The real
121 : // length of this array will be stored in |block_info_count|. The array itself
122 : // is allocated on the stack so that it gets shipped with minidumps.
123 m : AsanBlockInfo* block_info;
124 m : };
125 :
126 : // Store the information about a bad memory access.
127 m : struct AsanErrorInfo {
128 : // The address where the bad access happened.
129 m : void* location;
130 : // The context prior to the crash.
131 m : CONTEXT context;
132 : // The ID of the crash stack, this is needed to be able to blacklist some
133 : // known bugs.
134 m : common::StackCapture::StackId crash_stack_id;
135 : // The information about the block that contains the invalid location.
136 m : AsanBlockInfo block_info;
137 : // The error type.
138 m : BadAccessKind error_type;
139 : // The access mode.
140 m : AccessMode access_mode;
141 : // The access size.
142 m : size_t access_size;
143 : // The information about the shadow memory for this address, this would be
144 : // something like: "0x12345678 is located 8 bytes inside of a 10-byte region
145 : // [0x12345670,0x1234567A)."
146 m : char shadow_info[128];
147 : // A textual description of the shadow memory around |location|.
148 m : char shadow_memory[512];
149 : // Indicates if the heap is corrupt.
150 m : bool heap_is_corrupt;
151 : // The number of corrupt ranges encountered.
152 m : size_t corrupt_range_count;
153 : // The number of corrupt blocks encountered.
154 m : size_t corrupt_block_count;
155 : // The number of corrupt ranges reported in |corrupt_ranges|.
156 m : size_t corrupt_ranges_reported;
157 : // The information about the corrupt ranges of memory. The real length of this
158 : // array will be stored in |corrupt_ranges_reported|. This will be NULL if
159 : // |corrupt_ranges_reported| is zero.
160 m : AsanCorruptBlockRange* corrupt_ranges;
161 m : };
162 :
163 : // This callback allows a heap manager to report heap consistency problems that
164 : // it encounters during its operation. This is usually plumbed into the Asan
165 : // runtime so that the errors may be appropriately reported.
166 : //
167 : // |asan_error_info| contains information about the primary heap error that
168 : // was encountered. It is guaranteed to be on the stack.
169 m : typedef base::Callback<void(AsanErrorInfo* asan_error_info)>
170 m : HeapErrorCallback;
171 :
172 : // Returns a string describing a bad access kind.
173 : // @param bad_access_kind The bad access kind for which we want a textual
174 : // representation.
175 : // @returns a string describing the bad access kind.
176 m : const char* ErrorInfoAccessTypeToStr(BadAccessKind bad_access_kind);
177 :
178 : // Get information about a bad access.
179 : // @param stack_cache The stack cache that owns the alloc and free stack traces
180 : // of the blocks.
181 : // @param bad_access_info Will receive the information about this access.
182 : // @returns true if the address belongs to a memory block, false otherwise.
183 m : bool ErrorInfoGetBadAccessInformation(StackCaptureCache* stack_cache,
184 m : AsanErrorInfo* bad_access_info);
185 :
186 : // Give the type of a bad heap access corresponding to an address.
187 : // @param addr The address causing a bad heap access.
188 : // @param header The header of the block containing this address.
189 : // @returns The type of the bad heap access corresponding to this address.
190 : // @note Exposed for unittesting.
191 m : BadAccessKind ErrorInfoGetBadAccessKind(const void* addr,
192 m : const BlockHeader* header);
193 :
194 : // Retrieves a block's metadata.
195 : // @param stack_cache The stack cache that owns the alloc and free stack traces
196 : // of this block.
197 : // @param block_info THe block whose info is to be gathered.
198 : // @param asan_block_info Will receive the block's metadata.
199 m : void ErrorInfoGetAsanBlockInfo(const BlockInfo& block_info,
200 m : StackCaptureCache* stack_cache,
201 m : AsanBlockInfo* asan_block_info);
202 :
203 : // Given a populated AsanBlockInfo struct, fills out a corresponding crashdata
204 : // protobuf.
205 : // @param block_info The block info information.
206 : // @param value The uninitialized protobuf value to be populated.
207 m : void PopulateBlockInfo(const AsanBlockInfo& block_info,
208 m : crashdata::Value* value);
209 :
210 : // Given a populated AsanCorruptBlockRange struct, fills out a corresponding
211 : // crashdata protobuf.
212 : // @param range The corrupt block range information.
213 : // @param value The uninitialized protobuf value to be populated.
214 m : void PopulateCorruptBlockRange(const AsanCorruptBlockRange& range,
215 m : crashdata::Value* value);
216 :
217 : // Given a populated AsanErrorInfo struct, fills out a corresponding crashdata
218 : // protobuf.
219 : // @param error_info The filled in error information.
220 : // @param value The uninitialized protobuf value to be populated.
221 m : void PopulateErrorInfo(const AsanErrorInfo& error_info,
222 m : crashdata::Value* value);
223 :
224 m : } // namespace asan
225 m : } // namespace agent
226 :
227 : #endif // SYZYGY_AGENT_ASAN_ERROR_INFO_H_
|