tracesrv/tracecore/btrace_handler/src/BTraceKernelCategoryHandler.cpp
changeset 56 aa2539c91954
equal deleted inserted replaced
54:a151135b0cf9 56:aa2539c91954
       
     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