commsfwtools/commstools/utracedecoder/src/utraceframe.cpp
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <cassert>
       
    17 #include <iostream>
       
    18 #include <sstream>
       
    19 #include <iomanip>
       
    20 
       
    21 #include "utraceframe.h"
       
    22 #include "e32btrace.h"
       
    23 #include "util.h"
       
    24 
       
    25 CUTraceFrame::CUTraceFrame(const unsigned char* aFrameData, unsigned int aEntryNumber)
       
    26     {
       
    27     SetFrameBuffer(aFrameData);
       
    28     iEventEntryNumber = aEntryNumber;
       
    29     }
       
    30 
       
    31 CUTraceFrame::~CUTraceFrame()
       
    32     {
       
    33     delete [] iFrameBuffer;
       
    34     }
       
    35 
       
    36 
       
    37 void CUTraceFrame::SetFrameBuffer(const unsigned char *aData)
       
    38     {
       
    39 	int length = aData[0];
       
    40 	iFrameBuffer = new unsigned char[length + 4];
       
    41 	memset(iFrameBuffer, 0, length + 4); //need to do this so payload() doesnt blow out when used as string
       
    42 	memcpy((char *)iFrameBuffer, (const char*)aData, length);
       
    43     }
       
    44 
       
    45 
       
    46 unsigned char* CUTraceFrame::Data() const
       
    47     {
       
    48     // Get a pointer to the data after the header
       
    49 	unsigned char *p = (unsigned char*)(iFrameBuffer + CalculateEntryOffset(0));
       
    50 
       
    51     // Make adjustments for any extra fields such as multipart information
       
    52     // and the arg1 value
       
    53     if (IsMultiPart())
       
    54         {
       
    55         /*
       
    56 	    The structure of the data part of each trace record in a multipart trace is described
       
    57 	    below. In this description, the following labels are used.
       
    58 	    -	A is the initial 4 bytes of data; the a1 argument of BTraceBig.
       
    59 	    -	D is the array of bytes of additional data; the aData argument of BTraceBig.
       
    60 	    -	N is the size of D; the aDataSize argument of BTraceBig
       
    61 	    -	X is the maximum number of additional bytes which will fit into a trace record. 
       
    62 		    This is usually KMaxBTraceDataArray but this should not be assumed, instead
       
    63 		    the size and other information present in each trace record should be examined.
       
    64 
       
    65 	    For the first part of a multipart trace, the data in a trace record has the following
       
    66 	    structure:
       
    67 	    -	4 bytes containing N.
       
    68 	    -	4 bytes containing A.
       
    69 	    -	X bytes containing D[0..X-1]
       
    70     
       
    71 	    If the parts are numbered 0 through to 'j', then a middle part of a multipart trace
       
    72 	    is numbered 'i' where 0<i<j. The data in these parts has the structure:
       
    73 	    -	4 bytes containing N.
       
    74 	    -	4 bytes containing X*i. I.e. the offset within D for the data in this trace record.
       
    75 	    -	X bytes containing D[X*i..X*i+X-1]
       
    76 	
       
    77 	    For the last part of a multipart trace, the data has the structure:
       
    78 	    -	4 bytes containing N.
       
    79 	    -	4 bytes containing X*j. I.e. the offset within D for the data in this trace record.
       
    80 	    -	N modulo X bytes containing D[X*j..N-1]. I.e. the final bytes of the trace data.*/
       
    81         
       
    82         p += 8; // trace arg1 and the offset to where this piece of data should go
       
    83         }
       
    84     else
       
    85         {
       
    86         p += 4; // trace arg1
       
    87         }
       
    88 
       
    89     return p;
       
    90     }
       
    91 
       
    92 
       
    93 unsigned int CUTraceFrame::EventEntryNumber() const
       
    94     {
       
    95     return iEventEntryNumber;
       
    96     }
       
    97 
       
    98 unsigned int CUTraceFrame::DataLength() const
       
    99     {
       
   100     unsigned char* data = Data();
       
   101     unsigned int dataLength = (unsigned int)((iFrameBuffer + FrameLength()) - data);
       
   102     return dataLength;
       
   103     }
       
   104 
       
   105 unsigned int CUTraceFrame::DataFullLength() const
       
   106     {
       
   107     if (MultiPartType() == BTrace::EMultiPartFirst)
       
   108         {
       
   109 	    unsigned char* p = (unsigned char*)(iFrameBuffer + CalculateEntryOffset(0));
       
   110         return *((unsigned int*)(p));
       
   111         }
       
   112     else if (MultiPartType() == BTrace::ENotMultiPart)
       
   113         {
       
   114         return DataLength();
       
   115         }
       
   116 
       
   117 #ifdef _DEBUG
       
   118     assert(0); // called out of context
       
   119 #endif
       
   120     std::cerr << "Error: CUTraceFrame::DataFullLength() called out of context" << std::endl;
       
   121     return 0;
       
   122     }
       
   123 
       
   124 
       
   125 unsigned int CUTraceFrame::FrameLength() const
       
   126     {
       
   127     return unsigned int(iFrameBuffer[BTrace::ESizeIndex]);
       
   128     }
       
   129 
       
   130 
       
   131 unsigned int CUTraceFrame::Flags() const
       
   132     {
       
   133     return int(iFrameBuffer[BTrace::EFlagsIndex]);
       
   134     }
       
   135 
       
   136 
       
   137 unsigned int CUTraceFrame::PrimaryFilter() const
       
   138     {
       
   139     return int(iFrameBuffer[BTrace::ECategoryIndex]);
       
   140     }
       
   141 
       
   142 
       
   143 unsigned int CUTraceFrame::SecondaryFilter() const
       
   144     {
       
   145     // TODO:
       
   146     std::cerr << "Error: CUTraceFrame::SecondaryFilter() not implemented" << std::endl;
       
   147     assert(0);
       
   148 	return 0;
       
   149     }
       
   150 
       
   151 
       
   152 unsigned int CUTraceFrame::SubCategory() const
       
   153     {
       
   154     return iFrameBuffer[BTrace::ESubCategoryIndex];
       
   155     }
       
   156 
       
   157 
       
   158 bool CUTraceFrame::Header2Present() const
       
   159     {
       
   160     return iFrameBuffer[BTrace::EFlagsIndex] & BTrace::EHeader2Present;
       
   161     }
       
   162 
       
   163 bool CUTraceFrame::Timestamp1Present() const
       
   164     {
       
   165     return (iFrameBuffer[BTrace::EFlagsIndex] & BTrace::ETimestampPresent) == BTrace::ETimestampPresent;
       
   166     }
       
   167 
       
   168 bool CUTraceFrame::Timestamp2Present() const
       
   169     {
       
   170     return (iFrameBuffer[BTrace::EFlagsIndex] & BTrace::ETimestamp2Present) == BTrace::ETimestamp2Present;
       
   171     }
       
   172 
       
   173 bool CUTraceFrame::ContextIdPresent() const
       
   174     {
       
   175     return (iFrameBuffer[BTrace::EFlagsIndex] & BTrace::EContextIdPresent) == BTrace::EContextIdPresent;
       
   176     }
       
   177 
       
   178 bool CUTraceFrame::PcPresent() const
       
   179     {
       
   180     return (iFrameBuffer[BTrace::EFlagsIndex] & BTrace::EPcPresent) == BTrace::EPcPresent;
       
   181     }
       
   182 
       
   183 bool CUTraceFrame::ExtraPresent() const
       
   184     {
       
   185     return (iFrameBuffer[BTrace::EFlagsIndex] & BTrace::EExtraPresent) == BTrace::EExtraPresent;
       
   186     }
       
   187 
       
   188 bool CUTraceFrame::RecordTruncated() const
       
   189     {
       
   190     return (iFrameBuffer[BTrace::EFlagsIndex] & BTrace::ERecordTruncated) == BTrace::ERecordTruncated;
       
   191     }
       
   192 
       
   193 bool CUTraceFrame::MissingRecord() const
       
   194     {
       
   195     return (iFrameBuffer[BTrace::EFlagsIndex] & BTrace::EMissingRecord) == BTrace::EMissingRecord;
       
   196     }
       
   197 
       
   198 
       
   199 unsigned int CUTraceFrame::Header2() const
       
   200     {
       
   201     if (Header2Present())
       
   202         {
       
   203         return BytesToInt(iFrameBuffer + CalculateEntryOffset(BTrace::EHeader2Present));
       
   204 	    }
       
   205 
       
   206 #ifdef _DEBUG
       
   207     assert(0); // Test for presence
       
   208 #endif
       
   209     std::cerr << "Error: CUTraceFrame::Header2() called out of context" << std::endl;
       
   210     return 0;
       
   211     }
       
   212 
       
   213 
       
   214 unsigned int CUTraceFrame::Timestamp1() const
       
   215     {
       
   216 	if (Timestamp1Present())
       
   217         {
       
   218         return BytesToInt(iFrameBuffer  + CalculateEntryOffset(BTrace::ETimestampPresent));
       
   219 	    }
       
   220 
       
   221 #ifdef _DEBUG
       
   222     assert(0); // Test for presence
       
   223 #endif
       
   224     std::cerr << "Error: CUTraceFrame::Timestamp1() called out of context" << std::endl;
       
   225     return 0;
       
   226     }
       
   227 
       
   228 
       
   229 unsigned int CUTraceFrame::Timestamp2() const
       
   230     {
       
   231     if (Timestamp2Present())
       
   232 	    {
       
   233         return BytesToInt(iFrameBuffer  + CalculateEntryOffset(BTrace::ETimestamp2Present));
       
   234 	    }
       
   235 
       
   236 #ifdef _DEBUG
       
   237     assert(0); // Test for presence
       
   238 #endif
       
   239     std::cerr << "Error: CUTraceFrame::Timestamp2() called out of context" << std::endl;
       
   240     return 0;
       
   241     }
       
   242 
       
   243 
       
   244 unsigned int CUTraceFrame::ContextType() const
       
   245     {
       
   246     if (ContextIdPresent())
       
   247         {
       
   248         return BytesToInt(iFrameBuffer  + CalculateEntryOffset(BTrace::EContextIdPresent)) & (3UL);
       
   249         }
       
   250 
       
   251     #ifdef _DEBUG
       
   252     assert(0); // Test for presence
       
   253 #endif
       
   254     std::cerr << "Error: CUTraceFrame::ContextType() called out of context" << std::endl;
       
   255     return 0;
       
   256     }
       
   257 
       
   258 
       
   259 unsigned int CUTraceFrame::ContextId() const
       
   260     {
       
   261     if (ContextIdPresent())
       
   262 	    {
       
   263         return BytesToInt(iFrameBuffer  + CalculateEntryOffset(BTrace::EContextIdPresent)) & (~3UL);
       
   264 	    }
       
   265 
       
   266 #ifdef _DEBUG
       
   267     assert(0); // Test for presence
       
   268 #endif
       
   269     std::cerr << "Error: CUTraceFrame::ContextId() called out of context" << std::endl;
       
   270     return 0;
       
   271     }
       
   272 
       
   273 
       
   274 unsigned int CUTraceFrame::ProgramCounter() const
       
   275     {
       
   276     if (PcPresent())
       
   277         {
       
   278         return BytesToInt(iFrameBuffer  + CalculateEntryOffset(BTrace::EPcPresent));
       
   279 	    }
       
   280 
       
   281 #ifdef _DEBUG
       
   282     assert(0); // Test for presence
       
   283 #endif
       
   284     std::cerr << "Error: CUTraceFrame::ProgramCounter() called out of context" << std::endl;
       
   285     return 0;
       
   286     }
       
   287 
       
   288 
       
   289 unsigned int CUTraceFrame::Extra() const
       
   290     {
       
   291     if (ExtraPresent())
       
   292 	    {
       
   293         return BytesToInt(iFrameBuffer  + CalculateEntryOffset(BTrace::EExtraPresent));
       
   294 	    }
       
   295 
       
   296 #ifdef _DEBUG
       
   297     assert(0); // Test for presence
       
   298 #endif
       
   299     std::cerr << "Error: CUTraceFrame::Extra() called out of context" << std::endl;
       
   300     return 0;
       
   301     }
       
   302 
       
   303 
       
   304 BTrace::TMultiPart CUTraceFrame::MultiPartType() const
       
   305     {
       
   306     if (Header2Present())
       
   307         {
       
   308         return (BTrace::TMultiPart)(Header2() & BTrace::EMultiPartFlagMask);
       
   309         }
       
   310 
       
   311     return BTrace::ENotMultiPart;
       
   312     }
       
   313 
       
   314 
       
   315 unsigned int CUTraceFrame::MultiPartSequenceNumber() const
       
   316     {
       
   317     if (MultiPartType() == BTrace::ENotMultiPart)
       
   318         {
       
   319 #ifdef _DEBUG
       
   320         assert(0); // called out of context
       
   321 #endif
       
   322         std::cerr << "Error: CUTraceFrame::MultiPartSequenceNumber() called out of context" << std::endl;
       
   323         return 0;
       
   324         }
       
   325 
       
   326     return Extra();
       
   327     }
       
   328 
       
   329 
       
   330 unsigned int CUTraceFrame::Arg1() const
       
   331     {
       
   332     BTrace::TMultiPart partType = MultiPartType();
       
   333 
       
   334     assert(partType == BTrace::ENotMultiPart || partType ==  BTrace::EMultiPartFirst);
       
   335     return *((unsigned int*)(Data() - 4)); // Arg1 always 4 bytes before the start of the data
       
   336     }
       
   337 
       
   338 
       
   339 unsigned int CUTraceFrame::Truncated() const
       
   340     {
       
   341     if (RecordTruncated())
       
   342         {
       
   343 		return BytesToInt(iFrameBuffer  + CalculateEntryOffset(BTrace::ERecordTruncated));
       
   344 	    }
       
   345 
       
   346 #ifdef _DEBUG
       
   347     assert(0); // Test for presence
       
   348 #endif
       
   349     return 0;
       
   350     }
       
   351 
       
   352 
       
   353 unsigned int CUTraceFrame::Missing() const
       
   354     {
       
   355     if (MissingRecord())
       
   356         {
       
   357     	return BytesToInt(iFrameBuffer  + CalculateEntryOffset(BTrace::EMissingRecord));
       
   358 	    }
       
   359     
       
   360 #ifdef _DEBUG
       
   361     assert(0); // Test for presence
       
   362 #endif
       
   363     return 0;
       
   364     }
       
   365 
       
   366 
       
   367 /**
       
   368 Calculates the offset from the start of the frame to either the data after the header,
       
   369 or to the data for the specified flag.
       
   370 
       
   371 @param aEntry - Either a value from BTrace::TFlags or zero to retrieve the offset to the data after the header.
       
   372 The requested flag must be set in the flags field of the frame.
       
   373 The requested flag must not be BTrace::ERecordTruncated or BTrace::EMissingRecord which have no associated data
       
   374 */
       
   375 unsigned int CUTraceFrame::CalculateEntryOffset(unsigned char aEntry) const
       
   376     {
       
   377 	assert(aEntry == 0 || (aEntry & Flags()) > 0);
       
   378 	assert(aEntry != BTrace::ERecordTruncated);
       
   379 	assert(aEntry != BTrace::EMissingRecord);
       
   380 
       
   381     int offset = 4; // size, flags, 1ry category, subcategory
       
   382     unsigned char mask = aEntry - 1;
       
   383 	mask &= ~(BTrace::ERecordTruncated | BTrace::EMissingRecord);
       
   384 
       
   385     unsigned char n = Flags() & mask;    
       
   386 	while (n)
       
   387 	    {
       
   388 		offset += ((n & 1UL) * 4) ;
       
   389 		n >>= 1 ;
       
   390 	    }
       
   391 
       
   392 	return offset;
       
   393     }
       
   394 
       
   395 
       
   396 void CUTraceFrame::DumpFlags(std::ostream& aStream) const
       
   397     {
       
   398     if (Flags() & BTrace::EHeader2Present)
       
   399         {
       
   400         aStream << "Header2Present ";
       
   401         }
       
   402 
       
   403     if (Flags() & BTrace::ETimestampPresent)
       
   404         {
       
   405         aStream << "TimestampPresent ";
       
   406         }
       
   407 
       
   408     if (Flags() & BTrace::ETimestamp2Present)
       
   409         {
       
   410         aStream << "Timestamp2Present ";
       
   411         }
       
   412 
       
   413     if (Flags() & BTrace::EContextIdPresent)
       
   414         {
       
   415         aStream << "ContextIdPresent ";
       
   416         }
       
   417 
       
   418     if (Flags() & BTrace::EPcPresent)
       
   419         {
       
   420         aStream << "PcPresent ";
       
   421         }
       
   422 
       
   423     if (Flags() & BTrace::EExtraPresent)
       
   424         {
       
   425         aStream << "ExtraPresent ";
       
   426         }
       
   427 
       
   428     if (Flags() & BTrace::ERecordTruncated)
       
   429         {
       
   430         aStream << "RecordTruncated ";
       
   431         }
       
   432 
       
   433     if (Flags() & BTrace::EMissingRecord)
       
   434         {
       
   435         aStream << "MissingRecord ";
       
   436         }
       
   437     }
       
   438 
       
   439 void CUTraceFrame::DumpFrame(std::ostream& aStream) const
       
   440     {
       
   441     aStream
       
   442         << "Size: " << std::dec << FrameLength() << std::endl
       
   443         << "Flags: 0x" << std::noshowbase << std::setw(2)
       
   444         << std::setfill('0') << std::nouppercase << std::hex
       
   445         << Flags() << " (";
       
   446 
       
   447     DumpFlags(aStream);
       
   448 
       
   449     aStream << ")" << std::endl
       
   450         << "Primary Filter: 0x" << std::noshowbase << std::setw(2)
       
   451         << std::setfill('0') << std::nouppercase << std::hex
       
   452         << PrimaryFilter() << std::endl
       
   453         << "Subcategory: 0x" << std::noshowbase << std::setw(2)
       
   454         << std::setfill('0') << std::nouppercase << std::hex
       
   455         << SubCategory() << std::endl;
       
   456 
       
   457     if (Header2Present())
       
   458         {
       
   459         aStream << "Header2: 0x" << std::noshowbase << std::setw(8)
       
   460             << std::setfill('0') << std::nouppercase << std::hex
       
   461             << Header2() << std::endl;
       
   462         }
       
   463 
       
   464     if (Timestamp1Present())
       
   465         {
       
   466         aStream << "Timestamp1: " << std::noshowbase << std::dec
       
   467             << Timestamp1() << std::endl;
       
   468         }
       
   469 
       
   470     if (Timestamp2Present())
       
   471         {
       
   472         aStream << "Timestamp2: " << std::noshowbase << std::dec
       
   473             << Timestamp2() << std::endl;
       
   474         }
       
   475     if (ContextIdPresent())
       
   476         {
       
   477         aStream << "Context Type: ";
       
   478         switch (ContextType())
       
   479             {
       
   480             case 0:
       
   481                 aStream << "NThread" << std::endl;
       
   482                 aStream << "Context ID: 0x" << std::noshowbase << std::hex << std::nouppercase
       
   483                     << std::setw(8) << std::setfill('0') << ContextId() << std::endl;
       
   484                 break;
       
   485 
       
   486             case 1:
       
   487                 aStream << "Fast Interrupt (FIQ)" << std::endl;
       
   488                 break;
       
   489 
       
   490             case 2:
       
   491                 aStream << "Interrupt (IRQ)" << std::endl;                    
       
   492                 break;
       
   493 
       
   494             case 3:
       
   495                 aStream << "Immediate Delayed Function Call (IDFC)" << std::endl;
       
   496                 break;
       
   497             }
       
   498         }
       
   499 
       
   500     if (PcPresent())
       
   501         {
       
   502         aStream << "PC: 0x" << std::noshowbase << std::setw(8)
       
   503             << std::setfill('0') << std::nouppercase << std::hex
       
   504             << ProgramCounter() << std::endl;
       
   505         }
       
   506 
       
   507     if (IsMultiPart())
       
   508         {
       
   509         aStream << "Multipart Frame: ";
       
   510         switch (Header2() & BTrace::EMultiPartFlagMask)
       
   511             {
       
   512             case 1:
       
   513                 aStream << "EMultiPartFirst";
       
   514                 break;
       
   515 
       
   516             case 2:
       
   517                 aStream << "EMultiPartMiddle";
       
   518                 break;
       
   519 
       
   520             case 3:
       
   521                 aStream << "EMultiPartLast";
       
   522                 break;
       
   523             }
       
   524         aStream << std::endl;
       
   525         }
       
   526 
       
   527     if (ExtraPresent())
       
   528         {
       
   529         if (IsMultiPart())
       
   530             {
       
   531             aStream << "MultiPart Event Id: 0x";
       
   532             }
       
   533         else
       
   534             {
       
   535             aStream << "Extra: 0x";
       
   536             }
       
   537 
       
   538         aStream << std::noshowbase << std::setw(8)
       
   539             << std::setfill('0') << std::nouppercase << std::hex
       
   540             << Extra() << std::endl;
       
   541         }
       
   542 
       
   543     if (!IsMultiPart() || MultiPartType() == BTrace::EMultiPartFirst)
       
   544         {
       
   545         aStream << "Arg1: 0x" << std::noshowbase << std::setw(8)
       
   546             << std::setfill('0') << std::nouppercase << std::hex
       
   547             << Arg1() << std::endl;
       
   548         }
       
   549 
       
   550     unsigned int zones[1] = { (unsigned int)(Data() - iFrameBuffer) };
       
   551     DumpBytes(aStream, iFrameBuffer, FrameLength(), zones, 1);
       
   552     aStream << std::endl;
       
   553     aStream.flush();
       
   554     }
       
   555 
       
   556 
       
   557 void CUTraceFrame::DumpFrame(std::string& aOutput) const
       
   558     {
       
   559     std::ostringstream ss;
       
   560     DumpFrame(ss);
       
   561     aOutput += ss.str();
       
   562     }
       
   563 
       
   564 
       
   565 CMultiPartFrameCollection::CMultiPartFrameCollection(CUTraceFrame* aFrame)
       
   566     {
       
   567     assert(aFrame->IsMultiPart());
       
   568     push_back(aFrame);
       
   569     }
       
   570 
       
   571 CMultiPartFrameCollection::~CMultiPartFrameCollection()
       
   572     {
       
   573     while (!empty())
       
   574         {
       
   575         CUTraceFrame* frame = this->back();
       
   576         this->pop_back();
       
   577         delete frame;
       
   578         }
       
   579     }
       
   580 
       
   581 void CMultiPartFrameCollection::AddFrame(CUTraceFrame* aFrame)
       
   582     {
       
   583     assert(aFrame->IsMultiPart() && aFrame->MultiPartSequenceNumber() == MultiPartId());
       
   584     push_back(aFrame);
       
   585     }
       
   586 
       
   587 unsigned int CMultiPartFrameCollection::MultiPartId() const
       
   588     {
       
   589     return at(0)->MultiPartSequenceNumber();
       
   590     }
       
   591