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 : // An Asan Runtime manager.
38 : // This class take care of initializing the different modules (stack cache,
39 : // logger...) and provide the functions to report an error.
40 : // Basic usage:
41 : // AsanRuntime* asan_runtime = new AsanRuntime();
42 : // std::wstring asan_flags_str;
43 : // AsanRuntime::GetAsanFlagsEnvVar(&asan_flags_str);
44 : // asan_runtime->SetUp(asan_flags_str); // Initialize the modules.
45 : // ...
46 : // CONTEXT context;
47 : // ::RtlCaptureContext(&context);
48 : // StackCapture stack;
49 : // stack.InitFromStack();
50 : // stack.set_stack_id(stack.ComputeRelativeStackId());
51 : // asan_runtime->OnError((&context, stack.stack_id());
52 : // asan_runtime->TearDown(); // Release the modules.
53 : // delete asan_runtime;
54 : class AsanRuntime {
55 : public:
56 : typedef std::set<StackCapture::StackId> StackIdSet;
57 :
58 : AsanRuntime();
59 : ~AsanRuntime();
60 :
61 : // @name Accessors.
62 : // @{
63 E : AsanLogger* logger() {
64 E : DCHECK(logger_.get() != NULL);
65 E : return logger_.get();
66 E : }
67 E : StackCaptureCache* stack_cache() {
68 E : DCHECK(stack_cache_.get() != NULL);
69 E : return stack_cache_.get();
70 E : }
71 : // @}
72 :
73 : // Initialize asan runtime library.
74 : // @param flags_command_line The parameters string.
75 : void SetUp(const std::wstring& flags_command_line);
76 :
77 : // Release asan runtime library.
78 : void TearDown();
79 :
80 : // The error handler.
81 : // @param context The context when the error has been reported.
82 : void OnError(CONTEXT* context);
83 :
84 : // Set the callback called on error.
85 : // TODO(sebmarchand): Move the signature of this callback to an header file
86 : // so it'll be easier to update it.
87 : void SetErrorCallBack(void (*callback)(CONTEXT*));
88 :
89 : // Try to read the Asan environment variable.
90 : // @param env_var_wstr The wstring where to store the environment variable.
91 : // returns true on success, false otherwise.
92 : static bool GetAsanFlagsEnvVar(std::wstring* env_var_wstr);
93 :
94 : // Add an heap proxy to the heap proxies list.
95 : void AddHeap(HeapProxy* heap);
96 :
97 : // Remove an heap proxy from the heap proxies list.
98 : void RemoveHeap(HeapProxy* heap);
99 :
100 : // Report the details of an Asan error by walking the heap proxies list.
101 : // @param addr The red-zoned address causing a bad access.
102 : // @param context The context at which the access occurred.
103 : // @param stack The stack capture at the point of error.
104 : // @param access_mode The kind of the access (read or write).
105 : // @param access_size The size of the access (in bytes).
106 : void ReportAsanErrorDetails(const void* addr,
107 : const CONTEXT& context,
108 : const StackCapture& stack,
109 : HeapProxy::AccessMode access_mode,
110 : size_t access_size);
111 :
112 : // Returns true if we should ignore the given @p stack_id, false
113 : // otherwise.
114 E : bool ShouldIgnoreError(size_t stack_id) const {
115 : // TODO(sebmarchand): Keep a list of the stack ids that have already been
116 : // reported so we can avoid reporting the same error multiple times.
117 : return flags_.ignored_stack_ids.find(stack_id) !=
118 E : flags_.ignored_stack_ids.end();
119 E : }
120 :
121 : protected:
122 : // A structure to track the values of the flags.
123 : struct AsanFlags {
124 : AsanFlags()
125 : : quarantine_size(0U),
126 : reporting_period(0U),
127 : bottom_frames_to_skip(0U),
128 E : max_num_frames(0U) {
129 E : }
130 :
131 : // The default size of the quarantine of the HeapProxy, in bytes.
132 : size_t quarantine_size;
133 :
134 : // The number of allocations between reports of the stack trace cache
135 : // compression ratio.
136 : size_t reporting_period;
137 :
138 : // The number of bottom frames to skip on a stack trace.
139 : size_t bottom_frames_to_skip;
140 :
141 : // The max number of frames for a stack trace.
142 : size_t max_num_frames;
143 :
144 : // The stack ids we ignore.
145 : StackIdSet ignored_stack_ids;
146 : };
147 :
148 : // The name of the environment variable containing the command-line.
149 : static const char kSyzyAsanEnvVar[];
150 :
151 : // @name Flag strings.
152 : // @{
153 : static const char kBottomFramesToSkip[];
154 : static const char kMaxNumberOfFrames[];
155 : static const char kQuarantineSize[];
156 : static const char kCompressionReportingPeriod[];
157 : static const char kIgnoredStackIds[];
158 : static const wchar_t kSyzyAsanDll[];
159 : // @}
160 :
161 : // @name Accessors.
162 : // @{
163 E : const AsanFlags* const flags() { return &flags_; }
164 : // @}
165 :
166 : // @name Mutators.
167 : // @{
168 : void set_flags(const AsanFlags* flags);
169 : // @}
170 :
171 : // Propagate the values of the flags to the target modules.
172 : void PropagateFlagsValues() const;
173 :
174 : private:
175 : // The type of callback used by the OnError function.
176 : typedef base::Callback<void(CONTEXT*)> AsanOnErrorCallBack;
177 :
178 : // Set up the logger.
179 : void SetUpLogger();
180 :
181 : // Tear down the logger.
182 : void TearDownLogger();
183 :
184 : // Set up the stack cache.
185 : void SetUpStackCache();
186 :
187 : // Tear down the stack cache.
188 : void TearDownStackCache();
189 :
190 : // Parse and set the flags from the wide string @p str.
191 : bool ParseFlagsFromString(std::wstring str);
192 :
193 : // The shared logger instance that will be used by all heap proxies.
194 : scoped_ptr<AsanLogger> logger_;
195 :
196 : // The shared stack cache instance that will be used by all heap proxies.
197 : scoped_ptr<StackCaptureCache> stack_cache_;
198 :
199 : // The asan error callback functor.
200 : AsanOnErrorCallBack asan_error_callback_;
201 :
202 : // The values of the flags.
203 : AsanFlags flags_;
204 :
205 : // The heap proxies list lock.
206 : base::Lock heap_proxy_dlist_lock_;
207 :
208 : // The heap proxies list.
209 : LIST_ENTRY heap_proxy_dlist_; // Under heap_proxy_dlist_lock.
210 :
211 : DISALLOW_COPY_AND_ASSIGN(AsanRuntime);
212 : };
213 :
214 : } // namespace asan
215 : } // namespace agent
216 :
217 : #endif // SYZYGY_AGENT_ASAN_ASAN_RUNTIME_H_
|