memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapData.cpp
branchRCL_3
changeset 49 7fdc9a71d314
parent 44 52e343bb8f80
child 59 8ad140f3dd41
equal deleted inserted replaced
46:e26895079d7c 49:7fdc9a71d314
   160     // b) Make a copy of the heap data
   160     // b) Make a copy of the heap data
   161     // c) Walk copy in order to extract statistics (meta data, i.e. TMemSpyHeapInfo)
   161     // c) Walk copy in order to extract statistics (meta data, i.e. TMemSpyHeapInfo)
   162     //
   162     //
   163     // The driver leaves kernel context with the copy of the kernel heap still associated with MemSpy's process.
   163     // The driver leaves kernel context with the copy of the kernel heap still associated with MemSpy's process.
   164     // The second driver call will copy the chunk data to user side and release the kernel side chunk.
   164     // The second driver call will copy the chunk data to user side and release the kernel side chunk.
   165     const TBool isInit = iKernelHeap.ChunkIsInitialised();
   165     //const TBool isInit = iKernelHeap.ChunkIsInitialised();
   166     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelInit() - START - isInit: %d", isInit ));
   166     //TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelInit() - START - isInit: %d", isInit ));
   167     __ASSERT_ALWAYS( !isInit, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicKernelHeapDataInitError ) );
   167     //__ASSERT_ALWAYS( !isInit, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicKernelHeapDataInitError ) );
   168 
   168 
   169     iKernelHeap.Reset();
   169     iKernelHeap.Reset();
   170     NKern::ThreadEnterCS();
   170     NKern::ThreadEnterCS();
   171 
       
   172     // We must identify if we have a debug kernel allocator
       
   173     const TBool debugAllocator = IsDebugKernel();
       
   174     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelInit() - debugAllocator: %d", debugAllocator ) );
       
   175 
   171 
   176     TFullName heapChunkName;
   172     TFullName heapChunkName;
   177     TInt r = OpenKernelHeap( iKernelHeap, &heapChunkName );
   173     TInt r = OpenKernelHeap( iKernelHeap, &heapChunkName );
   178     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelInit() - open err: %d", r));
   174     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelInit() - open err: %d", r));
   179 
   175 
   180     if  ( r == KErrNone )
   176     if  ( r == KErrNone )
   181         {
   177         {
   182         r = GetHeapInfoKernel( iKernelHeap, debugAllocator, heapChunkName, aInfo, aFreeCells );
   178         r = GetHeapInfoKernel( iKernelHeap, aInfo, aFreeCells );
   183         TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel() - base class get heap info: %d", r) );
   179         TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapDataKernelInit() - base class get heap info: %d", r) );
   184 
   180 
   185         // If everything was okay, we can now return back to user-side, indicating the amount of heap data
   181         // If everything was okay, we can now return back to user-side, indicating the amount of heap data
   186         // that they must prepare to read (in the next operation).
   182         // that they must prepare to read (in the next operation).
   187         if  ( r == KErrNone )
   183         if  ( r == KErrNone )
   188             {
   184             {
   189             // Indicate how big a buffer the user-side must prepare.
   185             // Indicate how big a buffer the user-side must prepare.
   190             r = OSAdaption().DChunk().GetSize( iKernelHeap.Chunk() );
   186             r = OSAdaption().DChunk().GetSize( iKernelHeap.Chunk() );
   191             TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel() - user side buffer needs to be: %d", r) );
   187             TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapDataKernelInit() - user side buffer needs to be: %d", r) );
   192             }
   188             }
   193         else if ( iKernelHeap.ChunkIsInitialised() )
   189         else
   194             {
   190             {
   195             // Error scenario - must close heap
   191             // Error scenario - must close heap
   196             iKernelHeap.DisassociateWithKernelChunk();
   192             iKernelHeap.Close();
   197             }
   193             }
   198         }
   194         }
   199 
   195 
   200     NKern::ThreadLeaveCS();
   196     NKern::ThreadLeaveCS();
   201 
   197 
   204     }
   200     }
   205 
   201 
   206 
   202 
   207 TInt DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch( TDes8* aSink )
   203 TInt DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch( TDes8* aSink )
   208     {
   204     {
       
   205 	//TOMSCI TODO this function is fundamentally flawed
       
   206 	return KErrNotSupported;
       
   207 	/*
   209     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - START"));
   208     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - START"));
   210 
   209 
   211     NKern::ThreadEnterCS();
   210     NKern::ThreadEnterCS();
   212 
   211 
   213     // We should already have an initialised copy of the kernel heap
   212     // We should already have an initialised copy of the kernel heap
   214     const TBool isInit = iKernelHeap.ChunkIsInitialised();
   213     const TBool isInit = iKernelHeap.Helper() != NULL;
   215     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - isInit: %d", isInit ));
   214     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - isInit: %d", isInit ));
   216     __ASSERT_ALWAYS( isInit, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicKernelHeapDataFetchError ) );
   215     __ASSERT_ALWAYS( isInit, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicKernelHeapDataFetchError ) );
   217 
   216 
   218     // Get user side (MemSpy) descriptor length info
   217     // Get user side (MemSpy) descriptor length info
   219     TInt destLen;
   218     TInt destLen;
   259 
   258 
   260     NKern::ThreadLeaveCS();
   259     NKern::ThreadLeaveCS();
   261 
   260 
   262 	TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - END - ret: %d", r));
   261 	TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - END - ret: %d", r));
   263     return r;
   262     return r;
   264     }
   263 	*/
   265 
   264     }
   266 
   265 
   267 
   266 
   268 
   267 
   269 
   268 
   270 
   269 
   271 
   270 
   272 
   271 
   273 
   272 
   274 
   273 
   275 
   274 
   276 
   275 
   277 
   276 
   278 
   277 
   279 
   278 
   280 
   279 
   281 
   280 
   282 
   281 
       
   282 const TInt KPageSize = 4096;
   283 
   283 
   284 TInt DMemSpyDriverLogChanHeapData::GetHeapDataUser( TMemSpyDriverInternalHeapDataParams& aParams )
   284 TInt DMemSpyDriverLogChanHeapData::GetHeapDataUser( TMemSpyDriverInternalHeapDataParams& aParams )
   285     {
   285     {
   286     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser() - START") );
   286     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser() - START") );
   287 
   287 
   302     	    Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser() - END - Not allowing dump of DRM heap - matchType: %d, thread: %O", drmMatchType, thread );
   302     	    Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser() - END - Not allowing dump of DRM heap - matchType: %d, thread: %O", drmMatchType, thread );
   303             CloseTempObject();
   303             CloseTempObject();
   304 		    return KErrAccessDenied;
   304 		    return KErrAccessDenied;
   305             }
   305             }
   306         }
   306         }
   307     
   307 
   308     // Check that the process' thread's are suspended
   308     // Check that the process' thread's are suspended
   309     DThread* thread = (DThread*) TempObject();
   309     DThread* thread = (DThread*) TempObject();
   310     if  ( SuspensionManager().IsSuspended( *thread ) )
   310     if  ( SuspensionManager().IsSuspended( *thread ) )
   311         {
   311         {
   312         // Find the chunk with the correct handle
   312         // Open the heap
   313 	    TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - thread: %O", thread) );
   313 	    TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - thread: %O", thread) );
   314         RMemSpyDriverRHeapUser heap( OSAdaption() );
   314         RMemSpyDriverRHeapUser heap( OSAdaption() );
   315         const TBool allocatorIsReallyRHeap = GetUserHeapHandle( *thread, heap, aParams.iRHeapVTable );
   315 		r = heap.OpenUserHeap(*thread, aParams.iDebugAllocator);
   316         if  ( allocatorIsReallyRHeap )
   316 		TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - opening heap returned: %d", r) );
   317             {
   317         if  (r == KErrNone)
   318             const TInt chunkHandle = heap.iChunkHandle;
   318             {
   319 	        TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunkHandle: 0x%08x, thread: %O", chunkHandle, thread) );
   319             if  ( aParams.iChecksum != 0 )
   320 
       
   321   	        NKern::ThreadEnterCS();
       
   322  	        NKern::LockSystem();
       
   323             DChunk* chunk = (DChunk*) Kern::ObjectFromHandle( thread, chunkHandle, EChunk );
       
   324             NKern::UnlockSystem();
       
   325 	        TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunk: 0x%08x", chunk ) );
       
   326   	        NKern::ThreadLeaveCS();
       
   327 
       
   328             if  ( chunk != NULL )
       
   329                 {
   320                 {
   330                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunkBase: 0x%08x, size: %8d, maxLen: %8d, chunk: %O", chunk->iBase, chunk->iSize, chunk->iMaxSize, chunk) );
   321                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - checksum validation requested - expecting: 0x%08x", aParams.iChecksum ) );
   331 
   322                 RMemSpyDriverHeapWalker heapWalker(heap);
   332                 // If the client specified a checksum value, then we must walk the heap just to make sure
   323                 
   333                 // it hasn't changed. Expensive operation, but good for paranoia purposes...
   324                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - starting traversal..." ));
   334                 if  ( aParams.iChecksum != 0 )
   325 #if ( defined( TRACE_TYPE_USERHEAP ) && defined( TRACE_TYPE_HEAPWALK ) )
       
   326                 heapWalker.SetPrintDebug();
       
   327 #endif
       
   328                 r = heapWalker.Traverse();
       
   329                 const TUint32 calculatedChecksum = heapWalker.Stats().iFreeCellCRC;
       
   330                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - finished traversal - err: %d, checksum: 0x%08x", r, calculatedChecksum ));
       
   331 
       
   332                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - comparing CALCULATED: 0x%08x vs EXPECTED: 0x%08x", calculatedChecksum, aParams.iChecksum ));
       
   333                 if  ( calculatedChecksum != aParams.iChecksum )
   335                     {
   334                     {
   336                     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - checksum validation requested - expecting: 0x%08x", aParams.iChecksum ) );
   335                     Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - comparing CALCULATED: 0x%08x vs EXPECTED: 0x%08x for thread %O", calculatedChecksum, aParams.iChecksum, thread );
   337 
   336                     r = KErrCorrupt;
   338                     RMemSpyDriverRHeapUser rHeap( OSAdaption() );
       
   339                     DChunk* userHeapChunk = NULL;
       
   340                     r = OpenUserHeap( *thread, aParams.iRHeapVTable, rHeap, userHeapChunk );
       
   341                     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - opening client heap returned: %d", r) );
       
   342                     if  ( r == KErrNone )
       
   343                         {
       
   344                         TMemSpyHeapWalkerNullObserver observer; 
       
   345                         RMemSpyDriverHeapWalker heapWalker( rHeap, aParams.iDebugAllocator );
       
   346                         heapWalker.SetObserver( &observer );
       
   347                         
       
   348                         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - starting traversal..." ));
       
   349 #if ( defined( TRACE_TYPE_USERHEAP ) && defined( TRACE_TYPE_HEAPWALK ) )
       
   350                         heapWalker.SetPrintDebug();
       
   351 #endif
       
   352                         r = heapWalker.Traverse();
       
   353                         const TUint32 calculatedChecksum = heapWalker.Stats().iFreeCellCRC;
       
   354                         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - finished traversal - err: %d, checksum: 0x%08x", r, calculatedChecksum ));
       
   355 
       
   356                         // Release resources
       
   357                         rHeap.DisassociateWithKernelChunk();
       
   358 
       
   359                         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - comparing CALCULATED: 0x%08x vs EXPECTED: 0x%08x", calculatedChecksum, aParams.iChecksum ));
       
   360                         if  ( calculatedChecksum != aParams.iChecksum )
       
   361                             {
       
   362                             Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - comparing CALCULATED: 0x%08x vs EXPECTED: 0x%08x for thread %O", calculatedChecksum, aParams.iChecksum, thread );
       
   363                             r = KErrCorrupt;
       
   364                             }
       
   365                         }
       
   366                     else
       
   367                         {
       
   368                         // Couldn't verify checksum in this situation...
       
   369                         }
       
   370                     }
   337                     }
   371 
   338                 }
   372                 // Get user side (MemSpy) descriptor length info
   339 
       
   340             // Get user side (MemSpy) descriptor length info
       
   341             if  ( r == KErrNone )
       
   342                 {
       
   343                 TInt destLen = 0;
       
   344                 TInt destMax = 0;
       
   345                 TUint8* destPtr = NULL;
       
   346                 r = Kern::ThreadGetDesInfo( &ClientThread(), aParams.iDes, destLen, destMax, destPtr, ETrue );
       
   347                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - user side descriptor: 0x%08x (0x%08x), len: %8d, maxLen: %8d, r: %d", aParams.iDes, destPtr, destLen, destMax, r ));
       
   348 				destMax = destMax & ~(KPageSize-1); // Round down dest max to page size
       
   349 				if (destMax <= 0 || (aParams.iReadAddress & (KPageSize-1))) r = KErrArgument; // If destMax is less than a page or the read address isn't a multiple of page size then we don't want to know
       
   350 
   373                 if  ( r == KErrNone )
   351                 if  ( r == KErrNone )
   374                     {
   352                     {
   375                     TInt destLen;
   353 					const TLinAddr chunkBase = (TLinAddr)OSAdaption().DChunk().GetBase(heap.Chunk());
   376                     TInt destMax;
   354 					const TLinAddr chunkMaxAddr = chunkBase + OSAdaption().DChunk().GetMaxSize(heap.Chunk());
   377                     TUint8* destPtr = NULL;
   355         	        TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunkBase:    0x%08x", chunkBase) );
   378                     r = Kern::ThreadGetDesInfo( &ClientThread(), aParams.iDes, destLen, destMax, destPtr, ETrue );
   356         
   379                     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - user side descriptor: 0x%08x (0x%08x), len: %8d, maxLen: %8d, r: %d", aParams.iDes, destPtr, destLen, destMax, r ));
   357 					TLinAddr readAddress = aParams.iReadAddress;
   380 
   358                     if (aParams.iRemaining < 0 )
   381                     if  ( r == KErrNone )
       
   382                         {
   359                         {
   383                         // Calculate start of real heap data (skipping over embedded RHeap object)
   360                         // Initial case, start from the bottom
   384                         const TUint8* startOfHeapOffset = heap.iBase;
   361                         readAddress = chunkBase;
   385         	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - startOfHeapOffset:    0x%08x", startOfHeapOffset) );
   362 						aParams.iRemaining = heap.Helper()->CommittedSize();
   386             
       
   387                         // Deal with initial case
       
   388                         const TUint heapSize = heap.Size();
       
   389         	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - heapSize:               %8d", heapSize) );
       
   390                         if  ( aParams.iRemaining < 0 )
       
   391                             {
       
   392                             // Initial case, remaining initialised to -1
       
   393                             aParams.iRemaining = heapSize;
       
   394                             }
       
   395 
       
   396                         // The remaining number of bytes should allow us to calculate the position
       
   397                         // to read from.
       
   398                         const TInt amountToRead = Min( aParams.iRemaining, destMax );
       
   399         	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - amountToRead:           %8d", amountToRead) );
       
   400                         const TInt readOffset = ( heapSize - aParams.iRemaining );
       
   401         	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - readOffset:             %8d", readOffset) );
       
   402                         const TAny* readAddress = startOfHeapOffset + readOffset;
       
   403         	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - readAddress:          0x%08x", readAddress) );
       
   404             
       
   405                         // Do the read from the heap we are spying on into MemSpy's address space
       
   406                         r = Kern::ThreadRawRead( thread, readAddress, destPtr, amountToRead );
       
   407         	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - read result: %d", r) );
       
   408                         //
       
   409                         if  (r == KErrNone)
       
   410                             {
       
   411                             // Client takes care of updating descriptor length.
       
   412                             r = amountToRead;
       
   413                             }
       
   414                         else if ( r == KErrBadDescriptor )
       
   415                             {
       
   416                             MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor );
       
   417                             }
       
   418             
       
   419                         // Update remaining bytes
       
   420                         aParams.iRemaining -= amountToRead;
       
   421                         aParams.iReadAddress = (TUint) readAddress;
       
   422                         }
   363                         }
       
   364 
       
   365                     // The remaining number of bytes should allow us to calculate the position
       
   366                     // to read from.
       
   367                     TInt amountToRead = Min( aParams.iRemaining, destMax );
       
   368         	        TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - amountToRead:           %8d", amountToRead) );
       
   369         
       
   370                     // Do the read from the heap we are spying on into MemSpy's address space
       
   371 					// TomS: I didn't know you could do this - you live and learn
       
   372 					do
       
   373 						{
       
   374 						r = Kern::ThreadRawRead( thread, (const void*)readAddress, destPtr, amountToRead );
       
   375         				TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - read result: %d", r) );
       
   376 
       
   377 						if (r == KErrBadDescriptor)
       
   378 							{
       
   379 							// This is not necessarily an error - it could be we've hit an unmapped page
       
   380 							if (amountToRead > KPageSize)
       
   381 								{
       
   382 								// retry reading a single page instead
       
   383 								amountToRead = KPageSize;
       
   384 								}
       
   385 							else
       
   386 								{
       
   387 								// Try the next page
       
   388 								readAddress += KPageSize;
       
   389 								}
       
   390 							}
       
   391 						} while (r == KErrBadDescriptor && readAddress < chunkMaxAddr);
       
   392                     //
       
   393                     if  (r == KErrNone)
       
   394                         {
       
   395                         // Client takes care of updating descriptor length.
       
   396                         r = amountToRead;
       
   397                         }
       
   398         
       
   399                     // Update remaining bytes
       
   400                     aParams.iRemaining -= amountToRead;
       
   401                     aParams.iReadAddress = readAddress;
   423                     }
   402                     }
   424                 }
   403                 }
   425             else
   404 			}
   426                 {
       
   427     	        Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunk not found! thread: %O", thread );
       
   428                 r = KErrNotFound;
       
   429                 }
       
   430             }
       
   431         else
   405         else
   432             {
   406             {
   433     	    Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - couldnt find heap - vtable mis-match? thread: %O", thread );
   407     	    Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - couldnt open heap for thread %O, err=%d", thread, r);
   434             r = KErrNotSupported;
   408             r = KErrNotSupported;
   435             }
   409             }
       
   410 		heap.Close();
   436         }
   411         }
   437     else
   412     else
   438         {
   413         {
   439         Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - parent process not suspended => KErrAccessDenied - thread: %O", thread );
   414         Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - parent process not suspended => KErrAccessDenied - thread: %O", thread );
   440         r = KErrAccessDenied;
   415         r = KErrAccessDenied;