memspy/Engine/Source/Helpers/MemSpyEngineHelperActiveObject.cpp
changeset 0 a03f92240627
child 30 86a2e675b80a
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/memspyenginehelperactiveobject.h>
       
    19 
       
    20 // System includes
       
    21 #include <s32mem.h>
       
    22 #include <e32svr.h>
       
    23 
       
    24 // Driver includes
       
    25 #include <memspy/driver/memspydriverclient.h>
       
    26 
       
    27 // User includes
       
    28 #include <memspy/engine/memspyengine.h>
       
    29 #include <memspy/engine/memspyengineutils.h>
       
    30 #include <memspy/engine/memspyengineoutputsink.h>
       
    31 #include <memspy/engine/memspyengineobjectthread.h>
       
    32 #include <memspy/engine/memspyengineobjectprocess.h>
       
    33 #include <memspy/engine/memspyenginehelperheap.h>
       
    34 
       
    35 // Driver includes
       
    36 #include <memspy/driver/memspydriverconstants.h>
       
    37 
       
    38 // Literal constants
       
    39 _LIT( KMemSpyEngineAOOutputComma, ", " );
       
    40 
       
    41 
       
    42 
       
    43 CMemSpyEngineHelperActiveObject::CMemSpyEngineHelperActiveObject( CMemSpyEngine& aEngine )
       
    44 :   iEngine( aEngine )
       
    45     {
       
    46     }
       
    47 
       
    48     
       
    49 CMemSpyEngineHelperActiveObject::~CMemSpyEngineHelperActiveObject()
       
    50     {
       
    51     }
       
    52 
       
    53 
       
    54 void CMemSpyEngineHelperActiveObject::ConstructL()
       
    55     {
       
    56     }
       
    57 
       
    58 
       
    59 CMemSpyEngineHelperActiveObject* CMemSpyEngineHelperActiveObject::NewL( CMemSpyEngine& aEngine )
       
    60     {
       
    61     CMemSpyEngineHelperActiveObject* self = new(ELeave) CMemSpyEngineHelperActiveObject( aEngine );
       
    62     CleanupStack::PushL( self );
       
    63     self->ConstructL();
       
    64     CleanupStack::Pop( self );
       
    65     return self;
       
    66     }
       
    67 
       
    68 
       
    69 EXPORT_C CMemSpyEngineActiveObjectArray* CMemSpyEngineHelperActiveObject::ActiveObjectListL( const CMemSpyThread& aThread )
       
    70     {
       
    71     //RDebug::Printf("CMemSpyEngineHelperActiveObject::ActiveObjectListLC() - START");
       
    72     CMemSpyEngineActiveObjectArray* array = CMemSpyEngineActiveObjectArray::NewLC();
       
    73 
       
    74     // Is the thread's process already suspended? If not, we need to do it now.
       
    75     const TProcessId parentProcessId( aThread.Process().Id() );
       
    76     const TBool isSuspended = ( iEngine.SuspendedProcessId() == parentProcessId );
       
    77     if  ( !isSuspended )
       
    78         {
       
    79         //RDebug::Printf("CMemSpyEngineHelperActiveObject::ActiveObjectListLC() - suspending process");
       
    80         iEngine.ProcessSuspendLC( parentProcessId );
       
    81         }
       
    82 
       
    83     // Push a cleanup item to close the heap walk in case of leaves
       
    84     CleanupStack::PushL( TCleanupItem( CleanupHeapWalk, this ) );
       
    85 
       
    86     // Get the thread info
       
    87     //RDebug::Printf("CMemSpyEngineHelperActiveObject::ActiveObjectListLC() - getting thread info...");
       
    88     TMemSpyDriverThreadInfo threadInfo;
       
    89     TInt err = iEngine.Driver().GetThreadInfo( aThread.Id(), threadInfo );
       
    90     User::LeaveIfError( err );
       
    91     TAny* scheduler = threadInfo.iScheduler;
       
    92 
       
    93 #if defined( _DEBUG ) && !defined( __WINS__ )
       
    94     iEngine.HelperHeap().OutputCellListingUserL( aThread );
       
    95 #endif
       
    96 
       
    97     // Get the heap info - we need this for verification purposes
       
    98     //RDebug::Printf("CMemSpyEngineHelperActiveObject::ActiveObjectListLC() - getting heap info...");
       
    99     err = iEngine.Driver().GetHeapInfoUser( iHeapInfo, aThread.Id() );
       
   100     User::LeaveIfError( err );
       
   101     //RDebug::Printf("CMemSpyEngineHelperActiveObject::ActiveObjectListLC() - allocated cell header length is: %d", iHeapInfo.iHeapCellHeaderLengthAllocated);
       
   102 
       
   103     // Do we have a ROM-based scheduler pointer?
       
   104     if  ( scheduler != NULL && iHeapInfo.Type() == TMemSpyHeapInfo::ETypeRHeap )
       
   105         {
       
   106         //RDebug::Printf("CMemSpyEngineHelperActiveObject::ActiveObjectListLC() - scheduler: 0x%08x", scheduler);
       
   107 
       
   108         // Let's try to get the scheduler's heap cell...
       
   109         HBufC8* data = SchedulerHeapCellDataLC( scheduler, aThread.Id() );
       
   110         
       
   111         // Try to extract the active object addresses
       
   112         ExtractActiveObjectAddressesL( scheduler, *data, *array );
       
   113         CleanupStack::PopAndDestroy( data );
       
   114         }
       
   115 
       
   116     // Tidy up
       
   117     CleanupStack::PopAndDestroy(); // heap walk cleanup item
       
   118     if  ( !isSuspended )
       
   119         {
       
   120         iEngine.ProcessResume();
       
   121         }
       
   122     //
       
   123     CleanupStack::Pop( array );
       
   124     //RDebug::Printf("CMemSpyEngineHelperActiveObject::ActiveObjectListLC() - END");
       
   125     return array;
       
   126     }
       
   127 
       
   128 
       
   129 HBufC8* CMemSpyEngineHelperActiveObject::SchedulerHeapCellDataLC( TAny*& aCellAddress, TThreadId aThreadId )
       
   130     {
       
   131     //RDebug::Printf("CMemSpyEngineHelperActiveObject::SchedulerHeapCellDataLC() - START - aCellAddress: 0x%08x, aThread: %d", aCellAddress, I64INT(aThreadId.Id()));
       
   132 
       
   133     // This is what we'll return, if we find it...
       
   134     HBufC8* heapCellData = NULL;
       
   135 
       
   136     // Now walk the heap!
       
   137     TInt err = iEngine.Driver().WalkHeapInit( aThreadId );
       
   138     User::LeaveIfError( err );
       
   139 
       
   140     // Now we can try to find the cell's info
       
   141     TMemSpyDriverCellType cellType;
       
   142     TInt cellLength;
       
   143     TInt cellNestingLevel;
       
   144     TInt cellAllocationNumber;
       
   145     TInt cellHeaderSize;
       
   146     TAny* cellPayloadAddress;
       
   147     //
       
   148     err = iEngine.Driver().WalkHeapGetCellInfo( aCellAddress, cellType, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   149     //RDebug::Printf("CMemSpyEngineHelperActiveObject::SchedulerHeapCellDataLC() - err: %d, cellLength: %d, cellAllocationNumber: %d, cellType: %d", err, cellLength, cellAllocationNumber, cellType);
       
   150     User::LeaveIfError( err );
       
   151     
       
   152     if  ( cellType == EMemSpyDriverGoodAllocatedCell )
       
   153         {
       
   154         const TInt payloadLength = cellLength - iHeapInfo.AsRHeap().MetaData().HeaderSizeAllocated();
       
   155         HBufC8* data = HBufC8::NewLC( payloadLength );
       
   156         TPtr8 pData( data->Des() );
       
   157         //
       
   158         err = iEngine.Driver().WalkHeapReadCellData( aCellAddress, pData, payloadLength );
       
   159         //RDebug::Printf("CMemSpyEngineHelperActiveObject::SchedulerHeapCellDataLC() - data fetch returned error: %d", err);
       
   160         User::LeaveIfError( err );
       
   161         heapCellData = data;
       
   162         CleanupStack::Pop( data );
       
   163         }
       
   164     //
       
   165     if  ( heapCellData == NULL )
       
   166         {
       
   167         //RDebug::Printf("CMemSpyEngineHelperActiveObject::SchedulerHeapCellDataLC() - END - didn't find the right cell => KErrNotFound");
       
   168         User::Leave( KErrNotFound );
       
   169         }
       
   170     //
       
   171     CleanupStack::PushL( heapCellData );
       
   172 
       
   173     //RDebug::Printf("CMemSpyEngineHelperActiveObject::SchedulerHeapCellDataLC() - END - everything okay, cell is: 0x%08x", aCellAddress);
       
   174     return heapCellData;
       
   175     }
       
   176 
       
   177 
       
   178 void CMemSpyEngineHelperActiveObject::ExtractActiveObjectAddressesL( TAny* aSchedulerCellAddress, const TDesC8& aSchedulerCellData, CMemSpyEngineActiveObjectArray& aArray )
       
   179     {
       
   180     // Create read stream
       
   181     RDesReadStream stream( aSchedulerCellData );
       
   182     CleanupClosePushL( stream );
       
   183 
       
   184     // First item is vtable
       
   185     TUint address = stream.ReadUint32L();
       
   186     //RDebug::Printf("CMemSpyEngineHelperActiveObject::ExtractActiveObjectAddressesL() - vtable: 0x%08x", address );
       
   187     (void) address;
       
   188 
       
   189     // Next item is CActiveScheduler::iStack - which we'll skip, because it might be a stack address
       
   190     // I suppose we could validate this against the thread's stack address range, but can't be bothered
       
   191     // at the moment.
       
   192     address = stream.ReadUint32L();
       
   193     //RDebug::Printf("CMemSpyEngineHelperActiveObject::ExtractActiveObjectAddressesL() - got CActiveScheduler::iStack as: 0x%08x", address);
       
   194     (void) address;
       
   195 
       
   196     // Then comes CActiveScheduler::iActiveQ - this is what we are interested in.... 
       
   197     //
       
   198     //  class TPriQue : public TDblQueBase
       
   199     //        [TDblQueBase::iHead] - this just derives from TDblQueLinkBase and doesn't have any direct data members
       
   200     //            class TDblQueLink : public TDblQueLinkBase
       
   201     //                [ptr]  TDblQueLinkBase::iNext*
       
   202     //                [ptr]  TDblQueLinkBase::iPrev*
       
   203     // [TInt] TDblQueBase::iOffset
       
   204     __ASSERT_COMPILE( sizeof( TDblQueLinkBase* ) == sizeof(TUint) );
       
   205     __ASSERT_COMPILE( sizeof( TInt ) == 4 );
       
   206 
       
   207     // Get read offset so that we know the starting address of the queue
       
   208     const TStreamPos pos = stream.Source()->TellL(MStreamBuf::ERead);
       
   209 #ifdef __WINS__
       
   210     const TAny* terminatingQueueAddress = (TAny*) (TUint(aSchedulerCellAddress) + pos.Offset());
       
   211 #else
       
   212     const TAny* terminatingQueueAddress = (TAny*) aSchedulerCellAddress;
       
   213 #endif
       
   214 
       
   215     const TAny* queueNext = (TAny*) stream.ReadUint32L();
       
   216     const TAny* queuePrev = (TAny*) stream.ReadUint32L();
       
   217     const TUint queueItemOffset = stream.ReadUint32L();
       
   218     //RDebug::Printf("CMemSpyEngineHelperActiveObject::ExtractActiveObjectAddressesL() - queueNext: 0x%08x, queuePrev: 0x%08x, queueItemOffset: %d, pos: %d, terminatingQueueAddress: 0x%08x", queueNext, queuePrev, queueItemOffset, pos.Offset(), terminatingQueueAddress);
       
   219     (void) queuePrev;
       
   220     CleanupStack::PopAndDestroy( &stream );
       
   221         
       
   222     // Iterate through the active objects
       
   223     if  ( queueNext != NULL )
       
   224         {
       
   225         TAny* realNextCellHeapCell = NULL;
       
   226         TAny* calculatedCellAddress = ((TAny*) (TUint(queueNext) - queueItemOffset));
       
   227 
       
   228         while( !( calculatedCellAddress == NULL || calculatedCellAddress == terminatingQueueAddress || realNextCellHeapCell == terminatingQueueAddress ) )
       
   229             {
       
   230             // Create an active object for this cell
       
   231             TAny* nextCell = ReadActiveObjectDataL( calculatedCellAddress, aArray );
       
   232             
       
   233             // Work out next cell address
       
   234             calculatedCellAddress = ((TAny*) ( TUint( nextCell ) - queueItemOffset ) );
       
   235             //RDebug::Printf("CMemSpyEngineHelperActiveObject::ExtractActiveObjectAddressesL() - calculatedCellAddress: 0x%08x, terminatingQueueAddress: 0x%08x", calculatedCellAddress, terminatingQueueAddress);
       
   236 
       
   237             // Identify the next cell address
       
   238             realNextCellHeapCell = ConvertAddressToRealHeapCellAddressL( nextCell );
       
   239             }
       
   240         }
       
   241     }
       
   242 
       
   243 
       
   244 TAny* CMemSpyEngineHelperActiveObject::ConvertAddressToRealHeapCellAddressL( TAny* aAddress )
       
   245     {
       
   246     //RDebug::Printf("CMemSpyEngineHelperActiveObject::ConvertAddressToRealHeapCellAddressL() - START - aAddress: 0x%08x", aAddress);
       
   247 
       
   248     TMemSpyDriverCellType cellType;
       
   249     TInt cellLength;
       
   250     TInt cellNestingLevel;
       
   251     TInt cellAllocationNumber;
       
   252     TInt cellHeaderSize;
       
   253     TAny* cellPayloadAddress;
       
   254 
       
   255     TInt err = iEngine.Driver().WalkHeapGetCellInfo( aAddress, cellType, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   256     //RDebug::Printf("CMemSpyEngineHelperActiveObject::ConvertAddressToRealHeapCellAddressL() - END - err: %d, realCellAddress: 0x%08x, cellLength: %d, cellAllocationNumber: %d, cellType: %d", err, aAddress, cellLength, cellAllocationNumber, cellType);
       
   257     User::LeaveIfError( err );
       
   258 
       
   259     return aAddress;
       
   260     }
       
   261 
       
   262 
       
   263 TAny* CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL( TAny* aCellAddress, CMemSpyEngineActiveObjectArray& aArray )
       
   264     {
       
   265     //RDebug::Printf("CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL() - START");
       
   266 
       
   267     //RDebug::Printf("CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL() - AO.cellAddress:     0x%08x", aCellAddress);
       
   268     TAny* nextCellAddress = NULL;
       
   269     
       
   270     TMemSpyDriverCellType cellType;
       
   271     TInt cellLength;
       
   272     TInt cellNestingLevel;
       
   273     TInt cellAllocationNumber;
       
   274     TInt cellHeaderSize;
       
   275     TAny* cellPayloadAddress;
       
   276 
       
   277     // Make a separate copy of the cell address - calling GetCellInfo may well result in the address being
       
   278     // changed in order to match the real starting address of a *heap cell*.
       
   279     TAny* requestedCellAddress = aCellAddress;
       
   280     TInt err = iEngine.Driver().WalkHeapGetCellInfo( requestedCellAddress, cellType, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   281     //RDebug::Printf("CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL() - err: %d, cellLength: %d, cellAllocationNumber: %d, cellType: %d", err, cellLength, cellAllocationNumber, cellType);
       
   282     User::LeaveIfError( err );
       
   283     
       
   284     if  ( cellType == EMemSpyDriverGoodAllocatedCell )
       
   285         {
       
   286         const TInt payloadLength = cellLength - iHeapInfo.AsRHeap().MetaData().HeaderSizeAllocated();
       
   287         //RDebug::Printf("CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL() - payloadLength: %d", payloadLength);
       
   288 
       
   289         // const TInt payloadLength = Max( 512, cellLength - iHeapInfo.iHeapCellHeaderLengthAllocated ); // Prevent negative payload lengths?
       
   290         CBufFlat* data = CBufFlat::NewL( payloadLength );
       
   291         CleanupStack::PushL( data );
       
   292         data->ResizeL( payloadLength );
       
   293         TPtr8 pData( data->Ptr( 0 ) );
       
   294         //
       
   295         err = iEngine.Driver().WalkHeapReadCellData( requestedCellAddress, pData, payloadLength );
       
   296         //RDebug::Printf("CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL() - AO.heapCellAddress: 0x%08x (err: %d)", requestedCellAddress, err);
       
   297         User::LeaveIfError( err );
       
   298 
       
   299         // If an object is embedded directly within a class, for example
       
   300         //
       
   301         // class CSomething : public CBase
       
   302         //   {
       
   303         //   CIdle iEmbeddedIdler;
       
   304         //   }
       
   305         //
       
   306         // then aCellAddress actually points to somewhere *within* a heap cell, not to the actual starting address of
       
   307         // the heap cell itself. We must take this into account when parsing the heap cell data (i.e. the bit of the cell we
       
   308         // are interested in starts part way through the cell data).
       
   309         TInt cellOffset = TUint32( aCellAddress ) - TUint32( requestedCellAddress );
       
   310         //RDebug::Printf("CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL() - AO.cellOffset:      %d (ignoring cell header)", cellOffset);
       
   311         cellOffset -= cellHeaderSize;
       
   312         //RDebug::Printf("CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL() - AO.cellOffset:      %d (adjusted for cell header)", cellOffset);
       
   313 
       
   314         // Got the cell data for the active object. Let's parse it.
       
   315         RBufReadStream stream( *data, cellOffset );
       
   316         CleanupClosePushL( stream );
       
   317 
       
   318         // First item should be vTable
       
   319         TAny* vTable = (TAny*) stream.ReadUint32L();
       
   320         //RDebug::Printf("CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL() - AO.vTable:          0x%08x", vTable );
       
   321 
       
   322         // Next item should be the request status. First the iStatus, then the iFlags
       
   323         const TInt requestStatusValue = stream.ReadInt32L();
       
   324         //RDebug::Printf("CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL() - AO.rsVal:           %10d", requestStatusValue );
       
   325         const TUint requestStatusFlags = stream.ReadUint32L();
       
   326         //RDebug::Printf("CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL() - AO.rsFlags:         0x%02x", requestStatusFlags );
       
   327 
       
   328         // Next comes the baseclass for the link - TDblQueLinkBase
       
   329         TAny* nextEntryAddress = (TAny*) stream.ReadUint32L();
       
   330         //RDebug::Printf("CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL() - AO.iLink.Next:      0x%08x", nextEntryAddress );
       
   331         TAny* prevEntryAddress = (TAny*) stream.ReadUint32L();
       
   332         //RDebug::Printf("CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL() - AO.iLink.Prev:      0x%08x", prevEntryAddress );
       
   333 
       
   334         // Next comes the TPriQueueLink itself
       
   335         const TInt priority = stream.ReadInt32L();
       
   336         //RDebug::Printf("CMemSpyEngineHelperActiveObject::ReadActiveObjectDataL() - AO.iLink.Pri:       %d", priority );
       
   337         
       
   338         // Done - save object & tidy up
       
   339         CMemSpyEngineActiveObject* object = CMemSpyEngineActiveObject::NewLC( aCellAddress, vTable, priority, requestStatusValue, requestStatusFlags, nextEntryAddress, prevEntryAddress, iEngine );
       
   340         aArray.AddItemL( object );
       
   341         CleanupStack::Pop( object );
       
   342         CleanupStack::PopAndDestroy( 2, data ); // stream & data
       
   343         
       
   344         nextCellAddress = (TAny*) nextEntryAddress;
       
   345         //RDebug::Printf(" ");
       
   346         }
       
   347 
       
   348     return nextCellAddress;
       
   349     }
       
   350 
       
   351 
       
   352 void CMemSpyEngineHelperActiveObject::CleanupHeapWalk( TAny* aSelf )
       
   353     {
       
   354     CMemSpyEngineHelperActiveObject* self = reinterpret_cast< CMemSpyEngineHelperActiveObject* >( aSelf );
       
   355     self->iEngine.Driver().WalkHeapClose();
       
   356     }
       
   357 
       
   358 
       
   359 
       
   360 
       
   361 
       
   362 
       
   363 
       
   364 
       
   365 
       
   366 
       
   367 
       
   368 
       
   369 
       
   370 
       
   371 
       
   372 
       
   373 
       
   374 
       
   375 
       
   376 
       
   377 
       
   378 
       
   379 
       
   380 
       
   381 
       
   382 
       
   383 
       
   384 
       
   385 
       
   386 
       
   387 
       
   388 
       
   389 
       
   390 CMemSpyEngineActiveObjectArray::CMemSpyEngineActiveObjectArray()
       
   391     {
       
   392     }
       
   393 
       
   394 
       
   395 EXPORT_C CMemSpyEngineActiveObjectArray::~CMemSpyEngineActiveObjectArray()
       
   396     {
       
   397     delete iHeader;
       
   398     iObjects.ResetAndDestroy();
       
   399     iObjects.Close();
       
   400     }
       
   401 
       
   402 
       
   403 void CMemSpyEngineActiveObjectArray::ConstructL()
       
   404     {
       
   405     }
       
   406 
       
   407 
       
   408 CMemSpyEngineActiveObjectArray* CMemSpyEngineActiveObjectArray::NewLC(  )
       
   409     {
       
   410     CMemSpyEngineActiveObjectArray* self = new(ELeave) CMemSpyEngineActiveObjectArray();
       
   411     CleanupStack::PushL( self );
       
   412     self->ConstructL();
       
   413     return self;
       
   414     }
       
   415 
       
   416 
       
   417 EXPORT_C TInt CMemSpyEngineActiveObjectArray::Count() const
       
   418     {
       
   419     return iObjects.Count();
       
   420     }
       
   421 
       
   422 
       
   423 EXPORT_C CMemSpyEngineActiveObject& CMemSpyEngineActiveObjectArray::At( TInt aIndex )
       
   424     {
       
   425     return *iObjects[ aIndex ];
       
   426     }
       
   427 
       
   428 
       
   429 EXPORT_C const CMemSpyEngineActiveObject& CMemSpyEngineActiveObjectArray::At( TInt aIndex ) const
       
   430     {
       
   431     return *iObjects[ aIndex ];
       
   432     }
       
   433 
       
   434 
       
   435 EXPORT_C CMemSpyEngineActiveObject& CMemSpyEngineActiveObjectArray::ObjectByAddressL( TAny* aAddress )
       
   436     {
       
   437     const TInt index = ObjectIndexByAddress( aAddress );
       
   438     User::LeaveIfError( index );
       
   439     CMemSpyEngineActiveObject& ret = At( index );
       
   440     return ret;
       
   441     }
       
   442 
       
   443 
       
   444 EXPORT_C TInt CMemSpyEngineActiveObjectArray::ObjectIndexByAddress( TAny* aAddress ) const
       
   445     {
       
   446     TInt ret = KErrNotFound;
       
   447     //
       
   448     const TInt count = Count();
       
   449     for( TInt i=0; i<count; i++ )
       
   450         {
       
   451         const CMemSpyEngineActiveObject& object = At( i );
       
   452         //
       
   453         if  ( object.Address() == aAddress )
       
   454             {
       
   455             ret = i;
       
   456             break;
       
   457             }
       
   458         }
       
   459     //
       
   460     return ret;
       
   461     }
       
   462 
       
   463 
       
   464 EXPORT_C void CMemSpyEngineActiveObjectArray::OutputDataColumnsL( CMemSpyEngine& aEngine )
       
   465     {
       
   466     HBufC* columns = HBufC::NewLC( 1024 );
       
   467     TPtr pColumns( columns->Des() );
       
   468     //
       
   469     _LIT(KCol1, "Address");
       
   470     pColumns.Append( KCol1 );
       
   471     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   472     //
       
   473     _LIT(KCol3, "Priority");
       
   474     pColumns.Append( KCol3 );
       
   475     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   476     //
       
   477     _LIT(KCol4, "Is Active");
       
   478     pColumns.Append( KCol4 );
       
   479     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   480     //
       
   481     _LIT(KCol5, "Request Pending");
       
   482     pColumns.Append( KCol5 );
       
   483     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   484     //
       
   485     _LIT(KCol6, "Status Value");
       
   486     pColumns.Append( KCol6 );
       
   487     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   488     //
       
   489     _LIT(KCol7, "Status Flags");
       
   490     pColumns.Append( KCol7 );
       
   491     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   492     //
       
   493     _LIT(KCol8, "vTable Address");
       
   494     pColumns.Append( KCol8 );
       
   495     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   496     //
       
   497     _LIT(KCol9, "vTable for Symbolic Lookup");
       
   498     pColumns.Append( KCol9 );
       
   499     //
       
   500     aEngine.Sink().OutputLineL( pColumns );
       
   501     CleanupStack::PopAndDestroy( columns );
       
   502     }
       
   503 
       
   504 
       
   505 EXPORT_C TInt CMemSpyEngineActiveObjectArray::MdcaCount() const
       
   506     {
       
   507     TInt count = Count();
       
   508     //
       
   509     if  ( count > 0 )
       
   510         {
       
   511         ++count;
       
   512         }
       
   513     //
       
   514     return count;
       
   515     }
       
   516 
       
   517 
       
   518 EXPORT_C TPtrC CMemSpyEngineActiveObjectArray::MdcaPoint( TInt aIndex ) const
       
   519     {
       
   520     TPtrC ret( *iHeader );
       
   521     //
       
   522     if  ( aIndex > 0 )
       
   523         {
       
   524         const CMemSpyEngineActiveObject& object = At( aIndex - 1 );
       
   525         ret.Set( object.Caption() );
       
   526         }
       
   527     //
       
   528     return ret;
       
   529     }
       
   530 
       
   531 
       
   532 void CMemSpyEngineActiveObjectArray::AddItemL( CMemSpyEngineActiveObject* aItem )
       
   533     {
       
   534     iObjects.AppendL( aItem );
       
   535     BuildHeaderCaptionL();
       
   536     }
       
   537 
       
   538 
       
   539 void CMemSpyEngineActiveObjectArray::InsertL( CMemSpyEngineActiveObject* aItem, TInt aIndex )
       
   540     {
       
   541     iObjects.InsertL( aItem, aIndex );
       
   542     BuildHeaderCaptionL();
       
   543     }
       
   544 
       
   545 
       
   546 void CMemSpyEngineActiveObjectArray::BuildHeaderCaptionL()
       
   547     {
       
   548     const TInt KHeaderLength = 100;
       
   549     //
       
   550     if  ( !iHeader )
       
   551         {
       
   552         iHeader = HBufC::NewL( KHeaderLength );
       
   553         }
       
   554     //
       
   555     TPtr pHeader( iHeader->Des() );
       
   556     //
       
   557     _LIT(KCaption, "\tNumber of AO\'s\t\t%d");
       
   558     pHeader.Format( KCaption, Count() );
       
   559     }
       
   560 
       
   561 
       
   562 
       
   563 
       
   564 
       
   565 
       
   566 
       
   567 
       
   568 
       
   569 
       
   570 
       
   571 
       
   572 
       
   573 
       
   574 
       
   575 
       
   576 
       
   577 
       
   578 
       
   579 
       
   580 
       
   581 
       
   582 
       
   583 
       
   584 
       
   585 CMemSpyEngineActiveObject::CMemSpyEngineActiveObject( TAny* aAddress, TAny* aVTable, TInt aPriority, TInt aRSValue, TUint aRSFlags, TAny* aNextAOAddress, TAny* aPrevAOAddress )
       
   586 :   CDesCArrayFlat(6), iAddress( aAddress ), iVTable( aVTable ), iPriority( aPriority ), iRequestStatusValue( aRSValue ), iRequestStatusFlags( aRSFlags ), iNextAOAddress( aNextAOAddress ), iPrevAOAddress( aPrevAOAddress )
       
   587     {
       
   588     }
       
   589 
       
   590 
       
   591 EXPORT_C CMemSpyEngineActiveObject::~CMemSpyEngineActiveObject()
       
   592     {
       
   593     delete iCaption;
       
   594     }
       
   595 
       
   596 
       
   597 void CMemSpyEngineActiveObject::ConstructL( CMemSpyEngine& /*aEngine*/ )
       
   598     {
       
   599     TBuf<256> item;
       
   600 
       
   601     _LIT(KBasicFormat, "\t0x%08x\t\t");
       
   602     item.Format( KBasicFormat, VTable() );
       
   603 
       
   604     // Add modifiers
       
   605     _LIT( KModifiers, "%d" );
       
   606     _LIT( KBoxedCharFormat, " [%c]" );
       
   607     item.AppendFormat( KModifiers, RequestStatusValue() );
       
   608     if  ( IsActive() )
       
   609         {
       
   610         item.AppendFormat( KBoxedCharFormat, 'A' );
       
   611         }
       
   612     if  ( RequestIsPending() )
       
   613         {
       
   614         item.AppendFormat( KBoxedCharFormat, 'P' );
       
   615         }
       
   616     iCaption = item.AllocL();
       
   617 
       
   618     // Listbox items
       
   619     TPtrC value;
       
   620 
       
   621     // Address
       
   622     _LIT(KCaption1, "\tAddress\t\t0x%08x");
       
   623     item.Format( KCaption1, iAddress );
       
   624     AppendL( item );
       
   625 
       
   626     // vTable
       
   627     _LIT(KCaption2, "\tVTable\t\t0x%08x");
       
   628     item.Format( KCaption2, iVTable );
       
   629     AppendL( item );
       
   630 
       
   631     //
       
   632     _LIT(KCaption3, "\tStatus Value\t\t%d");
       
   633     item.Format( KCaption3, iRequestStatusValue );
       
   634     AppendL( item );
       
   635 
       
   636     //
       
   637     _LIT(KCaption5, "\tIs Active\t\t%S");
       
   638     value.Set( YesNoValue( IsActive() ) );
       
   639     item.Format( KCaption5, &value );
       
   640     AppendL( item );
       
   641 
       
   642     //
       
   643     _LIT(KCaption6, "\tRequest Pending\t\t%S");
       
   644     value.Set( YesNoValue( RequestIsPending() ) );
       
   645     item.Format( KCaption6, &value );
       
   646     AppendL( item );
       
   647 
       
   648     //
       
   649     _LIT(KCaption4, "\tPriority\t\t%d");
       
   650     item.Format( KCaption4, iPriority );
       
   651     AppendL( item );
       
   652     }
       
   653 
       
   654 
       
   655 CMemSpyEngineActiveObject* CMemSpyEngineActiveObject::NewLC( TAny* aAddress, TAny* aVTable, TInt aPriority, TInt aRSValue, TUint aRSFlags, TAny* aNextAOAddress, TAny* aPrevAOAddress, CMemSpyEngine& aEngine )
       
   656     {
       
   657     CMemSpyEngineActiveObject* self = new(ELeave) CMemSpyEngineActiveObject( aAddress, aVTable, aPriority, aRSValue, aRSFlags, aNextAOAddress, aPrevAOAddress );
       
   658     CleanupStack::PushL( self );
       
   659     self->ConstructL( aEngine );
       
   660     return self;
       
   661     }
       
   662 
       
   663 
       
   664 EXPORT_C TBool CMemSpyEngineActiveObject::IsActive() const
       
   665     {
       
   666     return ( iRequestStatusFlags & CMemSpyEngineActiveObject::EActive );
       
   667     }
       
   668 
       
   669 
       
   670 EXPORT_C TBool CMemSpyEngineActiveObject::IsAddedToScheduler() const
       
   671     {
       
   672     return ( iNextAOAddress != NULL );
       
   673     }
       
   674 
       
   675 
       
   676 EXPORT_C TBool CMemSpyEngineActiveObject::RequestIsPending() const
       
   677     {
       
   678     return ( iRequestStatusFlags & CMemSpyEngineActiveObject::ERequestPending );
       
   679     }
       
   680 
       
   681 
       
   682 EXPORT_C void CMemSpyEngineActiveObject::OutputDataL( CMemSpyEngine& aEngine ) const
       
   683     {
       
   684     _LIT(KMemSpyEngineAOOutputHex, "0x%08x");
       
   685     _LIT(KMemSpyEngineAOOutputDecimal, "%d");
       
   686     _LIT(KMemSpyEngineAOOutputDecimalFixed10, "%10d");
       
   687     _LIT(KMemSpyEngineAOOutputString, "%S");
       
   688     _LIT(KMemSpyEngineAOOutputVTable, "vTable: 0x%08x");
       
   689     //
       
   690     TPtrC yesNoValue( KNullDesC );
       
   691     HBufC* columns = HBufC::NewLC( 1024 );
       
   692     TPtr pColumns( columns->Des() );
       
   693     //
       
   694     pColumns.AppendFormat( KMemSpyEngineAOOutputHex, Address() );
       
   695     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   696     //
       
   697     pColumns.AppendFormat( KMemSpyEngineAOOutputDecimal, Priority() );
       
   698     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   699     //
       
   700     yesNoValue.Set( YesNoValue( IsActive() ) );
       
   701     pColumns.AppendFormat( KMemSpyEngineAOOutputString, &yesNoValue );
       
   702     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   703     //
       
   704     yesNoValue.Set( YesNoValue( RequestIsPending() ) );
       
   705     pColumns.AppendFormat( KMemSpyEngineAOOutputString, &yesNoValue );
       
   706     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   707     //
       
   708     pColumns.AppendFormat( KMemSpyEngineAOOutputDecimalFixed10, RequestStatusValue() );
       
   709     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   710     //
       
   711     pColumns.AppendFormat( KMemSpyEngineAOOutputDecimal, RequestStatusFlags() );
       
   712     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   713     //
       
   714     pColumns.AppendFormat( KMemSpyEngineAOOutputHex, VTable() );
       
   715     pColumns.Append( KMemSpyEngineAOOutputComma );
       
   716     //
       
   717     pColumns.AppendFormat( KMemSpyEngineAOOutputVTable, VTable() );
       
   718     //
       
   719     aEngine.Sink().OutputLineL( pColumns );
       
   720     CleanupStack::PopAndDestroy( columns );
       
   721     }
       
   722 
       
   723 
       
   724 TPtrC CMemSpyEngineActiveObject::YesNoValue( TBool aValue )
       
   725     {
       
   726     _LIT(KYesString, "Yes");
       
   727     _LIT(KNoString, "No");
       
   728     //
       
   729     TPtrC pRet( KNoString );
       
   730     if  ( aValue )
       
   731         {
       
   732         pRet.Set( KYesString );
       
   733         }
       
   734     //
       
   735     return pRet;
       
   736     }
       
   737