memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapWalk.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 "MemSpyDriverLogChanHeapWalk.h"
       
    19 
       
    20 // System includes
       
    21 #include <u32hal.h>
       
    22 #include <e32rom.h>
       
    23 #include <memspy/driver/memspydriverconstants.h>
       
    24 #include <memspy/driver/memspydriverobjectsshared.h>
       
    25 
       
    26 // Shared includes
       
    27 #include "MemSpyDriverOpCodes.h"
       
    28 #include "MemSpyDriverObjectsInternal.h"
       
    29 
       
    30 // User includes
       
    31 #include "MemSpyDriverHeap.h"
       
    32 #include "MemSpyDriverUtils.h"
       
    33 #include "MemSpyDriverDevice.h"
       
    34 #include "MemSpyDriverOSAdaption.h"
       
    35 #include "MemSpyDriverSuspensionManager.h"
       
    36 
       
    37 
       
    38 
       
    39 DMemSpyDriverLogChanHeapWalk::DMemSpyDriverLogChanHeapWalk( DMemSpyDriverDevice& aDevice, DThread& aThread )
       
    40 :	DMemSpyDriverLogChanHeapBase( aDevice, aThread ), iWalkHeap( aDevice.OSAdaption() )
       
    41     {
       
    42     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::DMemSpyDriverLogChanHeapWalk() - this: 0x%08x", this ));
       
    43     }
       
    44 
       
    45 
       
    46 DMemSpyDriverLogChanHeapWalk::~DMemSpyDriverLogChanHeapWalk()
       
    47 	{
       
    48 	TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::~DMemSpyDriverLogChanHeapWalk() - START - this: 0x%08x", this ));
       
    49 
       
    50     NKern::ThreadEnterCS();
       
    51 
       
    52     WalkHeapClose();
       
    53 
       
    54     NKern::ThreadLeaveCS();
       
    55 
       
    56 	TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::~DMemSpyDriverLogChanHeapWalk() - END - this: 0x%08x", this ));
       
    57 	}
       
    58 
       
    59 
       
    60 
       
    61 
       
    62 
       
    63 
       
    64 
       
    65 TInt DMemSpyDriverLogChanHeapWalk::Request( TInt aFunction, TAny* a1, TAny* a2 )
       
    66 	{
       
    67 	TInt r = DMemSpyDriverLogChanBase::Request( aFunction, a1, a2 );
       
    68     if  ( r == KErrNone )
       
    69         {
       
    70 	    switch( aFunction )
       
    71 		    {
       
    72 	    case EMemSpyDriverOpCodeWalkHeapInit:
       
    73             r = WalkHeapInit( (TMemSpyDriverInternalWalkHeapParamsInit*) a1 );
       
    74             break;
       
    75         case EMemSpyDriverOpCodeWalkHeapGetCellInfo:
       
    76             r = WalkHeapGetCellInfo( (TAny*) a1, (TMemSpyDriverInternalWalkHeapParamsCell*) a2 );
       
    77             break;
       
    78 	    case EMemSpyDriverOpCodeWalkHeapReadCellData:
       
    79             r = WalkHeapReadCellData( (TMemSpyDriverInternalWalkHeapCellDataReadParams*) a1 );
       
    80             break;
       
    81 	    case EMemSpyDriverOpCodeWalkHeapNextCell:
       
    82             r = WalkHeapNextCell( (TUint) a1, (TMemSpyDriverInternalWalkHeapParamsCell*) a2 );
       
    83             break;
       
    84 	    case EMemSpyDriverOpCodeWalkHeapClose:
       
    85             r = WalkHeapClose();
       
    86             break;
       
    87 
       
    88         default:
       
    89             r = KErrNotSupported;
       
    90 		    break;
       
    91 		    }
       
    92         }
       
    93     //
       
    94     return r;
       
    95 	}
       
    96 
       
    97 
       
    98 TBool DMemSpyDriverLogChanHeapWalk::IsHandler( TInt aFunction ) const
       
    99     {
       
   100     return ( aFunction > EMemSpyDriverOpCodeWalkHeapBase && aFunction < EMemSpyDriverOpCodeWalkHeapEnd );
       
   101     }
       
   102 
       
   103 
       
   104 
       
   105 
       
   106 
       
   107 
       
   108 
       
   109 
       
   110 
       
   111 
       
   112 
       
   113 
       
   114 
       
   115 
       
   116 
       
   117 
       
   118 
       
   119 
       
   120 
       
   121 
       
   122 
       
   123 
       
   124 TInt DMemSpyDriverLogChanHeapWalk::WalkHeapInit( TMemSpyDriverInternalWalkHeapParamsInit* aParams )
       
   125     {
       
   126 	TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapInit() - START"));
       
   127     __ASSERT_ALWAYS( !iHeapWalkInitialised && iWalkHeap.ChunkIsInitialised() == EFalse, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicHeapWalkPending ) );
       
   128 
       
   129     TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, &iHeapWalkInitialParameters, sizeof(TMemSpyDriverInternalWalkHeapParamsInit) );
       
   130     if  ( r == KErrNone )
       
   131         {
       
   132 	    TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapInit - thread id: %d, vtable: 0x%08x, debugAllocator: %d", iHeapWalkInitialParameters.iTid, iHeapWalkInitialParameters.iRHeapVTable, iHeapWalkInitialParameters.iDebugAllocator));
       
   133 
       
   134 	    r = OpenTempObject( iHeapWalkInitialParameters.iTid, EThread );
       
   135 	    if  ( r == KErrNone )
       
   136 		    {
       
   137             // Find the chunk with the correct handle
       
   138             DThread* thread = (DThread*) TempObject();
       
   139             if  ( SuspensionManager().IsSuspended( *thread ) )
       
   140                 {
       
   141                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapInit - thread: %O", thread));
       
   142 
       
   143                 // Open client's heap
       
   144                 DChunk* userHeapChunk = NULL;
       
   145                 r = OpenUserHeap( *thread, iHeapWalkInitialParameters.iRHeapVTable, iWalkHeap, userHeapChunk );
       
   146                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapInit - opening client heap returned: %d", r) );
       
   147 
       
   148                 if  ( r == KErrNone )
       
   149                     {
       
   150                     // Indicates that we've initiated a walk - so we can tell whether to close
       
   151                     // the chunk later on.
       
   152                     iHeapWalkInitialised = ETrue;
       
   153                     iWalkHeapCellIndex = 0;
       
   154 
       
   155                     // Walk the client's heap
       
   156                     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapInit - calling heap walker constructor..."));
       
   157                     RMemSpyDriverHeapWalker heapWalker( iWalkHeap, iHeapWalkInitialParameters.iDebugAllocator );
       
   158                     
       
   159                     TMemSpyDriverLogChanHeapWalkObserver observer( *this );
       
   160                     heapWalker.SetObserver( &observer );
       
   161 
       
   162                     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapInit - starting traversal..."));
       
   163                     r = heapWalker.Traverse();
       
   164                     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapInit - finished traversal - err: %d", r));
       
   165                     }
       
   166 
       
   167                 // If the initialise process didn't complete successfully, then we must be sure
       
   168                 // to release the associated heap chunk
       
   169                 if  ( r < KErrNone )
       
   170                     {
       
   171                     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapInit - error scenario - releasing kernel heap chunk copy" ));
       
   172                     iWalkHeap.DisassociateWithKernelChunk();
       
   173                     }
       
   174                 }
       
   175             else
       
   176                 {
       
   177                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapInit - parent process not suspended => KErrAccessDenied"));
       
   178                 r = KErrAccessDenied;
       
   179                 }
       
   180             
       
   181 	        CloseTempObject();
       
   182             }
       
   183         else
       
   184             {
       
   185     	    TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapInit - thread not found"));
       
   186 		    }
       
   187         }
       
   188     else
       
   189         {
       
   190     	TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapInit - params read error: %d", r));
       
   191         }
       
   192 
       
   193 	TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapInit() - END - ret: %d", r));
       
   194     return r;
       
   195     }
       
   196 
       
   197 
       
   198 TInt DMemSpyDriverLogChanHeapWalk::WalkHeapNextCell( TUint aTid, TMemSpyDriverInternalWalkHeapParamsCell* aParams )
       
   199     {
       
   200     const TInt walkedHeapCellCount = iWalkHeapCells.Count();
       
   201 	TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapNextCell() - START - current cell count: %d", walkedHeapCellCount));
       
   202     __ASSERT_ALWAYS( iHeapWalkInitialised && iWalkHeap.ChunkIsInitialised(), MemSpyDriverUtils::PanicThread( ClientThread(), EPanicHeapWalkNotInitialised ) );
       
   203 
       
   204     // Open the original thread
       
   205 	TInt r = OpenTempObject( aTid, EThread );
       
   206 	if  ( r == KErrNone )
       
   207 		{
       
   208         // Get the thread handle and that we have suspended the process' threads
       
   209         DThread* thread = (DThread*) TempObject();
       
   210         if  ( SuspensionManager().IsSuspended( *thread ) )
       
   211             {
       
   212             NKern::ThreadEnterCS();
       
   213 
       
   214             if  ( walkedHeapCellCount > 0 && iWalkHeapCellIndex >= 0 && iWalkHeapCellIndex < walkedHeapCellCount )
       
   215                 {
       
   216                 // Write back head cell to user-space
       
   217                 TMemSpyDriverInternalWalkHeapParamsCell cell( iWalkHeapCells[ iWalkHeapCellIndex++ ] );
       
   218                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapNextCell - returning... cellType: %1d, addr: 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", cell.iCellType, cell.iCellAddress, cell.iLength, cell.iNestingLevel, cell.iAllocNumber ));
       
   219  
       
   220                 r = Kern::ThreadRawWrite( &ClientThread(), aParams, &cell, sizeof(TMemSpyDriverInternalWalkHeapParamsCell) );
       
   221                 if  ( r != KErrNone )
       
   222                     {
       
   223     	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapNextCell - params read error: %d", r));
       
   224                     }
       
   225                 }
       
   226             else
       
   227                 {
       
   228                 r = KErrEof;
       
   229                 }
       
   230 
       
   231             NKern::ThreadLeaveCS();
       
   232             }
       
   233         else
       
   234             {
       
   235             TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapNextCell - parent process not suspended => KErrAccessDenied"));
       
   236             r = KErrAccessDenied;
       
   237             }
       
   238     
       
   239         CloseTempObject();
       
   240         }
       
   241     else
       
   242         {
       
   243     	Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapNextCell - thread not found");
       
   244 		}
       
   245     //    
       
   246 	TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapNextCell() - END - ret: %d", r));
       
   247     return r;
       
   248     }
       
   249 
       
   250 
       
   251 TInt DMemSpyDriverLogChanHeapWalk::WalkHeapClose()
       
   252     {
       
   253     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapClose() - START"));
       
   254     //
       
   255     if  ( iHeapWalkInitialised )
       
   256         {
       
   257         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapClose - heap walk was still open..."));
       
   258       	NKern::ThreadEnterCS();
       
   259 
       
   260         if  ( iWalkHeap.ChunkIsInitialised() )
       
   261             {
       
   262             TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapClose - removing chunk (%O) from process", &iWalkHeap.Chunk() ) );
       
   263             iWalkHeap.DisassociateWithKernelChunk();
       
   264             iWalkHeap.Reset();
       
   265             }
       
   266 
       
   267         // Discard handled cells
       
   268         iWalkHeapCells.Reset();
       
   269 
       
   270         iHeapWalkInitialised = EFalse;
       
   271 
       
   272     	NKern::ThreadLeaveCS();
       
   273         }
       
   274     //
       
   275     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapClose() - END"));
       
   276     return KErrNone;
       
   277     }
       
   278 
       
   279 
       
   280 TInt DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData(TMemSpyDriverInternalWalkHeapCellDataReadParams* aParams)
       
   281     {
       
   282     __ASSERT_ALWAYS( iHeapWalkInitialised && iWalkHeap.ChunkIsInitialised(), MemSpyDriverUtils::PanicThread( ClientThread(), EPanicHeapWalkNotInitialised ) );
       
   283     //
       
   284     const TBool debugEUser = iHeapWalkInitialParameters.iDebugAllocator;
       
   285 	TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData() - START - thread id: %d, vtable: 0x%08x, debugAllocator: %d", iHeapWalkInitialParameters.iTid, iHeapWalkInitialParameters.iRHeapVTable, debugEUser));
       
   286     //
       
   287 	TMemSpyDriverInternalWalkHeapCellDataReadParams params;
       
   288     TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, &params, sizeof(TMemSpyDriverInternalWalkHeapCellDataReadParams) );
       
   289     if  ( r != KErrNone )
       
   290         {
       
   291     	TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData() - END - params read error: %d", r));
       
   292         return r;
       
   293         }
       
   294     
       
   295     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - cell: 0x%08x, readLen: %8d, writeAddr: 0x%08x", params.iCellAddress, params.iReadLen, params.iDes));
       
   296 
       
   297     // Open the original thread
       
   298 	r = OpenTempObject( iHeapWalkInitialParameters.iTid, EThread );
       
   299 	if  ( r == KErrNone )
       
   300 		{
       
   301         // Get the thread handle
       
   302         DThread* thread = (DThread*) TempObject();
       
   303 
       
   304         // Check the threads in the process are suspended
       
   305         if  ( SuspensionManager().IsSuspended( *thread ) )
       
   306             {
       
   307             // Check we can find the cell in the cell list...
       
   308             const TMemSpyDriverInternalWalkHeapParamsCell* cell = CellInfoForSpecificAddress( params.iCellAddress );
       
   309             if  ( cell == NULL )
       
   310                 {
       
   311                 // Maybe the client tried the base address of the cell data.
       
   312                 // try to take the header into account and retry.
       
   313                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - didnt find matching cell for address: 0x%08x... trying address minus allocatedCellHeaderSize", params.iCellAddress ));
       
   314 
       
   315                 const TUint32 cellHeaderSize = (TUint32) RMemSpyDriverRHeapBase::AllocatedCellHeaderSize( debugEUser );
       
   316         
       
   317                 TUint32 addr = (TUint32) params.iCellAddress;
       
   318                 addr -= cellHeaderSize;
       
   319                 params.iCellAddress = (TAny*) addr;
       
   320                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - new address: 0x%08x", params.iCellAddress ));
       
   321         
       
   322                 // Last try
       
   323                 cell = CellInfoForSpecificAddress( params.iCellAddress );
       
   324                 }
       
   325 
       
   326             TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - cell: 0x%08x for address: 0x%08x", cell, params.iCellAddress ));
       
   327 
       
   328             if  ( cell )
       
   329                 {
       
   330                 const TBool isValidCell = iWalkHeap.CheckCell( cell->iCellAddress, cell->iLength );
       
   331                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - isValidCell: %d", isValidCell ));
       
   332         
       
   333                 if  ( isValidCell )
       
   334                     {
       
   335                     // Check the length request is valid
       
   336                     const TInt cellLen = cell->iLength;
       
   337                     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - cellLen: %d", cellLen ));
       
   338 
       
   339                     if  ( params.iReadLen <= cellLen )
       
   340                         {
       
   341                         const TInt cellHeaderSize = RMemSpyDriverRHeapBase::CellHeaderSize( *cell, debugEUser );
       
   342         	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - cellHeaderSize: %8d", cellHeaderSize ));
       
   343 
       
   344                         // Get user side descriptor length info
       
   345          	            TInt destLen = 0;
       
   346         	            TInt destMax = 0;
       
   347                         TUint8* destPtr = NULL;
       
   348 
       
   349                         r = Kern::ThreadGetDesInfo( &ClientThread(), params.iDes, destLen, destMax, destPtr, ETrue );
       
   350         	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - user side descriptor: 0x%08x (0x%08x), len: %8d, maxLen: %8d, r: %d", params.iDes, destPtr, destLen, destMax, r ));
       
   351 
       
   352                         // Work out the start offset for the data...
       
   353                         if  ( r == KErrNone && destMax >= params.iReadLen )
       
   354                             {
       
   355                             const TAny* srcPos = ((TUint8*) cell->iCellAddress) + cellHeaderSize;
       
   356         	                TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - srcPos: 0x%08x", srcPos ));
       
   357 
       
   358                             // Read some data 
       
   359                             r = Kern::ThreadRawRead( thread, srcPos, destPtr, params.iReadLen );
       
   360     	                    TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - read from thread returned: %d", r));
       
   361 
       
   362                             if  ( r == KErrNone )
       
   363                                 {
       
   364                                 // Client will update descriptor length in this situation.
       
   365                                 r = params.iReadLen;
       
   366                                 }
       
   367                             else if ( r == KErrBadDescriptor )
       
   368                                 {
       
   369                                 MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor );
       
   370                                 }
       
   371                             }
       
   372                         else
       
   373                             {
       
   374                             if  ( r != KErrBadDescriptor )
       
   375                                 {
       
   376                                 r = KErrArgument;                
       
   377             	                Kern::Printf( "DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - error - user-descriptor isnt big enough for requested data" );
       
   378                                 }
       
   379                             else
       
   380                                 {
       
   381             	                Kern::Printf( "DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - error - bad or non-writable user-side descriptor" );
       
   382                                 }
       
   383                             }
       
   384                         }
       
   385                     else
       
   386                         {
       
   387                         r = KErrArgument;
       
   388         	            Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - error - read length is bigger than cell length");
       
   389                         }
       
   390                     }
       
   391                 else
       
   392                     {
       
   393                     r = KErrArgument;
       
   394                     Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - invalid cell address: 0x%08x", cell);
       
   395                     }
       
   396                 }
       
   397             else
       
   398                 {
       
   399                 r = KErrArgument;
       
   400                 Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - no cell at user supplied address!");
       
   401                 }
       
   402             }
       
   403         else
       
   404             {
       
   405             TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - parent process not suspended => KErrAccessDenied"));
       
   406             r = KErrAccessDenied;
       
   407             }
       
   408 
       
   409         CloseTempObject();
       
   410         }
       
   411     else
       
   412         {
       
   413     	Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData - thread not found");
       
   414 		}
       
   415     //
       
   416     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapReadCellData() - END"));
       
   417     return r;
       
   418     }
       
   419 
       
   420 
       
   421 TInt DMemSpyDriverLogChanHeapWalk::WalkHeapGetCellInfo( TAny* aCellAddress, TMemSpyDriverInternalWalkHeapParamsCell* aParams )
       
   422     {
       
   423     __ASSERT_ALWAYS( iHeapWalkInitialised && iWalkHeap.ChunkIsInitialised(), MemSpyDriverUtils::PanicThread( ClientThread(), EPanicHeapWalkNotInitialised ) );
       
   424     //
       
   425     const TBool debugEUser = iHeapWalkInitialParameters.iDebugAllocator;
       
   426     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapGetCellInfo() - START - thread id: %d, vtable: 0x%08x, debugAllocator: %d", iHeapWalkInitialParameters.iTid, iHeapWalkInitialParameters.iRHeapVTable, debugEUser));
       
   427     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapGetCellInfo - cell: 0x%08x", aCellAddress));
       
   428 
       
   429     // Open the original thread
       
   430 	TInt r = OpenTempObject( iHeapWalkInitialParameters.iTid, EThread );
       
   431 	if (r != KErrNone)
       
   432 		{
       
   433     	Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapGetCellInfo() - END - thread not found");
       
   434 		return r;
       
   435 		}
       
   436 
       
   437     // Get the thread handle
       
   438     DThread* thread = (DThread*) TempObject();
       
   439 
       
   440     // Check the threads in the process are suspended
       
   441     if  ( !SuspensionManager().IsSuspended( *thread ) )
       
   442         {
       
   443         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapGetCellInfo - END - parent process not suspended => KErrAccessDenied"));
       
   444         CloseTempObject();
       
   445         return KErrAccessDenied;
       
   446         }
       
   447 
       
   448     // Check we can find the cell in the cell list...
       
   449     const TMemSpyDriverInternalWalkHeapParamsCell* cell = CellInfoForSpecificAddress( aCellAddress );
       
   450     if  ( cell == NULL )
       
   451         {
       
   452         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapGetCellInfo - no exact match for address: 0x%08x...", aCellAddress));
       
   453 
       
   454         // Maybe the client tried the base address of the cell data.
       
   455         // try to take the header into account and retry.
       
   456         const TUint32 cellHeaderSize = (TUint32) RMemSpyDriverRHeapBase::AllocatedCellHeaderSize( debugEUser );
       
   457         TUint32 addr = (TUint32) aCellAddress;
       
   458         addr -= cellHeaderSize;
       
   459         
       
   460         TAny* cellByRawStartingAddress = (TAny*) addr;
       
   461         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapGetCellInfo - trying to search by start of cell address: 0x%08x (cellHeaderSize: %d)", cellByRawStartingAddress, cellHeaderSize));
       
   462         cell = CellInfoForSpecificAddress( cellByRawStartingAddress );
       
   463         
       
   464         // If the cell still wasn't found, then let's look for any heap cell that contains
       
   465         // the client-specified address (i.e. find the heap cell that contains the specified
       
   466         // address).
       
   467         if  ( cell == NULL )
       
   468             {
       
   469             TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapGetCellInfo - still couldnt find cell by exact address. Searching for the cell that contains the specified address..."));
       
   470             cell = CellInfoForAddressWithinCellRange( aCellAddress );
       
   471             }
       
   472         }
       
   473 
       
   474     if  ( cell )
       
   475         {
       
   476         const TBool isValidCell = iWalkHeap.CheckCell( cell->iCellAddress, cell->iLength );
       
   477         if  ( isValidCell )
       
   478             {
       
   479             // Have enough info to write back to client now
       
   480             TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapGetCellInfo - returning... cellType: %1d, addr: 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", cell->iCellType, cell->iCellAddress, cell->iLength, cell->iNestingLevel, cell->iAllocNumber ));
       
   481             r = Kern::ThreadRawWrite( &ClientThread(), aParams, cell, sizeof(TMemSpyDriverInternalWalkHeapParamsCell) );
       
   482             }
       
   483         else
       
   484             {
       
   485             r = KErrArgument;
       
   486             Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapGetCellInfo - invalid cell address: 0x%08x", cell);
       
   487             }
       
   488         }
       
   489     else
       
   490         {
       
   491         r = KErrArgument;
       
   492         Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapGetCellInfo - no cell at user supplied address!");
       
   493         }
       
   494     
       
   495     CloseTempObject();
       
   496     //
       
   497     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapWalk::WalkHeapGetCellInfo() - END"));
       
   498     return r;
       
   499     }
       
   500 
       
   501 
       
   502 
       
   503 
       
   504 
       
   505 
       
   506 
       
   507 
       
   508 
       
   509 
       
   510 
       
   511 
       
   512 
       
   513 
       
   514 
       
   515 
       
   516 
       
   517 
       
   518 
       
   519 
       
   520 
       
   521 
       
   522 
       
   523 
       
   524 
       
   525 
       
   526 
       
   527 const TMemSpyDriverInternalWalkHeapParamsCell* DMemSpyDriverLogChanHeapWalk::CellInfoForAddressWithinCellRange( TAny* aAddress ) const
       
   528     {
       
   529     const TMemSpyDriverInternalWalkHeapParamsCell* ret = NULL;
       
   530     //
       
   531     const TInt count = iWalkHeapCells.Count();
       
   532     for(TInt i=0; i<count; i++)
       
   533         {
       
   534         const TMemSpyDriverInternalWalkHeapParamsCell& item = iWalkHeapCells[i];
       
   535         const TAny* cellExtent = (TAny*) (TUint32( item.iCellAddress ) + item.iLength);
       
   536         //
       
   537         if  ( aAddress >= item.iCellAddress && aAddress < cellExtent )
       
   538             {
       
   539             ret = &item;
       
   540             }
       
   541         }
       
   542     //
       
   543     return ret;
       
   544     }
       
   545 
       
   546 
       
   547 const TMemSpyDriverInternalWalkHeapParamsCell* DMemSpyDriverLogChanHeapWalk::CellInfoForSpecificAddress( TAny* aAddress ) const
       
   548     {
       
   549     const TMemSpyDriverInternalWalkHeapParamsCell* ret = NULL;
       
   550     //
       
   551     const TInt count = iWalkHeapCells.Count();
       
   552     for(TInt i=0; i<count; i++)
       
   553         {
       
   554         const TMemSpyDriverInternalWalkHeapParamsCell& item = iWalkHeapCells[i];
       
   555         if  ( item.iCellAddress == aAddress )
       
   556             {
       
   557             ret = &item;
       
   558             }
       
   559         }
       
   560     //
       
   561     return ret;
       
   562     }
       
   563 
       
   564 
       
   565 
       
   566 
       
   567 
       
   568 
       
   569 
       
   570 
       
   571 
       
   572 
       
   573 
       
   574 
       
   575 
       
   576 
       
   577 
       
   578 
       
   579 TBool DMemSpyDriverLogChanHeapWalk::WalkerHandleHeapCell( TInt aCellType, TAny* aCellAddress, TInt aLength, TInt aNestingLevel, TInt aAllocNumber )
       
   580     {
       
   581     TInt error = KErrNone;
       
   582     //
       
   583     if  ( iHeapWalkInitialised )
       
   584         {
       
   585         TMemSpyDriverInternalWalkHeapParamsCell cell;
       
   586         cell.iCellType = aCellType;
       
   587 	    cell.iCellAddress = aCellAddress;
       
   588 	    cell.iLength = aLength;
       
   589 	    cell.iNestingLevel = aNestingLevel;
       
   590 	    cell.iAllocNumber = aAllocNumber;
       
   591         //
       
   592   	    NKern::ThreadEnterCS();
       
   593         error = iWalkHeapCells.Append( cell );
       
   594   	    NKern::ThreadLeaveCS();
       
   595         }
       
   596     //
       
   597     return ( error == KErrNone );
       
   598     }