1 : // Copyright 2012 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 : // A class that take care of initializing asan run-time library.
16 :
17 : #ifndef SYZYGY_AGENT_ASAN_ASAN_RUNTIME_H_
18 : #define SYZYGY_AGENT_ASAN_ASAN_RUNTIME_H_
19 :
20 : #include <set>
21 : #include <string>
22 :
23 : #include "base/callback.h"
24 : #include "base/logging.h"
25 : #include "base/memory/scoped_ptr.h"
26 : #include "base/synchronization/lock.h"
27 : #include "syzygy/agent/asan/asan_heap.h"
28 : #include "syzygy/agent/asan/stack_capture.h"
29 : #include "syzygy/agent/common/dlist.h"
30 :
31 : namespace agent {
32 : namespace asan {
33 :
34 : class AsanLogger;
35 : class StackCaptureCache;
36 :
37 : // Store the information about a bad memory access.
38 : // TODO(sebmarchand): Add an array with the copy of the shadow memory around
39 : // this bad access.
40 : struct AsanErrorInfo {
41 : void* alloc_stack[agent::asan::StackCapture::kMaxNumFrames];
42 : uint8 alloc_stack_size;
43 : DWORD alloc_tid;
44 : void* free_stack[agent::asan::StackCapture::kMaxNumFrames];
45 : uint8 free_stack_size;
46 : DWORD free_tid;
47 : HeapProxy::BadAccessKind error_type;
48 : HeapProxy::AccessMode access_mode;
49 : size_t access_size;
50 : char shadow_info[128];
51 : uint64 microseconds_since_free;
52 : };
53 :
54 : // An Asan Runtime manager.
55 : // This class take care of initializing the different modules (stack cache,
56 : // logger...) and provide the functions to report an error.
57 : // Basic usage:
58 : // AsanRuntime* asan_runtime = new AsanRuntime();
59 : // std::wstring asan_flags_str;
60 : // AsanRuntime::GetAsanFlagsEnvVar(&asan_flags_str);
61 : // asan_runtime->SetUp(asan_flags_str); // Initialize the modules.
62 : // ...
63 : // CONTEXT context;
64 : // ::RtlCaptureContext(&context);
65 : // StackCapture stack;
66 : // stack.InitFromStack();
67 : // stack.set_stack_id(stack.ComputeRelativeStackId());
68 : // asan_runtime->OnError((&context, stack.stack_id());
69 : // asan_runtime->TearDown(); // Release the modules.
70 : // delete asan_runtime;
71 : class AsanRuntime {
72 : public:
73 : typedef std::set<StackCapture::StackId> StackIdSet;
74 :
75 : // The type of callback used by the OnError function.
76 : typedef base::Callback<void(CONTEXT*, AsanErrorInfo*)> AsanOnErrorCallBack;
77 :
78 : AsanRuntime();
79 : ~AsanRuntime();
80 :
81 : // @name Accessors.
82 : // @{
83 E : AsanLogger* logger() {
84 E : DCHECK(logger_.get() != NULL);
85 E : return logger_.get();
86 E : }
87 E : StackCaptureCache* stack_cache() {
88 E : DCHECK(stack_cache_.get() != NULL);
89 E : return stack_cache_.get();
90 E : }
91 E : static const wchar_t* SyzyAsanDll() {
92 E : return kSyzyAsanDll;
93 E : }
94 : // @}
95 :
96 : // Initialize asan runtime library.
97 : // @param flags_command_line The parameters string.
98 : void SetUp(const std::wstring& flags_command_line);
99 :
100 : // Release asan runtime library.
101 : void TearDown();
102 :
103 : // The error handler.
104 : // @param context The context when the error has been reported.
105 : // @param error_info The information about this error.
106 : void OnError(CONTEXT* context, AsanErrorInfo* error_info);
107 :
108 : // Set the callback called on error.
109 : // TODO(sebmarchand): Move the signature of this callback to an header file
110 : // so it'll be easier to update it.
111 : void SetErrorCallBack(const AsanOnErrorCallBack& callback);
112 :
113 : // Try to read the Asan environment variable.
114 : // @param env_var_wstr The wstring where to store the environment variable.
115 : // returns true on success, false otherwise.
116 : static bool GetAsanFlagsEnvVar(std::wstring* env_var_wstr);
117 :
118 : // Add an heap proxy to the heap proxies list.
119 : void AddHeap(HeapProxy* heap);
120 :
121 : // Remove an heap proxy from the heap proxies list.
122 : void RemoveHeap(HeapProxy* heap);
123 :
124 : // Report the details of an Asan error by walking the heap proxies list.
125 : // @param addr The red-zoned address causing a bad access.
126 : // @param context The context at which the access occurred.
127 : // @param stack The stack capture at the point of error.
128 : // @param access_mode The kind of the access (read or write).
129 : // @param access_size The size of the access (in bytes).
130 : // @param bad_access_info Will receive the information about this access.
131 : void ReportAsanErrorDetails(const void* addr,
132 : const CONTEXT& context,
133 : const StackCapture& stack,
134 : HeapProxy::AccessMode access_mode,
135 : size_t access_size,
136 : AsanErrorInfo* bad_access_info);
137 :
138 : // Returns true if we should ignore the given @p stack_id, false
139 : // otherwise.
140 E : bool ShouldIgnoreError(size_t stack_id) const {
141 : // TODO(sebmarchand): Keep a list of the stack ids that have already been
142 : // reported so we can avoid reporting the same error multiple times.
143 : return flags_.ignored_stack_ids.find(stack_id) !=
144 E : flags_.ignored_stack_ids.end();
145 E : }
146 :
147 : protected:
148 : // A structure to track the values of the flags.
149 : struct AsanFlags {
150 : AsanFlags()
151 : : quarantine_size(0U),
152 : reporting_period(0U),
153 : bottom_frames_to_skip(0U),
154 : max_num_frames(0U),
155 : exit_on_failure(false),
156 : minidump_on_failure(false),
157 E : log_as_text(true) {
158 E : }
159 :
160 : // The default size of the quarantine of the HeapProxy, in bytes.
161 : size_t quarantine_size;
162 :
163 : // The number of allocations between reports of the stack trace cache
164 : // compression ratio.
165 : size_t reporting_period;
166 :
167 : // The number of bottom frames to skip on a stack trace.
168 : size_t bottom_frames_to_skip;
169 :
170 : // The max number of frames for a stack trace.
171 : size_t max_num_frames;
172 :
173 : // The stack ids we ignore.
174 : StackIdSet ignored_stack_ids;
175 :
176 : // If true, we should generate a minidump whenever an error is detected.
177 : // Defaults to false.
178 : bool minidump_on_failure;
179 :
180 : // If we should stop the logger (and the running program) after reporting
181 : // an error. Defaults to false.
182 : bool exit_on_failure;
183 :
184 : // If true, we should generate a textual log describing any errors.
185 : // Defaults to true;
186 : bool log_as_text;
187 : };
188 :
189 : // The name of the environment variable containing the command-line.
190 : static const char kSyzyAsanEnvVar[];
191 :
192 : // @name Flag strings.
193 : // @{
194 : static const char kBottomFramesToSkip[];
195 : static const char kCompressionReportingPeriod[];
196 : static const char kExitOnFailure[];
197 : static const char kIgnoredStackIds[];
198 : static const char kMaxNumberOfFrames[];
199 : static const char kMiniDumpOnFailure[];
200 : static const char kNoLogAsText[];
201 : static const char kQuarantineSize[];
202 : static const wchar_t kSyzyAsanDll[];
203 : // @}
204 :
205 : // @name Accessors.
206 : // @{
207 E : const AsanFlags* const flags() { return &flags_; }
208 : // @}
209 :
210 : // @name Mutators.
211 : // @{
212 : void set_flags(const AsanFlags* flags);
213 : // @}
214 :
215 : // Propagate the values of the flags to the target modules.
216 : void PropagateFlagsValues() const;
217 :
218 : private:
219 : // Set up the logger.
220 : void SetUpLogger();
221 :
222 : // Tear down the logger.
223 : void TearDownLogger();
224 :
225 : // Set up the stack cache.
226 : void SetUpStackCache();
227 :
228 : // Tear down the stack cache.
229 : void TearDownStackCache();
230 :
231 : // Parse and set the flags from the wide string @p str.
232 : bool ParseFlagsFromString(std::wstring str);
233 :
234 : // The shared logger instance that will be used by all heap proxies.
235 : scoped_ptr<AsanLogger> logger_;
236 :
237 : // The shared stack cache instance that will be used by all heap proxies.
238 : scoped_ptr<StackCaptureCache> stack_cache_;
239 :
240 : // The asan error callback functor.
241 : AsanOnErrorCallBack asan_error_callback_;
242 :
243 : // The values of the flags.
244 : AsanFlags flags_;
245 :
246 : // The heap proxies list lock.
247 : base::Lock heap_proxy_dlist_lock_;
248 :
249 : // The heap proxies list.
250 : LIST_ENTRY heap_proxy_dlist_; // Under heap_proxy_dlist_lock.
251 :
252 : DISALLOW_COPY_AND_ASSIGN(AsanRuntime);
253 : };
254 :
255 : } // namespace asan
256 : } // namespace agent
257 :
258 : #endif // SYZYGY_AGENT_ASAN_ASAN_RUNTIME_H_
|