|
1 // Copyright (c) 2007-2010 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 // Trace Core |
|
15 // |
|
16 |
|
17 // Include files |
|
18 #include "BTraceKernelCategoryHandler.h" |
|
19 #include "BTraceOstCategoryBitmap.h" |
|
20 #include "TraceCore.h" |
|
21 #include "TraceCoreDebug.h" |
|
22 #include "TraceCoreConstants.h" |
|
23 |
|
24 #include "OstTraceDefinitions.h" |
|
25 |
|
26 #ifdef OST_TRACE_COMPILER_IN_USE |
|
27 #include "BTraceKernelCategoryHandlerTraces.h" |
|
28 #endif |
|
29 |
|
30 #include "TraceCoreTComArgMacro.h" |
|
31 |
|
32 //Split: These needed from TraceCoreAutogen.h (which is removed): |
|
33 #define SYMBIAN_CF_SERVERDEN 0xC2 |
|
34 #define SYMBIAN_CF_MESHMACHINE 0xC3 |
|
35 #define SYMBIAN_CF_FACTORIES 0xC4 |
|
36 |
|
37 /** |
|
38 * Length of BTrace header |
|
39 */ |
|
40 const TUint KBTraceHeaderLen = 4; |
|
41 |
|
42 /** |
|
43 * Length of single BTrace variable |
|
44 */ |
|
45 const TUint KBTraceVariableLen = 4; |
|
46 |
|
47 /** |
|
48 * Four bytes |
|
49 */ |
|
50 const TUint KFourBytes = 4; |
|
51 |
|
52 // Trace group shift when checking if group is active |
|
53 #define GRP_SHIFT 16 |
|
54 |
|
55 // BTrace category shift for unknown categories |
|
56 #define CATEGORY_SHIFT 8 |
|
57 |
|
58 /** |
|
59 * Constructor |
|
60 */ |
|
61 DBTraceKernelCategoryHandler::DBTraceKernelCategoryHandler() |
|
62 : iPrimeDfc( DBTraceKernelCategoryHandler::PrimeDfc, this, DTraceCore::GetActivationQ(), KDefaultDfcPriority ) |
|
63 , iMultiPartActivationInfos(2, _FOFF( TMultiPartActivationInfo, iMultiPartId )) |
|
64 { |
|
65 } |
|
66 |
|
67 |
|
68 /** |
|
69 * Destructor |
|
70 */ |
|
71 DBTraceKernelCategoryHandler::~DBTraceKernelCategoryHandler() |
|
72 { |
|
73 iMultiPartActivationInfos.Close(); |
|
74 } |
|
75 |
|
76 |
|
77 /** |
|
78 * Initializes this handler |
|
79 * |
|
80 * @param aHandler The BTrace handler |
|
81 */ |
|
82 TInt DBTraceKernelCategoryHandler::Init() |
|
83 { |
|
84 TInt ret( KErrGeneral ); |
|
85 |
|
86 DTraceCore* traceCore = DTraceCore::GetInstance(); |
|
87 if ( traceCore != NULL ) |
|
88 { |
|
89 // Gets the Autogen category bitmap from the list of registered activation interfaces |
|
90 iTraceBitmap = static_cast< DBTraceOstCategoryBitmap* >( |
|
91 traceCore->GetActivation( KKernelHooksOSTComponentUID ) ); |
|
92 if ( iTraceBitmap != NULL ) |
|
93 { |
|
94 // Registers to bitmap for change notifications. The primary BTrace filters are |
|
95 // updated when the bitmap changes |
|
96 iTraceBitmap->RegisterActivationNotification( *this ); |
|
97 ret = KErrNone; |
|
98 } |
|
99 } |
|
100 |
|
101 // Registers kernel categories to BTrace |
|
102 if ( ret == KErrNone ) |
|
103 { |
|
104 for ( TInt i = KMinKernelCategory; ( ret == KErrNone ) && ( i <= KMaxKernelCategory ); i++ ) |
|
105 { |
|
106 ret = AddCategory( i ); |
|
107 } |
|
108 |
|
109 if ( ret == KErrNone ) |
|
110 { |
|
111 ret = Register(); |
|
112 } |
|
113 } |
|
114 TC_TRACE( ETraceLevelFlow, Kern::Printf( "<DBTraceKernelCategoryHandler::Init() - %d", ret ) ); |
|
115 return ret; |
|
116 } |
|
117 |
|
118 |
|
119 /** |
|
120 * Called before SetWriter with interrupts enabled |
|
121 * |
|
122 * @param aWriter The new writer |
|
123 */ |
|
124 void DBTraceKernelCategoryHandler::PrepareSetWriter( DTraceCoreWriter* aWriter ) |
|
125 { |
|
126 OstTrace1( TRACE_FLOW, DBTRACEKERNELCATEGORYHANDLER_PREPARESETWRITER_ENTRY,"> DBTraceKernelCategoryHandler::PrepareSetWriter 0x%x", ( TUint )( aWriter ) ); |
|
127 if ( iWriter == NULL && aWriter != NULL ) |
|
128 { |
|
129 DBTraceCategoryHandler::PrepareSetWriter( aWriter ); |
|
130 // When writer is set, the kernel categories are primed |
|
131 // Priming is done via DFC. |
|
132 PrimeKernelCategories(); |
|
133 } |
|
134 else |
|
135 { |
|
136 DBTraceCategoryHandler::PrepareSetWriter( aWriter ); |
|
137 if ( aWriter == NULL ) |
|
138 { |
|
139 // If writer is set to NULL, the kernel categories are disabled. |
|
140 // This needs to be done immediately, not via timer |
|
141 PrimeDfc(); |
|
142 } |
|
143 } |
|
144 if ( aWriter != NULL && aWriter->GetWriterType() == EWriterTypeUSBPhonet ) |
|
145 { |
|
146 // CPU events must be disabled when using media writer |
|
147 PrimeCategory( BTrace::ECpuUsage ); |
|
148 } |
|
149 } |
|
150 |
|
151 |
|
152 /** |
|
153 * Handler for KCategoryNokiaAutogen |
|
154 * |
|
155 * @param aHeader BTrace header |
|
156 * @param aHeader2 Extra header data |
|
157 * @param aContext The thread context in which this function was called |
|
158 * @param a1 The first trace parameter |
|
159 * @param a2 The second trace parameter |
|
160 * @param a3 The third trace parameter |
|
161 * @param aExtra Extra trace data |
|
162 * @param aPc The program counter value |
|
163 * @return ETrue if trace was processed, EFalse if not |
|
164 */ |
|
165 TBool DBTraceKernelCategoryHandler::HandleFrame( TUint32 aHeader, TUint32 aHeader2, const TUint32 aContext, |
|
166 const TUint32 a1, const TUint32 a2, const TUint32 a3, |
|
167 const TUint32 aExtra, const TUint32 aPc ) |
|
168 { |
|
169 TBool retval; |
|
170 if ( iWriter != NULL ) |
|
171 { |
|
172 //deal with any possible missing traces |
|
173 DTraceCore* tracecore = DTraceCore::GetInstance(); |
|
174 if(!tracecore) |
|
175 return EFalse; |
|
176 |
|
177 // Check if tracing is certified |
|
178 if (!tracecore->IsTraceCertified()) |
|
179 return EFalse; |
|
180 |
|
181 if ((tracecore->PreviousTraceDropped())) //if previous trace was dropped |
|
182 { |
|
183 //set flags back to EFalse first |
|
184 tracecore->SetPreviousTraceDropped(EFalse); |
|
185 |
|
186 //set missing flag in BTrace |
|
187 aHeader |= BTrace::EMissingRecord<<(BTrace::EFlagsIndex * KByteSize); |
|
188 } |
|
189 |
|
190 TUint8 category = ( aHeader >> ( BTrace::ECategoryIndex * KByteSize ) ) & KByteMask; |
|
191 TUint8 subCategory = ( aHeader >> ( BTrace::ESubCategoryIndex * KByteSize ) ) & KByteMask; |
|
192 TUint32 traceWord = MapCategoryToID( category, subCategory ); |
|
193 if ( traceWord > 0 ) |
|
194 { |
|
195 |
|
196 // Check if the trace is a multipart trace |
|
197 TBool isMultiPart = CheckMultiPart(aHeader, aHeader2); |
|
198 if (isMultiPart) |
|
199 { |
|
200 // Handle the multipart trace |
|
201 retval = HandleMultiPart(aHeader, aHeader2, aContext, traceWord, a2, a3, aExtra, aPc); |
|
202 } |
|
203 |
|
204 // Not a multipart trace |
|
205 else |
|
206 { |
|
207 // If previous trace was discarded, add info about it to the header |
|
208 if (tracecore->PreviousTraceDropped()) |
|
209 { |
|
210 aHeader |= BTrace::EMissingRecord<<(BTrace::EFlagsIndex * KByteSize); |
|
211 tracecore->SetPreviousTraceDropped(EFalse); |
|
212 } |
|
213 |
|
214 TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask ); |
|
215 iWriter->WriteTraceCoreFrame( KKernelHooksOSTComponentUID, |
|
216 traceWord, aHeader, aHeader2, aContext, a1, a2, a3, aExtra, aPc, recordSize ); |
|
217 |
|
218 retval = ETrue; |
|
219 } |
|
220 } |
|
221 else |
|
222 { |
|
223 retval = EFalse; |
|
224 } |
|
225 } |
|
226 else |
|
227 { |
|
228 retval = EFalse; |
|
229 } |
|
230 TC_TRACE( ETraceLevelTraceFlow, Kern::Printf("<DBTraceKernelCategoryHandler::HandleFrame - return %d", retval ) ); |
|
231 return retval; |
|
232 } |
|
233 |
|
234 |
|
235 /** |
|
236 * Maps a BTrace category / sub-category to group / trace ID |
|
237 * |
|
238 * @param aCategory The BTrace category |
|
239 * @param aSubCategory The BTrace sub-categoory |
|
240 * @return The group / trace ID combination |
|
241 */ |
|
242 TUint32 DBTraceKernelCategoryHandler::MapCategoryToID( TUint8 aCategory, TUint8 aSubCategory ) |
|
243 { |
|
244 TUint32 ret; |
|
245 |
|
246 switch( aCategory ) |
|
247 { |
|
248 case BTrace::EThreadIdentification: |
|
249 case BTrace::ECpuUsage: |
|
250 case BTrace::EClientServer: |
|
251 case BTrace::ERequests: |
|
252 case BTrace::EChunks: |
|
253 case BTrace::ECodeSegs: |
|
254 case BTrace::EPaging: |
|
255 case BTrace::EThreadPriority: |
|
256 case BTrace::EPagingMedia: |
|
257 ret = ( aCategory << GRP_SHIFT ) | aSubCategory; |
|
258 break; |
|
259 |
|
260 // Symbian 9.4 categories |
|
261 case BTrace::EKernelMemory: |
|
262 case BTrace::EHeap: |
|
263 case BTrace::EMetaTrace: |
|
264 case BTrace::ERamAllocator: |
|
265 case BTrace::EFastMutex: |
|
266 case BTrace::EProfiling: |
|
267 ret = ( aCategory << GRP_SHIFT ) | aSubCategory; |
|
268 break; |
|
269 |
|
270 // Symbian 9.5 categories |
|
271 case BTrace::EResourceManager: |
|
272 case BTrace::EResourceManagerUs: |
|
273 case BTrace::ERawEvent: |
|
274 case BTrace::EUsb: |
|
275 case BTrace::ESymbianKernelSync: |
|
276 case BTrace::EFlexibleMemModel: |
|
277 ret = ( aCategory << GRP_SHIFT ) | aSubCategory; |
|
278 break; |
|
279 |
|
280 // Symbian 9.6 categories |
|
281 case BTrace::EIic: |
|
282 ret = ( aCategory << GRP_SHIFT ) | aSubCategory; |
|
283 break; |
|
284 |
|
285 // These are for Symbian for debugging purposes |
|
286 case 194: |
|
287 ret = ( SYMBIAN_CF_SERVERDEN << GRP_SHIFT ) | aSubCategory; |
|
288 break; |
|
289 case 195: |
|
290 ret = ( SYMBIAN_CF_MESHMACHINE << GRP_SHIFT ) | aSubCategory; |
|
291 break; |
|
292 case 196: |
|
293 ret = ( SYMBIAN_CF_FACTORIES << GRP_SHIFT ) | aSubCategory; |
|
294 break; |
|
295 |
|
296 default: |
|
297 // Unknown category but let's still use the same ID as we received |
|
298 ret = ( aCategory << GRP_SHIFT ) | aSubCategory; |
|
299 break; |
|
300 } |
|
301 |
|
302 return ret; |
|
303 } |
|
304 |
|
305 |
|
306 /** |
|
307 * Called when an activation bitmap state changes |
|
308 * |
|
309 * @param aActivation the activation object |
|
310 * @param aFromSettings ETrue if changes was due to settings read |
|
311 * @param aComponentId Component ID of the activation |
|
312 */ |
|
313 void DBTraceKernelCategoryHandler::ActivationChanged( MTraceCoreActivation& TCOM_ARG(aActivation), TBool TCOM_ARG(aFromSettings), |
|
314 TUint32 aComponentId) |
|
315 { |
|
316 OstTraceExt2( TRACE_FLOW, DBTRACEKERNELCATEGORYHANDLER_ACTIVATIONCHANGED_ENTRY,"> DBTraceKernelCategoryHandler::ActivationChanged 0x%x. FromSettings:%d",( TUint )( &aActivation ), aFromSettings ); |
|
317 |
|
318 // Kernel categories are primed when activation bitmap changes |
|
319 if (aComponentId == KOldNokiaAutogenOSTComponentUID || aComponentId == KKernelHooksOSTComponentUID) |
|
320 { |
|
321 PrimeKernelCategories(); |
|
322 } |
|
323 } |
|
324 |
|
325 |
|
326 /** |
|
327 * Primes the kernel categories |
|
328 */ |
|
329 void DBTraceKernelCategoryHandler::PrimeKernelCategories() |
|
330 { |
|
331 // Priming is done asynchronously to avoid blocking this thread |
|
332 iPrimeDfc.Enque(); |
|
333 } |
|
334 |
|
335 |
|
336 /** |
|
337 * Dfc function to prime kernel categories |
|
338 */ |
|
339 void DBTraceKernelCategoryHandler::PrimeDfc( TAny* aHandler ) |
|
340 { |
|
341 OstTrace1( TRACE_FLOW, DBTRACEKERNELCATEGORYHANDLER_PRIMEDFC_ENTRY,"> DBTraceKernelCategoryHandler::PrimeDfc 0x%x", ( TUint )( aHandler ) ); |
|
342 |
|
343 // Get handler and prime kernel categories |
|
344 DBTraceKernelCategoryHandler* handler = static_cast< DBTraceKernelCategoryHandler* >( aHandler ); |
|
345 handler->PrimeDfc(); |
|
346 } |
|
347 |
|
348 |
|
349 /** |
|
350 * Called from the static DFC callback function |
|
351 */ |
|
352 void DBTraceKernelCategoryHandler::PrimeDfc() |
|
353 { |
|
354 OstTrace0( TRACE_FLOW, DBTRACEKERNELCATEGORYHANDLER_PRIMEDFC, |
|
355 "> DBTraceKernelCategoryHandler::PrimeDfc" ); |
|
356 |
|
357 // Start from Thread Identification as we don't want to active Printfs from the BTrace |
|
358 for ( TInt i = KMinKernelCategory; i <= KMaxKernelCategory; i++ ) |
|
359 { |
|
360 PrimeCategory( i ); |
|
361 } |
|
362 } |
|
363 |
|
364 |
|
365 /** |
|
366 * Primes a category |
|
367 * |
|
368 * @param aCategory the category to be primed |
|
369 */ |
|
370 void DBTraceKernelCategoryHandler::PrimeCategory( TUint8 aCategory ) |
|
371 { |
|
372 TUint32 traceWord = MapCategoryToID( aCategory, 0 ); |
|
373 // CPU events are not possible when using USB phonet writer |
|
374 // They result in context switch trace loop |
|
375 if ( iWriter != NULL && |
|
376 (iTraceBitmap->IsTraceActivated( KKernelHooksOSTComponentUID, traceWord ) ) |
|
377 && ( aCategory != BTrace::ECpuUsage || iWriter->GetWriterType() != EWriterTypeUSBPhonet ) ) |
|
378 { |
|
379 TInt ret = BTrace::SetFilter( aCategory, 1 ); |
|
380 if ( ret == KErrNone ) |
|
381 { |
|
382 OstTrace1( TRACE_NORMAL, DBTRACEKERNELCATEGORYHANDLER_PRIMEDFC__,"DBTraceKernelCategoryHandler::PrimeDfc - Priming 0x%x", aCategory ); |
|
383 BTrace::Prime( aCategory ); |
|
384 } |
|
385 else if ( ret == KErrNotSupported ) |
|
386 { |
|
387 OstTrace1( TRACE_INTERNAL, DBTRACEKERNELCATEGORYHANDLER_PRIMEDFC_NOT_SUPPORTED,"DBTraceKernelCategoryHandler::PrimeDfc - Category not supported 0x%x", aCategory ); |
|
388 } |
|
389 } |
|
390 else |
|
391 { |
|
392 (void) BTrace::SetFilter( aCategory, 0 ); |
|
393 } |
|
394 } |
|
395 |
|
396 /** |
|
397 * Handles this Multipart trace |
|
398 * |
|
399 * @param aHeader BTrace header |
|
400 * @param aHeader2 Extra header data |
|
401 * @param aContext The thread context in which this function was called |
|
402 * @param aTraceWord Trace Word |
|
403 * @param a1 First parameter |
|
404 * @param aData The data |
|
405 * @param aExtra Extra trace data |
|
406 * @param aPc The program counter value |
|
407 * @return ETrue if trace was processed |
|
408 */ |
|
409 TBool DBTraceKernelCategoryHandler::HandleMultiPart( TUint32 aHeader, TUint32 aHeader2, const TUint32 aContext, |
|
410 const TUint32 aTraceWord, const TUint32 a1, const TUint32 aData, const TUint32 aExtra, |
|
411 const TUint32 aPc) |
|
412 { |
|
413 TC_TRACE( ETraceLevelTraceFlow, Kern::Printf( ">DBTraceOstCategoryHandler::HandleMultiPart" ) ); |
|
414 TBool retval = ETrue; |
|
415 TInt multiPartOffset = aHeader2 & BTrace::EMultipartFlagMask; |
|
416 TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask ); |
|
417 |
|
418 // First part of multipart trace |
|
419 if (multiPartOffset == BTrace::EMultipartFirst) |
|
420 { |
|
421 // Create new MultiPart activation info and save it to the array |
|
422 TMultiPartActivationInfo activationInfo; |
|
423 activationInfo.iComponentId = KKernelHooksOSTComponentUID; |
|
424 activationInfo.iTraceWord = aTraceWord; |
|
425 activationInfo.iMultiPartId = aExtra; |
|
426 |
|
427 // Insert the item to the array |
|
428 TInt ret = iMultiPartActivationInfos.InsertInUnsignedKeyOrder(activationInfo); |
|
429 |
|
430 if (KErrNone == ret) |
|
431 { |
|
432 TUint32* ptr = reinterpret_cast< TUint32* >(aData); |
|
433 TUint32 a2 = *ptr++; |
|
434 |
|
435 // Write the trace. Move pointer by 4 bytes because first 4 bytes is moved from aData |
|
436 // to a2. Decrease record size by 4 bytes because the original a2 is not written |
|
437 iWriter->WriteTraceCoreFrame( activationInfo.iComponentId, activationInfo.iTraceWord, |
|
438 aHeader, aHeader2, aContext, a1, a2, |
|
439 aData + 4, aExtra, aPc, recordSize - 4); |
|
440 } |
|
441 else |
|
442 { |
|
443 retval = EFalse; |
|
444 DTraceCore* tcore = DTraceCore::GetInstance(); |
|
445 if(tcore) |
|
446 tcore->SetPreviousTraceDropped(ETrue); |
|
447 } |
|
448 } |
|
449 |
|
450 // Middle or last part of multipart trace |
|
451 else if (multiPartOffset == BTrace::EMultipartMiddle || multiPartOffset == BTrace::EMultipartLast) |
|
452 { |
|
453 // Check index of component id in array |
|
454 TMultiPartActivationInfo tempInfo; |
|
455 tempInfo.iMultiPartId = aExtra; |
|
456 TInt index = iMultiPartActivationInfos.FindInUnsignedKeyOrder(tempInfo); |
|
457 |
|
458 if (index != KErrNotFound) |
|
459 { |
|
460 TMultiPartActivationInfo activationInfo = iMultiPartActivationInfos[index]; |
|
461 |
|
462 TUint32 a1 = 0; |
|
463 TUint32 a2 = 0; |
|
464 TUint32 movePointerOffset = 0; |
|
465 |
|
466 // Calculate if we can move data from the aData to a1 and a2 |
|
467 TUint32 dataStartOffset = CalculateDataStartOffset(aHeader); |
|
468 if ( recordSize - dataStartOffset >= 4 ) |
|
469 { |
|
470 TUint32* ptr = reinterpret_cast< TUint32* >(aData); |
|
471 a1 = *ptr++; |
|
472 movePointerOffset += 4; |
|
473 |
|
474 if ( recordSize - dataStartOffset >= 8 ) |
|
475 { |
|
476 a2 = *ptr++; |
|
477 movePointerOffset += 4; |
|
478 } |
|
479 } |
|
480 |
|
481 // Write the trace. Decrease the record size by 8 because of the original a1 and a2 |
|
482 // are not written |
|
483 iWriter->WriteTraceCoreFrame( activationInfo.iComponentId, activationInfo.iTraceWord, |
|
484 aHeader, aHeader2, aContext, a1, a2, |
|
485 aData + movePointerOffset, aExtra, aPc, recordSize - 8); |
|
486 |
|
487 // Last part, remove the item from the array |
|
488 if (multiPartOffset == BTrace::EMultipartLast) |
|
489 { |
|
490 iMultiPartActivationInfos.Remove(index); |
|
491 } |
|
492 } |
|
493 } |
|
494 TC_TRACE( ETraceLevelTraceFlow, Kern::Printf( "<DBTraceOstCategoryHandler::HandleMultiPart > return %d", retval ) ); |
|
495 return retval; |
|
496 } |
|
497 |
|
498 /** |
|
499 * Checks if the given trace is a Multipart trace |
|
500 * |
|
501 * @param aHeader Header data |
|
502 * @param aHeader2 Extra header data |
|
503 * @return ETrue if trace is a Multipart trace, EFalse if not |
|
504 */ |
|
505 inline TBool DBTraceKernelCategoryHandler::CheckMultiPart( TUint32 aHeader, TUint32 aHeader2 ) |
|
506 { |
|
507 TC_TRACE( ETraceLevelTraceFlow, Kern::Printf( ">DBTraceKernelCategoryHandler::CheckMultiPart()" ) ); |
|
508 TBool retval = EFalse; |
|
509 TUint8 flags = static_cast< TUint8 >( ( aHeader >> ( BTrace::EFlagsIndex * KByteSize ) ) & KByteMask ); |
|
510 if (flags & BTrace::EHeader2Present) |
|
511 { |
|
512 // First, middle or last part of Multipart trace |
|
513 if (aHeader2 & BTrace::EMultipartFlagMask) |
|
514 { |
|
515 retval = ETrue; |
|
516 } |
|
517 } |
|
518 TC_TRACE( ETraceLevelTraceFlow, Kern::Printf( "<DBTraceKernelCategoryHandler::CheckMultiPart > return %d", retval ) ); |
|
519 return retval; |
|
520 } |
|
521 |
|
522 /** |
|
523 * Calculates data start offset |
|
524 * |
|
525 * @param aHeader BTrace header |
|
526 */ |
|
527 TUint32 DBTraceKernelCategoryHandler::CalculateDataStartOffset( TUint32 aHeader ) |
|
528 { |
|
529 TC_TRACE( ETraceLevelTraceFlow, Kern::Printf( ">DBTraceOstCategoryHandler::CalculateDataStartOffset()" ) ); |
|
530 TUint32 offset = 0; |
|
531 TUint8 flags = static_cast< TUint8 >( ( aHeader >> ( BTrace::EFlagsIndex * KByteSize ) ) & KByteMask ); |
|
532 |
|
533 // First add header length |
|
534 offset += KBTraceHeaderLen; |
|
535 |
|
536 // Header2 is present |
|
537 if ( flags & BTrace::EHeader2Present ) |
|
538 { |
|
539 offset += KBTraceVariableLen; |
|
540 } |
|
541 // Timestamp is present |
|
542 if ( flags & BTrace::ETimestampPresent ) |
|
543 { |
|
544 offset += KBTraceVariableLen; |
|
545 } |
|
546 // Timestamp2 is present |
|
547 if ( flags & BTrace::ETimestamp2Present ) |
|
548 { |
|
549 offset += KBTraceVariableLen; |
|
550 } |
|
551 // Context ID is present |
|
552 if ( flags & BTrace::EContextIdPresent ) |
|
553 { |
|
554 offset += KBTraceVariableLen; |
|
555 } |
|
556 // Program counter is present |
|
557 if ( flags & BTrace::EPcPresent ) |
|
558 { |
|
559 offset += KBTraceVariableLen; |
|
560 } |
|
561 // Extra value is present |
|
562 if ( flags & BTrace::EExtraPresent ) |
|
563 { |
|
564 offset += KBTraceVariableLen; |
|
565 } |
|
566 |
|
567 // Next 8 bytes came with first and second parameter of the multipart trace |
|
568 offset += KFourBytes; |
|
569 offset += KFourBytes; |
|
570 |
|
571 TC_TRACE( ETraceLevelTraceFlow, Kern::Printf( "<DBTraceOstCategoryHandler::CalculateDataStartOffset > return %d", offset ) ); |
|
572 return offset; |
|
573 } |
|
574 |
|
575 // End of File |