|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <cassert> |
|
17 #include <iostream> |
|
18 #include <iomanip> |
|
19 #include <sstream> |
|
20 |
|
21 #include "e32btrace.h" |
|
22 #include "utraceframe.h" |
|
23 #include "util.h" |
|
24 #include "eventoutputhandler.h" |
|
25 #include "logevents\traceeventbase.h" |
|
26 #include "utracedecoderapp.h" |
|
27 |
|
28 CTraceEventBase::CTraceEventBase(const CMultiPartFrameCollection& aFrames, MEventOutputHandler& aOutputHandler) |
|
29 : iOutputHandler(aOutputHandler) |
|
30 { |
|
31 CUTraceFrame* currentFrame = aFrames.at(0); |
|
32 Initialise(*currentFrame); |
|
33 |
|
34 // Initialise copied the data from the first frame so now we continue from the next frame |
|
35 unsigned int offset = currentFrame->DataLength(); |
|
36 unsigned int i; |
|
37 for (i=1; i<aFrames.size(); i++) |
|
38 { |
|
39 currentFrame = aFrames.at(i); |
|
40 assert(offset + currentFrame->DataLength() <= iDataLength); |
|
41 memcpy(iData + offset, currentFrame->Data(), currentFrame->DataLength()); |
|
42 offset += currentFrame->DataLength(); |
|
43 } |
|
44 } |
|
45 |
|
46 |
|
47 CTraceEventBase::CTraceEventBase(const CUTraceFrame& aFrame, MEventOutputHandler& aOutputHandler) |
|
48 : iOutputHandler(aOutputHandler) |
|
49 { |
|
50 Initialise(aFrame); |
|
51 } |
|
52 |
|
53 |
|
54 void CTraceEventBase::Initialise(const CUTraceFrame& aFrame) |
|
55 { |
|
56 iPrefix = ""; |
|
57 |
|
58 iFlags = 0; |
|
59 iPrimaryFilter = 0; |
|
60 iSecondaryFilter = 0; |
|
61 iSubCategory = 0; |
|
62 iArg1 = 0; |
|
63 iHeader2 = 0; |
|
64 iTimestamp1 = 0; |
|
65 iTimestamp2 = 0; |
|
66 iContext = 0; |
|
67 iProgramCounter = 0; |
|
68 iExtra = 0; |
|
69 |
|
70 iData = NULL; |
|
71 iDataLength = 0; |
|
72 |
|
73 iData = new unsigned char[aFrame.DataFullLength() + 4]; |
|
74 memset(iData, 0, aFrame.DataFullLength() + 4); |
|
75 |
|
76 iFlags = aFrame.Flags(); |
|
77 iPrimaryFilter = aFrame.PrimaryFilter(); |
|
78 //iSecondaryFilter = aFrame.SecondaryFilter(); |
|
79 iSubCategory = aFrame.SubCategory(); |
|
80 iArg1 = aFrame.Arg1(); |
|
81 |
|
82 if (Header2Present()) |
|
83 { |
|
84 iHeader2 = aFrame.Header2(); |
|
85 } |
|
86 |
|
87 if (Timestamp1Present()) |
|
88 { |
|
89 iTimestamp1 = aFrame.Timestamp1(); |
|
90 } |
|
91 |
|
92 if (Timestamp2Present()) |
|
93 { |
|
94 iTimestamp2 = aFrame.Timestamp2(); |
|
95 } |
|
96 |
|
97 if (ContextIdPresent()) |
|
98 { |
|
99 iContext = aFrame.ContextId() | aFrame.ContextType(); |
|
100 } |
|
101 |
|
102 if (PcPresent()) |
|
103 { |
|
104 iProgramCounter = aFrame.ProgramCounter(); |
|
105 } |
|
106 |
|
107 if (ExtraPresent()) |
|
108 { |
|
109 iExtra = aFrame.Extra(); |
|
110 } |
|
111 |
|
112 iDataLength = aFrame.DataFullLength(); |
|
113 |
|
114 memcpy(iData, aFrame.Data(), aFrame.DataLength()); |
|
115 iEventEntryNumber = aFrame.EventEntryNumber(); |
|
116 } |
|
117 |
|
118 CTraceEventBase::~CTraceEventBase() |
|
119 { |
|
120 delete [] iData; |
|
121 } |
|
122 |
|
123 unsigned char* CTraceEventBase::Data() const |
|
124 { |
|
125 return iData; |
|
126 } |
|
127 |
|
128 |
|
129 unsigned int CTraceEventBase::DataLength() const |
|
130 { |
|
131 return iDataLength; |
|
132 } |
|
133 |
|
134 |
|
135 unsigned int CTraceEventBase::Flags() const |
|
136 { |
|
137 return iFlags; |
|
138 } |
|
139 |
|
140 |
|
141 unsigned int CTraceEventBase::PrimaryFilter() const |
|
142 { |
|
143 return iPrimaryFilter; |
|
144 } |
|
145 |
|
146 |
|
147 unsigned int CTraceEventBase::SecondaryFilter() const |
|
148 { |
|
149 // TODO: |
|
150 std::cerr << "Error: CUTraceFrame::SecondaryFilter() not implemented" << std::endl; |
|
151 assert(0); |
|
152 return iSecondaryFilter; |
|
153 } |
|
154 |
|
155 |
|
156 unsigned int CTraceEventBase::SubCategory() const |
|
157 { |
|
158 return iSubCategory; |
|
159 } |
|
160 |
|
161 |
|
162 bool CTraceEventBase::Header2Present() const |
|
163 { |
|
164 return (iFlags & BTrace::EHeader2Present) == BTrace::EHeader2Present; |
|
165 } |
|
166 |
|
167 bool CTraceEventBase::Timestamp1Present() const |
|
168 { |
|
169 return (iFlags & BTrace::ETimestampPresent) == BTrace::ETimestampPresent; |
|
170 } |
|
171 |
|
172 bool CTraceEventBase::Timestamp2Present() const |
|
173 { |
|
174 return (iFlags & BTrace::ETimestamp2Present) == BTrace::ETimestamp2Present; |
|
175 } |
|
176 |
|
177 bool CTraceEventBase::ContextIdPresent() const |
|
178 { |
|
179 return (iFlags & BTrace::EContextIdPresent) == BTrace::EContextIdPresent; |
|
180 } |
|
181 |
|
182 bool CTraceEventBase::PcPresent() const |
|
183 { |
|
184 return (iFlags & BTrace::EPcPresent) == BTrace::EPcPresent; |
|
185 } |
|
186 |
|
187 bool CTraceEventBase::ExtraPresent() const |
|
188 { |
|
189 return (iFlags & BTrace::EExtraPresent) == BTrace::EExtraPresent; |
|
190 } |
|
191 |
|
192 unsigned int CTraceEventBase::Header2() const |
|
193 { |
|
194 if (Header2Present()) |
|
195 { |
|
196 return iHeader2; |
|
197 } |
|
198 |
|
199 #ifdef _DEBUG |
|
200 assert(0); // Test for presence - don't call this method blindly |
|
201 #endif |
|
202 std::cerr << "Error: CTraceEventBase::Header2() called out of context" << std::endl; |
|
203 return 0; |
|
204 } |
|
205 |
|
206 |
|
207 unsigned int CTraceEventBase::Timestamp1() const |
|
208 { |
|
209 if (Timestamp1Present()) |
|
210 { |
|
211 return iTimestamp1; |
|
212 } |
|
213 |
|
214 #ifdef _DEBUG |
|
215 assert(0); // Test for presence - don't call this method blindly |
|
216 #endif |
|
217 std::cerr << "Error: CTraceEventBase::Timestamp1() called out of context" << std::endl; |
|
218 return 0; |
|
219 } |
|
220 |
|
221 |
|
222 unsigned int CTraceEventBase::Timestamp2() const |
|
223 { |
|
224 if (Timestamp2Present()) |
|
225 { |
|
226 return iTimestamp2; |
|
227 } |
|
228 |
|
229 #ifdef _DEBUG |
|
230 assert(0); // Test for presence - don't call this method blindly |
|
231 #endif |
|
232 std::cerr << "Error: CTraceEventBase::Timestamp2() called out of context" << std::endl; |
|
233 return 0; |
|
234 } |
|
235 |
|
236 |
|
237 unsigned int CTraceEventBase::ContextType() const |
|
238 { |
|
239 if (ContextIdPresent()) |
|
240 { |
|
241 return iContext & (3UL); |
|
242 } |
|
243 |
|
244 #ifdef _DEBUG |
|
245 assert(0); // Test for presence - don't call this method blindly |
|
246 #endif |
|
247 std::cerr << "Error: CTraceEventBase::ContextType() called out of context" << std::endl; |
|
248 return 0; |
|
249 } |
|
250 |
|
251 |
|
252 unsigned int CTraceEventBase::ContextId() const |
|
253 { |
|
254 if (ContextIdPresent()) |
|
255 { |
|
256 return iContext & (~3UL); |
|
257 } |
|
258 |
|
259 #ifdef _DEBUG |
|
260 assert(0); // Test for presence - don't call this method blindly |
|
261 #endif |
|
262 std::cerr << "Error: CTraceEventBase::ContextId() called out of context" << std::endl; |
|
263 return 0; |
|
264 } |
|
265 |
|
266 |
|
267 unsigned int CTraceEventBase::ProgramCounter() const |
|
268 { |
|
269 if (PcPresent()) |
|
270 { |
|
271 return iProgramCounter; |
|
272 } |
|
273 |
|
274 #ifdef _DEBUG |
|
275 assert(0); // Test for presence - don't call this method blindly |
|
276 #endif |
|
277 std::cerr << "Error: CTraceEventBase::ProgramCounter() called out of context" << std::endl; |
|
278 return 0; |
|
279 } |
|
280 |
|
281 |
|
282 unsigned int CTraceEventBase::Extra() const |
|
283 { |
|
284 if (ExtraPresent()) |
|
285 { |
|
286 return iExtra; |
|
287 } |
|
288 |
|
289 #ifdef _DEBUG |
|
290 assert(0); // Test for presence - don't call this method blindly |
|
291 #endif |
|
292 std::cerr << "Error: CTraceEventBase::Extra() called out of context" << std::endl; |
|
293 return 0; |
|
294 } |
|
295 |
|
296 |
|
297 unsigned int CTraceEventBase::Arg1() const |
|
298 { |
|
299 return iArg1; |
|
300 } |
|
301 |
|
302 |
|
303 unsigned int CTraceEventBase::EventEntryNumber() const |
|
304 { |
|
305 return iEventEntryNumber; |
|
306 } |
|
307 |
|
308 |
|
309 void CTraceEventBase::WriteContextInfo(std::ostream& aOutput) const |
|
310 { |
|
311 unsigned int contextId = 0; |
|
312 unsigned int ts1 = 0; |
|
313 unsigned int ts2 = 0; |
|
314 |
|
315 if (ContextIdPresent()) |
|
316 { |
|
317 contextId = ContextId(); |
|
318 } |
|
319 |
|
320 if (Timestamp1Present()) |
|
321 { |
|
322 ts1 = Timestamp1(); |
|
323 } |
|
324 |
|
325 if (Timestamp2Present()) |
|
326 { |
|
327 ts2 = Timestamp2(); |
|
328 } |
|
329 |
|
330 // sorry, life is too short to figure out how to make ostream format floats nicely |
|
331 char timeStr[32]; |
|
332 if(CUTraceDecoderApp::UseTimes()) |
|
333 { |
|
334 switch(CUTraceDecoderApp::PeriodType()) |
|
335 { |
|
336 case CUTraceDecoderApp::ESplit: |
|
337 { |
|
338 // guessing - need to test on Uni |
|
339 double sec = (double) ts1 * CUTraceDecoderApp::Period1() + (double) ts2 * CUTraceDecoderApp::Period2(); |
|
340 sprintf_s(timeStr, sizeof(timeStr), "%1.6f,0", sec); |
|
341 break; |
|
342 } |
|
343 case CUTraceDecoderApp::E64Bit: |
|
344 { |
|
345 double sec = ((double) ((__int64) ts2 << 32) + ts1) * CUTraceDecoderApp::Period1(); |
|
346 sprintf_s(timeStr, sizeof(timeStr), "%1.6f,0", sec); |
|
347 break; |
|
348 } |
|
349 default: |
|
350 sprintf_s(timeStr, sizeof(timeStr), "-0,0"); |
|
351 break; |
|
352 } |
|
353 } |
|
354 else |
|
355 { |
|
356 sprintf_s(timeStr, sizeof(timeStr), "%d,%d", ts1, ts2); |
|
357 } |
|
358 |
|
359 aOutput << std::noshowbase << std::dec |
|
360 << iOutputHandler.CurrentFrame() << "," << PrimaryFilter() << "," |
|
361 << SubCategory() << "," |
|
362 << timeStr << ",0x" |
|
363 << std::noshowbase << std::setw(8) << std::setfill('0') |
|
364 << std::nouppercase << std::hex << contextId << "," ; |
|
365 } |
|
366 |
|
367 void CTraceEventBase::WriteEventPrefix(std::ostream& aOutput) const |
|
368 { |
|
369 if (iPrefix.length() > 0) |
|
370 { |
|
371 aOutput << iPrefix << ": "; |
|
372 } |
|
373 } |
|
374 |
|
375 void CTraceEventBase::SetPrefix(const std::string& aPrefix) |
|
376 { |
|
377 iPrefix = aPrefix; |
|
378 } |
|
379 |
|
380 void CTraceEventBase::SetPrefix(const char* aPrefix) |
|
381 { |
|
382 iPrefix = aPrefix; |
|
383 } |
|
384 |
|
385 void CTraceEventBase::ProcessEvent() const |
|
386 { |
|
387 iOutputHandler.WriteEvent(*this); |
|
388 } |
|
389 |
|
390 void CTraceEventBase::DumpEvent(std::ostream& aStream) const |
|
391 { |
|
392 aStream |
|
393 << "Size: " << std::dec << DataLength() << std::endl |
|
394 << "Flags: 0x" << std::noshowbase << std::setw(2) |
|
395 << std::setfill('0') << std::nouppercase << std::hex |
|
396 << Flags() << std::endl |
|
397 << "Primary Filter: 0x" << std::noshowbase << std::setw(2) |
|
398 << std::setfill('0') << std::nouppercase << std::hex |
|
399 << PrimaryFilter() << std::endl |
|
400 << "Subcategory: 0x" << std::noshowbase << std::setw(2) |
|
401 << std::setfill('0') << std::nouppercase << std::hex |
|
402 << SubCategory() << std::endl; |
|
403 |
|
404 if (Header2Present()) |
|
405 { |
|
406 aStream << "Header2: 0x" << std::noshowbase << std::setw(8) |
|
407 << std::setfill('0') << std::nouppercase << std::hex |
|
408 << Header2() << std::endl; |
|
409 } |
|
410 |
|
411 if (Timestamp1Present()) |
|
412 { |
|
413 aStream << "Timestamp1: " << std::noshowbase << std::dec |
|
414 << Timestamp1() << std::endl; |
|
415 } |
|
416 |
|
417 if (Timestamp2Present()) |
|
418 { |
|
419 aStream << "Timestamp2: " << std::noshowbase << std::dec |
|
420 << Timestamp2() << std::endl; |
|
421 } |
|
422 if (ContextIdPresent()) |
|
423 { |
|
424 aStream << "Context Type: "; |
|
425 switch (ContextType()) |
|
426 { |
|
427 case 0: |
|
428 aStream << "NThread" << std::endl; |
|
429 aStream << "Context ID: 0x" << std::noshowbase << std::hex << std::nouppercase |
|
430 << std::setw(8) << std::setfill('0') << ContextId() << std::endl; |
|
431 break; |
|
432 |
|
433 case 1: |
|
434 aStream << "Fast Interrupt (FIQ)" << std::endl; |
|
435 break; |
|
436 |
|
437 case 2: |
|
438 aStream << "Interrupt (IRQ)" << std::endl; |
|
439 break; |
|
440 |
|
441 case 3: |
|
442 aStream << "Immediate Delayed Function Call (IDFC)" << std::endl; |
|
443 break; |
|
444 } |
|
445 } |
|
446 |
|
447 if (PcPresent()) |
|
448 { |
|
449 aStream << "PC: 0x" << std::noshowbase << std::setw(8) |
|
450 << std::setfill('0') << std::nouppercase << std::hex |
|
451 << ProgramCounter() << std::endl; |
|
452 } |
|
453 |
|
454 if (ExtraPresent()) |
|
455 { |
|
456 aStream << "Extra: 0x" |
|
457 << std::noshowbase << std::setw(8) |
|
458 << std::setfill('0') << std::nouppercase << std::hex |
|
459 << Extra() << std::endl; |
|
460 } |
|
461 |
|
462 DumpBytes(aStream, Data(), DataLength()); |
|
463 aStream << std::endl; |
|
464 aStream.flush(); |
|
465 } |
|
466 |
|
467 |
|
468 |
|
469 unsigned int MTraceEvent::BytesToInt(const unsigned char *aBytes) const |
|
470 { |
|
471 unsigned int num = ((aBytes[3]<<24)&0xFF000000) | |
|
472 ((aBytes[2]<<16)&0xFF0000) | |
|
473 ((aBytes[1]<<8)&0xFF00) | |
|
474 (aBytes[0]&0xFF); |
|
475 |
|
476 return num; |
|
477 } |
|
478 |
|
479 |
|
480 unsigned int MTraceEvent::BytesToInt(const char *aBytes) const |
|
481 { |
|
482 return BytesToInt((const unsigned char *)aBytes); |
|
483 } |
|
484 |
|
485 |