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 : // Call trace event parsing classes.
16 :
17 : #ifndef SYZYGY_TRACE_PARSE_PARSER_H_
18 : #define SYZYGY_TRACE_PARSE_PARSER_H_
19 :
20 : #include <list>
21 :
22 : #include "base/files/file_path.h"
23 : #include "base/memory/scoped_ptr.h"
24 : #include "base/strings/string_piece.h"
25 : #include "base/time/time.h"
26 : #include "syzygy/core/address.h"
27 : #include "syzygy/core/address_space.h"
28 : #include "syzygy/pe/pe_file.h"
29 : #include "syzygy/trace/protocol/call_trace_defs.h"
30 :
31 : namespace trace {
32 : namespace parser {
33 :
34 : typedef pe::ModuleInformation ModuleInformation;
35 : typedef uint64 AbsoluteAddress64;
36 : typedef uint64 Size64;
37 :
38 : // This struct extends the pe::ModuleInformation structure to be possibly
39 : // annotated as dirty.
40 : struct AnnotatedModuleInformation : public ModuleInformation {
41 : AnnotatedModuleInformation() : ModuleInformation(), is_dirty(false) { }
42 :
43 : explicit AnnotatedModuleInformation(const ModuleInformation& module_info)
44 : : ModuleInformation(module_info),
45 E : is_dirty(false) {
46 E : }
47 :
48 : bool is_dirty;
49 : };
50 :
51 : // The module space tracked for each process observed by the parser.
52 : typedef core::AddressSpace<AbsoluteAddress64,
53 : Size64,
54 : AnnotatedModuleInformation> ModuleSpace;
55 :
56 : // Forward declarations.
57 : class ParseEngine;
58 : class ParseEventHandler;
59 :
60 : // A facade class that manages the various call trace parser engines which
61 : // Syzygy supports and presents a single interface that selects the most
62 : // appropriate one based on the files being parsed.
63 : class Parser {
64 : public:
65 : Parser();
66 : ~Parser();
67 :
68 : // Allows you to add a parse engine to the Parser facade. This should be
69 : // called prior to the call to Init. This is mainly intended for testing.
70 : // The Parser will assume responsibility for deleting the ParseEngine. The
71 : // parse engine is added to the front of the list, meaning it will be given
72 : // the chance to handle files before any of the built-in parsers.
73 : //
74 : // @param parse_engine pointer to a heap allocated ParseEngine.
75 : void AddParseEngine(ParseEngine* parse_engine);
76 :
77 : // Initialize the parser implementation.
78 : bool Init(ParseEventHandler* event_handler);
79 :
80 : // Returns true if an error occurred while parsing the trace files.
81 : bool error_occurred() const;
82 :
83 : // Set or reset the error flag.
84 : void set_error_occurred(bool value);
85 :
86 : // Add a trace file to the parse session. This can be called multiple times
87 : // with different trace file paths. The type of parser used is established
88 : // based on the type of the first trace file opened. It is an error to
89 : // open trace files of different type in a single parse session.
90 : bool OpenTraceFile(const base::FilePath& trace_file_path);
91 :
92 : // Consume all events across all currently open trace files.
93 : bool Consume();
94 :
95 : // Given an address and a process id, returns the module in memory at that
96 : // address. Returns NULL if no such module exists.
97 : const ModuleInformation* GetModuleInformation(uint32 process_id,
98 : AbsoluteAddress64 addr) const;
99 :
100 : // Close all currently open trace files.
101 : bool Close();
102 :
103 : protected:
104 : typedef std::list<ParseEngine*> ParseEngineSet;
105 : typedef ParseEngineSet::iterator ParseEngineIter;
106 :
107 : // Sets the currently active parse engine to the first engine that
108 : // recognizes the given trace file.
109 : bool SetActiveParseEngine(const base::FilePath& trace_file_path);
110 :
111 : // The set of parse engines available to consume and dispatch the events
112 : // contained in a set of trace files.
113 : ParseEngineSet parse_engine_set_;
114 :
115 : // The parse engine currently being used to parse trace files. This value
116 : // will be set based on the first trace file that gets opened.
117 : ParseEngine* active_parse_engine_;
118 :
119 : DISALLOW_COPY_AND_ASSIGN(Parser);
120 : };
121 :
122 : // Implemented by clients of Parser to receive trace event notifications.
123 : class ParseEventHandler {
124 : public:
125 : // Issued for the first call-trace event occurring in an instrumented module.
126 : // data may be NULL for parse engines in which it is unsupported or for
127 : // processes for which it has not been recorded.
128 : virtual void OnProcessStarted(base::Time time,
129 : DWORD process_id,
130 : const TraceSystemInfo* data) = 0;
131 :
132 : // Issued following the last call-trace event for the process given by
133 : // @p process_id.
134 : virtual void OnProcessEnded(base::Time time, DWORD process_id) = 0;
135 :
136 : // Issued for non-batch function entry traces.
137 : virtual void OnFunctionEntry(base::Time time,
138 : DWORD process_id,
139 : DWORD thread_id,
140 : const TraceEnterExitEventData* data) = 0;
141 :
142 : // Issued for function exit traces.
143 : virtual void OnFunctionExit(base::Time time,
144 : DWORD process_id,
145 : DWORD thread_id,
146 : const TraceEnterExitEventData* data) = 0;
147 :
148 : // Issued for batch function entry traces.
149 : virtual void OnBatchFunctionEntry(base::Time time,
150 : DWORD process_id,
151 : DWORD thread_id,
152 : const TraceBatchEnterData* data) = 0;
153 :
154 : // Issued for DLL_PROCESS_ATTACH on an instrumented module.
155 : virtual void OnProcessAttach(base::Time time,
156 : DWORD process_id,
157 : DWORD thread_id,
158 : const TraceModuleData* data) = 0;
159 :
160 : // Issued for DLL_PROCESS_DETACH on an instrumented module.
161 : virtual void OnProcessDetach(base::Time time,
162 : DWORD process_id,
163 : DWORD thread_id,
164 : const TraceModuleData* data) = 0;
165 :
166 : // Issued for DLL_THREAD_ATTACH on an instrumented module.
167 : virtual void OnThreadAttach(base::Time time,
168 : DWORD process_id,
169 : DWORD thread_id,
170 : const TraceModuleData* data) = 0;
171 :
172 : // Issued for DLL_THREAD_DETACH on an instrumented module.
173 : virtual void OnThreadDetach(base::Time time,
174 : DWORD process_id,
175 : DWORD thread_id,
176 : const TraceModuleData* data) = 0;
177 :
178 : // Issued for each batch of invocations on an instrumented module.
179 : virtual void OnInvocationBatch(base::Time time,
180 : DWORD process_id,
181 : DWORD thread_id,
182 : size_t num_invocations,
183 : const TraceBatchInvocationInfo* data) = 0;
184 :
185 : // Issued for each thread name captured.
186 : virtual void OnThreadName(base::Time time,
187 : DWORD process_id,
188 : DWORD thread_id,
189 : const base::StringPiece& thread_name) = 0;
190 :
191 : // Issued for indexed frequency counts. Depending on the mode of
192 : // instrumentation these may be per thread, per process, or per module.
193 : virtual void OnIndexedFrequency(
194 : base::Time time,
195 : DWORD process_id,
196 : DWORD thread_id,
197 : const TraceIndexedFrequencyData* data) = 0;
198 :
199 : // Issued for dynamic symbol records.
200 : virtual void OnDynamicSymbol(DWORD process_id,
201 : uint32 symbol_id,
202 : const base::StringPiece& symbol_name) = 0;
203 :
204 : // Issued for sampling profiler data records.
205 : virtual void OnSampleData(base::Time Time,
206 : DWORD process_id,
207 : const TraceSampleData* data) = 0;
208 :
209 : // Issued for detailed function call records.
210 : virtual void OnFunctionNameTableEntry(
211 : base::Time Time,
212 : DWORD process_id,
213 : const TraceFunctionNameTableEntry* data) = 0;
214 :
215 : // Issued for detailed function call records.
216 : virtual void OnStackTrace(
217 : base::Time Time,
218 : DWORD process_id,
219 : const TraceStackTrace* data) = 0;
220 :
221 : // Issued for detailed function call records.
222 : virtual void OnDetailedFunctionCall(
223 : base::Time Time,
224 : DWORD process_id,
225 : DWORD thread_id,
226 : const TraceDetailedFunctionCall* data) = 0;
227 :
228 : // Issued for comment records.
229 : virtual void OnComment(
230 : base::Time time,
231 : DWORD process_id,
232 : const TraceComment* data) = 0;
233 : };
234 :
235 : // A default implementation of the ParseEventHandler interface. Provides
236 : // empty implementations of all function so that clients only need to override
237 : // the events they are interested in.
238 : class ParseEventHandlerImpl : public ParseEventHandler {
239 : public:
240 : // @name ParseEventHandler implementation.
241 : // @{
242 : virtual void OnProcessStarted(base::Time time,
243 : DWORD process_id,
244 : const TraceSystemInfo* data) OVERRIDE;
245 : virtual void OnProcessEnded(base::Time time, DWORD process_id) OVERRIDE;
246 : virtual void OnFunctionEntry(base::Time time,
247 : DWORD process_id,
248 : DWORD thread_id,
249 : const TraceEnterExitEventData* data) OVERRIDE;
250 : virtual void OnFunctionExit(base::Time time,
251 : DWORD process_id,
252 : DWORD thread_id,
253 : const TraceEnterExitEventData* data) OVERRIDE;
254 : virtual void OnBatchFunctionEntry(base::Time time,
255 : DWORD process_id,
256 : DWORD thread_id,
257 : const TraceBatchEnterData* data) OVERRIDE;
258 : virtual void OnProcessAttach(base::Time time,
259 : DWORD process_id,
260 : DWORD thread_id,
261 : const TraceModuleData* data) OVERRIDE;
262 : virtual void OnProcessDetach(base::Time time,
263 : DWORD process_id,
264 : DWORD thread_id,
265 : const TraceModuleData* data) OVERRIDE;
266 : virtual void OnThreadAttach(base::Time time,
267 : DWORD process_id,
268 : DWORD thread_id,
269 : const TraceModuleData* data) OVERRIDE;
270 : virtual void OnThreadDetach(base::Time time,
271 : DWORD process_id,
272 : DWORD thread_id,
273 : const TraceModuleData* data) OVERRIDE;
274 : virtual void OnInvocationBatch(base::Time time,
275 : DWORD process_id,
276 : DWORD thread_id,
277 : size_t num_invocations,
278 : const TraceBatchInvocationInfo* data) OVERRIDE;
279 : virtual void OnThreadName(base::Time time,
280 : DWORD process_id,
281 : DWORD thread_id,
282 : const base::StringPiece& thread_name) OVERRIDE;
283 : virtual void OnIndexedFrequency(
284 : base::Time time,
285 : DWORD process_id,
286 : DWORD thread_id,
287 : const TraceIndexedFrequencyData* data) OVERRIDE;
288 : virtual void OnDynamicSymbol(DWORD process_id,
289 : uint32 symbol_id,
290 : const base::StringPiece& symbol_name) OVERRIDE;
291 : virtual void OnSampleData(base::Time time,
292 : DWORD process_id,
293 : const TraceSampleData* data) OVERRIDE;
294 : virtual void OnFunctionNameTableEntry(
295 : base::Time time,
296 : DWORD process_id,
297 : const TraceFunctionNameTableEntry* data) OVERRIDE;
298 : virtual void OnStackTrace(
299 : base::Time time,
300 : DWORD process_id,
301 : const TraceStackTrace* data) OVERRIDE;
302 : virtual void OnDetailedFunctionCall(
303 : base::Time time,
304 : DWORD process_id,
305 : DWORD thread_id,
306 : const TraceDetailedFunctionCall* data) OVERRIDE;
307 : virtual void OnComment(
308 : base::Time time,
309 : DWORD process_id,
310 : const TraceComment* data) OVERRIDE;
311 : // @}
312 : };
313 :
314 : } // namespace parser
315 : } // namespace trace
316 :
317 : #endif // SYZYGY_TRACE_PARSE_PARSER_H_
|