memspy/Engine/Source/Helpers/MemSpyEngineHelperStack.cpp
changeset 0 a03f92240627
child 18 3406c99bc375
equal deleted inserted replaced
-1:000000000000 0:a03f92240627
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #include <memspy/engine/memspyenginehelperstack.h>
       
    19 
       
    20 // Driver includes
       
    21 #include <memspy/driver/memspydriverclient.h>
       
    22 
       
    23 // User includes
       
    24 #include <memspy/engine/memspyengine.h>
       
    25 #include <memspy/engine/memspyengineoutputsink.h>
       
    26 #include <memspy/engine/memspyengineoutputlist.h>
       
    27 #include <memspy/engine/memspyengineobjectthread.h>
       
    28 #include <memspy/engine/memspyengineobjectprocess.h>
       
    29 #include "MemSpyEngineOutputListItem.h"
       
    30 #include <memspy/engine/memspyengineobjectcontainer.h>
       
    31 #include <memspy/engine/memspyenginehelpercodesegment.h>
       
    32 
       
    33 // Literal constants
       
    34 _LIT( KMemSpyPrefixStackData, "StackData - %S - " );
       
    35 _LIT( KMemSpyMarkerStackData, "<%SMEMSPY_STACK_DATA_%03d>" );
       
    36 
       
    37 
       
    38 CMemSpyEngineHelperStack::CMemSpyEngineHelperStack( CMemSpyEngine& aEngine )
       
    39 :   iEngine( aEngine )
       
    40     {
       
    41     }
       
    42 
       
    43     
       
    44 CMemSpyEngineHelperStack::~CMemSpyEngineHelperStack()
       
    45     {
       
    46     }
       
    47 
       
    48 
       
    49 void CMemSpyEngineHelperStack::ConstructL()
       
    50     {
       
    51     }
       
    52 
       
    53 
       
    54 CMemSpyEngineHelperStack* CMemSpyEngineHelperStack::NewL( CMemSpyEngine& aEngine )
       
    55     {
       
    56     CMemSpyEngineHelperStack* self = new(ELeave) CMemSpyEngineHelperStack( aEngine );
       
    57     CleanupStack::PushL( self );
       
    58     self->ConstructL();
       
    59     CleanupStack::Pop( self );
       
    60     return self;
       
    61     }
       
    62 
       
    63 
       
    64 EXPORT_C void CMemSpyEngineHelperStack::OutputStackInfoL( const CMemSpyThread& aThread )
       
    65     {
       
    66     const TFullName pName( aThread.FullName() );
       
    67     //
       
    68     _LIT(KHeader, "STACK INFO FOR THREAD '%S'");
       
    69     TBuf<KMaxFullName + 100> printFormat;
       
    70     printFormat.Format( KHeader, &pName );
       
    71     iEngine.Sink().OutputSectionHeadingL( printFormat, '=' );
       
    72 
       
    73     OutputStackInfoL( aThread.Process().Id(), aThread.Id(), printFormat );
       
    74     }
       
    75 
       
    76 
       
    77 EXPORT_C void CMemSpyEngineHelperStack::OutputStackInfoL( TProcessId aPid, TThreadId aTid, TDes& aLineBuffer )
       
    78     {
       
    79     TMemSpyDriverStackInfo info;
       
    80     //
       
    81     iEngine.ProcessSuspendLC( aPid );
       
    82     const TInt r = iEngine.Driver().GetStackInfo( aTid, info );
       
    83     CleanupStack::PopAndDestroy(); // ProcessSuspendLC
       
    84     //
       
    85     if  ( r == KErrNone )
       
    86         {
       
    87         CMemSpyEngineOutputList* list = CMemSpyEngineOutputList::NewLC( iEngine.Sink() );
       
    88 
       
    89         {
       
    90         // Header - user stack
       
    91         list->AddItemL( _L("USER STACK") );
       
    92         list->AddUnderlineForPreviousItemL();
       
    93 
       
    94         // Summary
       
    95         list->AddItemFormatL( _L("Address range"), _L("0x%08x - 0x%08x (%8d)"), info.iUserStackBase, info.iUserStackBase + info.iUserStackSize, info.iUserStackSize );
       
    96         list->AddItemHexL( _L("Current stack pointer"), info.iUserStackPointer );
       
    97 
       
    98         // Calculate usage
       
    99         const TInt usedUserStack = (TInt) ( info.iUserStackBase + info.iUserStackSize ) - info.iUserStackPointer;
       
   100         const TInt userStackUsagePct = (TInt) (( (TReal) usedUserStack / (TReal) info.iUserStackSize) * 100.0);
       
   101         aLineBuffer.Format(_L("%d (%3d"), usedUserStack, userStackUsagePct);
       
   102         aLineBuffer.Append(_L(" pct)"));
       
   103         list->AddItemL( _L("Stack usage"), aLineBuffer );
       
   104 
       
   105         // High watermark
       
   106         list->AddItemHexL( _L("High watermark"), info.iUserStackHighWatermark );
       
   107         const TInt userHighWaterMarkUsage = (TInt) ( info.iUserStackBase + info.iUserStackSize ) - info.iUserStackHighWatermark;
       
   108         const TInt userStackHighWaterMarkUsagePct = (TInt) (( (TReal) userHighWaterMarkUsage / (TReal) info.iUserStackSize) * 100.0);
       
   109         aLineBuffer.Format(_L("%d (%3d"), userHighWaterMarkUsage, userStackHighWaterMarkUsagePct);
       
   110         aLineBuffer.Append(_L(" pct)"));
       
   111         list->AddItemL( _L("High watermark usage"), aLineBuffer );
       
   112         }
       
   113 
       
   114 
       
   115         {
       
   116         // Header - supervisor stack
       
   117         list->AddItemL( _L("SUPERVISOR STACK") );
       
   118         list->AddUnderlineForPreviousItemL();
       
   119 
       
   120         // Summary
       
   121         list->AddItemFormatL( _L("Address range"), _L("0x%08x - 0x%08x (%8d)"), info.iSupervisorStackBase, info.iSupervisorStackBase + info.iSupervisorStackSize, info.iSupervisorStackSize );
       
   122         list->AddItemHexL( _L("Current stack pointer"), info.iSupervisorStackPointer );
       
   123 
       
   124         // Calculate usage
       
   125         const TInt usedSupervisorStack = (TInt) ( info.iSupervisorStackBase + info.iSupervisorStackSize ) - info.iSupervisorStackPointer;
       
   126         const TInt supervisorStackUsagePct = (TInt) (( (TReal) usedSupervisorStack / (TReal) info.iSupervisorStackSize) * 100.0);
       
   127         aLineBuffer.Format(_L("%d (%3d"), usedSupervisorStack, supervisorStackUsagePct );
       
   128         aLineBuffer.Append(_L(" pct)"));
       
   129         list->AddItemL( _L("Stack usage"), aLineBuffer );
       
   130 
       
   131         // High watermark
       
   132         list->AddItemHexL( _L("High watermark"), info.iSupervisorStackHighWatermark );
       
   133         const TInt supervisorStackHighWaterMarkUsage = (TInt) ( info.iSupervisorStackBase + info.iSupervisorStackSize ) - info.iSupervisorStackHighWatermark;
       
   134         const TInt supervisorStackHighWaterMarkUsagePct = (TInt) (( (TReal) supervisorStackHighWaterMarkUsage / (TReal) info.iSupervisorStackSize) * 100.0);
       
   135         aLineBuffer.Format(_L("%d (%3d"), supervisorStackHighWaterMarkUsage, supervisorStackHighWaterMarkUsagePct );
       
   136         aLineBuffer.Append(_L(" pct)"));
       
   137         list->AddItemL( _L("High watermark usage"), aLineBuffer );
       
   138         }
       
   139 
       
   140         list->PrintL();
       
   141         CleanupStack::PopAndDestroy( list );
       
   142         }
       
   143 
       
   144     }
       
   145 
       
   146 
       
   147 EXPORT_C void CMemSpyEngineHelperStack::OutputStackDataL( const CMemSpyThread& aThread, TMemSpyDriverDomainType aType )
       
   148     {
       
   149     OutputStackDataL( aThread, aType, ETrue );
       
   150     }
       
   151 
       
   152 
       
   153 EXPORT_C void CMemSpyEngineHelperStack::OutputStackDataL( const CMemSpyThread& aThread, TMemSpyDriverDomainType aType, TBool aEntireStack )
       
   154     {
       
   155     TBuf<KMaxFullName + 100> printFormat;
       
   156     printFormat = aThread.FullName();
       
   157 
       
   158     // Begin a new data stream
       
   159     _LIT( KMemSpyFolder, "Stack" );
       
   160     HBufC* context = HBufC::NewLC( KMaxFileName );
       
   161     TPtr pContext( context->Des() );
       
   162     if  ( aType == EMemSpyDriverDomainUser )
       
   163         {
       
   164         _LIT(KMemSpyContext, "Data (User) - %S");
       
   165         pContext.Format( KMemSpyContext, &printFormat );
       
   166         }
       
   167     else if ( aType == EMemSpyDriverDomainKernel )
       
   168         {
       
   169         _LIT(KMemSpyContext, "Data (Supervisor) - %S");
       
   170         pContext.Format( KMemSpyContext, &printFormat );
       
   171         }
       
   172     iEngine.Sink().DataStreamBeginL( pContext, KMemSpyFolder );
       
   173     CleanupStack::PopAndDestroy( context );
       
   174 
       
   175     // Suspend all threads in the process
       
   176     iEngine.ProcessSuspendLC( aThread.Process().Id() );
       
   177 
       
   178     // Start marker
       
   179     iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerStackData, &KNullDesC, (TUint) aThread.Id() );
       
   180 
       
   181     // Set overall prefix
       
   182     iEngine.Sink().OutputPrefixSetFormattedLC( KMemSpyPrefixStackData, &printFormat );
       
   183 
       
   184     // Prepare data buffer
       
   185     HBufC8* data = HBufC8::NewLC( 4096 * 4 );
       
   186     TPtr8 pData(data->Des());
       
   187     TUint remaining = 0;
       
   188 
       
   189     TMemSpyDriverStackInfo info;
       
   190     TInt r = iEngine.Driver().GetStackInfo( aThread.Id(), info );
       
   191     if  ( r == KErrNone )
       
   192         {
       
   193         TUint spAddress = 0;
       
   194         if  ( aType == EMemSpyDriverDomainUser )
       
   195             {
       
   196             _LIT(KHeaderUser, "USER STACK DATA");
       
   197             iEngine.Sink().OutputSectionHeadingL(KHeaderUser, '-');
       
   198             spAddress = info.iUserStackPointer;
       
   199             }
       
   200         else if ( aType == EMemSpyDriverDomainKernel )
       
   201             {
       
   202             _LIT(KHeaderKernel, "SUPERVISOR STACK DATA");
       
   203             iEngine.Sink().OutputSectionHeadingL(KHeaderKernel, '-');
       
   204             spAddress = info.iSupervisorStackPointer;
       
   205             }
       
   206 
       
   207         // Print header information
       
   208         // ========================
       
   209         TBuf<240> buf;
       
   210 
       
   211         // Stack pointer
       
   212         _LIT( KLine1, "Current stack pointer: 0x%08x");
       
   213         buf.Format( KLine1, spAddress );
       
   214         iEngine.Sink().OutputLineL( buf );
       
   215 
       
   216         // Stack address range
       
   217         _LIT( KLine2, "Stack address range:   0x%08x - 0x%08x");
       
   218         if  ( aType == EMemSpyDriverDomainUser )
       
   219             {
       
   220             buf.Format( KLine2, info.iUserStackBase, info.iUserStackBase + info.iUserStackSize );
       
   221             }
       
   222         else
       
   223             {
       
   224             buf.Format( KLine2, info.iSupervisorStackBase, info.iSupervisorStackBase + info.iSupervisorStackSize );
       
   225             }
       
   226         iEngine.Sink().OutputLineL( buf );
       
   227 
       
   228         // Stack size
       
   229         _LIT( KLine3, "Stack size:              %d");
       
   230         buf.Format( KLine3, ( aType == EMemSpyDriverDomainUser ) ? info.iUserStackSize : info.iSupervisorStackSize );
       
   231         iEngine.Sink().OutputLineL( buf );
       
   232         iEngine.Sink().OutputBlankLineL();
       
   233 
       
   234         // If we are only fetching the 'current' part of the stack, then we need to maniuplate the
       
   235         // printing address used to display the stack content
       
   236         if  ( !aEntireStack )
       
   237             {
       
   238             // We start at the stack pointer address and work towards the end of the stack.
       
   239             info.iUserStackBase = spAddress;
       
   240             }
       
   241 
       
   242         // Code segments (needed for map file reading...)
       
   243         _LIT(KCodeSegInfoPrefix, "CodeSeg - ");
       
   244         iEngine.HelperCodeSegment().OutputCodeSegmentsL( aThread.Process().Id(), printFormat, KCodeSegInfoPrefix );
       
   245         
       
   246         // Get the stack data
       
   247         // ==================
       
   248         _LIT(KStackDataPrefix, "%S");
       
   249         r = iEngine.Driver().GetStackData( aThread.Id(), pData, remaining, aType, aEntireStack );
       
   250 
       
   251         if  ( r == KErrNone )
       
   252             {
       
   253             while ( r == KErrNone )
       
   254                 {
       
   255                 iEngine.Sink().OutputBinaryDataL( KStackDataPrefix, pData.Ptr(), (const TUint8*) info.iUserStackBase, pData.Length() );
       
   256                 //
       
   257                 if  ( remaining > 0 )
       
   258                     {
       
   259                     info.iUserStackBase += pData.Length();
       
   260                     r = iEngine.Driver().GetStackDataNext( aThread.Id(), pData, remaining, aType, aEntireStack );
       
   261                     }
       
   262                 else
       
   263                     {
       
   264                     break;
       
   265                     }
       
   266                 }
       
   267             }
       
   268 
       
   269         }
       
   270     CleanupStack::PopAndDestroy( data );
       
   271 
       
   272     CleanupStack::PopAndDestroy(); // clear prefix
       
   273     CleanupStack::PopAndDestroy(); // resume process
       
   274 
       
   275     // End marker
       
   276     iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerStackData, &KMemSpySinkTagClose, (TUint) aThread.Id() );
       
   277     iEngine.Sink().DataStreamEndL();
       
   278     }
       
   279 
       
   280 
       
   281 EXPORT_C void CMemSpyEngineHelperStack::OutputStackInfoForDeviceL()
       
   282     {
       
   283     const TInt count = iEngine.Container().Count();
       
   284     //
       
   285     HBufC* buf = HBufC::NewLC( 1024 );
       
   286     TPtr pBuf(buf->Des());
       
   287     //
       
   288     _LIT( KMemSpyContext, "Stack" );
       
   289     _LIT( KMemSpyFolder, "Device-Wide" );
       
   290     _LIT( KMemSpyExtension, ".csv" );
       
   291     iEngine.Sink().DataStreamBeginL( KMemSpyContext, KMemSpyFolder, KMemSpyExtension );
       
   292 
       
   293     // Set overall prefix
       
   294     _LIT(KOverallPrefix, "[Stack Summary]");
       
   295     iEngine.Sink().OutputPrefixSetLC( KOverallPrefix );
       
   296 
       
   297     _LIT(KListingHeader, "Thread, US. Base Address, US. Size, US. Addr, US. Usage, US. Usage Pct, US. HWM Addr, US. HWM Usage, US. HWM Usage Pct, SS. Base Address, SS. Size, SS. Addr, SS. Usage, SS. Usage Pct., SS. HWM Addr, SS. HWM Usage, SS. HWM Usage Pct");
       
   298     iEngine.Sink().OutputBlankLineL();
       
   299     iEngine.Sink().OutputLineL(KListingHeader);
       
   300     
       
   301     for(TInt ii=0; ii<count; ii++)
       
   302         {
       
   303         const CMemSpyProcess& process = iEngine.Container().At( ii );
       
   304         const TPtrC procName( process.Name() );
       
   305         //
       
   306         if  ( iEngine.ProcessSuspendAndGetErrorLC( process.Id() ) == KErrNone )
       
   307             {
       
   308             TMemSpyDriverStackInfo info;
       
   309             const TInt threadCount = process.Count();
       
   310             //
       
   311             for(TInt j=0; j<threadCount; j++)
       
   312                 {
       
   313                 const CMemSpyThread& thread = process.At( j );
       
   314                 const TPtrC threadName(thread.Name());
       
   315 
       
   316                 const TInt error = iEngine.Driver().GetStackInfo( thread.Id(), info );
       
   317                 if  ( error == KErrNone )
       
   318                     {
       
   319                     const TInt userStackUsage = (TInt) ( info.iUserStackBase + info.iUserStackSize ) - info.iUserStackPointer;
       
   320                     const TInt userStackUsagePct = (TInt) (( (TReal) userStackUsage / (TReal) info.iUserStackSize) * 100.0);
       
   321                     const TInt userStackHighWaterMarkUsage = (TInt) ( info.iUserStackBase + info.iUserStackSize ) - info.iUserStackHighWatermark;
       
   322                     const TInt userStackHighWaterMarkUsagePct = (TInt) (( (TReal) userStackHighWaterMarkUsage / (TReal) info.iUserStackSize) * 100.0);
       
   323                     const TInt supervisorStackUsage = (TInt) ( info.iSupervisorStackBase + info.iSupervisorStackSize ) - info.iSupervisorStackPointer;
       
   324                     const TInt supervisorStackUsagePct = (TInt) (( (TReal) supervisorStackUsage / (TReal) info.iSupervisorStackSize) * 100.0);
       
   325                     const TInt supervisorStackHighWaterMarkUsage = (TInt) ( info.iSupervisorStackBase + info.iSupervisorStackSize ) - info.iSupervisorStackHighWatermark;
       
   326                     const TInt supervisorStackHighWaterMarkUsagePct = (TInt) (( (TReal) supervisorStackHighWaterMarkUsage / (TReal) info.iSupervisorStackSize) * 100.0);
       
   327 
       
   328                     _LIT(KFormat, "%S::%S, 0x%08x, %8d, 0x%08x, %8d, %8d, 0x%08x, %8d, %8d, 0x%08x, %8d, 0x%08x, %8d, %8d, 0x%08x, %8d, %8d");
       
   329                     pBuf.Format(  KFormat, &procName, &threadName, 
       
   330                                  info.iUserStackBase, 
       
   331                                  info.iUserStackSize, 
       
   332                                  info.iUserStackPointer, 
       
   333                                  userStackUsage,
       
   334                                  userStackUsagePct,
       
   335                                  info.iUserStackHighWatermark,
       
   336                                  userStackHighWaterMarkUsage,
       
   337                                  userStackHighWaterMarkUsagePct,
       
   338                                  info.iSupervisorStackBase,
       
   339                                  info.iSupervisorStackSize,
       
   340                                  info.iSupervisorStackPointer,
       
   341                                  supervisorStackUsage,
       
   342                                  supervisorStackUsagePct,
       
   343                                  info.iSupervisorStackHighWatermark,
       
   344                                  supervisorStackHighWaterMarkUsage,
       
   345                                  supervisorStackHighWaterMarkUsagePct
       
   346                                  );
       
   347                     iEngine.Sink().OutputLineL( pBuf );
       
   348                     }
       
   349                 }
       
   350             }
       
   351         
       
   352         CleanupStack::PopAndDestroy(); // ProcessSuspendLC
       
   353         }
       
   354 
       
   355     CleanupStack::PopAndDestroy(); // clear prefix
       
   356 
       
   357     CleanupStack::PopAndDestroy( buf );
       
   358 
       
   359     _LIT(KEndOfHeapListing, "<= End Stack Summary =>");
       
   360     iEngine.Sink().OutputLineL( KEndOfHeapListing );
       
   361 
       
   362     iEngine.Sink().DataStreamEndL();
       
   363     }
       
   364 
       
   365 
       
   366 EXPORT_C TInt CMemSpyEngineHelperStack::CalculateStackSizes( const CMemSpyProcess& aProcess )
       
   367     {
       
   368     TInt ret = 0;
       
   369     //
       
   370     TRAPD( error, ret = CalculateStackSizesL( aProcess ) );
       
   371     //
       
   372     if ( error != KErrNone )
       
   373         {
       
   374         ret = error;
       
   375         }
       
   376     //
       
   377     return ret;
       
   378     }
       
   379 
       
   380 
       
   381 TInt CMemSpyEngineHelperStack::CalculateStackSizesL( const CMemSpyProcess& aProcess )
       
   382     {
       
   383 	TInt ret = 0;
       
   384 	//
       
   385     iEngine.ProcessSuspendLC( aProcess.Id() );
       
   386 
       
   387     TMemSpyDriverStackInfo info;
       
   388     //
       
   389     const TInt threadCount = aProcess.Count();
       
   390     for( TInt i=0; i<threadCount; i++ )
       
   391         {
       
   392         const CMemSpyThread& thread = aProcess.At( i );
       
   393         //
       
   394         TInt r = iEngine.Driver().GetStackInfo( thread.Id(), info );
       
   395         if  ( r == KErrNone )
       
   396             {
       
   397             ret += info.iUserStackSize;
       
   398             ret += info.iSupervisorStackSize;
       
   399             }
       
   400         }
       
   401     //
       
   402     CleanupStack::PopAndDestroy(); // ProcessSuspendLC
       
   403 	return ret;
       
   404     }
       
   405 
       
   406 
       
   407