memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanChunks.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 "MemSpyDriverLogChanChunks.h"
       
    19 
       
    20 // System includes
       
    21 #include <memspy/driver/memspydriverobjectsshared.h>
       
    22 
       
    23 // Shared includes
       
    24 #include "MemSpyDriverOpCodes.h"
       
    25 #include "MemSpyDriverObjectsInternal.h"
       
    26 
       
    27 // User includes
       
    28 #include "MemSpyDriverUtils.h"
       
    29 #include "MemSpyDriverDevice.h"
       
    30 #include "MemSpyDriverOSAdaption.h"
       
    31 
       
    32 // Constants
       
    33 _LIT8( KMemSpyLitDllDollarData, "DLL$DATA" );
       
    34 _LIT8( KMemSpyLitDollarDat, "$DAT" );
       
    35 _LIT8( KMemSpyLitDollarCode, "$CODE" );
       
    36 _LIT8( KMemSpyLitDollarGlobalCode, "GLOBAL$CODE" );
       
    37 _LIT8( KMemSpyLitLocalObject, "Local-" );
       
    38 
       
    39 
       
    40 DMemSpyDriverLogChanChunks::DMemSpyDriverLogChanChunks( DMemSpyDriverDevice& aDevice, DThread& aThread )
       
    41 :   DMemSpyDriverLogChanBase( aDevice, aThread )
       
    42     {
       
    43 	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::DMemSpyDriverLogChanChunks() - this: 0x%08x", this ));
       
    44     }
       
    45 
       
    46 
       
    47 DMemSpyDriverLogChanChunks::~DMemSpyDriverLogChanChunks()
       
    48 	{
       
    49 	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::~DMemSpyDriverLogChanChunks() - START - this: 0x%08x", this ));
       
    50 
       
    51 	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::~DMemSpyDriverLogChanChunks() - END - this: 0x%08x", this ));
       
    52 	}
       
    53 
       
    54 
       
    55 
       
    56 TInt DMemSpyDriverLogChanChunks::Request( TInt aFunction, TAny* a1, TAny* a2 )
       
    57 	{
       
    58 	TInt r = DMemSpyDriverLogChanBase::Request( aFunction, a1, a2 );
       
    59     if  ( r == KErrNone )
       
    60         {
       
    61 	    switch( aFunction )
       
    62 		    {
       
    63         case EMemSpyDriverOpCodeChunkGetHandles:
       
    64             r = GetChunkHandles( (TMemSpyDriverInternalChunkHandleParams*) a1 );
       
    65             break;
       
    66         case EMemSpyDriverOpCodeChunkGetInfo:
       
    67             r = GetChunkInfo( (TMemSpyDriverInternalChunkInfoParams*) a1 );
       
    68             break;
       
    69 
       
    70         default:
       
    71             r = KErrNotSupported;
       
    72 		    break;
       
    73     		}
       
    74         }
       
    75     //
       
    76     return r;
       
    77 	}
       
    78 
       
    79 
       
    80 TBool DMemSpyDriverLogChanChunks::IsHandler( TInt aFunction ) const
       
    81     {
       
    82     return ( aFunction > EMemSpyDriverOpCodeChunkBase && aFunction < EMemSpyDriverOpCodeChunkEnd );
       
    83     }
       
    84 
       
    85 
       
    86 
       
    87 
       
    88 
       
    89 
       
    90 
       
    91 
       
    92 
       
    93 
       
    94 
       
    95 
       
    96 
       
    97 
       
    98 
       
    99 
       
   100 
       
   101 
       
   102 
       
   103 
       
   104 TInt DMemSpyDriverLogChanChunks::GetChunkHandles( TMemSpyDriverInternalChunkHandleParams* aParams )
       
   105     {
       
   106 	TMemSpyDriverInternalChunkHandleParams params;
       
   107     TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, &params, sizeof(TMemSpyDriverInternalChunkHandleParams) );
       
   108     if  ( r != KErrNone )
       
   109         {
       
   110     	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - params read error: %d", r));
       
   111         return r;
       
   112         }
       
   113 
       
   114 	const TInt maxCount = params.iMaxCount;
       
   115 	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - START - id: %d,  maxCount: %d, type: %d", params.iId, maxCount, params.iType));
       
   116 
       
   117     DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk();
       
   118     DMemSpyDriverOSAdaptionDThread& threadAdaption = OSAdaption().DThread();
       
   119     DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess();
       
   120 
       
   121 
       
   122     // This variable holds the number of handles that we have already
       
   123     // written to the client-side.
       
   124     TInt currentWriteIndex = 0;
       
   125 	
       
   126     if  ( params.iType == EMemSpyDriverPrivateObjectTypeProcess || params.iType == EMemSpyDriverPrivateObjectTypeThread )
       
   127         {
       
   128         if  ( params.iType == EMemSpyDriverPrivateObjectTypeThread )
       
   129     	    {
       
   130 	        r = OpenTempObject( params.iId, EThread );
       
   131             if  ( r == KErrNone )
       
   132                 {
       
   133                 // Open the owning process instead, so that we can see which chunks are mapped
       
   134                 // into the thread.
       
   135                 DThread* thread = (DThread*) TempObject();
       
   136                 DProcess* process = threadAdaption.GetOwningProcess( *thread );
       
   137                 if  ( process )
       
   138                     {
       
   139                     const TUint parentProcessId = processAdaption.GetId( *process );
       
   140                     CloseTempObject();
       
   141                     r = OpenTempObject( parentProcessId, EProcess );
       
   142                     }
       
   143                 else
       
   144                     {
       
   145                     CloseTempObject();
       
   146                     r = KErrNotFound;
       
   147                     }
       
   148                 }
       
   149        	    }
       
   150         else
       
   151             {
       
   152 	        r = OpenTempObject( params.iId, EProcess );
       
   153             }
       
   154 
       
   155         // Handle error opening correct process
       
   156         if (r != KErrNone)
       
   157     	    {
       
   158     	    Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - parent process not found");
       
   159     	    return r;
       
   160     	    }
       
   161    
       
   162         DProcess* process = (DProcess*) TempObject();
       
   163 	    NKern::ThreadEnterCS();
       
   164 
       
   165 	    // Iterate through each handle in the process
       
   166 	    MemSpyObjectIx* processHandles = processAdaption.GetHandles( *process );
       
   167         MemSpyObjectIx_Wait( processHandles );
       
   168 
       
   169         const TInt processHandleCount = processHandles->Count();
       
   170 	    for( TInt processHandleIndex = 0; processHandleIndex<processHandleCount && r == KErrNone && currentWriteIndex < maxCount; processHandleIndex++ )
       
   171     	    {
       
   172     	    // Get a handle from the process container...
       
   173             NKern::LockSystem();
       
   174     	    DObject* object = (*processHandles)[ processHandleIndex ];
       
   175             NKern::UnlockSystem();
       
   176             
       
   177             if  ( object )
       
   178                 {
       
   179                 const TObjectType objectType = processAdaption.GetObjectType( *object );
       
   180                 if ( objectType == EChunk )
       
   181                     {
       
   182                     DChunk* chunk = (DChunk*) object;
       
   183                     TAny* handle = (TAny*) chunk;
       
   184                     r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &handle, sizeof(TAny*) );
       
   185                     if  ( r == KErrNone )
       
   186                         {
       
   187                         ++currentWriteIndex;
       
   188                         }
       
   189                     }
       
   190                 }
       
   191     	    }
       
   192 
       
   193         MemSpyObjectIx_Signal( processHandles );
       
   194 
       
   195         // If we were asked for process-related chunks, also check the chunk container
       
   196         // for entries which we don't have handles to, but do refer to our process
       
   197         // Need a listing of all chunks in the system. Let client filter duplicates.
       
   198         DObjectCon* container = Kern::Containers()[ EChunk ];
       
   199         container->Wait();
       
   200         //
       
   201         const TInt count = container->Count();
       
   202         for( TInt i=0; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ )
       
   203             {
       
   204             DChunk* chunk= (DChunk*) (*container)[ i ];
       
   205             //
       
   206             const TBool isRelated = DoesChunkRelateToProcess( *chunk, TempObjectAsProcess() );
       
   207             if  ( isRelated )
       
   208                 {
       
   209                 r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) );
       
   210                 if  ( r == KErrNone )
       
   211                     {
       
   212                     ++currentWriteIndex;
       
   213                     }
       
   214                 }
       
   215             }
       
   216         //
       
   217         container->Signal();
       
   218         NKern::ThreadLeaveCS();
       
   219 
       
   220         CloseTempObject();
       
   221         }
       
   222     else
       
   223         {
       
   224         // Need a listing of all chunks in the system. Let client filter duplicates.
       
   225         DObjectCon* container = Kern::Containers()[ EChunk ];
       
   226         NKern::ThreadEnterCS();
       
   227         container->Wait();
       
   228         //
       
   229         const TInt count = container->Count();
       
   230         for( TInt i=0; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ )
       
   231             {
       
   232             DChunk* chunk= (DChunk*) (*container)[ i ];
       
   233             //
       
   234             r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) );
       
   235             if  (r == KErrNone)
       
   236                 {
       
   237                 ++currentWriteIndex;
       
   238                 }
       
   239             }
       
   240         //
       
   241         container->Signal();
       
   242         NKern::ThreadLeaveCS();
       
   243         }
       
   244 	
       
   245 	if  ( r == KErrBadDescriptor )
       
   246         {
       
   247         MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor );
       
   248         }
       
   249     else
       
   250         {
       
   251         const TInt finalWrite = Kern::ThreadRawWrite( &ClientThread(), params.iCountPtr, &currentWriteIndex, sizeof(TInt) );
       
   252         if  ( r == KErrNone )
       
   253             {
       
   254             r = finalWrite;
       
   255             }
       
   256         }
       
   257 
       
   258 	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - number of handles written to client: %d, ret: %d", currentWriteIndex, r));
       
   259 	return r;
       
   260     }
       
   261 
       
   262 
       
   263 TInt DMemSpyDriverLogChanChunks::GetChunkInfo( TMemSpyDriverInternalChunkInfoParams* aParams )
       
   264     {
       
   265 	TMemSpyDriverInternalChunkInfoParams params;
       
   266     TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, &params, sizeof(TMemSpyDriverInternalChunkInfoParams) );
       
   267     if  ( r != KErrNone )
       
   268         {
       
   269     	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - params read error: %d", r));
       
   270         return r;
       
   271         }
       
   272 
       
   273     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - START - handle: 0x%08x", params.iHandle));
       
   274 		
       
   275 	DObjectCon* container = Kern::Containers()[EChunk];
       
   276 	NKern::ThreadEnterCS();
       
   277 
       
   278     container->Wait();
       
   279     NKern::LockSystem();
       
   280     const TInt count = container->Count();
       
   281     NKern::UnlockSystem();
       
   282 
       
   283     DChunk* foundChunk = NULL;
       
   284     
       
   285     for(TInt i=0; i<count; i++)
       
   286         {
       
   287         NKern::LockSystem();
       
   288         DChunk* chunk = (DChunk*) (*container)[i];
       
   289         NKern::UnlockSystem();
       
   290         //
       
   291         if  ( chunk == params.iHandle )
       
   292             {
       
   293             foundChunk = chunk;
       
   294             TRACE( PrintChunkInfo( *chunk ) );
       
   295             break;
       
   296             }
       
   297         }
       
   298 
       
   299     container->Signal();
       
   300 	NKern::ThreadLeaveCS();
       
   301 
       
   302     if  ( foundChunk == NULL )
       
   303         {
       
   304     	Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - KErrNotFound - couldnt find chunk");
       
   305         return KErrNotFound;
       
   306         }
       
   307 
       
   308     // Prepare return data
       
   309     DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk();
       
   310     //
       
   311     params.iBaseAddress = chunkAdaption.GetBase( *foundChunk );
       
   312     params.iSize = chunkAdaption.GetSize( *foundChunk );
       
   313     params.iMaxSize = chunkAdaption.GetMaxSize( *foundChunk );
       
   314     foundChunk->FullName( params.iName );
       
   315 
       
   316     // Mirror the process memory tracker
       
   317     DProcess* owner = chunkAdaption.GetOwningProcess( *foundChunk );
       
   318     if  ( owner )
       
   319         {
       
   320         params.iOwnerId = OSAdaption().DProcess().GetId( *owner );
       
   321         }
       
   322     else
       
   323         {
       
   324         owner = static_cast< DProcess* >( chunkAdaption.GetOwner( *foundChunk, EProcess ) );
       
   325         if  ( owner )
       
   326             {
       
   327             params.iOwnerId = OSAdaption().DProcess().GetId( *owner );
       
   328             }
       
   329         else
       
   330             {
       
   331             params.iOwnerId = chunkAdaption.GetControllingOwnerId( *foundChunk );
       
   332             }
       
   333         }
       
   334 
       
   335     // Get type & attribs
       
   336     params.iType = IdentifyChunkType( *foundChunk );
       
   337     params.iAttributes = chunkAdaption.GetAttributes( *foundChunk );
       
   338     
       
   339     // Write back to client
       
   340     r = Kern::ThreadRawWrite( &ClientThread(), aParams, &params, sizeof(TMemSpyDriverInternalChunkInfoParams) );
       
   341 	if  ( r == KErrBadDescriptor )
       
   342         {
       
   343         MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor );
       
   344         }
       
   345 
       
   346 	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - handle: 0x%08x, params.iOwnerId: %d, r: %d", params.iHandle, params.iOwnerId, r ));
       
   347     return r;
       
   348     }
       
   349 
       
   350 
       
   351 void DMemSpyDriverLogChanChunks::PrintChunkInfo( DChunk& aChunk )
       
   352     {
       
   353     MemSpyDriverUtils::PrintChunkInfo( aChunk, OSAdaption() );
       
   354     }
       
   355 
       
   356 
       
   357 TMemSpyDriverChunkType DMemSpyDriverLogChanChunks::IdentifyChunkType( DChunk& aChunk )
       
   358     {
       
   359     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - START" ) );
       
   360 
       
   361     TMemSpyDriverChunkType ret = EMemSpyDriverChunkTypeUnknown;
       
   362 
       
   363     TName name;
       
   364     aChunk.Name( name );
       
   365     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - name: %S", &name ) );
       
   366 
       
   367     DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk();
       
   368     const TChunkType type = chunkAdaption.GetType( aChunk );
       
   369 
       
   370     if  ( name == KMemSpyLitDllDollarData )
       
   371         {
       
   372         // This chunk contains Dll Global Data for the process
       
   373         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeGlobalData" ) );
       
   374         ret = EMemSpyDriverChunkTypeGlobalData;
       
   375         }
       
   376     else if ( type == ERamDrive )
       
   377         {
       
   378         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeRamDrive" ) );
       
   379         ret = EMemSpyDriverChunkTypeRamDrive;
       
   380         }
       
   381     else if ( type == EKernelStack )
       
   382         {
       
   383         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeStackKernel" ) );
       
   384         ret = EMemSpyDriverChunkTypeStackKernel;
       
   385         }
       
   386     else if ( name == KMemSpyLitDollarDat )
       
   387         {
       
   388         // This chunk contains process global data as well as user-side stacks for
       
   389         // the process. 
       
   390         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeStackAndProcessGlobalData" ) );
       
   391         ret = EMemSpyDriverChunkTypeStackAndProcessGlobalData;
       
   392         }
       
   393     else if ( name == KMemSpyLitDollarGlobalCode && type == EDll )
       
   394         {
       
   395         // GLOBAL$CODE is used for RAM loaded code which is globally visible. This
       
   396         // basically means locale DLLs - these must be visible to every process, even
       
   397         // those which haven't loaded them.        
       
   398         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCodeGlobal" ) );
       
   399         ret = EMemSpyDriverChunkTypeCodeGlobal;
       
   400         }
       
   401     else if ( name == KMemSpyLitDollarCode || type == EKernelCode || type == EDll || type == EUserCode )
       
   402         {
       
   403         // RAM-loaded code, which on the multiple memory model at least means that the code chunk is eseentially just a mapping
       
   404         // artifact. The RAM itself is owned by the code segment, therefore counting the size of these CODE elements may result
       
   405         // in inaccurate results if the code is shared amongst multiple processes.
       
   406         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCode" ) );
       
   407         ret = EMemSpyDriverChunkTypeCode;
       
   408         }
       
   409     else if ( type == EUserSelfModCode )
       
   410         {
       
   411         // Dynamically create code chunk
       
   412         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCodeSelfModifiable" ) );
       
   413         ret = EMemSpyDriverChunkTypeCodeSelfModifiable;
       
   414         }
       
   415     else if ( IsHeapChunk( aChunk, name ) )
       
   416         {
       
   417         // Catch kernel heap too
       
   418         if  ( type == EKernelData )
       
   419             {
       
   420             TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeHeapKernel" ) );
       
   421             ret = EMemSpyDriverChunkTypeHeapKernel;
       
   422             }
       
   423         else
       
   424             {
       
   425             TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeHeap" ) );
       
   426             ret = EMemSpyDriverChunkTypeHeap;
       
   427             }
       
   428         }
       
   429     else if ( type == EUserData && chunkAdaption.GetOwningProcess( aChunk ) == NULL )
       
   430         {
       
   431         // Global shared chunks match this pattern. Of course, we could check the memory model mapping attributes
       
   432         // as that would give us the info in a heartbeat, but it's too specific.
       
   433         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeGlobal" ) );
       
   434         ret = EMemSpyDriverChunkTypeGlobal;
       
   435         }
       
   436     else if ( type == EUserData && chunkAdaption.GetOwner( aChunk ) != NULL && name.Length() > KMemSpyLitLocalObject().Length() && name.Left( KMemSpyLitLocalObject().Length() ) == KMemSpyLitLocalObject )
       
   437         {
       
   438         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeLocal" ) );
       
   439         ret = EMemSpyDriverChunkTypeLocal;
       
   440         }
       
   441     else
       
   442         {
       
   443         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeUnknown" ) );
       
   444         TRACE( PrintChunkInfo( aChunk ) );
       
   445         ret = EMemSpyDriverChunkTypeUnknown;
       
   446         }
       
   447 
       
   448     return ret;
       
   449     }
       
   450 
       
   451 
       
   452 TBool DMemSpyDriverLogChanChunks::IsHeapChunk( DChunk& aChunk, const TName& aName )
       
   453     {
       
   454     (void) aName; // UREL warning
       
   455     const TUint rHeapVTable = MemSpyDevice().RHeapVTable();
       
   456     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - START - this: 0x%08x, aChunk: 0x%08x, RHeapVTable: 0x%08x, aName: %S, [%O]", this, &aChunk, rHeapVTable, &aName, &aChunk ) );
       
   457 
       
   458     DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk();
       
   459     DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess();
       
   460     
       
   461     // The first 4 bytes of every chunk correspond to the allocator VTable (For heap chunks).
       
   462     // If it matches RHeap's vtable, we'll treat it as a heap.
       
   463     TBool isHeap = EFalse;
       
   464 
       
   465     // There must be an owning process or else it's definitely not a heap chunk.
       
   466     DProcess* process = chunkAdaption.GetOwningProcess( aChunk );
       
   467     TUint8* base = chunkAdaption.GetBase( aChunk );
       
   468     const TInt size = chunkAdaption.GetSize( aChunk );
       
   469     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - base: 0x%08x, size: %d, process: 0x%08x (%O)", base, size, process, process ) );
       
   470 
       
   471     if  ( process && size >= 4 )
       
   472         {
       
   473         // Chunks are mapped into entire process so any thread within the process is enough...
       
   474         DThread* firstThread = processAdaption.GetFirstThread( *process );
       
   475         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - firstThread: 0x%08x (%O)", firstThread, firstThread ) );
       
   476         if  ( firstThread != NULL )
       
   477             {
       
   478             TInt err = firstThread->Open();
       
   479             TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - firstThread open result: %d", err ) );
       
   480 
       
   481             if  ( err == KErrNone )
       
   482                 {
       
   483                 TBuf8<4> allocatorVTableBuffer;
       
   484                 err = Kern::ThreadRawRead( firstThread, base, (TUint8*) allocatorVTableBuffer.Ptr(), allocatorVTableBuffer.MaxLength() );
       
   485                 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk - read result of vtable data from requested thread is: %d", err ));
       
   486                 //
       
   487                 if  ( err == KErrNone )
       
   488                     {
       
   489                     TRACE( MemSpyDriverUtils::DataDump("possible chunk vtable data - %lS", allocatorVTableBuffer.Ptr(), allocatorVTableBuffer.MaxLength(), allocatorVTableBuffer.MaxLength() ) );
       
   490                     allocatorVTableBuffer.SetLength( allocatorVTableBuffer.MaxLength() );
       
   491                     
       
   492                     const TUint32 vtable =   allocatorVTableBuffer[0] +
       
   493                                             (allocatorVTableBuffer[1] << 8) + 
       
   494                                             (allocatorVTableBuffer[2] << 16) + 
       
   495                                             (allocatorVTableBuffer[3] << 24);
       
   496                     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk - [possible] vTable within chunk is: 0x%08x", vtable) );
       
   497 
       
   498                     // Check the v-table to work out if it really is an RHeap
       
   499                     isHeap = ( vtable == rHeapVTable );
       
   500                     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - isHeap: %d", isHeap ) );
       
   501                     }
       
   502 
       
   503                 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - closing first thread..." ) );
       
   504             	Kern::SafeClose( (DObject*&) firstThread, NULL );
       
   505                 }
       
   506             }
       
   507         }
       
   508 
       
   509     /* We only want RHeap's at the moment
       
   510     if  ( !isHeap && aName == KMemSpyLitDollarHeap )
       
   511         {
       
   512         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - its called $HEAP, but its not an RHeap... we\'ll let it through though..." ) );
       
   513         isHeap = ETrue;
       
   514         }
       
   515     */
       
   516 
       
   517     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - END - this: 0x%08x, isHeap: %d", this, isHeap ) );
       
   518     return isHeap;
       
   519     }
       
   520 
       
   521 
       
   522 TBool DMemSpyDriverLogChanChunks::DoesChunkRelateToProcess( DChunk& aChunk, DProcess& aProcess )
       
   523     {
       
   524     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::DoesChunkRelateToProcess() - START - this: 0x%08x, chunk: 0x%08x (%O), process: 0x%08x (%O)", this, &aChunk, &aChunk, &aProcess, &aProcess ) );
       
   525     TBool ret = EFalse;
       
   526     //
       
   527     DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk();
       
   528     DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess();
       
   529     //
       
   530     const TUint pid = processAdaption.GetId( aProcess );
       
   531     DProcess* process = chunkAdaption.GetOwningProcess( aChunk );
       
   532     if  ( process )
       
   533         {
       
   534         ret = ( pid == processAdaption.GetId( *process ) );
       
   535         }
       
   536     else
       
   537         {
       
   538         DObject* owner = chunkAdaption.GetOwner( aChunk, EProcess );
       
   539         if  ( owner )
       
   540             {
       
   541             process = (DProcess*) owner;
       
   542             ret = ( pid == processAdaption.GetId( *process ) );
       
   543             }
       
   544         else
       
   545             {
       
   546             ret = ( pid == chunkAdaption.GetControllingOwnerId( aChunk ) );
       
   547             }
       
   548         }
       
   549     //
       
   550     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::DoesChunkRelateToProcess() - END - this: 0x%08x, chunk: 0x%08x (%O), process: 0x%08x (%O), ret: %d", this, &aChunk, &aChunk, &aProcess, &aProcess, ret ) );
       
   551     return ret;
       
   552     }
       
   553