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