memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapData.cpp
branchRCL_3
changeset 59 8ad140f3dd41
parent 49 7fdc9a71d314
equal deleted inserted replaced
49:7fdc9a71d314 59:8ad140f3dd41
   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 ) );
   171 
   175 
   172     TFullName heapChunkName;
   176     TFullName heapChunkName;
   173     TInt r = OpenKernelHeap( iKernelHeap, &heapChunkName );
   177     TInt r = OpenKernelHeap( iKernelHeap, &heapChunkName );
   174     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelInit() - open err: %d", r));
   178     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelInit() - open err: %d", r));
   175 
   179 
   176     if  ( r == KErrNone )
   180     if  ( r == KErrNone )
   177         {
   181         {
   178         r = GetHeapInfoKernel( iKernelHeap, aInfo, aFreeCells );
   182         r = GetHeapInfoKernel( iKernelHeap, debugAllocator, heapChunkName, aInfo, aFreeCells );
   179         TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapDataKernelInit() - base class get heap info: %d", r) );
   183         TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel() - base class get heap info: %d", r) );
   180 
   184 
   181         // If everything was okay, we can now return back to user-side, indicating the amount of heap data
   185         // If everything was okay, we can now return back to user-side, indicating the amount of heap data
   182         // that they must prepare to read (in the next operation).
   186         // that they must prepare to read (in the next operation).
   183         if  ( r == KErrNone )
   187         if  ( r == KErrNone )
   184             {
   188             {
   185             // Indicate how big a buffer the user-side must prepare.
   189             // Indicate how big a buffer the user-side must prepare.
   186             r = OSAdaption().DChunk().GetSize( iKernelHeap.Chunk() );
   190             r = OSAdaption().DChunk().GetSize( iKernelHeap.Chunk() );
   187             TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapDataKernelInit() - user side buffer needs to be: %d", r) );
   191             TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel() - user side buffer needs to be: %d", r) );
   188             }
   192             }
   189         else
   193         else if ( iKernelHeap.ChunkIsInitialised() )
   190             {
   194             {
   191             // Error scenario - must close heap
   195             // Error scenario - must close heap
   192             iKernelHeap.Close();
   196             iKernelHeap.DisassociateWithKernelChunk();
   193             }
   197             }
   194         }
   198         }
   195 
   199 
   196     NKern::ThreadLeaveCS();
   200     NKern::ThreadLeaveCS();
   197 
   201 
   200     }
   204     }
   201 
   205 
   202 
   206 
   203 TInt DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch( TDes8* aSink )
   207 TInt DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch( TDes8* aSink )
   204     {
   208     {
   205 	//TOMSCI TODO this function is fundamentally flawed
       
   206 	return KErrNotSupported;
       
   207 	/*
       
   208     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - START"));
   209     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - START"));
   209 
   210 
   210     NKern::ThreadEnterCS();
   211     NKern::ThreadEnterCS();
   211 
   212 
   212     // We should already have an initialised copy of the kernel heap
   213     // We should already have an initialised copy of the kernel heap
   213     const TBool isInit = iKernelHeap.Helper() != NULL;
   214     const TBool isInit = iKernelHeap.ChunkIsInitialised();
   214     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - isInit: %d", isInit ));
   215     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - isInit: %d", isInit ));
   215     __ASSERT_ALWAYS( isInit, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicKernelHeapDataFetchError ) );
   216     __ASSERT_ALWAYS( isInit, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicKernelHeapDataFetchError ) );
   216 
   217 
   217     // Get user side (MemSpy) descriptor length info
   218     // Get user side (MemSpy) descriptor length info
   218     TInt destLen;
   219     TInt destLen;
   258 
   259 
   259     NKern::ThreadLeaveCS();
   260     NKern::ThreadLeaveCS();
   260 
   261 
   261 	TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - END - ret: %d", r));
   262 	TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - END - ret: %d", r));
   262     return r;
   263     return r;
   263 	*/
   264     }
   264     }
   265 
   265 
   266 
   266 
   267 
   267 
   268 
   268 
   269 
   269 
   270 
   270 
   271 
   271 
   272 
   272 
   273 
   273 
   274 
   274 
   275 
   275 
   276 
   276 
   277 
   277 
   278 
   278 
   279 
   279 
   280 
   280 
   281 
   281 
   282 
   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         // Open the heap
   312         // Find the chunk with the correct handle
   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 		r = heap.OpenUserHeap(*thread, aParams.iDebugAllocator);
   315         const TBool allocatorIsReallyRHeap = GetUserHeapHandle( *thread, heap, aParams.iRHeapVTable );
   316 		TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - opening heap returned: %d", r) );
   316         if  ( allocatorIsReallyRHeap )
   317         if  (r == KErrNone)
   317             {
   318             {
   318             const TInt chunkHandle = heap.iChunkHandle;
   319             if  ( aParams.iChecksum != 0 )
   319 	        TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunkHandle: 0x%08x, thread: %O", chunkHandle, thread) );
       
   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 )
   320                 {
   329                 {
   321                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - checksum validation requested - expecting: 0x%08x", aParams.iChecksum ) );
   330                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunkBase: 0x%08x, size: %8d, maxLen: %8d, chunk: %O", chunk->iBase, chunk->iSize, chunk->iMaxSize, chunk) );
   322                 RMemSpyDriverHeapWalker heapWalker(heap);
   331 
   323                 
   332                 // If the client specified a checksum value, then we must walk the heap just to make sure
   324                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - starting traversal..." ));
   333                 // it hasn't changed. Expensive operation, but good for paranoia purposes...
       
   334                 if  ( aParams.iChecksum != 0 )
       
   335                     {
       
   336                     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - checksum validation requested - expecting: 0x%08x", aParams.iChecksum ) );
       
   337 
       
   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..." ));
   325 #if ( defined( TRACE_TYPE_USERHEAP ) && defined( TRACE_TYPE_HEAPWALK ) )
   349 #if ( defined( TRACE_TYPE_USERHEAP ) && defined( TRACE_TYPE_HEAPWALK ) )
   326                 heapWalker.SetPrintDebug();
   350                         heapWalker.SetPrintDebug();
   327 #endif
   351 #endif
   328                 r = heapWalker.Traverse();
   352                         r = heapWalker.Traverse();
   329                 const TUint32 calculatedChecksum = heapWalker.Stats().iFreeCellCRC;
   353                         const TUint32 calculatedChecksum = heapWalker.Stats().iFreeCellCRC;
   330                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - finished traversal - err: %d, checksum: 0x%08x", r, calculatedChecksum ));
   354                         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - finished traversal - err: %d, checksum: 0x%08x", r, calculatedChecksum ));
   331 
   355 
   332                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - comparing CALCULATED: 0x%08x vs EXPECTED: 0x%08x", calculatedChecksum, aParams.iChecksum ));
   356                         // Release resources
   333                 if  ( calculatedChecksum != aParams.iChecksum )
   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                     }
       
   371 
       
   372                 // Get user side (MemSpy) descriptor length info
       
   373                 if  ( r == KErrNone )
   334                     {
   374                     {
   335                     Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - comparing CALCULATED: 0x%08x vs EXPECTED: 0x%08x for thread %O", calculatedChecksum, aParams.iChecksum, thread );
   375                     TInt destLen;
   336                     r = KErrCorrupt;
   376                     TInt destMax;
       
   377                     TUint8* destPtr = NULL;
       
   378                     r = Kern::ThreadGetDesInfo( &ClientThread(), aParams.iDes, destLen, destMax, destPtr, ETrue );
       
   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 ));
       
   380 
       
   381                     if  ( r == KErrNone )
       
   382                         {
       
   383                         // Calculate start of real heap data (skipping over embedded RHeap object)
       
   384                         const TUint8* startOfHeapOffset = heap.iBase;
       
   385         	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - startOfHeapOffset:    0x%08x", startOfHeapOffset) );
       
   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                         }
   337                     }
   423                     }
   338                 }
   424                 }
   339 
   425             else
   340             // Get user side (MemSpy) descriptor length info
       
   341             if  ( r == KErrNone )
       
   342                 {
   426                 {
   343                 TInt destLen = 0;
   427     	        Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunk not found! thread: %O", thread );
   344                 TInt destMax = 0;
   428                 r = KErrNotFound;
   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 
       
   351                 if  ( r == KErrNone )
       
   352                     {
       
   353 					const TLinAddr chunkBase = (TLinAddr)OSAdaption().DChunk().GetBase(heap.Chunk());
       
   354 					const TLinAddr chunkMaxAddr = chunkBase + OSAdaption().DChunk().GetMaxSize(heap.Chunk());
       
   355         	        TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunkBase:    0x%08x", chunkBase) );
       
   356         
       
   357 					TLinAddr readAddress = aParams.iReadAddress;
       
   358                     if (aParams.iRemaining < 0 )
       
   359                         {
       
   360                         // Initial case, start from the bottom
       
   361                         readAddress = chunkBase;
       
   362 						aParams.iRemaining = heap.Helper()->CommittedSize();
       
   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;
       
   402                     }
       
   403                 }
   429                 }
   404 			}
   430             }
   405         else
   431         else
   406             {
   432             {
   407     	    Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - couldnt open heap for thread %O, err=%d", thread, r);
   433     	    Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - couldnt find heap - vtable mis-match? thread: %O", thread );
   408             r = KErrNotSupported;
   434             r = KErrNotSupported;
   409             }
   435             }
   410 		heap.Close();
       
   411         }
   436         }
   412     else
   437     else
   413         {
   438         {
   414         Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - parent process not suspended => KErrAccessDenied - thread: %O", thread );
   439         Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - parent process not suspended => KErrAccessDenied - thread: %O", thread );
   415         r = KErrAccessDenied;
   440         r = KErrAccessDenied;