diff -r 000000000000 -r a03f92240627 memspy/Engine/Source/Helpers/MemSpyEngineHelperChunk.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/Engine/Source/Helpers/MemSpyEngineHelperChunk.cpp Tue Feb 02 01:57:15 2010 +0200 @@ -0,0 +1,812 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +#include + +// Driver includes +#include + +// User includes +#include +#include +#include +#include +#include +#include + +// Constants +const TInt KMemSpyEngineMaxChunkCount = 768; + +// Literal constants +_LIT( KMemSpyEngineChunkListOutputComma, ", " ); + + + +CMemSpyEngineHelperChunk::CMemSpyEngineHelperChunk( CMemSpyEngine& aEngine ) +: iEngine( aEngine ) + { + } + + +CMemSpyEngineHelperChunk::~CMemSpyEngineHelperChunk() + { + } + + +void CMemSpyEngineHelperChunk::ConstructL() + { + } + + +CMemSpyEngineHelperChunk* CMemSpyEngineHelperChunk::NewL( CMemSpyEngine& aEngine ) + { + CMemSpyEngineHelperChunk* self = new(ELeave) CMemSpyEngineHelperChunk( aEngine ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + + +EXPORT_C void CMemSpyEngineHelperChunk::OutputChunkInfoForThreadL( const CMemSpyThread& aThread ) + { + OutputChunkInfoForThreadL( aThread.Id() ); + } + + +EXPORT_C void CMemSpyEngineHelperChunk::OutputChunkInfoForThreadL( TThreadId aTid ) + { + TBuf<512> lineBuffer; + OutputChunkInfoForThreadL( aTid, lineBuffer ); + } + + +EXPORT_C void CMemSpyEngineHelperChunk::OutputChunkInfoForThreadL( TThreadId aTid, TDes& aLineBuffer ) + { + DoOutputChunkInfoForObjectL( aTid, aLineBuffer, EThread ); + } + + +EXPORT_C void CMemSpyEngineHelperChunk::OutputChunkInfoForProcessL( const CMemSpyProcess& aProcess ) + { + OutputChunkInfoForProcessL( aProcess.Id() ); + } + + +EXPORT_C void CMemSpyEngineHelperChunk::OutputChunkInfoForProcessL( TProcessId aPid ) + { + TBuf<512> lineBuffer; + OutputChunkInfoForProcessL( aPid, lineBuffer ); + } + + +EXPORT_C void CMemSpyEngineHelperChunk::OutputChunkInfoForProcessL( TProcessId aPid, TDes& aLineBuffer ) + { + DoOutputChunkInfoForObjectL( aPid, aLineBuffer, EProcess ); + } + + +EXPORT_C CMemSpyEngineChunkList* CMemSpyEngineHelperChunk::ListL() + { + RArray handles( 128 ); + CleanupClosePushL( handles ); + // + GetChunkHandlesL( handles, EAll ); + CMemSpyEngineChunkList* list = CreateListFromHandlesL( handles ); + // + CleanupStack::PopAndDestroy( &handles ); + return list; + } + + +EXPORT_C CMemSpyEngineChunkList* CMemSpyEngineHelperChunk::ListForThreadL( TThreadId aTid ) + { + RArray handles( 128 ); + CleanupClosePushL( handles ); + // + GetChunkHandlesL( handles, EThread, aTid ); + CMemSpyEngineChunkList* list = CreateListFromHandlesL( handles ); + // + CleanupStack::PopAndDestroy( &handles ); + return list; + } + + +EXPORT_C CMemSpyEngineChunkList* CMemSpyEngineHelperChunk::ListForProcessL( TProcessId aPid ) + { + RArray handles( 128 ); + CleanupClosePushL( handles ); + // + GetChunkHandlesL( handles, EProcess, aPid ); + CMemSpyEngineChunkList* list = CreateListFromHandlesL( handles ); + // + CleanupStack::PopAndDestroy( &handles ); + return list; + } + + +void CMemSpyEngineHelperChunk::DoOutputChunkInfoForObjectL( TUint aId, TDes& aLineBuffer, TType aType ) + { + TFullName ownerName; + // + RArray handles( 128 ); + CleanupClosePushL( handles ); + // + GetChunkHandlesL( handles, aType, aId ); + CMemSpyEngineChunkList* list = CreateListFromHandlesL( handles ); + // + CleanupStack::PopAndDestroy( &handles ); + CleanupStack::PushL( list ); + // + const TInt count = list->Count(); + for (TInt i=0; iAt( i ); + // + _LIT(KLine1, "Name"); + iEngine.Sink().OutputItemAndValueL( KLine1, entry.Name() ); + // + _LIT(KLine2, "Owner"); + entry.OwnerName( ownerName ); + iEngine.Sink().OutputItemAndValueL( KLine2, ownerName ); + // + _LIT(KLine3, "Address"); + _LIT(KLine3Format, "0x%08x - 0x%08x"); + aLineBuffer.Format(KLine3Format, entry.BaseAddress(), entry.UpperAddress() ); + iEngine.Sink().OutputItemAndValueL( KLine3, aLineBuffer ); + // + _LIT(KLine4, "Size (max)"); + _LIT(KLine4Format, "%d (%d)"); + aLineBuffer.Format(KLine4Format, entry.Size(), entry.MaxSize()); + iEngine.Sink().OutputItemAndValueL( KLine4, aLineBuffer ); + // + if ( i < count - 1 ) + { + iEngine.Sink().OutputBlankLineL(); + } + } + // + CleanupStack::PopAndDestroy( list ); + } + + +void CMemSpyEngineHelperChunk::GetChunkHandlesL( RArray& aHandles, TType aType, TUint aId ) + { + TAny* handles[ KMemSpyEngineMaxChunkCount ]; + TInt count = KMemSpyEngineMaxChunkCount; + + TInt r = 0; + // + switch( aType ) + { + case EThread: + r = iEngine.Driver().GetChunkHandlesForThread( aId, handles, count ); + break; + case EProcess: + r = iEngine.Driver().GetChunkHandlesForProcess( aId, handles, count ); + break; + default: + case EAll: + r = iEngine.Driver().GetChunkHandles( handles, count ); + break; + } + // + if ( r == KErrNone ) + { + count = Min( count, KMemSpyEngineMaxChunkCount ); + for( TInt index = 0; index < count; index++ ) + { + TAny* handle = handles[ index ]; + + if ( aHandles.Find( handle ) == KErrNotFound ) + { + aHandles.AppendL( handle ); + } + } + } + } + + +CMemSpyEngineChunkList* CMemSpyEngineHelperChunk::CreateListFromHandlesL( const RArray& aHandles ) + { + CMemSpyEngineChunkList* list = CMemSpyEngineChunkList::NewLC( iEngine ); + // + TMemSpyDriverChunkInfo info; + const TInt count = aHandles.Count(); + // + for( TInt i=0; iAddItemL( entry ); + CleanupStack::Pop( entry ); + } + } + // + list->SortBySizeL(); + // + CleanupStack::Pop( list ); + return list; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +CMemSpyEngineChunkList::CMemSpyEngineChunkList( CMemSpyEngine& aEngine ) +: iEngine( aEngine ) + { + } + + +EXPORT_C CMemSpyEngineChunkList::~CMemSpyEngineChunkList() + { + iItems.ResetAndDestroy(); + iItems.Close(); + } + + +void CMemSpyEngineChunkList::ConstructL() + { + } + + +CMemSpyEngineChunkList* CMemSpyEngineChunkList::NewLC( CMemSpyEngine& aEngine ) + { + CMemSpyEngineChunkList* self = new(ELeave) CMemSpyEngineChunkList( aEngine ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + + +EXPORT_C TInt CMemSpyEngineChunkList::Count() const + { + return iItems.Count(); + } + + +EXPORT_C CMemSpyEngineChunkEntry& CMemSpyEngineChunkList::At( TInt aIndex ) + { + return *iItems[ aIndex ]; + } + + +EXPORT_C const CMemSpyEngineChunkEntry& CMemSpyEngineChunkList::At( TInt aIndex ) const + { + return *iItems[ aIndex ]; + } + + +EXPORT_C void CMemSpyEngineChunkList::SortByNameL() + { + TLinearOrder< CMemSpyEngineChunkEntry > comparer( CompareByName ); + iItems.Sort( comparer ); + } + + +EXPORT_C void CMemSpyEngineChunkList::SortBySizeL() + { + TLinearOrder< CMemSpyEngineChunkEntry > comparer( CompareBySize ); + iItems.Sort( comparer ); + } + + +EXPORT_C TInt CMemSpyEngineChunkList::ItemIndex( const CMemSpyEngineChunkEntry& aEntry ) const + { + TInt ret = KErrNotFound; + // + const TInt count = Count(); + for( TInt i=0; iDes() ); + + // + _LIT(KCol1, "Name"); + pColumns.Append( KCol1 ); + pColumns.Append( KMemSpyEngineChunkListOutputComma ); + + // + _LIT(KCol2, "Owning Process"); + pColumns.Append( KCol2 ); + pColumns.Append( KMemSpyEngineChunkListOutputComma ); + + // + _LIT(KCol3, "Size"); + pColumns.Append( KCol3 ); + pColumns.Append( KMemSpyEngineChunkListOutputComma ); + + // + _LIT(KCol4, "Max. Size"); + pColumns.Append( KCol4 ); + pColumns.Append( KMemSpyEngineChunkListOutputComma ); + + // + _LIT(KCol5, "Address"); + pColumns.Append( KCol5 ); + + // + aEngine.Sink().OutputLineL( pColumns ); + CleanupStack::PopAndDestroy( columns ); + } + + +EXPORT_C TBool CMemSpyEngineChunkList::EntryExists( TAny* aHandle ) const + { + TBool ret = EFalse; + // + const TInt count = Count(); + for( TInt i=0; iHandle() == aHandle ); + } + // + return ret; + } + + +void CMemSpyEngineChunkList::AddItemL( CMemSpyEngineChunkEntry* aItem ) + { + iItems.AppendL( aItem ); + } + + +void CMemSpyEngineChunkList::Remove( TInt aIndex ) + { + CMemSpyEngineChunkEntry* item = iItems[ aIndex ]; + delete item; + iItems.Remove( aIndex ); + } + + +void CMemSpyEngineChunkList::RemoveByHandle( TAny* aChunkHandle ) + { + const TInt index = ItemIndexByChunkHandle( aChunkHandle ); + if ( index >= 0 ) + { + Remove( index ); + } + } + + +TInt CMemSpyEngineChunkList::ItemIndexByProcessId( TUint aPid ) const + { + const TInt ret = ItemIndexByProcessId( aPid, 0 ); + return ret; + } + + +TInt CMemSpyEngineChunkList::ItemIndexByProcessId( TUint aPid, TInt aStartIndex ) const + { + TInt ret = KErrNotFound; + // + const TInt count = Count(); + for( TInt i=aStartIndex; iOwnerId() == aPid ) + { + ret = i; + break; + } + } + // + return ret; + } + + +TInt CMemSpyEngineChunkList::ItemIndexByProcessId( TUint aPid, TMemSpyDriverChunkType aType ) const + { + TInt ret = KErrNotFound; + // + const TInt count = Count(); + for( TInt i=0; iOwnerId() == aPid && item->Info().iType == aType ) + { + ret = i; + break; + } + } + // + return ret; + } + + +TInt CMemSpyEngineChunkList::ItemIndexByChunkHandle( TAny* aHandle ) const + { + TInt ret = KErrNotFound; + // + const TInt count = Count(); + for( TInt i=0; iHandle() == aHandle ) + { + ret = i; + break; + } + } + // + return ret; + } + + +EXPORT_C TInt CMemSpyEngineChunkList::MdcaCount() const + { + return Count(); + } + + +EXPORT_C TPtrC CMemSpyEngineChunkList::MdcaPoint( TInt aIndex ) const + { + const CMemSpyEngineChunkEntry& item = At( aIndex ); + return TPtrC( item.Caption() ); + } + + +TInt CMemSpyEngineChunkList::CompareByName( const CMemSpyEngineChunkEntry& aLeft, const CMemSpyEngineChunkEntry& aRight ) + { + const TInt ret = aLeft.Name().CompareF( aRight.Name() ); + return ret; + } + + +TInt CMemSpyEngineChunkList::CompareBySize( const CMemSpyEngineChunkEntry& aLeft, const CMemSpyEngineChunkEntry& aRight ) + { + TInt ret = -1; + // + if ( aLeft.Size() < aRight.Size() ) + { + ret = 1; + } + else if ( aLeft.Size() == aRight.Size() ) + { + ret = 0; + } + // + return ret; + } + + + + + + + + + + + + + + + + + + +CMemSpyEngineChunkEntry::CMemSpyEngineChunkEntry( CMemSpyEngine& aEngine ) +: iEngine( aEngine ) + { + } + + +CMemSpyEngineChunkEntry::~CMemSpyEngineChunkEntry() + { + delete iCaption; + delete iInfo; + delete iList; + } + + +void CMemSpyEngineChunkEntry::ConstructL( const TMemSpyDriverChunkInfo& aInfo ) + { + // Copy info + iInfo = new(ELeave) TMemSpyDriverChunkInfo(); + *iInfo = aInfo; + + // Make caption + TBuf item; + _LIT(KCaptionFormat, "\t%S\t\t%d"); + item.Format( KCaptionFormat, &Name(), Size() ); + iCaption = item.AllocL(); + + // Make other items + iList = CMemSpyEngineOutputList::NewL(); + + _LIT( KEntry0, "Name"); + iList->AddItemL( KEntry0, Name() ); + + _LIT( KEntryType, "Type" ); + switch( aInfo.iType ) + { + default: + case EMemSpyDriverChunkTypeUnknown: + iList->AddItemL( KEntryType, _L("Unknown") ); + break; + case EMemSpyDriverChunkTypeHeap: + iList->AddItemL( KEntryType, _L("Heap") ); + break; + case EMemSpyDriverChunkTypeHeapKernel: + iList->AddItemL( KEntryType, _L("Kernel Heap") ); + break; + case EMemSpyDriverChunkTypeStackAndProcessGlobalData: + iList->AddItemL( KEntryType, _L("Stack and Process Global Data") ); + break; + case EMemSpyDriverChunkTypeStackKernel: + iList->AddItemL( KEntryType, _L("Kernel Stack") ); + break; + case EMemSpyDriverChunkTypeGlobalData: + iList->AddItemL( KEntryType, _L("Global Data") ); + break; + case EMemSpyDriverChunkTypeCode: + iList->AddItemL( KEntryType, _L("Code") ); + break; + case EMemSpyDriverChunkTypeCodeGlobal: + iList->AddItemL( KEntryType, _L("Global Code") ); + break; + case EMemSpyDriverChunkTypeCodeSelfModifiable: + iList->AddItemL( KEntryType, _L("Self Modifiable Code") ); + break; + case EMemSpyDriverChunkTypeLocal: + iList->AddItemL( KEntryType, _L("Local") ); + break; + case EMemSpyDriverChunkTypeGlobal: + iList->AddItemL( KEntryType, _L("Global") ); + break; + case EMemSpyDriverChunkTypeRamDrive: + iList->AddItemL( KEntryType, _L("RAM Drive") ); + break; + } + + _LIT( KEntry1, "Owning Process"); + OwnerName( item ); + iList->AddItemL( KEntry1, item ); + + _LIT( KEntry2, "Address" ); + _LIT( KEntry2Format, "0x%08x - 0x%08x" ); + item.Format( KEntry2Format, BaseAddress(), UpperAddress() ); + iList->AddItemL( KEntry2, item ); + + _LIT( KEntry3, "Size"); + iList->AddItemL( KEntry3, Size() ); + + _LIT( KEntry4, "Max. Size"); + iList->AddItemL( KEntry4, MaxSize() ); + + _LIT( KEntryAttributeFormat, "Attribute %d"); + TInt attribNum = 0; + // + if ( aInfo.iAttributes & ENormal ) + { + item.Format( KEntryAttributeFormat, ++attribNum ); + iList->AddItemL( item, _L("Normal") ); + } + if ( aInfo.iAttributes & EDoubleEnded ) + { + item.Format( KEntryAttributeFormat, ++attribNum ); + iList->AddItemL( item, _L("Double Ended") ); + } + if ( aInfo.iAttributes & EDisconnected ) + { + item.Format( KEntryAttributeFormat, ++attribNum ); + iList->AddItemL( item, _L("Disconnected") ); + } + if ( aInfo.iAttributes & EConstructed ) + { + item.Format( KEntryAttributeFormat, ++attribNum ); + iList->AddItemL( item, _L("Constructed") ); + } + if ( aInfo.iAttributes & EMemoryNotOwned ) + { + item.Format( KEntryAttributeFormat, ++attribNum ); + iList->AddItemL( item, _L("Memory Not Owned") ); + } + } + + +CMemSpyEngineChunkEntry* CMemSpyEngineChunkEntry::NewLC( CMemSpyEngine& aEngine, const TMemSpyDriverChunkInfo& aInfo ) + { + CMemSpyEngineChunkEntry* self = new(ELeave) CMemSpyEngineChunkEntry( aEngine ); + CleanupStack::PushL( self ); + self->ConstructL( aInfo ); + return self; + } + + +const TDesC& CMemSpyEngineChunkEntry::Name() const + { + return iInfo->iName; + } + + +TAny* CMemSpyEngineChunkEntry::Handle() const + { + return iInfo->iHandle; + } + + +TInt CMemSpyEngineChunkEntry::Size() const + { + return iInfo->iSize; + } + + +TInt CMemSpyEngineChunkEntry::MaxSize() const + { + return iInfo->iMaxSize; + } + + +TAny* CMemSpyEngineChunkEntry::BaseAddress() const + { + return iInfo->iBaseAddress; + } + + +TAny* CMemSpyEngineChunkEntry::UpperAddress() const + { + return (TAny*) (TUint(BaseAddress()) + TUint(Size())); + } + + +TUint CMemSpyEngineChunkEntry::OwnerId() const + { + return iInfo->iOwnerId; + } + + +EXPORT_C void CMemSpyEngineChunkEntry::OwnerName( TDes& aDes ) const + { + aDes.Zero(); + AppendOwnerName( aDes ); + } + + +EXPORT_C void CMemSpyEngineChunkEntry::AppendOwnerName( TDes& aDes ) const + { + RProcess owner; + const TInt error = owner.Open( (TProcessId) OwnerId() ); + if ( error == KErrNone ) + { + aDes.Append( owner.FullName() ); + owner.Close(); + } + } + + +EXPORT_C void CMemSpyEngineChunkEntry::OutputDataL( CMemSpyEngineHelperChunk& aHelper ) const + { + HBufC* columns = HBufC::NewLC( 1024 ); + TPtr pColumns( columns->Des() ); + + // Name + pColumns.Copy( Name() ); + MemSpyEngineUtils::TextAfterDoubleColon( pColumns ); + pColumns.Append( KMemSpyEngineChunkListOutputComma ); + + // Owning Process + AppendOwnerName( pColumns ); + pColumns.Append( KMemSpyEngineChunkListOutputComma ); + + // Size + pColumns.AppendNum( Size(), EDecimal ); + pColumns.Append( KMemSpyEngineChunkListOutputComma ); + + // Max. Size + pColumns.AppendNum( MaxSize(), EDecimal ); + pColumns.Append( KMemSpyEngineChunkListOutputComma ); + + // Address + _LIT( KAddressFormat, "0x%08x - 0x%08x"); + pColumns.AppendFormat( KAddressFormat, BaseAddress(), UpperAddress() ); + + // + aHelper.Engine().Sink().OutputLineL( pColumns ); + CleanupStack::PopAndDestroy( columns ); + } + + +EXPORT_C TInt CMemSpyEngineChunkEntry::MdcaCount() const + { + return iList->MdcaCount(); + } + + +EXPORT_C TPtrC CMemSpyEngineChunkEntry::MdcaPoint( TInt aIndex ) const + { + return iList->MdcaPoint( aIndex ); + } + + +TMemSpyDriverChunkInfo& CMemSpyEngineChunkEntry::Info() + { + return *iInfo; + } + + +const TMemSpyDriverChunkInfo& CMemSpyEngineChunkEntry::Info() const + { + return *iInfo; + } + +