tracesrv/tracecore/btrace_handler/test/tracedataparser/src/tracedataparser.cpp
changeset 56 aa2539c91954
equal deleted inserted replaced
54:a151135b0cf9 56:aa2539c91954
       
     1 // Copyright (c) 2005-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 Data parser
       
    15 //
       
    16 
       
    17 #include <e32svr.h>
       
    18 #include <e32def.h>
       
    19 #include <e32def_private.h>
       
    20 #include <e32btrace.h>
       
    21 
       
    22 #include "tracedataparser.h"
       
    23 #include "testdatawriternotifier.h"
       
    24 #include "tracecoreconstants.h"
       
    25 #include "d32tracebuffer.h"
       
    26 
       
    27 
       
    28 EXPORT_C TUint32 TTraceDataParser::Swap(TUint32 x)
       
    29     {
       
    30     return  (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24);
       
    31     }
       
    32 
       
    33 EXPORT_C TUint32 TTraceDataParser::ReadUint32FromBuf(TUint8*& aBuf, TBool aFromTestWriter)
       
    34     {
       
    35 #ifdef __WINS__
       
    36     aFromTestWriter = EFalse;
       
    37 #endif
       
    38     // reads a 4 byte integer of expected endianess
       
    39     TUint32 n;
       
    40     if (!aFromTestWriter)
       
    41         {
       
    42         n = *(aBuf+3) + (*(aBuf+2) << 8) + (*(aBuf+1) << 16) + (*aBuf << 24);
       
    43         }
       
    44     else
       
    45         {
       
    46         // endianess order is reversed for TestWriter on hw
       
    47         n = (*aBuf) + (*(aBuf+1) << 8) + (*(aBuf+2) << 16) + (*(aBuf+3) << 24);    
       
    48         }
       
    49     aBuf += sizeof(TUint32);
       
    50     return n;
       
    51     }
       
    52 
       
    53 EXPORT_C TUint16 TTraceDataParser::ReadUint16FromBuf(TUint8*& aBuf)
       
    54     {
       
    55     // reads a 2 byte integer of expected endianess
       
    56     TUint16 n = (*aBuf << 8)+ (*(aBuf+1));
       
    57     aBuf += sizeof(TUint16);
       
    58     return n;
       
    59     }
       
    60 
       
    61 TPtr8 TTraceDataParser::ReadTracePrintf(TUint8* aData, TInt aSize)
       
    62     {
       
    63     TPtr8 printfString(aData, aSize, aSize);
       
    64     TInt endPosition = printfString.Locate(TChar(0));
       
    65     if (endPosition >= 0)
       
    66         {
       
    67         printfString = printfString.Left(endPosition);
       
    68         }
       
    69     else
       
    70         {
       
    71         printfString.Trim();
       
    72         }
       
    73     return printfString;
       
    74     }
       
    75 
       
    76 TBool TTraceDataParser::StringsMatch(const TDesC8& aString1, const TDesC8& aString2)
       
    77     {
       
    78     TInt compareLength = (aString1.Length() > aString2.Length()) ? aString2.Length() : aString1.Length();
       
    79     if ( (aString2.Left(compareLength).Compare(aString1) == 0) ||
       
    80          (aString1.Left(compareLength).Compare(aString2) == 0) )
       
    81         {
       
    82         return ETrue;
       
    83         }
       
    84     return EFalse;
       
    85     }
       
    86 
       
    87 /**
       
    88  * Function to string for a number
       
    89  * @param aBuffer Trace data descriptor
       
    90  * @param aFindStringPattern Pattern that indicates where in the string the number will be, using an asterisk
       
    91  * @param aNumberFound If found, the number in the string
       
    92  * @return Symbian error code
       
    93  */
       
    94 TInt TTraceDataParser::ParseStringForNumber(const TDesC8& aBuffer, const TDesC8& aFindStringPattern, TInt& aNumberFound)
       
    95     {
       
    96     TInt err = KErrNotFound;
       
    97     TInt posOfNum = aFindStringPattern.Locate('*');
       
    98     TInt lengthOfNum = 1 + aBuffer.Length() - aFindStringPattern.Length();
       
    99     if (posOfNum >= 0 && lengthOfNum >= 1)
       
   100         {
       
   101         TBuf<KMaxNumberBufferLength> numberBuffer;
       
   102         numberBuffer.Copy(aBuffer.Mid(posOfNum, lengthOfNum));
       
   103         TLex lex(numberBuffer);
       
   104         err = lex.Val(aNumberFound);
       
   105         }
       
   106     return err;
       
   107     }
       
   108 
       
   109 /*
       
   110  * Validate the trace data in buffer
       
   111  *
       
   112  * @param aBuffer the buffer containing the trace data
       
   113  * @param aExpectedNum expected number of traces
       
   114  * @param aComponentID component ID of traces
       
   115  * @param aGroupID group ID of traces
       
   116  * @param aData first expected trace data
       
   117  * @param aTraceWord trace word of traces
       
   118  * @param aIdentical indicates that the payload of each trace packet should be identical
       
   119  * @param aBufferMode The mode of the trace buffer.. 0=straight, 1=circular.
       
   120  * @param aOrdinalData indicates whether the payload data reflects its position in the stream of trace packets
       
   121  * @param aNumTraces number of traces written to circular buffer
       
   122  * @param aMaxTraces maximum number of traces circular buffer can hold
       
   123  * @return Standard Symbian error code
       
   124  */
       
   125 EXPORT_C TInt TTraceDataParser::ValidatePayload(TDesC8&         aBuffer,
       
   126                                                 TInt            aExpectedNum,
       
   127                                                 TComponentId    aComponentID, 
       
   128                                                 TGroupId        aGroupID, 
       
   129                                                 TUint32         aData, 
       
   130                                                 TUint32         aTraceWord,
       
   131                                                 TBool           aIdentical, 
       
   132                                                 TInt            aBufferMode, 
       
   133                                                 TBool           aOrdinalData, 
       
   134                                                 TInt            aNumTraces, 
       
   135                                                 TInt            aMaxTraces)
       
   136     {
       
   137     if ((aBuffer.Length() == 0) && (aExpectedNum <= 0))    // size is zero and there should be no traces
       
   138         {
       
   139         return KErrNone;
       
   140         }
       
   141     if ((aBuffer.Length() == 0) && (aExpectedNum > 0))     // size is zero and there should be traces
       
   142         {
       
   143         return KErrCorrupt;
       
   144         }
       
   145     if (aBuffer.Length() != 0 && (aExpectedNum <= 0))      // size is non-zero and there should be no traces
       
   146         {
       
   147         return KErrCorrupt;
       
   148         }
       
   149 
       
   150     TUint32 lastData = aData;
       
   151     TBool firstInStream = ETrue;
       
   152 
       
   153     // get the current position on the stream of traces so we can determine what the payload value should be.
       
   154     TInt overwrites = 0;
       
   155     if (aBufferMode == RTraceBuffer::EFreeRunning)
       
   156         {
       
   157         TInt overwrittenTraces = aNumTraces; // initialise to number of traces we wrote to the buffer for circular test
       
   158         while (overwrittenTraces > aMaxTraces)
       
   159             {
       
   160             overwrittenTraces = overwrittenTraces - aMaxTraces; // aMaxTraces is the max the buffer can hold 
       
   161             overwrites++;
       
   162             }
       
   163         lastData = (aMaxTraces * (overwrites - 1)) + overwrittenTraces + 1; // get where we are in the buffer
       
   164         }
       
   165 
       
   166     TInt            numberOSTtraces = 0;
       
   167     TUint8*         data            = (TUint8*) aBuffer.Ptr();
       
   168     TUint8*         endOfData       = data + aBuffer.Size();    
       
   169     TUint8          testGID         = aGroupID;
       
   170     TUint32         testCID         = aComponentID;
       
   171     TUint32         testTraceWord   = 0;
       
   172 
       
   173     TTraceHeaderSettings  traceHeaderSettings;
       
   174 
       
   175     // Loop through all traces
       
   176     while (data < endOfData)
       
   177         {
       
   178         // Get trace info from header
       
   179         TInt err = ParseHeader(data, endOfData-data, traceHeaderSettings);
       
   180         
       
   181         if (err != KErrNone)
       
   182             {
       
   183             return err;
       
   184             }
       
   185 
       
   186         //check the missing flag if we expect it
       
   187         if ((firstInStream&&(overwrites>0)))
       
   188             {
       
   189             if(!(traceHeaderSettings.iHeaderFlags & BTrace::EMissingRecord))
       
   190                 {
       
   191                 return KErrCorrupt;
       
   192                 }
       
   193             }
       
   194 
       
   195         if (!traceHeaderSettings.iPrintfTrace)
       
   196             {
       
   197             testTraceWord = ((TUint32) (testGID << GROUPIDSHIFT)) + 1;
       
   198             
       
   199             // check group ID
       
   200             if (traceHeaderSettings.iCategory != testGID)
       
   201                 {
       
   202                 return KErrCorrupt;
       
   203                 }
       
   204             // check component ID
       
   205             if (traceHeaderSettings.iComponentID != testCID)
       
   206                 {
       
   207                 return KErrCorrupt;
       
   208                 }
       
   209             // check trace word
       
   210             if (traceHeaderSettings.iTraceWord != testTraceWord)
       
   211                 {
       
   212                 return KErrCorrupt;
       
   213                 }
       
   214             
       
   215             TBool lastTrace = EFalse;
       
   216             if ( (traceHeaderSettings.iMultiPartType == BTrace::EMultipartLast) || (!traceHeaderSettings.iMultiPartType) )
       
   217                 {
       
   218                 lastTrace = ETrue;
       
   219                 }
       
   220 
       
   221             // check trace payload
       
   222             for (TInt i=0; traceHeaderSettings.iLengthOfPayload>0; i++)
       
   223                 {
       
   224                 TUint32 param = Swap(ReadUint32FromBuf(data, traceHeaderSettings.iFromTestWriter));
       
   225                 // For circular case, we try to estimate to within +/- 2 where we are in payload
       
   226                 // for straight case we should get it exactly correct.
       
   227                 if ( ((param != lastData) && (aBufferMode == 0)) || 
       
   228                       ( ((param > lastData + 2) || (param < lastData - 2)) && (aBufferMode == RTraceBuffer::EFreeRunning) ) )
       
   229                     {
       
   230                     return KErrCorrupt;
       
   231                     }
       
   232                 lastData = param; // in case we weren't accurate in circular case.
       
   233                 traceHeaderSettings.iLengthOfPayload -= 4;
       
   234                 lastData++;
       
   235                 }
       
   236             lastData = (!aOrdinalData)? aData : lastData;
       
   237             if (!aOrdinalData)
       
   238                 {
       
   239                 lastData = (lastTrace || aIdentical) ? aData : lastData;
       
   240                 }
       
   241 
       
   242             if (traceHeaderSettings.iMultiPartType || aIdentical || aOrdinalData)
       
   243                 {
       
   244                 testGID = aGroupID;
       
   245                 testCID = aComponentID;
       
   246                 testTraceWord = aTraceWord;
       
   247                 }
       
   248             else
       
   249                 {
       
   250                 testGID++;
       
   251                 testCID++;
       
   252                 testTraceWord += (1 << GROUPIDSHIFT);
       
   253                 }
       
   254             numberOSTtraces++;
       
   255             }
       
   256         else
       
   257             {
       
   258             // Go to the next trace
       
   259             data += traceHeaderSettings.iLengthOfPayload;
       
   260             }
       
   261         firstInStream = EFalse; //after this, it's defnitely not the first trace in the stream.
       
   262         }
       
   263 
       
   264     // Check that we're getting the correct number of traces
       
   265     //or approximate ammount (+/-1) for circular buffer because
       
   266     //the arithmetic to overwrite traces sometimes also skips one
       
   267     //extra trace
       
   268 
       
   269     if (numberOSTtraces != aExpectedNum)
       
   270         {
       
   271         if ((aBufferMode==RTraceBuffer::EFreeRunning)
       
   272                 &&((numberOSTtraces>=aExpectedNum-1)||(numberOSTtraces<=aExpectedNum+1)))
       
   273             {
       
   274             return KErrNone;
       
   275             }
       
   276         return KErrCorrupt;
       
   277         }
       
   278 
       
   279     return KErrNone;
       
   280     }
       
   281 
       
   282 /*
       
   283  * Validate the single trace data in buffer
       
   284  * 
       
   285  * @param aBuffer the buffer containing the trace data
       
   286  * @param aTracePresent determines if trace data should be present or not
       
   287  * @param aGroupID expected GID
       
   288  * @param aComponentID expected CID
       
   289  * @param aData expected trace data
       
   290  * @param aPrintfTrace determines if trace data should be printf data or not
       
   291  * @param aMissingTrace determines if trace data should indicate missing data or not
       
   292  * @param aExpectedPrintfTrace expected printf trace data
       
   293  * @return Standard Symbian error code
       
   294  */
       
   295 EXPORT_C TInt TTraceDataParser::ValidatePayload(TDesC8&        aBuffer, 
       
   296                                                 TBool          aTracePresent, 
       
   297                                                 TGroupId       aGroupID, 
       
   298                                                 TComponentId   aComponentID, 
       
   299                                                 TUint32        aData,
       
   300                                                 TBool          aPrintfTrace,
       
   301                                                 TBool          aMissingTrace,
       
   302                                                 TDesC8*        aExpectedPrintfTrace)
       
   303     {
       
   304     if ((aBuffer.Length() == 0) && (!aTracePresent))    // size is zero and there should be no traces
       
   305         {
       
   306         return KErrNone;
       
   307         }
       
   308     if ((aBuffer.Length() == 0) && (aTracePresent))     // size is zero and there should be traces
       
   309         {
       
   310         return KErrCorrupt;
       
   311         }
       
   312     if (aBuffer.Length() != 0 && (!aTracePresent))      // size is non-zero and there should be no traces
       
   313         {
       
   314         return KErrCorrupt;
       
   315         }
       
   316 
       
   317     TUint8*         data            = (TUint8*) aBuffer.Ptr();
       
   318     TUint8*         endOfData       = data + aBuffer.Size();    
       
   319 
       
   320     TTraceHeaderSettings  traceHeaderSettings;
       
   321 
       
   322     // Get trace info from header
       
   323     TInt err = ParseHeader(data, endOfData-data, traceHeaderSettings);
       
   324     
       
   325     if (err != KErrNone)
       
   326         {
       
   327         return err;
       
   328         }
       
   329 
       
   330     // check trace type
       
   331     if (traceHeaderSettings.iPrintfTrace != aPrintfTrace)
       
   332         {
       
   333         return KErrCorrupt;
       
   334         }
       
   335 
       
   336     if (!traceHeaderSettings.iPrintfTrace)
       
   337         {
       
   338         TUint32 testTraceWord = ((TUint32) (aGroupID << GROUPIDSHIFT)) + 1;
       
   339         
       
   340         // check group ID
       
   341         if (traceHeaderSettings.iCategory != aGroupID)
       
   342             {
       
   343             return KErrCorrupt;
       
   344             }
       
   345         // check component ID
       
   346         if (traceHeaderSettings.iComponentID != aComponentID)
       
   347             {
       
   348             return KErrCorrupt;
       
   349             }
       
   350         // check trace word
       
   351         if (traceHeaderSettings.iTraceWord != testTraceWord)
       
   352             {
       
   353             return KErrCorrupt;
       
   354             }
       
   355         
       
   356         if (aMissingTrace)
       
   357             {
       
   358             // check missing flag
       
   359             if (!(traceHeaderSettings.iHeaderFlags & BTrace::EMissingRecord))
       
   360                 {
       
   361                 return KErrCorrupt;
       
   362                 }
       
   363             }
       
   364         
       
   365         TInt i = 0;
       
   366         while (data < endOfData)
       
   367             {
       
   368             TUint32 param = Swap(ReadUint32FromBuf(data, traceHeaderSettings.iFromTestWriter));
       
   369             if (param != aData + i)
       
   370                 {
       
   371                 return KErrCorrupt;
       
   372                 }
       
   373             i++;
       
   374             }
       
   375         }
       
   376     else if (!aExpectedPrintfTrace)
       
   377         {
       
   378         return KErrArgument;
       
   379         }
       
   380     else
       
   381         {
       
   382         TBuf8<KExpectedPrintfMaxLength> expectedPrintf;
       
   383         
       
   384         // In the case of an expected dropped trace, we only check for "* Dropped Trace" because
       
   385         // the test writer has completed the request for data when it writes that bit first (right 
       
   386         // before the next trace), and when it goes to write the actual trace, it doesn't.
       
   387         // If we change this, the "* Dropped Trace" will be overwritten by the actual trace before
       
   388         // the test can check it, since the test writer doesn't buffer trace data.
       
   389         if (aMissingTrace)
       
   390             {
       
   391             // check that "* Dropped Trace" is in the buffer
       
   392             expectedPrintf = KDroppedTrace;
       
   393             }
       
   394         else
       
   395             {
       
   396             // check that "Test Printf Trace" is in the buffer"
       
   397             expectedPrintf = *aExpectedPrintfTrace;
       
   398             }
       
   399         
       
   400         expectedPrintf.Append(TChar(0)); // printf handler appends null at the end.
       
   401 
       
   402         TPtrC8 actualprintf(data, traceHeaderSettings.iLengthOfPayload);
       
   403 
       
   404         // Need to fix endianess for hw
       
   405 #ifndef __WINS__
       
   406         TInt bufpos = 0;
       
   407         while (bufpos < (actualprintf.Length()-4))
       
   408             {
       
   409             // reads a 4 byte integer of expected endianess
       
   410             TUint32 n = actualprintf[bufpos] + (actualprintf[bufpos+1] << 8) + (actualprintf[bufpos+2] << 16) + (actualprintf[bufpos+3] << 24);
       
   411             bufpos += sizeof(TUint32);
       
   412             TUint32 tempData = Swap(n);
       
   413             memcpy((TAny*)(actualprintf.Ptr()+bufpos-4),(TAny*)&tempData, sizeof(TUint32));
       
   414             }        
       
   415 #endif //__WINS__
       
   416         
       
   417         if (expectedPrintf.Compare(actualprintf) != 0)
       
   418             {
       
   419             return KErrCorrupt;
       
   420             }
       
   421 
       
   422         // Check if there is another trace to follow
       
   423         data += traceHeaderSettings.iLengthOfPayload;
       
   424         if (data != endOfData)
       
   425             {
       
   426             TPtrC8 buffer(data, endOfData - data);
       
   427             
       
   428             return ValidatePayload(buffer, 
       
   429                                    aTracePresent, 
       
   430                                    aGroupID, 
       
   431                                    aComponentID, 
       
   432                                    aData,
       
   433                                    aPrintfTrace,
       
   434                                    EFalse,
       
   435                                    aExpectedPrintfTrace);
       
   436             }
       
   437         }    
       
   438     return KErrNone;
       
   439     }
       
   440 
       
   441 /*
       
   442  * Verify the priming data contains all the expected values
       
   443  *
       
   444  * @param aBuffer Buffer containing the trace data
       
   445  * @param aSize Size of the trace buffer
       
   446  * @param aCategory BTrace category of the trace data
       
   447  * @param aSubCategory BTrace subcategory of the trace data
       
   448  * @param aElementsFound Parameter to hold current state of expected data found so far
       
   449  * @param aVerificationData1 Optional input value - used differently for different categories
       
   450  * @param aVerificationData2 Optional input value - used differently for different categories
       
   451  * @return Standard Symbian error code
       
   452  */
       
   453 TInt TTraceDataParser::VerifyPrimingData(TUint8* aBuffer, 
       
   454                                          TInt    aSize, 
       
   455                                          TUint8  aCategory, 
       
   456                                          TUint8  aSubCategory, 
       
   457                                          TInt&   aElementsFound,
       
   458                                          TBool   aFromTestWriter, 
       
   459                                          TUint32 aVerificationData1, 
       
   460                                          TUint32 aVerificationData2)
       
   461     {
       
   462     TInt err = KErrNotSupported;
       
   463     switch(aCategory)
       
   464         {
       
   465         case BTrace::EThreadIdentification:
       
   466             err = VerifyThreadPrimingData(aBuffer, aSize, aSubCategory, aElementsFound, aFromTestWriter, aVerificationData1, aVerificationData2);
       
   467             break;
       
   468         case BTrace::EFastMutex:
       
   469             err = VerifyFastMutexPrimingData(aBuffer, aSize, aSubCategory, aElementsFound, aFromTestWriter);
       
   470             break;
       
   471         case BTrace::ECodeSegs:
       
   472             err = VerifyCodeSegsPrimingData(aBuffer, aSize, aSubCategory, aElementsFound, aFromTestWriter, aVerificationData1, aVerificationData2);
       
   473             break;
       
   474         default:
       
   475             break;
       
   476         }
       
   477     return err;    
       
   478     }
       
   479 
       
   480 /*
       
   481  * Verify the EThreadIdentification priming data contains all the expected values
       
   482  *
       
   483  * @param aBuffer Buffer containing the trace data
       
   484  * @param aSize Size of the trace buffer
       
   485  * @param aSubCategory BTrace subcategory of the trace data
       
   486  * @param aElementsFound Parameter to hold current state of expected data found so far
       
   487  * @param aThreadAddr The address of the thread to search for
       
   488  * @param aProcessAddr The address of the process to search for
       
   489  * @return Standard Symbian error code
       
   490  */
       
   491 TInt TTraceDataParser::VerifyThreadPrimingData(TUint8* aBuffer, 
       
   492                                                TInt    aSize, 
       
   493                                                TUint8  aSubCategory, 
       
   494                                                TInt&   aElementsFound,
       
   495                                                TBool   aFromTestWriter, 
       
   496                                                TUint32 aThreadAddr, 
       
   497                                                TUint32 aProcessAddr)
       
   498     {
       
   499     RThread currentThread;    
       
   500     RProcess currentProcess;
       
   501 
       
   502     TUint32 tempThreadAddr;
       
   503     TUint32 tempProcessAddr;
       
   504     
       
   505     switch(aSubCategory)
       
   506         {
       
   507         case BTrace::EProcessCreate:
       
   508             {
       
   509             tempProcessAddr = Swap(ReadUint32FromBuf(aBuffer, aFromTestWriter));
       
   510             if (tempProcessAddr == aProcessAddr)
       
   511                 {
       
   512                 aElementsFound |= 0x000000ff;
       
   513                 }
       
   514             }
       
   515             break;
       
   516             
       
   517         case BTrace::EProcessName:
       
   518             {
       
   519             tempThreadAddr = Swap(ReadUint32FromBuf(aBuffer, aFromTestWriter));
       
   520             tempProcessAddr = Swap(ReadUint32FromBuf(aBuffer, aFromTestWriter));
       
   521             if ( (tempThreadAddr == aThreadAddr) && (tempProcessAddr == aProcessAddr) )
       
   522                 {
       
   523                 TBuf8<KMaxName> currentProcessName;
       
   524                 currentProcessName.Copy(currentProcess.Name());
       
   525                 TPtr8 processName(aBuffer,(aSize-8),(aSize-8)); //should be name of the process
       
   526                 processName.Trim();
       
   527                 if (StringsMatch(currentProcessName, processName))
       
   528                     {
       
   529                     aElementsFound |= 0x0000ff00;
       
   530                     }
       
   531                 }
       
   532             }
       
   533             break;
       
   534         
       
   535         case BTrace::EThreadName:
       
   536             {
       
   537             tempThreadAddr = Swap(ReadUint32FromBuf(aBuffer, aFromTestWriter));
       
   538             tempProcessAddr = Swap(ReadUint32FromBuf(aBuffer, aFromTestWriter));
       
   539             if ( (tempThreadAddr == aThreadAddr) && (tempProcessAddr == aProcessAddr) )
       
   540                 {
       
   541                 TBuf8<KMaxName> currentThreadName;
       
   542                 currentThreadName.Copy(currentThread.Name());
       
   543                 TPtr8 threadName(aBuffer,(aSize-8),(aSize-8)); //should be name of the thread
       
   544                 threadName.Trim();
       
   545                 if (StringsMatch(currentThreadName, threadName))
       
   546                     {
       
   547                     aElementsFound |= 0x00ff0000;
       
   548                     }
       
   549                 }
       
   550             }
       
   551             break;
       
   552             
       
   553         case BTrace::EThreadId:
       
   554             {
       
   555             tempThreadAddr = Swap(ReadUint32FromBuf(aBuffer, aFromTestWriter));
       
   556             tempProcessAddr = Swap(ReadUint32FromBuf(aBuffer, aFromTestWriter));
       
   557             if ( (tempThreadAddr == aThreadAddr) && (tempProcessAddr == aProcessAddr) )
       
   558                 {
       
   559                 TThreadId threadId = Swap(ReadUint32FromBuf(aBuffer, aFromTestWriter));
       
   560                 if (currentThread.Id() == threadId)
       
   561                     {
       
   562                     aElementsFound |= 0xff000000;
       
   563                     }
       
   564                 }
       
   565             }
       
   566             break; 
       
   567             
       
   568         default:
       
   569             break;
       
   570         }
       
   571     
       
   572     TInt err = KErrNotFound;
       
   573     if (aElementsFound == 0xffffffff)
       
   574         {
       
   575         err = KErrNone;
       
   576         }
       
   577     return err;
       
   578     }
       
   579 
       
   580 /*
       
   581  * Verify the EFastMutex priming data contains all the expected values
       
   582  *
       
   583  * @param aBuffer Buffer containing the trace data
       
   584  * @param aSize Size of the trace buffer
       
   585  * @param aSubCategory BTrace subcategory of the trace data
       
   586  * @param aElementsFound Parameter to hold current state of expected data found so far
       
   587  * @return Standard Symbian error code
       
   588  */
       
   589 TInt TTraceDataParser::VerifyFastMutexPrimingData(TUint8* aBuffer, 
       
   590                                                   TInt    aSize, 
       
   591                                                   TUint8  aSubCategory, 
       
   592                                                   TInt&   aElementsFound,
       
   593                                                   TBool   aFromTestWriter)
       
   594     {
       
   595     if (aSubCategory == BTrace::EFastMutexName)
       
   596         {
       
   597         TUint32 fastMutexId = Swap(ReadUint32FromBuf(aBuffer, aFromTestWriter));
       
   598         TUint32 unspecified = Swap(ReadUint32FromBuf(aBuffer, aFromTestWriter));
       
   599         if (fastMutexId && !unspecified)
       
   600             {
       
   601             TPtr8 fastMutexName(aBuffer,(aSize-8),(aSize-8)); //should be name of the fast mutex
       
   602             fastMutexName.Trim();
       
   603             if (StringsMatch(KFastMutexNameSystemLock(), fastMutexName))
       
   604                 {
       
   605                 aElementsFound |= 0x000000ff;
       
   606                 }
       
   607             else if (StringsMatch(KFastMutexNameMsgLock(), fastMutexName))
       
   608                 {
       
   609                 aElementsFound |= 0x0000ff00;
       
   610                 }
       
   611             else if (StringsMatch(KFastMutexNameObjLock(), fastMutexName))
       
   612                 {
       
   613                 aElementsFound |= 0x00ff0000;
       
   614                 }
       
   615             else if (StringsMatch(KFastMutexNameLogonLock(), fastMutexName))
       
   616                 {
       
   617                 aElementsFound |= 0xff000000;
       
   618                 }
       
   619             }
       
   620         }
       
   621     
       
   622     TInt err = KErrNotFound;
       
   623     if (aElementsFound == 0xffffffff)
       
   624         {
       
   625         err = KErrNone;
       
   626         }
       
   627     return err;
       
   628     }
       
   629 
       
   630 /*
       
   631  * Verify the ECodeSegs priming data contains all the expected values
       
   632  *
       
   633  * @param aBuffer Buffer containing the trace data
       
   634  * @param aSize Size of the trace buffer
       
   635  * @param aSubCategory BTrace subcategory of the trace data
       
   636  * @param aElementsFound Parameter to hold current state of expected data found so far
       
   637  * @param aSegAddr1 The address of the first code seg to search for
       
   638  * @param aSegAddr2 The address of the second code seg to search for
       
   639  * @return Standard Symbian error code
       
   640  */
       
   641 TInt TTraceDataParser::VerifyCodeSegsPrimingData(TUint8* aBuffer, 
       
   642                                                  TInt    aSize, 
       
   643                                                  TUint8  aSubCategory, 
       
   644                                                  TInt&   aElementsFound,
       
   645                                                  TBool   aFromTestWriter, 
       
   646                                                  TUint32 aSegAddr1, 
       
   647                                                  TUint32 aSegAddr2)
       
   648     {
       
   649     TUint32 codeSegAddr;
       
   650     if (aSubCategory == BTrace::ECodeSegCreated)
       
   651         {
       
   652         codeSegAddr = Swap(ReadUint32FromBuf(aBuffer, aFromTestWriter));
       
   653         if (codeSegAddr == aSegAddr1 || codeSegAddr == aSegAddr2)
       
   654             {
       
   655             TPtr8 codeSegName(aBuffer,(aSize-4),(aSize-4)); //should be name of the code seg
       
   656             codeSegName.Trim();
       
   657             if (codeSegAddr == aSegAddr1 && StringsMatch(KCodeSegsName1(), codeSegName))
       
   658                 {
       
   659                 aElementsFound |= 0x000000ff;
       
   660                 }
       
   661             else if (codeSegAddr == aSegAddr2 && StringsMatch(KCodeSegsName2(), codeSegName))
       
   662                 {
       
   663                 aElementsFound |= 0x0000ff00;
       
   664                 }
       
   665             }
       
   666         }
       
   667     else if (aSubCategory == BTrace::ECodeSegInfo)
       
   668         {
       
   669         codeSegAddr = Swap(ReadUint32FromBuf(aBuffer, aFromTestWriter));
       
   670         if (codeSegAddr == aSegAddr1)
       
   671             {
       
   672             aElementsFound |= 0x00ff0000;
       
   673             }
       
   674         else if (codeSegAddr == aSegAddr2)
       
   675             {
       
   676             aElementsFound |= 0xff000000;
       
   677             }
       
   678         }
       
   679     
       
   680     TInt err = KErrNotFound;
       
   681     if (aElementsFound == 0xffffffff)
       
   682         {
       
   683         err = KErrNone;
       
   684         }
       
   685     return err;
       
   686     }
       
   687 
       
   688 /*
       
   689  * Work out if a trace point is potentially kernel priming data based on category and subcategory
       
   690  *
       
   691  * @param aCategory BTrace category of the trace data
       
   692  * @param aSubCategory BTrace subcategory of the trace data
       
   693  * @param aIsPotentialPrimingTrace Output value set if there is no error
       
   694  * @return Standard Symbian error code
       
   695  */
       
   696 TBool TTraceDataParser::IsPotentialPrimingTrace(TUint8 aCategory, TUint8 aSubCategory, TBool& aIsPotentialPrimingTrace)
       
   697     {
       
   698     TInt err = KErrNone;
       
   699     
       
   700     switch(aCategory)
       
   701         {
       
   702         case BTrace::EThreadIdentification:
       
   703             {
       
   704             switch(aSubCategory)
       
   705                 {
       
   706                 case BTrace::EProcessCreate:
       
   707                 case BTrace::EProcessName:
       
   708                 case BTrace::EThreadName:
       
   709                 case BTrace::EThreadId:
       
   710                     aIsPotentialPrimingTrace = ETrue;
       
   711                     break;
       
   712                 default:
       
   713                     aIsPotentialPrimingTrace = EFalse;
       
   714                     break;
       
   715                 }
       
   716             }
       
   717             break;
       
   718         case BTrace::ECpuUsage:
       
   719             {
       
   720             switch(aSubCategory)
       
   721                 {
       
   722                 case BTrace::ENewThreadContext:
       
   723                     aIsPotentialPrimingTrace = ETrue;
       
   724                     break;
       
   725                 default:
       
   726                     aIsPotentialPrimingTrace = EFalse;
       
   727                     break;
       
   728                 }
       
   729             }
       
   730             break;
       
   731         case BTrace::EChunks:
       
   732             {
       
   733             switch(aSubCategory)
       
   734                 {
       
   735                 case BTrace::EChunkCreated:
       
   736                 case BTrace::EChunkOwner:
       
   737                 case BTrace::EChunkInfo:
       
   738                     aIsPotentialPrimingTrace = ETrue;
       
   739                     break;
       
   740                 default:
       
   741                     aIsPotentialPrimingTrace = EFalse;
       
   742                     break;
       
   743                 }
       
   744             }
       
   745             break;
       
   746         case BTrace::ECodeSegs:
       
   747             {
       
   748             switch(aSubCategory)
       
   749                 {
       
   750                 case BTrace::ECodeSegCreated:
       
   751                 case BTrace::ECodeSegInfo:
       
   752                     aIsPotentialPrimingTrace = ETrue;
       
   753                     break;
       
   754                 default:
       
   755                     aIsPotentialPrimingTrace = EFalse;
       
   756                     break;
       
   757                 }
       
   758             }
       
   759             break;
       
   760         case BTrace::EPaging:
       
   761             {
       
   762             switch(aSubCategory)
       
   763                 {
       
   764                 case BTrace::EPagingMemoryModel:
       
   765                     aIsPotentialPrimingTrace = ETrue;
       
   766                     break;
       
   767                 default:
       
   768                     aIsPotentialPrimingTrace = EFalse;
       
   769                     break;
       
   770                 }
       
   771             }
       
   772             break;
       
   773         case BTrace::EThreadPriority:
       
   774             {
       
   775             switch(aSubCategory)
       
   776                 {
       
   777                 case BTrace::EProcessPriority:
       
   778                 case BTrace::EDThreadPriority:
       
   779                 case BTrace::ENThreadPriority:
       
   780                     aIsPotentialPrimingTrace = ETrue;
       
   781                     break;
       
   782                 default:
       
   783                     aIsPotentialPrimingTrace = EFalse;
       
   784                     break;
       
   785                 }
       
   786             }
       
   787             break;
       
   788         case BTrace::EFastMutex:
       
   789             {
       
   790             switch(aSubCategory)
       
   791                 {
       
   792                 case BTrace::EFastMutexName:
       
   793                     aIsPotentialPrimingTrace = ETrue;
       
   794                     break;
       
   795                 default:
       
   796                     aIsPotentialPrimingTrace = EFalse;
       
   797                     break;
       
   798                 }
       
   799             }
       
   800             break;
       
   801         case BTrace::ESymbianKernelSync:
       
   802             {
       
   803             switch(aSubCategory)
       
   804                 {
       
   805                 case BTrace::EMutexCreate:
       
   806                 case BTrace::ESemaphoreCreate:
       
   807                 case BTrace::ECondVarCreate:
       
   808                     aIsPotentialPrimingTrace = ETrue;
       
   809                     break;
       
   810                 default:
       
   811                     aIsPotentialPrimingTrace = EFalse;
       
   812                     break;
       
   813                 }
       
   814             }
       
   815             break;
       
   816         case BTrace::EClientServer:
       
   817             {
       
   818             switch(aSubCategory)
       
   819                 {
       
   820                 case BTrace::EServerCreate:
       
   821                 case BTrace::ESessionAttach:
       
   822                     aIsPotentialPrimingTrace = ETrue;
       
   823                     break;
       
   824                 default:
       
   825                     aIsPotentialPrimingTrace = EFalse;
       
   826                     break;
       
   827                 }
       
   828             }
       
   829             break;
       
   830         default:
       
   831             err = KErrNotSupported;
       
   832             break;
       
   833         }
       
   834     
       
   835     return err;
       
   836     }
       
   837 
       
   838 /*
       
   839  * If the next trace is a meta trace true is returned if it is the start of priming data for a given group ID
       
   840  *
       
   841  * @param aBuffer Buffer containing the trace data
       
   842  * @param aGroupId Group ID of kernel priming data
       
   843  * @param aCategory BTrace category of the current trace
       
   844  * @param aSubCategory BTrace subcategory of the current trace
       
   845  * @return True if start of priming data for given group ID, false otherwise
       
   846  */
       
   847 TBool TTraceDataParser::IsStartOfKernelPrimingBatch(TUint8* aBuffer, TGroupId aGroupId, TUint8 aCategory, TUint8 aSubCategory)
       
   848     {
       
   849     TBool startOfBatch = EFalse;
       
   850     if (aCategory == BTrace::EMetaTrace)
       
   851         {
       
   852         if (aSubCategory == BTrace::EMetaTraceFilterChange)
       
   853             {
       
   854             TUint8 metaCategory = aBuffer[0];
       
   855             TUint8 isActive = aBuffer[1];
       
   856             if (metaCategory == aGroupId && isActive)
       
   857                 {
       
   858                 startOfBatch = ETrue;
       
   859                 }
       
   860             }        
       
   861         }
       
   862     return startOfBatch;
       
   863     }
       
   864 
       
   865 /*
       
   866  * Use heuristics to work out if current trace is part of kernel priming data
       
   867  *
       
   868  * @param aCategory BTrace category of the trace data
       
   869  * @param aSubCategory BTrace subcategory of the trace data
       
   870  * @param aTimeDifference Time difference (in microseconds) since last trace for given category
       
   871  * @param aIsInPrimingBatch Output parameter set to true if in priming data
       
   872  * @param aFirstTrace Boolean used to indicate if this is first trace (so there is no valid time difference)
       
   873  * @param aStartOfBatch Output parameter set to true if start of batch of kernel priming data
       
   874  * @return Standard Symbian error code
       
   875  */
       
   876 TInt TTraceDataParser::IsInPrimingBatch(TUint8  aCategory, 
       
   877                                         TUint8  aSubCategory, 
       
   878                                         TUint32 aTimeDifference, 
       
   879                                         TBool&  aIsInPrimingBatch, 
       
   880                                         TBool&  aFirstTrace, 
       
   881                                         TBool&  aStartOfBatch)
       
   882     {
       
   883     TBool isPotentialPrimingTrace = EFalse;
       
   884     TInt err = IsPotentialPrimingTrace(aCategory, aSubCategory, isPotentialPrimingTrace);
       
   885     
       
   886     // Look at timestamp to see if this is a new batch of traces
       
   887     if (aFirstTrace)
       
   888         {
       
   889         aFirstTrace = EFalse;
       
   890         }
       
   891     else if (aTimeDifference > KMinMilliSecondsBatchGap * 1000)
       
   892         {
       
   893         aStartOfBatch = ETrue;
       
   894         aIsInPrimingBatch = EFalse;
       
   895         }
       
   896     else
       
   897         {
       
   898         aStartOfBatch = EFalse;
       
   899         }
       
   900     
       
   901     if (isPotentialPrimingTrace && aStartOfBatch)
       
   902         {
       
   903         aIsInPrimingBatch = ETrue;
       
   904         aStartOfBatch = EFalse;
       
   905         }
       
   906     else if (!isPotentialPrimingTrace)
       
   907         {
       
   908         aIsInPrimingBatch = EFalse;
       
   909         }
       
   910     
       
   911     return err;
       
   912     }
       
   913 
       
   914 /*
       
   915  * Parse the trace data header
       
   916  * 
       
   917  * The following trace types are supported:
       
   918  *     OST traces (ascii and binary)
       
   919  *     XTIv3 traces (ascii and binary)
       
   920  *     Traces from the Test Writer (ascii and binary)
       
   921  *
       
   922  * @param aData Buffer containing the trace data
       
   923  * @param aSize Size of trace data buffer
       
   924  * @param aTraceHeaderSettings Output parameters set to header settings of the trace data
       
   925  * @return Standard Symbian error code
       
   926  */
       
   927 TInt TTraceDataParser::ParseHeader(TUint8*&                 aData, 
       
   928                                    TInt                     aSize, 
       
   929                                    TTraceHeaderSettings&    aTraceHeaderSettings)
       
   930     {
       
   931     // Check buffer is large enough to contain header
       
   932     aSize--;
       
   933     if (aSize < 0)
       
   934         {
       
   935         return KErrOverflow;
       
   936         }
       
   937     
       
   938     TInt err = KErrNone;    
       
   939     TUint8* startOfData = aData;
       
   940     aTraceHeaderSettings.iMultiPartType = 0;
       
   941     aTraceHeaderSettings.iMultiPartTraceID = 0;
       
   942     aTraceHeaderSettings.iPrintfTrace = EFalse;
       
   943     aTraceHeaderSettings.iHeaderFlags = EFalse;
       
   944     aTraceHeaderSettings.iFromTestWriter = EFalse;
       
   945     TBool xtiTrace = EFalse;
       
   946     TUint8 version = aData[0];                        // Version (1 byte)
       
   947     aData++;
       
   948     
       
   949     if (version == KXtiHeaderVersion)
       
   950         {
       
   951         // Check buffer is large enough to contain header
       
   952         aSize -= KMinSizeXtiHeader;
       
   953         if (aSize < 0)
       
   954             {
       
   955             aData = startOfData;
       
   956             return KErrOverflow;
       
   957             }
       
   958         xtiTrace = ETrue;
       
   959         TUint8 xtiTraceType = aData[KXtiTraceTypeIndex-1];
       
   960         if (xtiTraceType != KXtiProtocolIdSimpleTrace)
       
   961             {
       
   962             aTraceHeaderSettings.iPrintfTrace = ETrue;
       
   963             aTraceHeaderSettings.iLengthOfPayload = aData[KXtiLengthIndex-1] - 15;
       
   964             aData += KMinSizeXtiHeader;
       
   965             }
       
   966         else
       
   967             {
       
   968             // Check buffer is large enough to contain header
       
   969             aSize -= 1;
       
   970             if (aSize < 0)
       
   971                 {
       
   972                 aData = startOfData;
       
   973                 return KErrOverflow;
       
   974                 }
       
   975             // Jump to start of OST buffer
       
   976             aData += KMinSizeXtiHeader + 1;
       
   977             version = aData[0];
       
   978             aData++;
       
   979             }
       
   980         }
       
   981     
       
   982     if (version == KHeaderVersion) // Ost header version byte is correct
       
   983         {
       
   984         // Check buffer is large enough to contain header
       
   985         aSize -= KMinSizeOstHeader;
       
   986         if (aSize < 0)
       
   987             {
       
   988             aData = startOfData;
       
   989             return KErrOverflow;
       
   990             }
       
   991         const TUint8 protocolId = aData[0];                 // Protocol ID (1 byte)
       
   992         aData++;
       
   993         if (xtiTrace)
       
   994             {
       
   995             aTraceHeaderSettings.iLengthOfPayload = aData[0];
       
   996             aData++;
       
   997             aSize++;
       
   998             }
       
   999         else
       
  1000             {
       
  1001             aTraceHeaderSettings.iLengthOfPayload = ReadUint16FromBuf(aData);        // Size (2 bytes)
       
  1002             }
       
  1003     
       
  1004         if (protocolId == KProtocolIdSimpleTrace) // Normal binary data
       
  1005             {
       
  1006             // Check buffer is large enough to contain header
       
  1007             aSize -= KMinSizeOstBinaryHeader;
       
  1008             if (aSize < 0)
       
  1009                 {
       
  1010                 aData = startOfData;
       
  1011                 return KErrOverflow;
       
  1012                 }
       
  1013             ReadUint32FromBuf(aData);                       // Timestamp 1 (4 bytes)
       
  1014             aTraceHeaderSettings.iTimestamp = ReadUint32FromBuf(aData);          // Timestamp 2 (4 bytes)
       
  1015             }
       
  1016         else if (protocolId == KProtocolIdAscii) // Ascii Printf data
       
  1017             {
       
  1018             aTraceHeaderSettings.iPrintfTrace = ETrue;
       
  1019             // Check buffer is large enough to contain header
       
  1020             aSize -= KMinSizeOstAsciiHeader;
       
  1021             if (aSize < 0)
       
  1022                 {
       
  1023                 aData = startOfData;
       
  1024                 return KErrOverflow;
       
  1025                 }
       
  1026             aData += 8;
       
  1027             aTraceHeaderSettings.iLengthOfPayload -= 8;
       
  1028             }
       
  1029         else // Protocol ID is incorrect
       
  1030             {
       
  1031             err = KErrCorrupt;
       
  1032             }
       
  1033         }
       
  1034     else if (version == SYMBIAN_TRACE) // Trace data is binary data from Test Writer
       
  1035         {
       
  1036         aTraceHeaderSettings.iFromTestWriter = ETrue;
       
  1037         }
       
  1038     else if (version == PRINTF_TRACE) // Trace data is ascii data from Test Writer
       
  1039         {
       
  1040         aTraceHeaderSettings.iFromTestWriter = ETrue;
       
  1041         aTraceHeaderSettings.iPrintfTrace = ETrue;
       
  1042         // The end of the printf trace data will have null char, so use that to find end of payload
       
  1043         TPtr8 printfString(aData, aSize, aSize);
       
  1044         aTraceHeaderSettings.iLengthOfPayload = printfString.Locate(TChar(0));
       
  1045         if (aTraceHeaderSettings.iLengthOfPayload >= 0)
       
  1046             {
       
  1047             aTraceHeaderSettings.iLengthOfPayload++;
       
  1048             }
       
  1049         else
       
  1050             {
       
  1051             err = KErrCorrupt;
       
  1052             }
       
  1053         }
       
  1054     else if (version != KXtiHeaderVersion)
       
  1055         {
       
  1056         err = KErrCorrupt;
       
  1057         
       
  1058         if(aTraceHeaderSettings.iLengthOfPayload < 0 )
       
  1059             {
       
  1060             err = KErrOverflow;
       
  1061             }
       
  1062         }
       
  1063               
       
  1064     if (aTraceHeaderSettings.iPrintfTrace)
       
  1065         {
       
  1066         aTraceHeaderSettings.iTimestamp = 0;
       
  1067         aTraceHeaderSettings.iComponentID = 0;
       
  1068         aTraceHeaderSettings.iCategory = 0;
       
  1069         aTraceHeaderSettings.iSubCategory = 0;
       
  1070         aTraceHeaderSettings.iTraceWord = 0;
       
  1071         }
       
  1072     else if (err == KErrNone)
       
  1073         {
       
  1074         // Check buffer is large enough to contain header
       
  1075         aSize -= KMinSizeBinaryHeader;
       
  1076         if (aSize < 0)
       
  1077             {
       
  1078             aData = startOfData;
       
  1079             return KErrOverflow;
       
  1080             }
       
  1081         aTraceHeaderSettings.iComponentID = ReadUint32FromBuf(aData, aTraceHeaderSettings.iFromTestWriter);    // ComponentId (4 bytes)
       
  1082         aTraceHeaderSettings.iTraceWord = ReadUint32FromBuf(aData, aTraceHeaderSettings.iFromTestWriter);      // GroupId (2 bytes). TraceId (2 bytes)
       
  1083         
       
  1084         TUint8* startOfPayload = aData;
       
  1085         TUint8 size;
       
  1086         
       
  1087         TBool testWriterHwData = EFalse;
       
  1088 #ifndef __WINS__
       
  1089         testWriterHwData = aTraceHeaderSettings.iFromTestWriter;
       
  1090 #endif
       
  1091 
       
  1092         // now look at BTrace header and payload.
       
  1093         if (!testWriterHwData)
       
  1094             {
       
  1095             size = aData[BTrace::ESizeIndex];
       
  1096             aTraceHeaderSettings.iHeaderFlags = aData[BTrace::EFlagsIndex];
       
  1097             aTraceHeaderSettings.iCategory = aData[BTrace::ECategoryIndex];
       
  1098             aTraceHeaderSettings.iSubCategory = aData[BTrace::ESubCategoryIndex];
       
  1099             }
       
  1100         else
       
  1101             {
       
  1102             // endianess order is reversed for TestWriter on hw
       
  1103             aTraceHeaderSettings.iSubCategory = aData[BTrace::ESizeIndex];
       
  1104             aTraceHeaderSettings.iCategory = aData[BTrace::EFlagsIndex];
       
  1105             aTraceHeaderSettings.iHeaderFlags = aData[BTrace::ECategoryIndex];
       
  1106             size = aData[BTrace::ESubCategoryIndex];
       
  1107             }
       
  1108         
       
  1109         aData+=4;
       
  1110 
       
  1111         //read header extensions
       
  1112         if(aTraceHeaderSettings.iHeaderFlags & BTrace::EHeader2Present)
       
  1113             {
       
  1114             // Check buffer is large enough to contain header
       
  1115             aSize -= 4;
       
  1116             if (aSize < 0)
       
  1117                 {
       
  1118                 aData = startOfData;
       
  1119                 return KErrOverflow;
       
  1120                 }
       
  1121             TUint32 header2 = Swap(ReadUint32FromBuf(aData, aTraceHeaderSettings.iFromTestWriter));
       
  1122             aTraceHeaderSettings.iMultiPartType = header2 & BTrace::EMultipartFlagMask;
       
  1123             }
       
  1124         if(aTraceHeaderSettings.iHeaderFlags & BTrace::ETimestampPresent)
       
  1125             {
       
  1126             // Check buffer is large enough to contain header
       
  1127             aSize -= 4;
       
  1128             if (aSize < 0)
       
  1129                 {
       
  1130                 aData = startOfData;
       
  1131                 return KErrOverflow;
       
  1132                 }
       
  1133             ReadUint32FromBuf(aData, aTraceHeaderSettings.iFromTestWriter);
       
  1134             }
       
  1135         if(aTraceHeaderSettings.iHeaderFlags & BTrace::ETimestamp2Present)
       
  1136             {
       
  1137             // Check buffer is large enough to contain header
       
  1138             aSize -= 4;
       
  1139             if (aSize < 0)
       
  1140                 {
       
  1141                 aData = startOfData;
       
  1142                 return KErrOverflow;
       
  1143                 }
       
  1144             ReadUint32FromBuf(aData, aTraceHeaderSettings.iFromTestWriter);
       
  1145             }
       
  1146         if(aTraceHeaderSettings.iHeaderFlags & BTrace::EContextIdPresent)
       
  1147             {
       
  1148             // Check buffer is large enough to contain header
       
  1149             aSize -= 4;
       
  1150             if (aSize < 0)
       
  1151                 {
       
  1152                 aData = startOfData;
       
  1153                 return KErrOverflow;
       
  1154                 }
       
  1155             ReadUint32FromBuf(aData, aTraceHeaderSettings.iFromTestWriter);
       
  1156             }
       
  1157         if(aTraceHeaderSettings.iHeaderFlags & BTrace::EPcPresent)
       
  1158             {
       
  1159             // Check buffer is large enough to contain header
       
  1160             aSize -= 4;
       
  1161             if (aSize < 0)
       
  1162                 {
       
  1163                 aData = startOfData;
       
  1164                 return KErrOverflow;
       
  1165                 }
       
  1166             ReadUint32FromBuf(aData, aTraceHeaderSettings.iFromTestWriter);
       
  1167             }
       
  1168         if(aTraceHeaderSettings.iHeaderFlags & BTrace::EExtraPresent)
       
  1169             {
       
  1170             // Check buffer is large enough to contain header
       
  1171             aSize -=4 ;
       
  1172             if (aSize < 0)
       
  1173                 {
       
  1174                 aData = startOfData;
       
  1175                 return KErrOverflow;
       
  1176                 }
       
  1177             aTraceHeaderSettings.iMultiPartTraceID = Swap(ReadUint32FromBuf(aData, aTraceHeaderSettings.iFromTestWriter));
       
  1178             }
       
  1179 
       
  1180         if (!xtiTrace)
       
  1181             {
       
  1182             size = (size+3)&~3;  // make it 4 byte aligned
       
  1183             }
       
  1184         if (size == 0)
       
  1185             {
       
  1186             // This happens when the trace is larger than maximum size, and we can't use the BTrace size field
       
  1187             // Instead calculate payload length based on size in OST header
       
  1188             aTraceHeaderSettings.iLengthOfPayload -= (aData-startOfPayload)+16; // size of rest of payload
       
  1189             }
       
  1190         else
       
  1191             {
       
  1192             aTraceHeaderSettings.iLengthOfPayload = size-(aData-startOfPayload); // size of rest of payload
       
  1193             }
       
  1194         }
       
  1195 
       
  1196     
       
  1197     // Check buffer is large enough to contain payload
       
  1198     aSize -= aTraceHeaderSettings.iLengthOfPayload;
       
  1199     if (aSize < 0)
       
  1200         {
       
  1201         aData = startOfData;
       
  1202         err = KErrOverflow;
       
  1203         }
       
  1204     
       
  1205     return err;
       
  1206     }
       
  1207 
       
  1208 /*
       
  1209  * Get the data required to verify kernel priming traces for EThreadIdentification
       
  1210  *
       
  1211  * @param aBuffer Buffer containing the trace data
       
  1212  * @param aSize Size of the trace buffer
       
  1213  * @param aThreadAddr Output parameter set to address of current thread
       
  1214  * @param aProcessAddr Output parameter set to address of current process
       
  1215  * @return Standard Symbian error code
       
  1216  */
       
  1217 TInt TTraceDataParser::GetThreadPrimingVerificationDataL(TUint8*     aBuffer, 
       
  1218                                                          TInt        aSize, 
       
  1219                                                          TUint32&    aThreadAddr, 
       
  1220                                                          TUint32&    aProcessAddr,
       
  1221                                                          RFile*      aFile)
       
  1222     {
       
  1223     TInt    err = KErrNone;
       
  1224     TInt    filePos = 0;
       
  1225     TUint8* data = NULL;
       
  1226     TUint8* startOfData = NULL;
       
  1227     TUint8* endOfData = NULL;    
       
  1228     RBuf8   fileBuffer;
       
  1229     
       
  1230     if (aFile)
       
  1231         {
       
  1232         // Create file buffer and read first chunk from file
       
  1233         err = CreateFileBuffer(fileBuffer, *aFile);
       
  1234         if (err != KErrNone)
       
  1235             {
       
  1236             return err;
       
  1237             }
       
  1238         fileBuffer.CleanupClosePushL();
       
  1239         err = ReadNextChunkFromFile(fileBuffer, *aFile, filePos, data, startOfData, endOfData);
       
  1240         if (err != KErrNone)
       
  1241             {
       
  1242             CleanupStack::PopAndDestroy(&fileBuffer); // close file buffer
       
  1243             return err;
       
  1244             }
       
  1245         }
       
  1246     else
       
  1247         {
       
  1248         data = aBuffer;
       
  1249         startOfData = data;
       
  1250         endOfData = data + aSize;
       
  1251         }
       
  1252     
       
  1253     TInt            headerErr = KErrNone; 
       
  1254     RThread         currentThread;            
       
  1255     TUint32         tempThreadAddr;
       
  1256     TUint32         tempProcessAddr;
       
  1257     TThreadId       threadid = 0;
       
  1258 
       
  1259     TTraceHeaderSettings  traceHeaderSettings;
       
  1260 
       
  1261     err = KErrGeneral;
       
  1262     
       
  1263     while(data < endOfData)
       
  1264         {
       
  1265         headerErr = ParseHeader(data, endOfData-data, traceHeaderSettings);
       
  1266         
       
  1267         if (aFile && headerErr == KErrOverflow)
       
  1268             {
       
  1269             // We don't have all the trace data, so read next chunk from file
       
  1270             headerErr = ReadNextChunkFromFile(fileBuffer, *aFile, filePos, data, startOfData, endOfData);
       
  1271             if (headerErr == KErrNone)
       
  1272                 {
       
  1273                 continue;
       
  1274                 }
       
  1275             }
       
  1276         if (headerErr != KErrNone)
       
  1277             {
       
  1278             err = headerErr;
       
  1279             break;
       
  1280             }
       
  1281         if ( (traceHeaderSettings.iCategory == BTrace::EThreadIdentification) && (traceHeaderSettings.iSubCategory == BTrace::EThreadId) )
       
  1282             {
       
  1283             tempThreadAddr = Swap(ReadUint32FromBuf(data, traceHeaderSettings.iFromTestWriter));
       
  1284             tempProcessAddr = Swap(ReadUint32FromBuf(data, traceHeaderSettings.iFromTestWriter));
       
  1285             threadid = Swap(ReadUint32FromBuf(data, traceHeaderSettings.iFromTestWriter));
       
  1286             if (currentThread.Id() == threadid)
       
  1287                 {
       
  1288                 aThreadAddr = tempThreadAddr;
       
  1289                 aProcessAddr = tempProcessAddr;
       
  1290                 err = KErrNone;
       
  1291                 break;
       
  1292                 }
       
  1293             }
       
  1294         else
       
  1295             {
       
  1296             data += traceHeaderSettings.iLengthOfPayload; //go to next trace
       
  1297             }
       
  1298 
       
  1299         if (aFile && data == endOfData)
       
  1300             {
       
  1301             // We might not have all the trace data, so read next chunk from file
       
  1302             headerErr = ReadNextChunkFromFile(fileBuffer, *aFile, filePos, data, startOfData, endOfData);
       
  1303             if (headerErr != KErrNone)
       
  1304                 {
       
  1305                 err = headerErr;
       
  1306                 break;
       
  1307                 }
       
  1308             }
       
  1309         }
       
  1310 
       
  1311     if (aFile)
       
  1312         {
       
  1313         CleanupStack::PopAndDestroy(&fileBuffer); // close file buffer
       
  1314         }
       
  1315 
       
  1316     return err;
       
  1317     }
       
  1318 
       
  1319 
       
  1320 /*
       
  1321  * Get the data required to verify kernel priming traces for ECodeSegs
       
  1322  *
       
  1323  * @param aBuffer Buffer containing the trace data
       
  1324  * @param aSize Size of the trace buffer
       
  1325  * @param aSegAddr1 Output parameter set to address of first code seg
       
  1326  * @param aSegAddr2 Output parameter set to address of second code seg
       
  1327  * @return Standard Symbian error code
       
  1328  */
       
  1329 TInt TTraceDataParser::GetCodeSegsVerificationDataL(TUint8*  aBuffer, 
       
  1330                                                     TInt     aSize, 
       
  1331                                                     TUint32& aSegAddr1, 
       
  1332                                                     TUint32& aSegAddr2,
       
  1333                                                     RFile*   aFile)
       
  1334     {
       
  1335     TInt    err = KErrNone;
       
  1336     TInt    filePos = 0;
       
  1337     TUint8* data = NULL;
       
  1338     TUint8* startOfData = NULL;
       
  1339     TUint8* endOfData = NULL;    
       
  1340     RBuf8   fileBuffer;
       
  1341     
       
  1342     if (aFile)
       
  1343         {
       
  1344         // Create file buffer and read first chunk from file
       
  1345         err = CreateFileBuffer(fileBuffer, *aFile);
       
  1346         if (err != KErrNone)
       
  1347             {
       
  1348             return err;
       
  1349             }
       
  1350         fileBuffer.CleanupClosePushL();
       
  1351         err = ReadNextChunkFromFile(fileBuffer, *aFile, filePos, data, startOfData, endOfData);
       
  1352         if (err != KErrNone)
       
  1353             {
       
  1354             CleanupStack::PopAndDestroy(&fileBuffer); // close file buffer
       
  1355             return err;
       
  1356             }
       
  1357         }
       
  1358     else
       
  1359         {
       
  1360         data = aBuffer;
       
  1361         startOfData = data;
       
  1362         endOfData = data + aSize;
       
  1363         }
       
  1364     
       
  1365     TInt            headerErr = KErrNone; 
       
  1366     TUint32         tempSegAddr;
       
  1367 
       
  1368     TTraceHeaderSettings  traceHeaderSettings;
       
  1369 
       
  1370     err = KErrGeneral;
       
  1371     
       
  1372     while(data < endOfData)
       
  1373         {
       
  1374         headerErr = ParseHeader(data, endOfData-data, traceHeaderSettings);
       
  1375         
       
  1376         if (aFile && headerErr == KErrOverflow)
       
  1377             {
       
  1378             // We don't have all the trace data, so read next chunk from file
       
  1379             headerErr = ReadNextChunkFromFile(fileBuffer, *aFile, filePos, data, startOfData, endOfData);
       
  1380             if (headerErr == KErrNone)
       
  1381                 {
       
  1382                 continue;
       
  1383                 }
       
  1384             }
       
  1385         if (headerErr != KErrNone)
       
  1386             {
       
  1387             err = headerErr;
       
  1388             break;
       
  1389             }
       
  1390         if ( (traceHeaderSettings.iCategory == BTrace::ECodeSegs) && (traceHeaderSettings.iSubCategory == BTrace::ECodeSegCreated) )
       
  1391             {
       
  1392             tempSegAddr = Swap(ReadUint32FromBuf(data, traceHeaderSettings.iFromTestWriter));
       
  1393             traceHeaderSettings.iLengthOfPayload -= 4;
       
  1394             TPtr8 codeSegName(data,traceHeaderSettings.iLengthOfPayload,traceHeaderSettings.iLengthOfPayload); //should be name of the code seg
       
  1395             codeSegName.Trim();
       
  1396             if (StringsMatch(KCodeSegsName1(), codeSegName))
       
  1397                 {
       
  1398                 aSegAddr1 = tempSegAddr;
       
  1399                 }
       
  1400             if (StringsMatch(KCodeSegsName2(), codeSegName))
       
  1401                 {
       
  1402                 aSegAddr2 = tempSegAddr;
       
  1403                 }
       
  1404             if (aSegAddr1 != 0 && aSegAddr2 != 0)
       
  1405                 {
       
  1406                 err = KErrNone;
       
  1407                 break;
       
  1408                 }
       
  1409             }
       
  1410 
       
  1411         data += traceHeaderSettings.iLengthOfPayload; //go to next trace
       
  1412 
       
  1413         if (aFile && data == endOfData)
       
  1414             {
       
  1415             // We might not have all the trace data, so read next chunk from file
       
  1416             headerErr = ReadNextChunkFromFile(fileBuffer, *aFile, filePos, data, startOfData, endOfData);
       
  1417             if (headerErr != KErrNone)
       
  1418                 {
       
  1419                 err = headerErr;
       
  1420                 break;
       
  1421                 }
       
  1422             }
       
  1423         }
       
  1424 
       
  1425     if (aFile)
       
  1426         {
       
  1427         CleanupStack::PopAndDestroy(&fileBuffer); // close file buffer
       
  1428         }
       
  1429     
       
  1430     return err;
       
  1431     }
       
  1432 
       
  1433 /*
       
  1434  * Get the data required to verify kernel priming traces
       
  1435  *
       
  1436  * @param aBuffer Buffer containing the trace data
       
  1437  * @param aSize Size of the trace buffer
       
  1438  * @param aGroupId Group ID of traces
       
  1439  * @param aVerificationData1 Output parameter set to first data required
       
  1440  * @param aVerificationData2 Output parameter set to second data required
       
  1441  * @return Standard Symbian error code
       
  1442  */
       
  1443 TInt TTraceDataParser::GetPrimingVerificationDataL(TUint8*  aBuffer, 
       
  1444                                                    TInt     aSize, 
       
  1445                                                    TGroupId aGroupId, 
       
  1446                                                    TUint32& aVerificationData1, 
       
  1447                                                    TUint32& aVerificationData2,
       
  1448                                                    RFile*   aFile)
       
  1449     {
       
  1450     TInt err = KErrNone;
       
  1451     switch(aGroupId)
       
  1452         {
       
  1453         case BTrace::EThreadIdentification:
       
  1454             err = GetThreadPrimingVerificationDataL(aBuffer, aSize, aVerificationData1, aVerificationData2, aFile);
       
  1455             break;
       
  1456         case BTrace::ECodeSegs:
       
  1457             err = GetCodeSegsVerificationDataL(aBuffer, aSize, aVerificationData1, aVerificationData2, aFile);
       
  1458             break;
       
  1459         default:
       
  1460             break;
       
  1461         }
       
  1462     return err;    
       
  1463     }
       
  1464 
       
  1465 /*
       
  1466  * Parse trace data for kernel priming data
       
  1467  * 
       
  1468  * Note that this function can only verify priming data if the group ID is EThreadIdentification or EFastMutex,
       
  1469  * otherwise KErrNotSupported is returned if aVerifyData is ETrue
       
  1470  *
       
  1471  * @param aBuffer Buffer containing the trace data
       
  1472  * @param aGroupId Group ID of traces to parse
       
  1473  * @param aNumPrimingTraces Output parameter set to number of priming traces found for given group ID
       
  1474  * @param aNumTraces Output parameter set to total number of traces found for given group ID
       
  1475  * @param aVerifyData Flag indicating if priming data should be verified
       
  1476  * @param aVerificationData1 Optional first data required for verifying priming data
       
  1477  * @param aVerificationData1 Optional second data required for verifying priming data
       
  1478  * @return Standard Symbian error code
       
  1479  */
       
  1480 EXPORT_C TInt TTraceDataParser::ParsePrimingDataL(TDesC8&        aBuffer, 
       
  1481                                                   TGroupId       aGroupId, 
       
  1482                                                   TInt&          aNumPrimingTraces, 
       
  1483                                                   TInt&          aNumTraces, 
       
  1484                                                   TBool          aVerifyData, 
       
  1485                                                   TUint32        aVerificationData1, 
       
  1486                                                   TUint32        aVerificationData2)
       
  1487     {
       
  1488     aNumPrimingTraces = 0;
       
  1489     aNumTraces = 0;
       
  1490 
       
  1491     TUint8*         data = (TUint8*) aBuffer.Ptr();
       
  1492     TUint8*         endOfData = data + aBuffer.Size();    
       
  1493     
       
  1494     // If the output data is to be verified but no verification data provided, try getting it automatically
       
  1495     if (aVerifyData && aVerificationData1 == 0 && aVerificationData2 == 0)
       
  1496         {
       
  1497         TInt err = GetPrimingVerificationDataL(data, endOfData-data, aGroupId, aVerificationData1, aVerificationData2);
       
  1498         if (err != KErrNone)
       
  1499             {
       
  1500             return err;
       
  1501             }
       
  1502         }
       
  1503     
       
  1504     TInt            returnErr = KErrNone;
       
  1505     TInt            dataVerificationErr = KErrNone;
       
  1506     TInt            generalErr = KErrNone;
       
  1507     TBool           firstTrace = ETrue;
       
  1508     TBool           startOfBatch = ETrue;
       
  1509     TBool           inPrimingData = EFalse;
       
  1510     TBool           useMetaTraces = EFalse;
       
  1511     TInt            numPotentialPrimingTraces = 0;
       
  1512     TUint32         lastTimestamp = 0;
       
  1513     TInt            elementsFound = 0;
       
  1514     
       
  1515     TTraceHeaderSettings  traceHeaderSettings;
       
  1516 
       
  1517     // Loop through all traces
       
  1518     while (data < endOfData)
       
  1519         {
       
  1520         // Get trace info from header
       
  1521         generalErr = ParseHeader(data, endOfData-data, traceHeaderSettings);
       
  1522         
       
  1523         if (generalErr != KErrNone)
       
  1524             {
       
  1525             if (returnErr == KErrNone)
       
  1526                 {
       
  1527                 // Set error to return, if this is first error so far
       
  1528                 returnErr = generalErr;
       
  1529                 }
       
  1530             break;
       
  1531             }
       
  1532 
       
  1533         // If this is a meta trace, work out if it signifies start of kernel priming data for GID of interest
       
  1534         if (traceHeaderSettings.iCategory == BTrace::EMetaTrace)
       
  1535             {
       
  1536             useMetaTraces = ETrue;
       
  1537             startOfBatch = IsStartOfKernelPrimingBatch(data, aGroupId, traceHeaderSettings.iCategory, traceHeaderSettings.iSubCategory);
       
  1538             }     
       
  1539         
       
  1540         // This is a trace of the correct GID/CID
       
  1541         if ( (traceHeaderSettings.iComponentID == KKernelHooksOSTComponentUID) && (traceHeaderSettings.iCategory == aGroupId) )
       
  1542             {
       
  1543             // Increase the number of traces for this GID
       
  1544             aNumTraces++;
       
  1545 
       
  1546             if (useMetaTraces)
       
  1547                 {
       
  1548                 // If data contains meta traces, work out if this is a priming trace
       
  1549                 if (startOfBatch)
       
  1550                     {
       
  1551                     // This is the start of a batch of priming traces
       
  1552                     inPrimingData = ETrue;
       
  1553                     startOfBatch = EFalse;
       
  1554                     }
       
  1555                 if (inPrimingData)
       
  1556                     {
       
  1557                     // This is a priming trace, so increase number found for this GID
       
  1558                     aNumPrimingTraces++; 
       
  1559                     // If data is to be verified, attempt the verification
       
  1560                     if (aVerifyData)
       
  1561                         {
       
  1562                         dataVerificationErr = VerifyPrimingData(data, traceHeaderSettings.iLengthOfPayload, traceHeaderSettings.iCategory, traceHeaderSettings.iSubCategory, elementsFound, traceHeaderSettings.iFromTestWriter, aVerificationData1, aVerificationData2);
       
  1563                         }
       
  1564                     }
       
  1565                 }
       
  1566             else
       
  1567                 {
       
  1568                 // If data contains no meta traces, work out if this is a priming trace using heuristics
       
  1569                 generalErr = IsInPrimingBatch(traceHeaderSettings.iCategory, traceHeaderSettings.iSubCategory, traceHeaderSettings.iTimestamp-lastTimestamp, inPrimingData, firstTrace, startOfBatch);
       
  1570                 if ( (generalErr != KErrNone) && (returnErr == KErrNone) )
       
  1571                     {
       
  1572                     // Set error to return, if this is first error so far
       
  1573                     returnErr = generalErr;
       
  1574                     }
       
  1575                 lastTimestamp = traceHeaderSettings.iTimestamp;
       
  1576                 if (inPrimingData)
       
  1577                     {
       
  1578                     // This is possibly a priming trace, so increase potential number found for this GID
       
  1579                     numPotentialPrimingTraces++;
       
  1580                     // If data is to be verified, attempt the verification
       
  1581                     if (aVerifyData)
       
  1582                         {
       
  1583                         dataVerificationErr = VerifyPrimingData(data, traceHeaderSettings.iLengthOfPayload, traceHeaderSettings.iCategory, traceHeaderSettings.iSubCategory, elementsFound, traceHeaderSettings.iFromTestWriter, aVerificationData1, aVerificationData2);
       
  1584                         }
       
  1585                     }
       
  1586                 else
       
  1587                     {
       
  1588                     // If we have enough potential priming traces, assume they are priming traces
       
  1589                     if (numPotentialPrimingTraces >= KMinimumPrimingTracesInBatch)
       
  1590                         {
       
  1591                         aNumPrimingTraces += numPotentialPrimingTraces;
       
  1592                         }
       
  1593                     numPotentialPrimingTraces = 0;
       
  1594                     }                
       
  1595                 }
       
  1596             }
       
  1597         else
       
  1598             {
       
  1599             // This is not a trace of the correct GID/CID
       
  1600             inPrimingData = EFalse;
       
  1601             }
       
  1602         
       
  1603         // Go to the next trace
       
  1604         data+=traceHeaderSettings.iLengthOfPayload;
       
  1605         }
       
  1606 
       
  1607     if (!useMetaTraces)
       
  1608         {
       
  1609         // If we have enough potential priming traces left over, assume they are priming traces
       
  1610         if (numPotentialPrimingTraces >= KMinimumPrimingTracesInBatch)
       
  1611             {
       
  1612             aNumPrimingTraces += numPotentialPrimingTraces;
       
  1613             }
       
  1614         }
       
  1615 
       
  1616     if ( (dataVerificationErr != KErrNone) && (returnErr == KErrNone) )
       
  1617         {
       
  1618         // Set error to return, if this is first error so far
       
  1619         returnErr = dataVerificationErr;
       
  1620         }
       
  1621     return returnErr;
       
  1622     }
       
  1623 
       
  1624 /*
       
  1625  * Parse trace data for kernel priming data
       
  1626  * 
       
  1627  * Note that this function can only verify priming data if the group ID is EThreadIdentification or EFastMutex,
       
  1628  * otherwise KErrNotSupported is returned if aVerifyData is ETrue
       
  1629  *
       
  1630  * @param aFilePath Full path of file containing the trace data
       
  1631  * @param aFs File system object
       
  1632  * @param aGroupId Group ID of traces to parse
       
  1633  * @param aNumPrimingTraces Output parameter set to number of priming traces found for given group ID
       
  1634  * @param aNumTraces Output parameter set to total number of traces found for given group ID
       
  1635  * @param aVerifyData Flag indicating if priming data should be verified
       
  1636  * @param aVerificationData1 Optional first data required for verifying priming data
       
  1637  * @param aVerificationData1 Optional second data required for verifying priming data
       
  1638  * @return Standard Symbian error code
       
  1639  */
       
  1640 EXPORT_C TInt TTraceDataParser::ParsePrimingDataL(const TDesC&   aFilePath,
       
  1641                                                   RFs&           aFs, 
       
  1642                                                   TGroupId       aGroupId, 
       
  1643                                                   TInt&          aNumPrimingTraces, 
       
  1644                                                   TInt&          aNumTraces, 
       
  1645                                                   TBool          aVerifyData, 
       
  1646                                                   TUint32        aVerificationData1, 
       
  1647                                                   TUint32        aVerificationData2)
       
  1648     {
       
  1649     aNumPrimingTraces = 0;
       
  1650     aNumTraces = 0;
       
  1651     
       
  1652     RFile file;
       
  1653 
       
  1654     // Open file with trace data
       
  1655     TInt err = file.Open(aFs, aFilePath, EFileRead|EFileShareAny);
       
  1656     if (err != KErrNone)
       
  1657         {
       
  1658         return err;
       
  1659         }
       
  1660     CleanupClosePushL(file);
       
  1661     
       
  1662     // If the output data is to be verified but no verification data provided, try getting it automatically
       
  1663     if (aVerifyData && aVerificationData1 == 0 && aVerificationData2 == 0)
       
  1664         {
       
  1665         err = GetPrimingVerificationDataL(NULL, 0, aGroupId, aVerificationData1, aVerificationData2, &file);
       
  1666         if (err != KErrNone)
       
  1667             {
       
  1668             CleanupStack::PopAndDestroy(&file); // close file
       
  1669             return err;
       
  1670             }
       
  1671         }
       
  1672     
       
  1673     RBuf8   fileBuffer;
       
  1674     TInt    filePos = 0;
       
  1675     
       
  1676     // Create file buffer and read first chunk from file
       
  1677     err = CreateFileBuffer(fileBuffer, file);
       
  1678     if (err != KErrNone)
       
  1679         {
       
  1680         CleanupStack::PopAndDestroy(&file); // close file
       
  1681         return err;
       
  1682         }
       
  1683     fileBuffer.CleanupClosePushL();
       
  1684     
       
  1685     TUint8* data = NULL;
       
  1686     TUint8* startOfData = NULL;
       
  1687     TUint8* endOfData = NULL;    
       
  1688 
       
  1689     err = ReadNextChunkFromFile(fileBuffer, file, filePos, data, startOfData, endOfData);
       
  1690     if (err != KErrNone)
       
  1691         {
       
  1692         CleanupStack::PopAndDestroy(&fileBuffer); // close file buffer
       
  1693         CleanupStack::PopAndDestroy(&file); // close file
       
  1694         return err;
       
  1695         }
       
  1696 
       
  1697     TInt            dataVerificationErr = KErrNone;
       
  1698     TInt            generalErr = KErrNone;
       
  1699     TBool           firstTrace = ETrue;
       
  1700     TBool           startOfBatch = ETrue;
       
  1701     TBool           inPrimingData = EFalse;
       
  1702     TBool           useMetaTraces = EFalse;
       
  1703     TInt            numPotentialPrimingTraces = 0;
       
  1704     TUint32         lastTimestamp = 0;
       
  1705     TInt            elementsFound = 0;
       
  1706     
       
  1707     TTraceHeaderSettings  traceHeaderSettings;
       
  1708 
       
  1709     // Loop through all traces
       
  1710     while (data < endOfData)
       
  1711         {
       
  1712         // Get trace info from header
       
  1713         generalErr = ParseHeader(data, endOfData-data, traceHeaderSettings);
       
  1714         
       
  1715         if (generalErr == KErrOverflow)
       
  1716             {
       
  1717             // We don't have all the trace data, so read next chunk from file
       
  1718             generalErr = ReadNextChunkFromFile(fileBuffer, file, filePos, data, startOfData, endOfData);
       
  1719             if (generalErr == KErrNone)
       
  1720                 {
       
  1721                 continue;
       
  1722                 }
       
  1723             }
       
  1724         if (generalErr != KErrNone)
       
  1725             {
       
  1726             if (err == KErrNone)
       
  1727                 {
       
  1728                 // Set error to return, if this is first error so far
       
  1729                 err = generalErr;
       
  1730                 }
       
  1731             break;
       
  1732             }
       
  1733 
       
  1734         // If this is a meta trace, work out if it signifies start of kernel priming data for GID of interest
       
  1735         if (traceHeaderSettings.iCategory == BTrace::EMetaTrace)
       
  1736             {
       
  1737             useMetaTraces = ETrue;
       
  1738             startOfBatch = IsStartOfKernelPrimingBatch(data, aGroupId, traceHeaderSettings.iCategory, traceHeaderSettings.iSubCategory);
       
  1739             }     
       
  1740         
       
  1741         // This is a trace of the correct GID/CID
       
  1742         if ( (traceHeaderSettings.iComponentID == KKernelHooksOSTComponentUID) && (traceHeaderSettings.iCategory == aGroupId) )
       
  1743             {
       
  1744             // Increase the number of traces for this GID
       
  1745             aNumTraces++;
       
  1746 
       
  1747             if (useMetaTraces)
       
  1748                 {
       
  1749                 // If data contains meta traces, work out if this is a priming trace
       
  1750                 if (startOfBatch)
       
  1751                     {
       
  1752                     // This is the start of a batch of priming traces
       
  1753                     inPrimingData = ETrue;
       
  1754                     startOfBatch = EFalse;
       
  1755                     }
       
  1756                 if (inPrimingData)
       
  1757                     {
       
  1758                     // This is a priming trace, so increase number found for this GID
       
  1759                     aNumPrimingTraces++; 
       
  1760                     // If data is to be verified, attempt the verification
       
  1761                     if (aVerifyData)
       
  1762                         {
       
  1763                         dataVerificationErr = VerifyPrimingData(data, traceHeaderSettings.iLengthOfPayload, traceHeaderSettings.iCategory, traceHeaderSettings.iSubCategory, elementsFound, traceHeaderSettings.iFromTestWriter, aVerificationData1, aVerificationData2);
       
  1764                         }
       
  1765                     }
       
  1766                 }
       
  1767             else
       
  1768                 {
       
  1769                 // If data contains no meta traces, work out if this is a priming trace using heuristics
       
  1770                 generalErr = IsInPrimingBatch(traceHeaderSettings.iCategory, traceHeaderSettings.iSubCategory, traceHeaderSettings.iTimestamp-lastTimestamp, inPrimingData, firstTrace, startOfBatch);
       
  1771                 if ( (generalErr != KErrNone) && (err == KErrNone) )
       
  1772                     {
       
  1773                     // Set error to return, if this is first error so far
       
  1774                     err = generalErr;
       
  1775                     }
       
  1776                 lastTimestamp = traceHeaderSettings.iTimestamp;
       
  1777                 if (inPrimingData)
       
  1778                     {
       
  1779                     // This is possibly a priming trace, so increase potential number found for this GID
       
  1780                     numPotentialPrimingTraces++;
       
  1781                     // If data is to be verified, attempt the verification
       
  1782                     if (aVerifyData)
       
  1783                         {
       
  1784                         dataVerificationErr = VerifyPrimingData(data, traceHeaderSettings.iLengthOfPayload, traceHeaderSettings.iCategory, traceHeaderSettings.iSubCategory, elementsFound, traceHeaderSettings.iFromTestWriter, aVerificationData1, aVerificationData2);
       
  1785                         }
       
  1786                     }
       
  1787                 else
       
  1788                     {
       
  1789                     // If we have enough potential priming traces, assume they are priming traces
       
  1790                     if (numPotentialPrimingTraces >= KMinimumPrimingTracesInBatch)
       
  1791                         {
       
  1792                         aNumPrimingTraces += numPotentialPrimingTraces;
       
  1793                         }
       
  1794                     numPotentialPrimingTraces = 0;
       
  1795                     }                
       
  1796                 }
       
  1797             }
       
  1798         else
       
  1799             {
       
  1800             // This is not a trace of the correct GID/CID
       
  1801             inPrimingData = EFalse;
       
  1802             }
       
  1803         
       
  1804         // Go to the next trace
       
  1805         data+=traceHeaderSettings.iLengthOfPayload;
       
  1806 
       
  1807         if (data == endOfData)
       
  1808             {
       
  1809             // We might not have all the trace data, so read next chunk from file
       
  1810             generalErr = ReadNextChunkFromFile(fileBuffer, file, filePos, data, startOfData, endOfData);
       
  1811             if (generalErr != KErrNone)
       
  1812                 {
       
  1813                 if (err == KErrNone)
       
  1814                     {
       
  1815                     // Set error to return, if this is first error so far
       
  1816                     err = generalErr;
       
  1817                     }
       
  1818                 break;
       
  1819                 }
       
  1820             }
       
  1821         }
       
  1822 
       
  1823     if (!useMetaTraces)
       
  1824         {
       
  1825         // If we have enough potential priming traces left over, assume they are priming traces
       
  1826         if (numPotentialPrimingTraces >= KMinimumPrimingTracesInBatch)
       
  1827             {
       
  1828             aNumPrimingTraces += numPotentialPrimingTraces;
       
  1829             }
       
  1830         }
       
  1831 
       
  1832     if ( (dataVerificationErr != KErrNone) && (err == KErrNone) )
       
  1833         {
       
  1834         // Set error to return, if this is first error so far
       
  1835         err = dataVerificationErr;
       
  1836         }
       
  1837 
       
  1838     CleanupStack::PopAndDestroy(&fileBuffer); // close file buffer
       
  1839     CleanupStack::PopAndDestroy(&file); // close file
       
  1840 
       
  1841     return err;
       
  1842     }
       
  1843 
       
  1844 TInt TTraceDataParser::CreateFileBuffer(RBuf8&  aFileBuffer, 
       
  1845                                         RFile&  aFile)
       
  1846     {
       
  1847     TInt fileSize;
       
  1848     TInt err = aFile.Size(fileSize);
       
  1849     if (err == KErrNone)
       
  1850         {
       
  1851         if (fileSize < KFileBufferSize)
       
  1852             {
       
  1853             err = aFileBuffer.Create(fileSize);
       
  1854             }
       
  1855         else
       
  1856             {
       
  1857             err = aFileBuffer.Create(KFileBufferSize);
       
  1858             }
       
  1859         }
       
  1860     return err;
       
  1861     }
       
  1862 
       
  1863 TInt TTraceDataParser::ReadNextChunkFromFile(TDes8&   aFileBuffer, 
       
  1864                                              RFile&   aFile, 
       
  1865                                              TInt&    aFilePosition,
       
  1866                                              TUint8*& aData,
       
  1867                                              TUint8*& aStartOfData,
       
  1868                                              TUint8*& aEndOfData)
       
  1869     {
       
  1870     aFilePosition += aData-aStartOfData;
       
  1871     TInt err = aFile.Read(aFilePosition, aFileBuffer);
       
  1872     if (err == KErrNone)
       
  1873         {
       
  1874         aData = (TUint8*) aFileBuffer.Ptr();
       
  1875         aStartOfData = aData;
       
  1876         aEndOfData = aData + aFileBuffer.Size();
       
  1877         }
       
  1878     return err;
       
  1879     }
       
  1880 
       
  1881 /*
       
  1882  * Parse trace data for Printf data, returning the number of occurances of a given string
       
  1883  *
       
  1884  * @param aBuffer Buffer containing the trace data
       
  1885  * @param aFindString String to search for
       
  1886  * @param aNumFound Output parameter set to number of occurances of given string
       
  1887  * @return Standard Symbian error code
       
  1888  */
       
  1889 EXPORT_C TInt TTraceDataParser::DataHasPrintfString(TDesC8&        aBuffer,
       
  1890                                                     const TDesC8&  aFindString,
       
  1891                                                     TInt&          aNumFound)
       
  1892     {
       
  1893     aNumFound = 0;
       
  1894     
       
  1895     TInt            err = KErrNone;
       
  1896     TUint8*         data = (TUint8*) aBuffer.Ptr();
       
  1897     TUint8*         endOfData = data + aBuffer.Size();    
       
  1898     
       
  1899     TTraceHeaderSettings  traceHeaderSettings;
       
  1900 
       
  1901     while(data < endOfData)
       
  1902         {
       
  1903         err = ParseHeader(data, endOfData-data, traceHeaderSettings);
       
  1904         
       
  1905         if (err != KErrNone)
       
  1906             {
       
  1907             break;
       
  1908             }
       
  1909         if (traceHeaderSettings.iPrintfTrace)
       
  1910             {
       
  1911             TPtr8 printfString = ReadTracePrintf(data, traceHeaderSettings.iLengthOfPayload);
       
  1912             if (StringsMatch(aFindString, printfString))
       
  1913                 {
       
  1914                 aNumFound++;
       
  1915                 }
       
  1916             }
       
  1917         data += traceHeaderSettings.iLengthOfPayload; //go to next trace
       
  1918         }
       
  1919 
       
  1920     return err;
       
  1921     }
       
  1922 
       
  1923 /*
       
  1924  * Parse trace data file for Printf data, returning the number of occurances of a given string
       
  1925  *
       
  1926  * @param aFilePath Full path of file containing the trace data
       
  1927  * @param aFs File system object
       
  1928  * @param aFindString String to search for
       
  1929  * @param aNumFound Output parameter set to number of occurances of given string
       
  1930  * @return Standard Symbian error code
       
  1931  */
       
  1932 EXPORT_C TInt TTraceDataParser::DataHasPrintfStringL(const TDesC&   aFilePath,
       
  1933                                                      RFs&           aFs,
       
  1934                                                      const TDesC8&  aFindString,
       
  1935                                                      TInt&          aNumFound)
       
  1936     {
       
  1937     aNumFound = 0;
       
  1938     
       
  1939     RFile file;
       
  1940 
       
  1941     // Open file with trace data
       
  1942     TInt err = file.Open(aFs, aFilePath, EFileRead|EFileShareAny);
       
  1943     if (err != KErrNone)
       
  1944         {
       
  1945         return err;
       
  1946         }
       
  1947     CleanupClosePushL(file);
       
  1948     
       
  1949     RBuf8   fileBuffer;
       
  1950     TInt    filePos = 0;
       
  1951     
       
  1952     // Create file buffer and read first chunk from file
       
  1953     err = CreateFileBuffer(fileBuffer, file);
       
  1954     if (err != KErrNone)
       
  1955         {
       
  1956         CleanupStack::PopAndDestroy(&file); // close file
       
  1957         return err;
       
  1958         }
       
  1959     fileBuffer.CleanupClosePushL();
       
  1960     
       
  1961     TUint8* data = NULL;
       
  1962     TUint8* startOfData = NULL;
       
  1963     TUint8* endOfData = NULL;    
       
  1964 
       
  1965     err = ReadNextChunkFromFile(fileBuffer, file, filePos, data, startOfData, endOfData);
       
  1966     if (err != KErrNone)
       
  1967         {
       
  1968         CleanupStack::PopAndDestroy(&fileBuffer); // close file buffer
       
  1969         CleanupStack::PopAndDestroy(&file); // close file
       
  1970         return err;
       
  1971         }
       
  1972 
       
  1973     TTraceHeaderSettings  traceHeaderSettings;
       
  1974 
       
  1975     while(data < endOfData)
       
  1976         {
       
  1977         err = ParseHeader(data, endOfData-data, traceHeaderSettings);
       
  1978         
       
  1979         if (err == KErrOverflow)
       
  1980             {
       
  1981             // We don't have all the trace data, so read next chunk from file
       
  1982             err = ReadNextChunkFromFile(fileBuffer, file, filePos, data, startOfData, endOfData);
       
  1983             if (err == KErrNone)
       
  1984                 {
       
  1985                 continue;
       
  1986                 }
       
  1987             }
       
  1988         if (err != KErrNone)
       
  1989             {
       
  1990             break;
       
  1991             }
       
  1992         if (traceHeaderSettings.iPrintfTrace)
       
  1993             {
       
  1994             TPtr8 printfString = ReadTracePrintf(data, traceHeaderSettings.iLengthOfPayload);
       
  1995             if (StringsMatch(aFindString, printfString))
       
  1996                 {
       
  1997                 aNumFound++;
       
  1998                 }
       
  1999             }
       
  2000         data += traceHeaderSettings.iLengthOfPayload; //go to next trace
       
  2001 
       
  2002         if (data == endOfData)
       
  2003             {
       
  2004             // We might not have all the trace data, so read next chunk from file
       
  2005             err = ReadNextChunkFromFile(fileBuffer, file, filePos, data, startOfData, endOfData);
       
  2006             if (err != KErrNone)
       
  2007                 {
       
  2008                 break;
       
  2009                 }
       
  2010             }
       
  2011         }
       
  2012 
       
  2013     CleanupStack::PopAndDestroy(&fileBuffer); // close file buffer
       
  2014     CleanupStack::PopAndDestroy(&file); // close file
       
  2015 
       
  2016     return err;
       
  2017     }
       
  2018 
       
  2019 /*
       
  2020  * Parse trace data file for a sequence of traces
       
  2021  *
       
  2022  * @param aFilePath Full path of file containing the trace data
       
  2023  * @param aFs File system object
       
  2024  * @param aLastNumberFound Output parameter set to number in last occurances of given string
       
  2025  * @param aNumDroppedTraces Output parameter set to number of dropped traces
       
  2026  * @param aFindPrintfPattern Pattern that indicates where in the printf string the number will be, using an asterisk
       
  2027  *                           This is only used if aGroupId = BTrace::ERDebugPrintf
       
  2028  * @param aGroupId Group ID of traces to parse
       
  2029  * @param aComponentID Component ID of traces to parse
       
  2030  * @return Standard Symbian error code
       
  2031  */
       
  2032 EXPORT_C TInt TTraceDataParser::DataHasTraceSequenceL(const TDesC&   aFilePath,
       
  2033                                                       RFs&           aFs,
       
  2034                                                       TInt&          aLastNumberFound,
       
  2035                                                       TInt&          aNumDroppedTraces, 
       
  2036                                                       TDesC8*        aFindPrintfPattern,
       
  2037                                                       TGroupId       aGroupId,
       
  2038                                                       TComponentId   aComponentID)
       
  2039     {
       
  2040     aLastNumberFound = 0;
       
  2041     aNumDroppedTraces = 0;
       
  2042     
       
  2043     RFile file;
       
  2044 
       
  2045     // Open file with trace data
       
  2046     TInt err = file.Open(aFs, aFilePath, EFileRead|EFileShareAny);
       
  2047     if (err != KErrNone)
       
  2048         {
       
  2049         return err;
       
  2050         }
       
  2051     CleanupClosePushL(file);
       
  2052     
       
  2053     RBuf8   fileBuffer;
       
  2054     TInt    filePos = 0;
       
  2055     
       
  2056     // Create file buffer and read first chunk from file
       
  2057     err = CreateFileBuffer(fileBuffer, file);
       
  2058     if (err != KErrNone)
       
  2059         {
       
  2060         CleanupStack::PopAndDestroy(&file); // close file
       
  2061         return err;
       
  2062         }
       
  2063     fileBuffer.CleanupClosePushL();
       
  2064     
       
  2065     TUint8* data = NULL;
       
  2066     TUint8* startOfData = NULL;
       
  2067     TUint8* endOfData = NULL;    
       
  2068 
       
  2069     err = ReadNextChunkFromFile(fileBuffer, file, filePos, data, startOfData, endOfData);
       
  2070     if (err != KErrNone)
       
  2071         {
       
  2072         CleanupStack::PopAndDestroy(&fileBuffer); // close file buffer
       
  2073         CleanupStack::PopAndDestroy(&file); // close file
       
  2074         return err;
       
  2075         }
       
  2076     
       
  2077     TInt            currentNumber = 0;
       
  2078     TInt            expectedNumber = 1;
       
  2079     TBool           gotNumberFromTrace = EFalse;
       
  2080     TBool           isDroppedTrace = EFalse;
       
  2081 
       
  2082     TTraceHeaderSettings  traceHeaderSettings;
       
  2083 
       
  2084     while(data < endOfData)
       
  2085         {
       
  2086         err = ParseHeader(data, endOfData-data, traceHeaderSettings);
       
  2087         
       
  2088         if (err == KErrOverflow)
       
  2089             {
       
  2090             // We don't have all the trace data, so read next chunk from file
       
  2091             err = ReadNextChunkFromFile(fileBuffer, file, filePos, data, startOfData, endOfData);
       
  2092             if (err == KErrNone)
       
  2093                 {
       
  2094                 continue;
       
  2095                 }
       
  2096             }
       
  2097         if (err != KErrNone)
       
  2098             {
       
  2099             break;
       
  2100             }
       
  2101         
       
  2102         gotNumberFromTrace = EFalse;
       
  2103                     
       
  2104         if (traceHeaderSettings.iPrintfTrace && aGroupId == BTrace::ERDebugPrintf)
       
  2105             {
       
  2106             TPtr8 printfString = ReadTracePrintf(data, traceHeaderSettings.iLengthOfPayload);
       
  2107             // See if this is a printf that matches given string
       
  2108             if (!aFindPrintfPattern)
       
  2109                 {
       
  2110                 err = KErrArgument;
       
  2111                 break;
       
  2112                 }
       
  2113             else if (printfString.Match(*aFindPrintfPattern) != KErrNotFound)
       
  2114                 {
       
  2115                 // Get the line number from the string
       
  2116                 err = ParseStringForNumber(printfString, *aFindPrintfPattern, currentNumber);
       
  2117                 if (err != KErrNone)
       
  2118                     {
       
  2119                     // Could not extract number from printf, so stop and fail
       
  2120                     break;
       
  2121                     }
       
  2122                 gotNumberFromTrace = ETrue;
       
  2123                 } 
       
  2124             // See if this is a dropped trace
       
  2125             else if (printfString.Compare(KDroppedTrace()) == 0)
       
  2126                 {
       
  2127                 // If we get 2 dropped trace notifications in a row, return an error
       
  2128                 if (isDroppedTrace)    
       
  2129                     {
       
  2130                     err = KErrGeneral;
       
  2131                     break;
       
  2132                     }
       
  2133                 isDroppedTrace = ETrue;
       
  2134                 }
       
  2135             else
       
  2136                 {
       
  2137                 isDroppedTrace = EFalse;
       
  2138                 }
       
  2139             }
       
  2140         else if (!traceHeaderSettings.iPrintfTrace && traceHeaderSettings.iCategory == aGroupId && traceHeaderSettings.iComponentID == aComponentID)
       
  2141             {
       
  2142             // check dropped trace flag
       
  2143             if (traceHeaderSettings.iHeaderFlags & BTrace::EMissingRecord)
       
  2144                 {
       
  2145                 // If we get 2 dropped trace notifications in a row, return an error
       
  2146                 if (isDroppedTrace)
       
  2147                     {
       
  2148                     err = KErrGeneral;
       
  2149                     break;
       
  2150                     }
       
  2151                 isDroppedTrace = ETrue;
       
  2152                 }
       
  2153             else
       
  2154                 {
       
  2155                 isDroppedTrace = EFalse;
       
  2156                 }
       
  2157 
       
  2158             if (traceHeaderSettings.iLengthOfPayload >= 4)
       
  2159                 {
       
  2160                 currentNumber = (TInt) Swap(ReadUint32FromBuf(data, traceHeaderSettings.iFromTestWriter));
       
  2161                 traceHeaderSettings.iLengthOfPayload -= 4;
       
  2162                 gotNumberFromTrace = ETrue;
       
  2163                 }                
       
  2164             else
       
  2165                 {
       
  2166                 // Could not get number from trace, so stop and fail
       
  2167                 err = KErrGeneral;
       
  2168                 break;
       
  2169                 }
       
  2170             }
       
  2171 
       
  2172         if (gotNumberFromTrace)
       
  2173             {
       
  2174             if (currentNumber < expectedNumber)
       
  2175                 {
       
  2176                 // Start of a new sequence, so stop
       
  2177                 break;
       
  2178                 }
       
  2179             aLastNumberFound = currentNumber;
       
  2180             if (aLastNumberFound != expectedNumber && !isDroppedTrace)
       
  2181                 {
       
  2182                 // A printf has been missed out with no notification, so stop and fail
       
  2183                 err = KErrGeneral;
       
  2184                 break;
       
  2185                 }
       
  2186             else if (aLastNumberFound == expectedNumber && isDroppedTrace)
       
  2187                 {
       
  2188                 // A printf hasn't been missed out despite notification, so stop and fail
       
  2189                 err = KErrGeneral;
       
  2190                 break;
       
  2191                 }
       
  2192             
       
  2193             aNumDroppedTraces += (aLastNumberFound - expectedNumber);
       
  2194             expectedNumber = aLastNumberFound + 1;
       
  2195             
       
  2196             if (traceHeaderSettings.iPrintfTrace)
       
  2197                 {
       
  2198                 isDroppedTrace = EFalse;
       
  2199                 }
       
  2200             }
       
  2201         
       
  2202         data += traceHeaderSettings.iLengthOfPayload; //go to next trace
       
  2203 
       
  2204         if (data == endOfData)
       
  2205             {
       
  2206             // We might not have all the trace data, so read next chunk from file
       
  2207             err = ReadNextChunkFromFile(fileBuffer, file, filePos, data, startOfData, endOfData);
       
  2208             if (err != KErrNone)
       
  2209                 {
       
  2210                 break;
       
  2211                 }
       
  2212             }
       
  2213         }
       
  2214 
       
  2215     CleanupStack::PopAndDestroy(&fileBuffer); // close file buffer
       
  2216     CleanupStack::PopAndDestroy(&file); // close file
       
  2217 
       
  2218     return err;
       
  2219     }
       
  2220 
       
  2221 /*
       
  2222  * Get Printf string from single trace data
       
  2223  *
       
  2224  * @param aBuffer Buffer containing the trace data
       
  2225  * @param aPrintfString Output parameter set to the print string in the trace data
       
  2226  * @return Standard Symbian error code
       
  2227  */
       
  2228 EXPORT_C TInt TTraceDataParser::GetPrintfFromTrace(TDesC8& aBuffer, TDes8& aPrintfString)
       
  2229     {
       
  2230     TUint8*         data = (TUint8*) aBuffer.Ptr();
       
  2231 
       
  2232     TTraceHeaderSettings  traceHeaderSettings;
       
  2233 
       
  2234     TInt err = ParseHeader(data, aBuffer.Size(), traceHeaderSettings);
       
  2235 
       
  2236     if (err == KErrNone && traceHeaderSettings.iPrintfTrace)
       
  2237         {
       
  2238         aPrintfString.Copy(ReadTracePrintf(data, traceHeaderSettings.iLengthOfPayload));
       
  2239         }
       
  2240     
       
  2241     return err;
       
  2242     }
       
  2243 
       
  2244 /*
       
  2245  * Parse trace data for multipart data, returning the number of traces found and total size of trace data.
       
  2246  * The data is expected to contain a sequence of integers, starting at 0
       
  2247  *
       
  2248  * @param aBuffer Buffer containing the trace data
       
  2249  * @param aGroupId Group ID of traces to parse
       
  2250  * @param aComponentID Component ID of traces to parse
       
  2251  * @param aMultipartDataSize Output parameter set to total size of data in multipart trace
       
  2252  * @param aNumMultipartTraces Output parameter set to number of traces that make up multipart trace
       
  2253  * @return Standard Symbian error code
       
  2254  */
       
  2255 EXPORT_C TInt TTraceDataParser::ValidateMultipartTraces(TDesC8&        aBuffer,
       
  2256                                                         TGroupId       aGroupID, 
       
  2257                                                         TComponentId   aComponentID, 
       
  2258                                                         TInt&          aMultipartDataSize, 
       
  2259                                                         TInt&          aNumMultipartTraces)
       
  2260     {
       
  2261     aMultipartDataSize = 0;
       
  2262     aNumMultipartTraces = 0;
       
  2263     
       
  2264     TInt            err = KErrNone;
       
  2265     TUint8*         data = (TUint8*) aBuffer.Ptr();
       
  2266     TUint8*         endOfData = data + aBuffer.Size();    
       
  2267     TUint8          currentNumber = 0;
       
  2268     TUint8          expectedNumber = 0;
       
  2269     TUint32         expectedMultiPartTraceID = 0;
       
  2270     TBool           foundStartOfMultipart = EFalse;
       
  2271     TBool           foundEndOfMultipart = EFalse;
       
  2272     TBool           isMultipartTrace = EFalse;
       
  2273     
       
  2274     TTraceHeaderSettings  traceHeaderSettings;
       
  2275 
       
  2276     while(data < endOfData)
       
  2277         {
       
  2278         err = ParseHeader(data, endOfData-data, traceHeaderSettings);
       
  2279         if (err != KErrNone)
       
  2280             {
       
  2281             return err;
       
  2282             }
       
  2283                
       
  2284         // Only look at traces with correct group ID / component ID
       
  2285         if (traceHeaderSettings.iCategory == aGroupID && traceHeaderSettings.iComponentID == aComponentID)
       
  2286             {
       
  2287             isMultipartTrace = EFalse;
       
  2288             if (traceHeaderSettings.iMultiPartType == BTrace::EMultipartFirst ||
       
  2289                 traceHeaderSettings.iMultiPartType == BTrace::EMultipartMiddle ||
       
  2290                 traceHeaderSettings.iMultiPartType == BTrace::EMultipartLast)
       
  2291                 {
       
  2292                 isMultipartTrace = ETrue;
       
  2293                 }
       
  2294             
       
  2295             if (!isMultipartTrace)
       
  2296                 {
       
  2297                 // If not a multipart trace, then this one trace should contain all data
       
  2298                 aNumMultipartTraces = 1;
       
  2299                 aMultipartDataSize = traceHeaderSettings.iLengthOfPayload;
       
  2300                 // If already found some of the data then we shouldn't have this trace
       
  2301                 if (foundStartOfMultipart || foundEndOfMultipart)
       
  2302                     {
       
  2303                     return KErrCorrupt;
       
  2304                     }
       
  2305                 foundStartOfMultipart = ETrue;
       
  2306                 foundEndOfMultipart = ETrue;
       
  2307 
       
  2308                 // Validate payload
       
  2309                 while (traceHeaderSettings.iLengthOfPayload > 0)
       
  2310                     {
       
  2311                     currentNumber = (TInt) data[0];
       
  2312                     data++;
       
  2313                     // Adjust length of payload remaining
       
  2314                     traceHeaderSettings.iLengthOfPayload -= 1;   
       
  2315                     if (currentNumber != expectedNumber)
       
  2316                         {
       
  2317                         if (traceHeaderSettings.iLengthOfPayload >= 4 || currentNumber != 0)
       
  2318                             {
       
  2319                             // Data is 4-byte aligned, so it's ok to have up to 3 zeros at the end of payload
       
  2320                             return KErrCorrupt;
       
  2321                             }
       
  2322                         // This byte is zero padding, so not part of data
       
  2323                         aMultipartDataSize--;
       
  2324                         }
       
  2325                     expectedNumber++;
       
  2326                     }
       
  2327                 }
       
  2328             // Only look at multipart traces with correct multipart trace ID
       
  2329             else if (traceHeaderSettings.iMultiPartTraceID == expectedMultiPartTraceID || expectedMultiPartTraceID == 0)
       
  2330                 {
       
  2331                 aNumMultipartTraces++;
       
  2332                 
       
  2333                 // If already found all data then we shouldn't get another trace with this ID
       
  2334                 if (foundEndOfMultipart)
       
  2335                     {
       
  2336                     return KErrCorrupt;
       
  2337                     }
       
  2338                 
       
  2339                 // Trace is start of multipart
       
  2340                 if (traceHeaderSettings.iMultiPartType == BTrace::EMultipartFirst)
       
  2341                     {
       
  2342                     // If already found start of data then we shouldn't get this part
       
  2343                     if (foundStartOfMultipart)
       
  2344                         {
       
  2345                         return KErrCorrupt;
       
  2346                         }
       
  2347                     foundStartOfMultipart = ETrue;
       
  2348                     aMultipartDataSize = 0;
       
  2349                     
       
  2350                     // Set the expected multipart trace ID
       
  2351                     expectedMultiPartTraceID = traceHeaderSettings.iMultiPartTraceID;                    
       
  2352                     }
       
  2353                 else if (traceHeaderSettings.iMultiPartType == BTrace::EMultipartMiddle ||
       
  2354                          traceHeaderSettings.iMultiPartType == BTrace::EMultipartLast)
       
  2355                     {
       
  2356                     // If not yet found start of data then we shouldn't get this part
       
  2357                     if (!foundStartOfMultipart)
       
  2358                         {
       
  2359                         return KErrCorrupt;
       
  2360                         }
       
  2361                     }
       
  2362                 
       
  2363                 // Add length of payload to size of total data found
       
  2364                 aMultipartDataSize += traceHeaderSettings.iLengthOfPayload;
       
  2365 
       
  2366                 while (traceHeaderSettings.iLengthOfPayload > 0)
       
  2367                     {
       
  2368                     // Validate the next part of payload
       
  2369                     currentNumber = (TInt) data[0];
       
  2370                     data++;
       
  2371                     // Adjust length of payload remaining
       
  2372                     traceHeaderSettings.iLengthOfPayload -= 1;   
       
  2373                     if (currentNumber != expectedNumber)
       
  2374                         {
       
  2375                         if (traceHeaderSettings.iLengthOfPayload >= 4 || currentNumber != 0)
       
  2376                             {
       
  2377                             // Data is 4-byte aligned, so it's ok to have up to 3 zeros at the end of payload
       
  2378                             return KErrCorrupt;
       
  2379                             }
       
  2380                         // This byte is zero padding, so not part of data
       
  2381                         aMultipartDataSize--;
       
  2382                         }
       
  2383                     expectedNumber++;
       
  2384                     }
       
  2385 
       
  2386                 if (traceHeaderSettings.iMultiPartType == BTrace::EMultipartLast)
       
  2387                     {                    
       
  2388                     // Found end of trace data
       
  2389                     foundEndOfMultipart = ETrue;
       
  2390                     }
       
  2391                 }
       
  2392             }
       
  2393         
       
  2394         data += traceHeaderSettings.iLengthOfPayload; //go to next trace
       
  2395         }
       
  2396 
       
  2397     if (!foundEndOfMultipart)
       
  2398         {
       
  2399         // Did not find end of trace data, so return KErrNotFound
       
  2400         err = KErrNotFound;
       
  2401         }
       
  2402     return err;
       
  2403     }