memspy/Engine/Source/MemSpyEngineImp.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 06 Jul 2010 16:05:13 +0300
changeset 34 7259cf1302ad
parent 22 a009639409f5
permissions -rw-r--r--
Revision: 201027 Kit: 2010127

/*
* 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 <memspy/engine/memspyengineimp.h>

// System includes
#include <e32svr.h>

// Driver includes
#include <memspy/driver/memspydriverclient.h>

// User includes
#include <memspy/engine/memspyengineobjectthread.h>
#include <memspy/engine/memspyengineobjectprocess.h>
#include <memspy/engine/memspyengineobjectcontainer.h>
#include <memspy/engine/memspyengineundertaker.h>
#include "MemSpyEngineChunkWatcher.h"
#include <memspy/engine/memspyengineobserver.h>
#include "MemSpyEngineServer.h"
#include <memspy/engine/memspyengineutils.h>
#include "MemSpyEngineOutputSinkDebug.h"
#include "MemSpyEngineOutputSinkFile.h"
#include <memspy/engine/memspyenginehelperchunk.h>
#include <memspy/engine/memspyenginehelpercodesegment.h>
#include <memspy/engine/memspyenginehelperheap.h>
#include <memspy/engine/memspyenginehelperstack.h>
#include <memspy/engine/memspyenginehelperthread.h>
#include <memspy/engine/memspyenginehelperserver.h>
#include <memspy/engine/memspyenginehelperprocess.h>
#include <memspy/engine/memspyenginehelperactiveobject.h>
#include <memspy/engine/memspyenginehelperkernelcontainers.h>
#include <memspy/engine/memspyenginehelperfilesystem.h>
#include <memspy/engine/memspyenginehelperecom.h>
#include <memspy/engine/memspyenginehelpersysmemtracker.h>
#include <memspy/engine/memspyenginehelperfbserv.h>
#include <memspy/engine/memspyenginehelperrom.h>
#include <memspy/engine/memspyenginehelperram.h>
#include <memspy/engine/memspyenginehelperwindowserver.h>
#include <memspy/engine/memspyenginehelpercondvar.h>

#ifdef _DEBUG
#define LOG(args...) RDebug::Printf(args)
#else
#define LOG(args...)
#endif

CMemSpyEngineImp::CMemSpyEngineImp( RFs& aFsSession, CMemSpyEngine& aEngine )
:   iFsSession( aFsSession ), iEngine( aEngine )
    {
    }


CMemSpyEngineImp::~CMemSpyEngineImp()
    {
    LOG( "CMemSpyEngineImp::~CMemSpyEngineImp() - START" );

    if  ( iMidwife )
        {
        iMidwife->RemoveObserver( *this );
        }

    LOG( "CMemSpyEngineImp::~CMemSpyEngineImp() - deleting helpers..." );
    delete iHelperSysMemTracker;
    delete iServer;
    delete iHelperKernelContainers;
    delete iHelperFbServ;
    delete iHelperHeap;
    delete iHelperStack;
    delete iHelperCodeSegment;
    delete iHelperChunk;
    delete iHelperThread;
    delete iHelperProcess;
    delete iHelperServer;
    delete iHelperActiveObject;
    delete iHelperFileSystem;
    delete iHelperECom;
    delete iHelperROM;
    delete iHelperRAM;
    delete iHelperWindowServer;
    delete iHelperCondVar;
    
    iHelperWindowServerLoader.Close();

    LOG( "CMemSpyEngineImp::~CMemSpyEngineImp() - deleting utilities..." );
    delete iChunkWatcher;
    delete iUndertaker;
    delete iMidwife;

    LOG( "CMemSpyEngineImp::~CMemSpyEngineImp() - destroying containers..." );
    iContainers.ResetAndDestroy();
    iContainers.Close();

    LOG( "CMemSpyEngineImp::~CMemSpyEngineImp() - destroying driver..." );
    if  ( iMemSpyDriver )
        {
        iMemSpyDriver->Close();
        delete iMemSpyDriver;
        }

    LOG( "CMemSpyEngineImp::~CMemSpyEngineImp() - destroying sink..." );
    delete iSink;

    LOG( "CMemSpyEngineImp::~CMemSpyEngineImp() - END" );
    }


void CMemSpyEngineImp::ConstructL()
    {
    LOG( "CMemSpyEngineImp::ConstructL() - START" );
    //
    iFsSession.SetSessionPath( _L("\\") );
    
    iServer = CMemSpyEngineServer::NewL( iEngine );
    
    iMemSpyDriver = new(ELeave) RMemSpyDriverClient();
    const TInt error = Driver().Open();
    User::LeaveIfError( error );
    //
    InstallSinkL( ESinkTypeDebug );
    //
    iUndertaker = CMemSpyEngineUndertaker::NewL( Driver() );
    iUndertaker->AddObserverL( *this );
    //
    iMidwife = CMemSpyEngineMidwife::NewL( Driver() );
    //
    iChunkWatcher = CMemSpyEngineChunkWatcher::NewL( Driver() );
    //
    CMemSpyEngineObjectContainer* container = CMemSpyEngineObjectContainer::NewL( iEngine );
    CleanupStack::PushL( container );
    iContainers.InsertL( container, 0 );
    CleanupStack::Pop( container );
    //
    ConstructHelpersL();
    //
    iHelperSysMemTracker = CMemSpyEngineHelperSysMemTracker::NewL( iEngine );
    iMidwife->AddObserverL( *this );

    LOG( "CMemSpyEngineImp::ConstructL() - END" );
    }


void CMemSpyEngineImp::ConstructHelpersL()
    {
    LOG( "CMemSpyEngineImp::ConstructHelpersL() - START" );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - Heap..." );
    iHelperHeap = CMemSpyEngineHelperHeap::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - Stack..." );
    iHelperStack = CMemSpyEngineHelperStack::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - Code Segments..." );
    iHelperCodeSegment = CMemSpyEngineHelperCodeSegment::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - Chunk..." );
    iHelperChunk = CMemSpyEngineHelperChunk::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - Thread..." );
    iHelperThread = CMemSpyEngineHelperThread::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - Process..." );
    iHelperProcess = CMemSpyEngineHelperProcess::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - Server..." );
    iHelperServer = CMemSpyEngineHelperServer::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - AO..." );
    iHelperActiveObject = CMemSpyEngineHelperActiveObject::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - Kernel Containers..." );
    iHelperKernelContainers = CMemSpyEngineHelperKernelContainers::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - File System..." );
    iHelperFileSystem = CMemSpyEngineHelperFileSystem::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - ECOM..." );
    iHelperECom = CMemSpyEngineHelperECom::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - FBSERV..." );
    iHelperFbServ = CMemSpyEngineHelperFbServ::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - ROM..." );
    iHelperROM = CMemSpyEngineHelperROM::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - RAM..." );
    iHelperRAM = CMemSpyEngineHelperRAM::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - WindowServer..." );
    
    TInt err = iHelperWindowServerLoader.Load( _L("memspywindowserverhelper.dll") );
    LOG( "CMemSpyEngineImp::ConstructHelpersL() - WindowServer load err: %d", err );
    if ( !err )
        {
#ifdef __WINS__ // ordinal is different 
        TLibraryFunction entry = iHelperWindowServerLoader.Lookup( 3 );
#else
        TLibraryFunction entry = iHelperWindowServerLoader.Lookup( 1 );
#endif
        if ( entry != NULL )
            {
			typedef MMemSpyEngineHelperWindowServer* (*TEntryFn)(void);
			TRAP(err, iHelperWindowServer = ((TEntryFn)entry)());
			if (err)
				{
				LOG("err from memspywindowserverhelper.dll - %d", err);
				}
            }
        }
    
    LOG( "CMemSpyEngineImp::ConstructHelpersL() - CondVar..." );
    iHelperCondVar = CMemSpyEngineHelperCondVar::NewL( iEngine );

    LOG( "CMemSpyEngineImp::ConstructHelpersL() - END" );
    }


RFs& CMemSpyEngineImp::FsSession()
    {
    return iFsSession;
    }


CMemSpyEngineObjectContainer& CMemSpyEngineImp::Container()
    {
    __ASSERT_ALWAYS( iContainers.Count() >= 1, MemSpyEngineUtils::Panic( EMemSpyEnginePanicInvalidContainer1 ) );
    CMemSpyEngineObjectContainer* headContainer = iContainers[ 0 ];
    return *headContainer;
    }


const CMemSpyEngineObjectContainer& CMemSpyEngineImp::Container() const
    {
    __ASSERT_ALWAYS( iContainers.Count() >= 1, MemSpyEngineUtils::Panic( EMemSpyEnginePanicInvalidContainer2 ) );
    const CMemSpyEngineObjectContainer* headContainer = iContainers[ 0 ];
    return *headContainer;
    }


void CMemSpyEngineImp::SetObserver( MMemSpyEngineObserver* aObserver )
    {
    iObserver = aObserver;
    }


void CMemSpyEngineImp::NotifyContainerChangeL()
    {
    if  ( iObserver )
        {
        iObserver->HandleMemSpyEngineEventL( MMemSpyEngineObserver::EHandleThreadsOrProcessesChanged, &Container() );
        }
    }


void CMemSpyEngineImp::NotifyClientServerOperationRequestL( TInt aType )
    {
    if  ( iObserver )
        {
        iObserver->HandleMemSpyEngineEventL( MMemSpyEngineObserver::EHandleClientServerOperationRequest, reinterpret_cast< TAny* >( aType ) );
        }
    }


CMemSpyEngineOutputSink& CMemSpyEngineImp::Sink()
    {
    return *iSink;
    }


TMemSpySinkType CMemSpyEngineImp::SinkType()
    {
    return iSink->Type();
    }

void CMemSpyEngineImp::InstallSinkL( TMemSpySinkType aType )
	{
	InstallSinkL( aType, KNullDesC );
	}

void CMemSpyEngineImp::InstallSinkL( TMemSpySinkType aType, const TDesC& aRootFolder )
    {
    LOG( "CMemSpyEngineImp::InstallSinkL() - START - switching sink from %d to %d...", (iSink != NULL ? iSink->Type() : -1), aType );
    //
    CMemSpyEngineOutputSink* sink = NULL;
    //
    switch( aType )
        {
    case ESinkTypeDebug:
        sink = CMemSpyEngineOutputSinkDebug::NewL( iEngine );
        break;
    case ESinkTypeFile:
        sink = CMemSpyEngineOutputSinkFile::NewL( iEngine, aRootFolder );
        break;
        }
    //
    delete iSink;
    iSink = sink;
    //
    LOG( "CMemSpyEngineImp::InstallSinkL() - END - sink type: %d", iSink->Type() );
    }


void CMemSpyEngineImp::ListOpenFilesL()
    {
    HelperFileSystem().ListOpenFilesL();
    }


void CMemSpyEngineImp::GetVersion( TVersion& aVersion )
    {
    iMemSpyDriver->GetVersion( aVersion );
    }


TBool CMemSpyEngineImp::IsHelperWindowServerSupported()
    {
    return iHelperWindowServer != NULL;
    }


CMemSpyEngineMidwife& CMemSpyEngineImp::Midwife()
    {
    return *iMidwife;
    }


CMemSpyEngineUndertaker& CMemSpyEngineImp::Undertaker()
    {
    return *iUndertaker;
    }


CMemSpyEngineChunkWatcher& CMemSpyEngineImp::ChunkWatcher()
    {
    return *iChunkWatcher;
    }


CMemSpyEngineHelperHeap& CMemSpyEngineImp::HelperHeap()
    {
    return *iHelperHeap;
    }


CMemSpyEngineHelperStack& CMemSpyEngineImp::HelperStack()
    {
    return *iHelperStack;
    }


CMemSpyEngineHelperCodeSegment& CMemSpyEngineImp::HelperCodeSegment()
    {
    return *iHelperCodeSegment;
    }


CMemSpyEngineHelperChunk& CMemSpyEngineImp::HelperChunk()
    {
    return *iHelperChunk;
    }


CMemSpyEngineHelperThread& CMemSpyEngineImp::HelperThread()
    {
    return *iHelperThread;
    }


CMemSpyEngineHelperProcess& CMemSpyEngineImp::HelperProcess()
    {
    return *iHelperProcess;
    }


CMemSpyEngineHelperServer& CMemSpyEngineImp::HelperServer()
    {
    return *iHelperServer;
    }


CMemSpyEngineHelperActiveObject& CMemSpyEngineImp::HelperActiveObject()
    {
    return *iHelperActiveObject;
    }


CMemSpyEngineHelperKernelContainers& CMemSpyEngineImp::HelperKernelContainers()
    {
    return *iHelperKernelContainers;
    }


CMemSpyEngineHelperFileSystem& CMemSpyEngineImp::HelperFileSystem()
    {
    return *iHelperFileSystem;
    }


CMemSpyEngineHelperECom& CMemSpyEngineImp::HelperECom()
    {
    return *iHelperECom;
    }


CMemSpyEngineHelperSysMemTracker& CMemSpyEngineImp::HelperSysMemTracker()
    {
    return *iHelperSysMemTracker;
    }


CMemSpyEngineHelperFbServ& CMemSpyEngineImp::HelperFbServ()
    {
    return *iHelperFbServ;
    }


CMemSpyEngineHelperROM& CMemSpyEngineImp::HelperROM()
    {
    return *iHelperROM;
    }


CMemSpyEngineHelperRAM& CMemSpyEngineImp::HelperRAM()
    {
    return *iHelperRAM;
    }


MMemSpyEngineHelperWindowServer& CMemSpyEngineImp::HelperWindowServer()
    {
    return *iHelperWindowServer;
    }


CMemSpyEngineHelperCondVar& CMemSpyEngineImp::HelperCondVar()
    {
    return *iHelperCondVar;
    }


RMemSpyDriverClient& CMemSpyEngineImp::Driver()
    {
    return *iMemSpyDriver;
    }


TInt CMemSpyEngineImp::ProcessSuspendAndGetErrorLC( TProcessId aId )
    {
    __ASSERT_ALWAYS( iSuspendedProcess == aId || iSuspendedProcess == 0, MemSpyEngineUtils::Panic( EMemSpyEnginePanicSuspendRequest1 ) );

    TInt errorOrCount = Driver().ProcessThreadsSuspend( aId );
    if  ( errorOrCount >= 0 )
        {
        if  ( errorOrCount == 1 )
            {
            iSuspendedProcess = aId;
            }
        else
            {
            // Suspending already suspended process
            __ASSERT_ALWAYS( iSuspendedProcess == aId, MemSpyEngineUtils::Panic( EMemSpyEnginePanicSuspendRequest2 ) );
            }
        //
        CleanupStack::PushL( TCleanupItem( ResumeSuspendedProcess, this ) );

        if  ( errorOrCount == 1 )
            {
            iSink->ProcessSuspendedL( aId );
            }
            
        // At this point, all was well
        errorOrCount = KErrNone;
        }

    return errorOrCount;
    }


void CMemSpyEngineImp::ProcessSuspendLC( TProcessId aId )
    {
    const TInt error = ProcessSuspendAndGetErrorLC( aId );
    User::LeaveIfError( error );
    }


void CMemSpyEngineImp::ProcessResume()
    {
    const TUint id = iSuspendedProcess;
    //
    const TInt errorOrCount = Driver().ProcessThreadsResume( id );
    //
    if  ( errorOrCount == 0 )
        {
        iSink->ProcessResumed( id );
        iSuspendedProcess = 0;
        }
    }
    

TProcessId CMemSpyEngineImp::SuspendedProcessId() const
    {
    return TProcessId( iSuspendedProcess );
    }


void CMemSpyEngineImp::ResumeSuspendedProcess( TAny* aSelf )
    {
    CMemSpyEngineImp* self = reinterpret_cast< CMemSpyEngineImp* >( aSelf );
    self->ProcessResume();
    }


void CMemSpyEngineImp::ThreadIsDeadL( const TThreadId& aId, const RThread& aThread )
    {
    if  ( aThread.Handle() != KNullHandle )
        {
        const TFullName name( aThread.FullName() );
        //
        TBuf<128> exitInfo;
        const TExitCategoryName exitCategory( aThread.ExitCategory() );
        CMemSpyThread::AppendExitInfo( exitInfo, aThread.ExitType(), aThread.ExitReason(), exitCategory );
        //
        _LIT( KMemSpyEventInfoText, "[MemSpy] Thread died: %S [%d - 0x%04x] %S" );
        Sink().OutputLineFormattedL( KMemSpyEventInfoText, &name, (TUint32) aId, (TUint32) aId, &exitInfo );
        }
    }
    

void CMemSpyEngineImp::ProcessIsDeadL( const TProcessId& aId, const RProcess& aProcess )
    {
    if  ( aProcess.Handle() != KNullHandle )
        {
        const TFullName name( aProcess.FullName() );
        //
        TBuf<128> exitInfo;
        const TExitCategoryName exitCategory( aProcess.ExitCategory() );
        CMemSpyThread::AppendExitInfo( exitInfo, aProcess.ExitType(), aProcess.ExitReason(), exitCategory );
        //
        _LIT( KMemSpyEventInfoText, "[MemSpy] Process died: %S [%d - 0x%04x] %S" );
        Sink().OutputLineFormattedL( KMemSpyEventInfoText, &name, (TUint32) aId, (TUint32) aId, &exitInfo );
        }
    }


void CMemSpyEngineImp::ThreadIsBornL( const TThreadId& aId, const RThread& aThread )
    {
    if  ( aThread.Handle() != KNullHandle )
        {
        const TFullName name( aThread.FullName() );
        //
        _LIT( KMemSpyEventInfoText, "[MemSpy] Thread created: %S (%d / 0x%08x)" );
        Sink().OutputLineFormattedL( KMemSpyEventInfoText, &name, (TUint32) aId, (TUint32) aId );
        }
    }


void CMemSpyEngineImp::ProcessIsBornL( const TProcessId& aId, const RProcess& aProcess )
    {
    if  ( aProcess.Handle() != KNullHandle )
        {
        const TFullName name( aProcess.FullName() );
        //
        _LIT( KMemSpyEventInfoText, "[MemSpy] Process created: %S (%d / 0x%08x)" );
        Sink().OutputLineFormattedL( KMemSpyEventInfoText, &name, (TUint32) aId, (TUint32) aId );
        }
    }