perfsrv/memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapDataBase.cpp
changeset 55 f2950aff7424
equal deleted inserted replaced
48:516af714ebb4 55:f2950aff7424
       
     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 "MemSpyDriverLogChanHeapDataUser.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 "MemSpyDriverLogChanHeapDataBase.h"
       
    32 #include "MemSpyDriverHeap.h"
       
    33 #include "MemSpyDriverUtils.h"
       
    34 #include "MemSpyDriverDevice.h"
       
    35 #include "MemSpyDriverOSAdaption.h"
       
    36 #include "MemSpyDriverHeapWalker.h"
       
    37 #include "MemSpyDriverUserEventMonitor.h"
       
    38 #include "MemSpyDriverSuspensionManager.h"
       
    39 
       
    40 DMemSpyDriverLogChanHeapDataBase::DMemSpyDriverLogChanHeapDataBase( DMemSpyDriverDevice& aDevice, DThread& aThread )
       
    41 :	DMemSpyDriverLogChanHeapBase( aDevice, aThread )
       
    42     {
       
    43     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::DMemSpyDriverLogChanHeapDataBase() - this: 0x%08x", this ));
       
    44     }
       
    45 
       
    46 DMemSpyDriverLogChanHeapDataBase::~DMemSpyDriverLogChanHeapDataBase()
       
    47 	{
       
    48 	TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::~DMemSpyDriverLogChanHeapDataBase() - START - this: 0x%08x", this ));
       
    49 	ReleaseCellList();
       
    50 	TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::~DMemSpyDriverLogChanHeapDataBase() - END - this: 0x%08x", this ));
       
    51 	}
       
    52 
       
    53 TInt DMemSpyDriverLogChanHeapDataBase::PrepareCellListTransferBuffer()
       
    54     {
       
    55     // Transfer free cells immediately from xfer stream
       
    56     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::PrepareCellListTransferBuffer() - START - iHeapStream: 0x%08x", iHeapStream ));
       
    57     __ASSERT_ALWAYS( !iHeapStream, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicHeapFreeCellStreamNotClosed ) );
       
    58     //
       
    59     TInt r = KErrNoMemory;
       
    60     //
       
    61     NKern::ThreadEnterCS();
       
    62     //
       
    63     iHeapStream = new RMemSpyMemStreamWriter();
       
    64     if  ( iHeapStream )
       
    65         {
       
    66         const TInt requiredMemory = CalculateCellListBufferSize();
       
    67         r = OpenXferStream( *iHeapStream, requiredMemory );
       
    68         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::PrepareCellListTransferBuffer() - requested %d bytes for free cell list, r: %d", requiredMemory, r ));
       
    69 
       
    70         if  ( r == KErrNone )
       
    71             {
       
    72             const TInt count = iCellList.Count();
       
    73             TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::PrepareCellListTransferBuffer() - cell count: %d", count ));
       
    74             //
       
    75             iHeapStream->WriteInt32( count );
       
    76             for( TInt i=0; i<count; i++ )
       
    77                 {
       
    78                 const TMemSpyDriverCell& cell = iCellList[ i ];
       
    79                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::PrepareCellListTransferBuffer() - storing entry: %d", i ));
       
    80                 //
       
    81                 iHeapStream->WriteInt32( cell.iType );
       
    82                 iHeapStream->WriteUint32( reinterpret_cast<TUint32>( cell.iAddress ) );
       
    83                 iHeapStream->WriteInt32( cell.iLength );
       
    84                 }
       
    85 
       
    86             // Finished with the array now
       
    87             iCellList.Reset();
       
    88 
       
    89             // We return the amount of client-side memory that needs to be allocated to hold the buffer
       
    90             r = requiredMemory;
       
    91             }
       
    92         }
       
    93     //
       
    94     NKern::ThreadLeaveCS();
       
    95                
       
    96     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::PrepareCellListTransferBuffer() - END - r: %d", r));
       
    97 	return r;
       
    98     }
       
    99 
       
   100 TInt DMemSpyDriverLogChanHeapDataBase::FetchCellList( TDes8* aBufferSink )
       
   101     {
       
   102     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::FetchCellList() - START - iHeapStream: 0x%08x", iHeapStream ));
       
   103     __ASSERT_ALWAYS( iHeapStream, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicHeapFreeCellStreamNotOpen ) );
       
   104 
       
   105     TInt r = KErrNone;
       
   106 
       
   107     // Write buffer to client
       
   108     NKern::ThreadEnterCS();
       
   109     r = iHeapStream->WriteAndClose( aBufferSink );
       
   110 
       
   111     // Tidy up
       
   112     ReleaseCellList();
       
   113 
       
   114     NKern::ThreadLeaveCS();
       
   115     //
       
   116     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::FetchCellList() - END - r: %d", r));
       
   117 	return r;
       
   118     }
       
   119 
       
   120 
       
   121 
       
   122 TInt DMemSpyDriverLogChanHeapDataBase::CalculateCellListBufferSize() const
       
   123     {
       
   124     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::CalculateCellListBufferSize() - START" ));
       
   125 
       
   126     const TInt count = iCellList.Count();
       
   127     const TInt entrySize = sizeof( TInt32 ) + sizeof( TInt32 ) + sizeof( TUint32 );
       
   128     const TInt r = ( count * entrySize ) + sizeof( TInt ); // Extra TInt to hold count
       
   129                 
       
   130     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::CalculateCellListBufferSize() - END - r: %d, count: %d, entrySize: %d", r, count, entrySize ));
       
   131 	return r;
       
   132     }
       
   133 
       
   134 
       
   135 
       
   136 void DMemSpyDriverLogChanHeapDataBase::ReleaseCellList()
       
   137     {
       
   138 	TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::ReleaseCellList() - START - this: 0x%08x", this ));
       
   139 
       
   140     NKern::ThreadEnterCS();
       
   141     iCellList.Reset();
       
   142     delete iHeapStream;
       
   143     iHeapStream = NULL;
       
   144     NKern::ThreadLeaveCS();
       
   145 
       
   146     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::ReleaseCellList() - END - this: 0x%08x", this ));
       
   147     }
       
   148 
       
   149 TBool DMemSpyDriverLogChanHeapDataBase::HandleHeapCell(TMemSpyDriverCellType aCellType, TAny* aCellAddress, TInt aLength, TInt /*aNestingLevel*/, TInt /*aAllocNumber*/)
       
   150     {
       
   151 	TInt err = KErrNone;
       
   152     if (((aCellType & EMemSpyDriverFreeCellMask) && iHeapInfoParams.iBuildFreeCellList) || 
       
   153         ((aCellType & EMemSpyDriverAllocatedCellMask) && iHeapInfoParams.iBuildAllocCellList))
       
   154 		{
       
   155 		TMemSpyDriverCell cell;
       
   156 		cell.iType = aCellType;
       
   157 		cell.iAddress = aCellAddress;
       
   158 		cell.iLength = aLength;
       
   159 
       
   160 		NKern::ThreadEnterCS();
       
   161 		err = iCellList.Append(cell);
       
   162 		NKern::ThreadLeaveCS();
       
   163 		}
       
   164 	return err == KErrNone;
       
   165 	}
       
   166 
       
   167 void DMemSpyDriverLogChanHeapDataBase::HandleHeapWalkInit()
       
   168 	{
       
   169 	}
       
   170 
       
   171 TInt DMemSpyDriverLogChanHeapDataBase::GetFullData( TMemSpyDriverInternalHeapDataParams* aParams )
       
   172     {
       
   173     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::GetFullData() - START"));
       
   174 
       
   175     TMemSpyDriverInternalHeapDataParams params;
       
   176     TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, &params, sizeof(TMemSpyDriverInternalHeapDataParams) );
       
   177     //
       
   178     if  ( r == KErrNone )
       
   179         {
       
   180         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::GetFullData - thread id: %d, remaining: %8d, vtable: 0x%08x", params.iTid, params.iRemaining, params.iRHeapVTable));
       
   181 
       
   182         // NB: The two 'get heap data' functions return either an error ( < KErrNone ) or then
       
   183         // return the length of the descriptor data that was written to the client's address
       
   184         // space.
       
   185         //
       
   186         r = GetFullData( params );
       
   187 
       
   188         // Write back to user space if everything went okay. Remember that the 
       
   189         // return value above will be the length of data that was written to the
       
   190         // client if there was no error.
       
   191         if  ( r >= KErrNone )
       
   192             {
       
   193             const TInt clientDescriptorLength = r;
       
   194 
       
   195             // Make sure we update client's remaining data
       
   196             r = Kern::ThreadRawWrite( &ClientThread(), aParams, &params, sizeof(TMemSpyDriverInternalHeapDataParams) );
       
   197             
       
   198             // ... and if that went okay, then we return the length of the descriptor data
       
   199             // back to the client.
       
   200             if  ( r == KErrNone )
       
   201                 {
       
   202                 r = clientDescriptorLength;
       
   203                 }
       
   204             }
       
   205         }
       
   206     else
       
   207         {
       
   208         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::GetFullData - params read error: %d", r));
       
   209         }
       
   210 
       
   211     // Done
       
   212     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::GetFullData() - END - ret: %d", r));
       
   213     return r;
       
   214     }
       
   215 
       
   216 TInt DMemSpyDriverLogChanHeapDataBase::DoGetFullData(TMemSpyDriverInternalHeapDataParams& aParams, 
       
   217                                                      DThread* aThread, 
       
   218                                                      RMemSpyDriverRHeapBase& aHeap)
       
   219     {
       
   220     TInt r = KErrNone;
       
   221     if  ( aParams.iChecksum != 0 )
       
   222         {
       
   223         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::DoGetFullData - checksum validation requested - expecting: 0x%08x", aParams.iChecksum ) );
       
   224         
       
   225         RMemSpyDriverHeapWalker heapWalker(aHeap);
       
   226         
       
   227         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::DoGetFullData - starting traversal..." ));
       
   228 #if ( defined( TRACE_TYPE_USERHEAP ) && defined( TRACE_TYPE_HEAPWALK ) )
       
   229         heapWalker.SetPrintDebug();
       
   230 #endif
       
   231         r = heapWalker.Traverse();
       
   232         const TUint32 calculatedChecksum = heapWalker.Stats().iFreeCellCRC;
       
   233         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::DoGetFullData - finished traversal - err: %d, checksum: 0x%08x", r, calculatedChecksum ));
       
   234 
       
   235         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::DoGetFullData - comparing CALCULATED: 0x%08x vs EXPECTED: 0x%08x", calculatedChecksum, aParams.iChecksum ));
       
   236         if  ( calculatedChecksum != aParams.iChecksum )
       
   237             {
       
   238             Kern::Printf("DMemSpyDriverLogChanHeapDataBase::DoGetFullData - comparing CALCULATED: 0x%08x vs EXPECTED: 0x%08x for thread %O", calculatedChecksum, aParams.iChecksum, aThread );
       
   239             r = KErrCorrupt;
       
   240             }
       
   241         }
       
   242 
       
   243     // Get user side (MemSpyApp) descriptor length info
       
   244     if  ( r == KErrNone )
       
   245         {
       
   246         TInt destLen = 0;
       
   247         TInt destMax = 0;
       
   248         TUint8* destPtr = NULL;
       
   249         r = Kern::ThreadGetDesInfo( &ClientThread(), aParams.iDes, destLen, destMax, destPtr, ETrue );
       
   250         TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::DoGetFullData - user side descriptor: 0x%08x (0x%08x), len: %8d, maxLen: %8d, r: %d", aParams.iDes, destPtr, destLen, destMax, r ));
       
   251         destMax = destMax & ~(KPageSize-1); // Round down dest max to page size
       
   252         if (destMax <= 0 || (aParams.iReadAddress & (KPageSize-1)))
       
   253             {
       
   254             // 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
       
   255             r = KErrArgument;
       
   256             }
       
   257 
       
   258         if  ( r == KErrNone )
       
   259             {
       
   260             const TLinAddr chunkBase = aHeap.ChunkBase(); 
       
   261             const TLinAddr chunkMaxAddr = chunkBase + OSAdaption().DChunk().GetMaxSize(aHeap.Chunk());
       
   262             TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::DoGetFullData - chunkBase:    0x%08x", chunkBase) );
       
   263 
       
   264             TLinAddr readAddress = aParams.iReadAddress;
       
   265             if (aParams.iRemaining < 0 )
       
   266                 {
       
   267                 // Initial case, start from the bottom
       
   268                 readAddress = chunkBase;
       
   269                 aParams.iRemaining = aHeap.Helper()->CommittedSize();
       
   270                 }
       
   271 
       
   272             // The remaining number of bytes should allow us to calculate the position
       
   273             // to read from.
       
   274             TInt amountToRead = Min( aParams.iRemaining, destMax );
       
   275             TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::DoGetFullData - amountToRead:           %8d", amountToRead) );
       
   276 
       
   277             // Do the read from the heap we are spying on into MemSpy's address space
       
   278             do
       
   279                 {
       
   280                 r = Kern::ThreadRawRead( aThread, (const void*)readAddress, destPtr, amountToRead );
       
   281                 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataBase::DoGetFullData - reading %d bytes starting at 0x%08x result: %d", 
       
   282                                      amountToRead, readAddress, r) );
       
   283 
       
   284                 if (r == KErrBadDescriptor)
       
   285                     {
       
   286                     // This is not necessarily an error - it could be we've hit an unmapped page
       
   287                     if (amountToRead > KPageSize)
       
   288                         {
       
   289                         // retry reading a single page instead
       
   290                         amountToRead = KPageSize;
       
   291                         }
       
   292                     else
       
   293                         {
       
   294                         // Try the next page
       
   295                         readAddress += KPageSize;
       
   296                         }
       
   297                     }
       
   298                 } while (r == KErrBadDescriptor && readAddress < chunkMaxAddr);
       
   299             //
       
   300             if  (r == KErrNone)
       
   301                 {
       
   302                 // Client takes care of updating descriptor length.
       
   303                 r = amountToRead;
       
   304                 }
       
   305 
       
   306             // Update remaining bytes
       
   307             aParams.iRemaining -= amountToRead;
       
   308             aParams.iReadAddress = readAddress;
       
   309             }
       
   310         }
       
   311     return r;
       
   312     }