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