perfsrv/memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanChunks.cpp
changeset 48 516af714ebb4
child 62 1c2bb2fc7c87
equal deleted inserted replaced
45:185201be11b0 48:516af714ebb4
       
     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_HandleLookupLock();
       
   168         const TInt processHandleCount = processHandles->Count();
       
   169 		MemSpyObjectIx_HandleLookupUnlock();
       
   170 
       
   171 	    for( TInt processHandleIndex = 0; processHandleIndex<processHandleCount && r == KErrNone && currentWriteIndex < maxCount; processHandleIndex++ )
       
   172     	    {
       
   173     	    // Get a handle from the process container...
       
   174             MemSpyObjectIx_HandleLookupLock();
       
   175 			if (processHandleIndex >= processHandles->Count()) break; // Count may have changed in the meantime
       
   176     	    DObject* object = (*processHandles)[ processHandleIndex ];
       
   177 			if (object && object->Open() != KErrNone) object = NULL;
       
   178 			MemSpyObjectIx_HandleLookupUnlock();
       
   179             
       
   180             if  ( object )
       
   181                 {
       
   182                 const TObjectType objectType = processAdaption.GetObjectType( *object );
       
   183                 if ( objectType == EChunk )
       
   184                     {
       
   185                     DChunk* chunk = (DChunk*) object;
       
   186                     TAny* handle = (TAny*) chunk;
       
   187                     r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &handle, sizeof(TAny*) );
       
   188                     if  ( r == KErrNone )
       
   189                         {
       
   190                         ++currentWriteIndex;
       
   191                         }
       
   192                     }
       
   193 				object->Close(NULL);
       
   194                 }
       
   195     	    }
       
   196 
       
   197         // If we were asked for process-related chunks, also check the chunk container
       
   198         // for entries which we don't have handles to, but do refer to our process
       
   199         // Need a listing of all chunks in the system. Let client filter duplicates.
       
   200         DObjectCon* container = Kern::Containers()[ EChunk ];
       
   201         container->Wait();
       
   202         //
       
   203         const TInt count = container->Count();
       
   204         for( TInt i=0; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ )
       
   205             {
       
   206             DChunk* chunk= (DChunk*) (*container)[ i ];
       
   207             //
       
   208             const TBool isRelated = DoesChunkRelateToProcess( *chunk, TempObjectAsProcess() );
       
   209             if  ( isRelated )
       
   210                 {
       
   211                 r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) );
       
   212                 if  ( r == KErrNone )
       
   213                     {
       
   214                     ++currentWriteIndex;
       
   215                     }
       
   216                 }
       
   217             }
       
   218         //
       
   219         container->Signal();
       
   220         NKern::ThreadLeaveCS();
       
   221 
       
   222         CloseTempObject();
       
   223         }
       
   224     else
       
   225         {
       
   226         // Need a listing of all chunks in the system. Let client filter duplicates.
       
   227         DObjectCon* container = Kern::Containers()[ EChunk ];
       
   228         NKern::ThreadEnterCS();
       
   229         container->Wait();
       
   230         //
       
   231         const TInt count = container->Count();
       
   232         for( TInt i=0; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ )
       
   233             {
       
   234             DChunk* chunk= (DChunk*) (*container)[ i ];
       
   235             //
       
   236             r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) );
       
   237             if  (r == KErrNone)
       
   238                 {
       
   239                 ++currentWriteIndex;
       
   240                 }
       
   241             }
       
   242         //
       
   243         container->Signal();
       
   244         NKern::ThreadLeaveCS();
       
   245         }
       
   246 	
       
   247 	if  ( r == KErrBadDescriptor )
       
   248         {
       
   249         MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor );
       
   250         }
       
   251     else
       
   252         {
       
   253         const TInt finalWrite = Kern::ThreadRawWrite( &ClientThread(), params.iCountPtr, &currentWriteIndex, sizeof(TInt) );
       
   254         if  ( r == KErrNone )
       
   255             {
       
   256             r = finalWrite;
       
   257             }
       
   258         }
       
   259 
       
   260 	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - number of handles written to client: %d, ret: %d", currentWriteIndex, r));
       
   261 	return r;
       
   262     }
       
   263 
       
   264 
       
   265 TInt DMemSpyDriverLogChanChunks::GetChunkInfo( TMemSpyDriverInternalChunkInfoParams* aParams )
       
   266     {
       
   267 	TMemSpyDriverInternalChunkInfoParams params;
       
   268     TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, &params, sizeof(TMemSpyDriverInternalChunkInfoParams) );
       
   269     if  ( r != KErrNone )
       
   270         {
       
   271     	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - params read error: %d", r));
       
   272         return r;
       
   273         }
       
   274 
       
   275     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - START - handle: 0x%08x", params.iHandle));
       
   276 		
       
   277 	DObjectCon* container = Kern::Containers()[EChunk];
       
   278 	NKern::ThreadEnterCS();
       
   279 
       
   280     container->Wait();
       
   281     const TInt count = container->Count();
       
   282 
       
   283     DChunk* foundChunk = NULL;
       
   284     
       
   285     for(TInt i=0; i<count; i++)
       
   286         {
       
   287         DChunk* chunk = (DChunk*) (*container)[i];
       
   288         if  ( chunk == params.iHandle )
       
   289             {
       
   290             foundChunk = chunk;
       
   291             TRACE( PrintChunkInfo( *chunk ) );
       
   292 			r = foundChunk->Open();
       
   293             break;
       
   294             }
       
   295         }
       
   296 
       
   297     container->Signal();
       
   298 
       
   299     if  ( foundChunk == NULL )
       
   300         {
       
   301     	Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - KErrNotFound - couldnt find chunk");
       
   302 		NKern::ThreadLeaveCS();
       
   303         return KErrNotFound;
       
   304         }
       
   305 	if (r)
       
   306 		{
       
   307 		Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - %d - Failed to open chunk", r);
       
   308 		NKern::ThreadLeaveCS();
       
   309 		return r;
       
   310 		}
       
   311 
       
   312     // Prepare return data
       
   313     DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk();
       
   314     //
       
   315     params.iBaseAddress = chunkAdaption.GetBase( *foundChunk );
       
   316     params.iSize = chunkAdaption.GetSize( *foundChunk );
       
   317     params.iMaxSize = chunkAdaption.GetMaxSize( *foundChunk );
       
   318     foundChunk->FullName( params.iName );
       
   319 
       
   320     // Mirror the process memory tracker
       
   321     DProcess* owner = chunkAdaption.GetOwningProcess( *foundChunk );
       
   322     if  ( owner )
       
   323         {
       
   324         params.iOwnerId = OSAdaption().DProcess().GetId( *owner );
       
   325         }
       
   326     else
       
   327         {
       
   328         owner = static_cast< DProcess* >( chunkAdaption.GetOwner( *foundChunk, EProcess ) );
       
   329         if  ( owner )
       
   330             {
       
   331             params.iOwnerId = OSAdaption().DProcess().GetId( *owner );
       
   332             }
       
   333         else
       
   334             {
       
   335             params.iOwnerId = chunkAdaption.GetControllingOwnerId( *foundChunk );
       
   336             }
       
   337         }
       
   338 
       
   339     // Get type & attribs
       
   340     params.iType = IdentifyChunkType( *foundChunk );
       
   341     params.iAttributes = chunkAdaption.GetAttributes( *foundChunk );
       
   342 
       
   343 	// Finished with foundChunk
       
   344 	foundChunk->Close(NULL);
       
   345 	NKern::ThreadLeaveCS();
       
   346     
       
   347     // Write back to client
       
   348     r = Kern::ThreadRawWrite( &ClientThread(), aParams, &params, sizeof(TMemSpyDriverInternalChunkInfoParams) );
       
   349 	if  ( r == KErrBadDescriptor )
       
   350         {
       
   351         MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor );
       
   352         }
       
   353 
       
   354 	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - handle: 0x%08x, params.iOwnerId: %d, r: %d", params.iHandle, params.iOwnerId, r ));
       
   355     return r;
       
   356     }
       
   357 
       
   358 
       
   359 void DMemSpyDriverLogChanChunks::PrintChunkInfo( DChunk& aChunk )
       
   360     {
       
   361     MemSpyDriverUtils::PrintChunkInfo( aChunk, OSAdaption() );
       
   362     }
       
   363 
       
   364 
       
   365 TMemSpyDriverChunkType DMemSpyDriverLogChanChunks::IdentifyChunkType( DChunk& aChunk )
       
   366     {
       
   367     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - START" ) );
       
   368 
       
   369     TMemSpyDriverChunkType ret = EMemSpyDriverChunkTypeUnknown;
       
   370 
       
   371     TName name;
       
   372     aChunk.Name( name );
       
   373     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - name: %S", &name ) );
       
   374 
       
   375     DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk();
       
   376     const TChunkType type = chunkAdaption.GetType( aChunk );
       
   377 
       
   378     if  ( name == KMemSpyLitDllDollarData )
       
   379         {
       
   380         // This chunk contains Dll Global Data for the process
       
   381         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeGlobalData" ) );
       
   382         ret = EMemSpyDriverChunkTypeGlobalData;
       
   383         }
       
   384     else if ( type == ERamDrive )
       
   385         {
       
   386         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeRamDrive" ) );
       
   387         ret = EMemSpyDriverChunkTypeRamDrive;
       
   388         }
       
   389     else if ( type == EKernelStack )
       
   390         {
       
   391         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeStackKernel" ) );
       
   392         ret = EMemSpyDriverChunkTypeStackKernel;
       
   393         }
       
   394     else if ( name == KMemSpyLitDollarDat )
       
   395         {
       
   396         // This chunk contains process global data as well as user-side stacks for
       
   397         // the process. 
       
   398         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeStackAndProcessGlobalData" ) );
       
   399         ret = EMemSpyDriverChunkTypeStackAndProcessGlobalData;
       
   400         }
       
   401     else if ( name == KMemSpyLitDollarGlobalCode && type == EDll )
       
   402         {
       
   403         // GLOBAL$CODE is used for RAM loaded code which is globally visible. This
       
   404         // basically means locale DLLs - these must be visible to every process, even
       
   405         // those which haven't loaded them.        
       
   406         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCodeGlobal" ) );
       
   407         ret = EMemSpyDriverChunkTypeCodeGlobal;
       
   408         }
       
   409     else if ( name == KMemSpyLitDollarCode || type == EKernelCode || type == EDll || type == EUserCode )
       
   410         {
       
   411         // RAM-loaded code, which on the multiple memory model at least means that the code chunk is eseentially just a mapping
       
   412         // artifact. The RAM itself is owned by the code segment, therefore counting the size of these CODE elements may result
       
   413         // in inaccurate results if the code is shared amongst multiple processes.
       
   414         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCode" ) );
       
   415         ret = EMemSpyDriverChunkTypeCode;
       
   416         }
       
   417     else if ( type == EUserSelfModCode )
       
   418         {
       
   419         // Dynamically create code chunk
       
   420         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCodeSelfModifiable" ) );
       
   421         ret = EMemSpyDriverChunkTypeCodeSelfModifiable;
       
   422         }
       
   423     else if ( IsHeapChunk( aChunk, name ) )
       
   424         {
       
   425         // Catch kernel heap too
       
   426         if  ( type == EKernelData )
       
   427             {
       
   428             TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeHeapKernel" ) );
       
   429             ret = EMemSpyDriverChunkTypeHeapKernel;
       
   430             }
       
   431         else
       
   432             {
       
   433             TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeHeap" ) );
       
   434             ret = EMemSpyDriverChunkTypeHeap;
       
   435             }
       
   436         }
       
   437     else if ( type == EUserData && chunkAdaption.GetOwningProcess( aChunk ) == NULL )
       
   438         {
       
   439         // Global shared chunks match this pattern. Of course, we could check the memory model mapping attributes
       
   440         // as that would give us the info in a heartbeat, but it's too specific.
       
   441         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeGlobal" ) );
       
   442         ret = EMemSpyDriverChunkTypeGlobal;
       
   443         }
       
   444     else if ( type == EUserData && chunkAdaption.GetOwner( aChunk ) != NULL && name.Length() > KMemSpyLitLocalObject().Length() && name.Left( KMemSpyLitLocalObject().Length() ) == KMemSpyLitLocalObject )
       
   445         {
       
   446         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeLocal" ) );
       
   447         ret = EMemSpyDriverChunkTypeLocal;
       
   448         }
       
   449     else
       
   450         {
       
   451         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeUnknown" ) );
       
   452         TRACE( PrintChunkInfo( aChunk ) );
       
   453         ret = EMemSpyDriverChunkTypeUnknown;
       
   454         }
       
   455 
       
   456     return ret;
       
   457     }
       
   458 
       
   459 
       
   460 TBool DMemSpyDriverLogChanChunks::IsHeapChunk( DChunk& aChunk, const TName& aName )
       
   461     {
       
   462     (void) aName; // UREL warning
       
   463     const TUint rHeapVTable = MemSpyDevice().RHeapVTable();
       
   464     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - START - this: 0x%08x, aChunk: 0x%08x, RHeapVTable: 0x%08x, aName: %S, [%O]", this, &aChunk, rHeapVTable, &aName, &aChunk ) );
       
   465 
       
   466     DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk();
       
   467     DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess();
       
   468     
       
   469     // The first 4 bytes of every chunk correspond to the allocator VTable (For heap chunks).
       
   470     // If it matches RHeap's vtable, we'll treat it as a heap.
       
   471     TBool isHeap = EFalse;
       
   472 
       
   473     // There must be an owning process or else it's definitely not a heap chunk.
       
   474     DProcess* process = chunkAdaption.GetOwningProcess( aChunk );
       
   475     TUint8* base = chunkAdaption.GetBase( aChunk );
       
   476     const TInt size = chunkAdaption.GetSize( aChunk );
       
   477     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - base: 0x%08x, size: %d, process: 0x%08x (%O)", base, size, process, process ) );
       
   478 
       
   479     if  ( process && size >= 4 )
       
   480         {
       
   481 		NKern::ThreadEnterCS();
       
   482         // Chunks are mapped into entire process so any thread within the process is enough...
       
   483         DThread* firstThread = processAdaption.OpenFirstThread( *process );
       
   484         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - firstThread: 0x%08x (%O)", firstThread, firstThread ) );
       
   485         if  ( firstThread != NULL )
       
   486             {
       
   487             TBuf8<4> allocatorVTableBuffer;
       
   488             TInt err = Kern::ThreadRawRead( firstThread, base, (TUint8*) allocatorVTableBuffer.Ptr(), allocatorVTableBuffer.MaxLength() );
       
   489             TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk - read result of vtable data from requested thread is: %d", err ));
       
   490             //
       
   491             if  ( err == KErrNone )
       
   492                 {
       
   493                 TRACE( MemSpyDriverUtils::DataDump("possible chunk vtable data - %lS", allocatorVTableBuffer.Ptr(), allocatorVTableBuffer.MaxLength(), allocatorVTableBuffer.MaxLength() ) );
       
   494                 allocatorVTableBuffer.SetLength( allocatorVTableBuffer.MaxLength() );
       
   495                 
       
   496                 const TUint32 vtable =   allocatorVTableBuffer[0] +
       
   497                                         (allocatorVTableBuffer[1] << 8) + 
       
   498                                         (allocatorVTableBuffer[2] << 16) + 
       
   499                                         (allocatorVTableBuffer[3] << 24);
       
   500                 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk - [possible] vTable within chunk is: 0x%08x", vtable) );
       
   501 
       
   502                 // Check the v-table to work out if it really is an RHeap
       
   503                 isHeap = ( vtable == rHeapVTable );
       
   504                 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - isHeap: %d", isHeap ) );
       
   505                 }
       
   506 
       
   507             TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - closing first thread..." ) );
       
   508             Kern::SafeClose( (DObject*&) firstThread, NULL );
       
   509             }
       
   510 		NKern::ThreadLeaveCS();
       
   511         }
       
   512 
       
   513     /* We only want RHeap's at the moment
       
   514     if  ( !isHeap && aName == KMemSpyLitDollarHeap )
       
   515         {
       
   516         TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - its called $HEAP, but its not an RHeap... we\'ll let it through though..." ) );
       
   517         isHeap = ETrue;
       
   518         }
       
   519     */
       
   520 
       
   521     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - END - this: 0x%08x, isHeap: %d", this, isHeap ) );
       
   522     return isHeap;
       
   523     }
       
   524 
       
   525 
       
   526 TBool DMemSpyDriverLogChanChunks::DoesChunkRelateToProcess( DChunk& aChunk, DProcess& aProcess )
       
   527     {
       
   528     TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::DoesChunkRelateToProcess() - START - this: 0x%08x, chunk: 0x%08x (%O), process: 0x%08x (%O)", this, &aChunk, &aChunk, &aProcess, &aProcess ) );
       
   529     TBool ret = EFalse;
       
   530     //
       
   531     DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk();
       
   532     DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess();
       
   533     //
       
   534     const TUint pid = processAdaption.GetId( aProcess );
       
   535     DProcess* process = chunkAdaption.GetOwningProcess( aChunk );
       
   536     if  ( process )
       
   537         {
       
   538         ret = ( pid == processAdaption.GetId( *process ) );
       
   539         }
       
   540     else
       
   541         {
       
   542         DObject* owner = chunkAdaption.GetOwner( aChunk, EProcess );
       
   543         if  ( owner )
       
   544             {
       
   545             process = (DProcess*) owner;
       
   546             ret = ( pid == processAdaption.GetId( *process ) );
       
   547             }
       
   548         else
       
   549             {
       
   550             ret = ( pid == chunkAdaption.GetControllingOwnerId( aChunk ) );
       
   551             }
       
   552         }
       
   553     //
       
   554     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 ) );
       
   555     return ret;
       
   556     }
       
   557