memspy/Driver/Kernel/Source/MemSpyDriverOSAdaption.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 13 Oct 2010 16:17:58 +0300
branchRCL_3
changeset 59 8ad140f3dd41
parent 49 7fdc9a71d314
permissions -rw-r--r--
Revision: 201039 Kit: 201041

/*
* 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 "MemSpyDriverOSAdaption.h"

// System includes
#include <kern_priv.h>
#include <nkern.h>
#include <nk_plat.h>

#ifdef __MARM__

#include <arm.h>
// Necessary when accessing data members by steam via offsets in order
// to prevent potential unaligned data aborts

#ifdef __CC_ARM
#define UNALIGNED_DATA_MEMBER __packed
#endif /* __CC_ARM */

#endif /* __MARM__ */

#ifndef UNALIGNED_DATA_MEMBER
#define UNALIGNED_DATA_MEMBER
#endif

// User includes
#include "MemSpyDriverLog.h"
#include "MemSpyDriverPAndS.h"
#include "MemSpyDriverDevice.h"

// Internal constants
const TInt KMemSpyLocalThreadDataSizeEstimate = 0x80; // The amount of user stack that MemSpy attempts to scan for the RHeaep vTable



DMemSpyDriverOSAdaptionDObject::DMemSpyDriverOSAdaptionDObject( DMemSpyDriverOSAdaption& aOSAdaption )
:   iOSAdaption( aOSAdaption )
    {
    }


TUint8 DMemSpyDriverOSAdaptionDObject::GetContainerID( DObject& aObject ) const
    {
    return aObject.iContainerID;
    }


TObjectType DMemSpyDriverOSAdaptionDObject::GetObjectType( DObject& aObject ) const
    {
    const TUint8 containerId = GetContainerID( aObject );
    const TObjectType ret = static_cast< TObjectType >( containerId - 1 );
    return ret;
    }


DObject* DMemSpyDriverOSAdaptionDObject::GetOwner( DObject& aObject ) const
    {
    return aObject.iOwner;
    }


DObject* DMemSpyDriverOSAdaptionDObject::GetOwner( DObject& aObject, TUint8 aExpectedContainerId ) const
    {
    DObject* owner = GetOwner( aObject );
    //
    const TUint8 containerId = GetContainerID( aObject ) - 1;
    if ( containerId != aExpectedContainerId )
        {
        owner = NULL;
        }
    //
    return owner;
    }

TInt DMemSpyDriverOSAdaptionDObject::GetAccessCount( DObject& aObject ) const
    {
    return aObject.AccessCount();
    }

TInt DMemSpyDriverOSAdaptionDObject::GetUniqueID( DObject& aObject ) const
    {
    return aObject.UniqueID();
    }

TUint DMemSpyDriverOSAdaptionDObject::GetProtection( DObject& aObject ) const
    {
    return aObject.Protection();
    }

TUint8* DMemSpyDriverOSAdaptionDObject::GetAddressOfKernelOwner( DObject& aObject ) const
    {
    return (TUint8*)aObject.Owner();
    }











DMemSpyDriverOSAdaptionDThread::DMemSpyDriverOSAdaptionDThread( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    // Get current NThread and map it on to DThread
    NThread* nThread = NKern::CurrentThread();
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::Construct() - nThread: 0x%08x", nThread ) );
    DThread* dThread = Kern::NThreadToDThread( nThread );
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::Construct() - dThread: 0x%08x", dThread ) );

    // At this point, it should be possible to work out the offset of the NThread within DThread.
    iOffset_NThread = reinterpret_cast<TUint32>( nThread ) - reinterpret_cast<TUint32>( dThread );
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::Construct() - difference: 0x%08x", iOffset_NThread ) );

    // Work out the delta between compile time and run time
    TInt delta = iOffset_NThread - _FOFF( DThread, iNThread );
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::Construct() - compile time vs run time offset delta: %d", delta ));

    // iNThread
    TRACE( Kern::Printf( "OSA - [DThread::iNThread]              compile time offset: 0x%08x, run time offset: 0x%08x", _FOFF(DThread,iNThread), iOffset_NThread ));

    // iExitType
    iOffset_ExitType = _FOFF( DThread, iExitType ) + delta;
    TRACE( Kern::Printf( "OSA - [DThread::iExitType]             compile time offset: 0x%08x, run time offset: 0x%08x", _FOFF(DThread,iExitType), iOffset_ExitType ));

    // iSupervisorStack
    iOffset_SupervisorStackBase = _FOFF( DThread, iSupervisorStack ) + delta;
    TRACE( Kern::Printf( "OSA - [DThread::iSupervisorStack]      compile time offset: 0x%08x, run time offset: 0x%08x", _FOFF(DThread,iSupervisorStack), iOffset_SupervisorStackBase ));

    // iSupervisorStackSize
    iOffset_SupervisorStackSize = _FOFF( DThread, iSupervisorStackSize ) + delta;
    TRACE( Kern::Printf( "OSA - [DThread::iSupervisorStackSize]  compile time offset: 0x%08x, run time offset: 0x%08x", _FOFF(DThread,iSupervisorStackSize), iOffset_SupervisorStackSize ));
    }


NThread* DMemSpyDriverOSAdaptionDThread::GetNThread( DThread& aObject ) const
    {
    DThread* dThread = &aObject;
    TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_NThread;
    NThread* pRet = reinterpret_cast< NThread* >( pTarget );
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetNThread() - aObject: 0x%08x, ret: 0x%08x", &aObject, pRet ) );
    return pRet;
    }


TExitType DMemSpyDriverOSAdaptionDThread::GetExitType( DThread& aObject ) const
    {
    DThread* dThread = &aObject;
    TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_ExitType;
    UNALIGNED_DATA_MEMBER TExitType* pRet = reinterpret_cast< TExitType* >( pTarget );
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetExitType() - aObject: 0x%08x, ret: 0x%08x", &aObject, pRet ) );
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetExitType() - value: %d", *pRet ) );
    return *pRet;
    }


TUint32 DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase( DThread& aObject ) const
    {
    DThread* dThread = &aObject;
    TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_SupervisorStackBase;
    UNALIGNED_DATA_MEMBER TUint32* pRet = reinterpret_cast< TUint32* >( pTarget );
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase() - aObject: 0x%08x, ret: 0x%08x", &aObject, pRet ) );
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase() - 0x%08x: %d", *pRet ) );
    return *pRet;
    }


TInt DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize( DThread& aObject ) const
    {
    DThread* dThread = &aObject;
    TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_SupervisorStackSize;
    UNALIGNED_DATA_MEMBER TInt* pRet = reinterpret_cast< TInt* >( pTarget );
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize() - aObject: 0x%08x, ret: 0x%08x", &aObject, pRet ) );
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize() - value: %d", *pRet ) );
    return *pRet;
    }


RAllocator* DMemSpyDriverOSAdaptionDThread::GetAllocator( DThread& aObject ) const
    {
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocator() - START" ) );
    //
    RAllocator* ret = aObject.iAllocator;
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocator() - allocator: 0x%08x", ret ) );
    //
    if  ( ret == NULL )
        {
        TUint32 stackAddress = 0;
        ret = GetAllocatorAndStackAddress( aObject, stackAddress );
        }
    //
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocator() - END - ret: 0x%08x", ret ) );
    return ret;
    }


CActiveScheduler* DMemSpyDriverOSAdaptionDThread::GetActiveScheduler( DThread& aObject ) const
    {
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetActiveScheduler() - START" ) );
    CActiveScheduler* ret = aObject.iScheduler;
    //
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetActiveScheduler() - scheduler: 0x%08x", ret ) );
    if  ( ret == NULL )
        {
        // We need the stack address of the heap in order to locate the active scheduler.
        // Implicitly this means that MemSpy can only list active scheduler contents for threads
        // that use a default RHeap. This has always been the case, so this is not a functional break.
        //
        // Assumed stack layout is something like this:
        // 
        // stack[0x00403ffc] 0x00000000, vTable: 0x00000000 (offset: 0004)
        // stack[0x00403ff8] 0x00000000, vTable: 0x00000000 (offset: 0008)
        // stack[0x00403ff4] 0x00000002, vTable: 0x00000000 (offset: 0012)
        // stack[0x00403ff0] 0x00000002, vTable: 0x00000000 (offset: 0016)
        // stack[0x00403fec] 0x00000000, vTable: 0x00000000 (offset: 0020)
        // stack[0x00403fe8] 0x0000000c, vTable: 0x00000000 (offset: 0024)
        // stack[0x00403fe4] 0x00600078, vTable: 0x80228938 (offset: 0028)
        // stack[0x00403fe0] 0x00000001, vTable: 0x00000000 (offset: 0032)
        // stack[0x00403fdc] 0x00600000, vTable: 0x80268430 (offset: 0036)		TLocalThreadData::iTlsHeap       RAllocator*		  80268428    0034    vtable for RHeap
        // stack[0x00403fd8] 0x0060009c, vTable: 0x80268394 (offset: 0040)		TLocalThreadData::iTrapHandler   TTrapHandler		  8026838c    0014    vtable for TCleanupTrapHandler
        // stack[0x00403fd4] 0x00600110, vTable: 0x802682ec (offset: 0044)		TLocalThreadData::iScheduler     CActiveScheduler*	  802682e4    002c    vtable for CActiveScheduler
        // stack[0x00403fd0] 0x00600000, vTable: 0x80268430 (offset: 0048)      TLocalThreadData::iHeap          RAllocator*          80268428    0034    vtable for RHeap
        // stack[0x00403fcc] 0x00000000, vTable: 0x00000000 (offset: 0052)
        // stack[0x00403fc8] 0x00100000, vTable: 0x00000000 (offset: 0056)
        //
        // GetAllocatorAndStackAddress() will return the first RHeap* it finds, so this will be iTlsHeap, which
        // is actually no bad thing as it will hopefully be initialised using an RHeap pointer.
        // CActiveScheduler* is 8 bytes further on from that.
        //
        const TUint32 KOffsetToCActiveScheduler = 8;
        // 
        TUint32 stackAddress = 0;
        RAllocator* allocator = GetAllocatorAndStackAddress( aObject, stackAddress );
        TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetActiveScheduler() - allocator: 0x%08x, stackAddress: 0x%08x", allocator, stackAddress ) );

        // This assumes the layout of the thread local data structure, i.e. that the four bytes that follow the
        // allocator pointer are always the active scheduler pointer.
        if  ( allocator != NULL && stackAddress > 0 )
            {
            TUint32* ptr = reinterpret_cast< TUint32* >( stackAddress - KOffsetToCActiveScheduler );
            const TInt r = Kern::ThreadRawRead( &aObject, ptr, &ret, sizeof( ret ) );
            TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetActiveScheduler() - stack address containing scheduler pointer: 0x%08x, read result: %d, CActiveScheduler*: 0x%08x", ptr, r, ret ) );
            if  ( r != KErrNone )
                {
                ret = NULL;
                }
            }
        }
    //
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetActiveScheduler() - END - ret: 0x%08x", ret ) );
    return ret;
    }


TUint32 DMemSpyDriverOSAdaptionDThread::GetUserStackBase( DThread& aObject ) const
    {
    return aObject.iUserStackRunAddress;
    }


TInt DMemSpyDriverOSAdaptionDThread::GetUserStackSize( DThread& aObject ) const
    {
    return aObject.iUserStackSize;
    }


DProcess* DMemSpyDriverOSAdaptionDThread::GetOwningProcess( DThread& aObject ) const
    {
    return aObject.iOwningProcess;
    }


TUint DMemSpyDriverOSAdaptionDThread::GetId( DThread& aObject ) const
    {
    return aObject.iId;
    }


MemSpyObjectIx* DMemSpyDriverOSAdaptionDThread::GetHandles( DThread& aObject ) const
    {
    MemSpyObjectIx* handles = MemSpyObjectIx_GetHandlePointer_Thread( aObject );
    return handles;
    }


TUint DMemSpyDriverOSAdaptionDThread::GetOwningProcessId( DThread& aObject ) const
    {
    DProcess* process = GetOwningProcess( aObject );
    TUint ret = 0;
    //
    if  ( process )
        {
        ret = OSAdaption().DProcess().GetId( *process );
        }
    //
    return ret;
    }


TInt DMemSpyDriverOSAdaptionDThread::GetPriority( DThread& aObject ) const
    {
    return aObject.iThreadPriority;
    }


TUint8* DMemSpyDriverOSAdaptionDThread::GetAddressOfOwningProcess( DThread& aObject ) const
    {
    return (TUint8*)aObject.iOwningProcess;
    }


void DMemSpyDriverOSAdaptionDThread::GetNameOfOwningProcess( DThread& aObject, TDes& aName ) const
    {
    if  ( aObject.iOwningProcess )
        {
        aObject.iOwningProcess->FullName( aName );
        }
    }


RAllocator* DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress( DThread& aObject, TUint32& aStackAddress ) const
    {
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - START" ) );
    //
    aStackAddress = 0;
    RAllocator* ret = NULL;

    // We will assume the thread is running and that the user-side stack has been set up
    // accordingly.
    const TUint32 base = GetUserStackBase( aObject );
    const TInt size = GetUserStackSize( aObject );
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - base: 0x%08x, size: %d, KMemSpyLocalThreadDataSizeEstimate: %d", base, size, KMemSpyLocalThreadDataSizeEstimate ) );
    const TUint32 top = base + size;

    // This is the RHeap vtable we are looking for
    const TUint32 rHeapVTable = OSAdaption().Device().RHeapVTable();
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - rHeapVTable: 0x%08x", rHeapVTable ) );
    //
    TInt r = KErrNone;

#ifdef TRACE_TYPE_GENERAL 
    for( TUint32 addr = top - 4; addr >= top - KMemSpyLocalThreadDataSizeEstimate; addr -= 4 )
        {
        TUint32 value = 0;
        TUint32 possibleVTable = 0;
        //
        TUint32* ptr = reinterpret_cast< TUint32* >( addr );
        //
        r = Kern::ThreadRawRead( &aObject, ptr, &value, sizeof( value ) );
        if  ( r == KErrNone )
            {
            Kern::ThreadRawRead( &aObject, reinterpret_cast< const TAny* >( value ), &possibleVTable, sizeof( possibleVTable ) );
            }
        TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - stack[0x%08x] 0x%08x, vTable: 0x%08x (offset: %04d)", addr, value, possibleVTable, top - addr ) );
        }
#endif

    for( TUint32 addr = top - 4; addr >= top - KMemSpyLocalThreadDataSizeEstimate; addr -= 4 )
        {
        TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - addr to read from: 0x%08x", addr ) );
        TUint32 value = 0;
        //
        TUint32* ptr = reinterpret_cast< TUint32* >( addr );
        //
        r = Kern::ThreadRawRead( &aObject, ptr, &value, sizeof( value ) );
        TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - read from: 0x%08x, result: %d, value: 0x%08x", addr, r, value ) );
        //
        if  ( r == KErrNone )
            {
            // Try and read from the address which is now stored within 'value'. We must do this because 
            // the TLD class holds an RAllocator* and we need to ascertain the vTable of the RAllocator* matches the
            // only supported vTable that MemSpy understands (RHeap*).
            TUint32 possibleVTable = 0;
            r = Kern::ThreadRawRead( &aObject, reinterpret_cast< const TAny* >( value ), &possibleVTable, sizeof( possibleVTable ) );
            TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - possible vtable read from: 0x%08x, result: %d, possibleVTable: 0x%08x", value, r, possibleVTable ) );
            if  ( r == KErrNone && possibleVTable == rHeapVTable )
                {
                aStackAddress = addr;
                ret = reinterpret_cast< RAllocator* >( value );
                break;
                }
            }
        }
    //
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - END - ret: 0x%08x, aStackAddress: 0x%08x", ret, aStackAddress ) );
    return ret;
    }    


TBool DMemSpyDriverOSAdaptionDThread::IsHandleIndexValid( DThread& aObject ) const
    {
    MemSpyObjectIx* handles = MemSpyObjectIx_GetHandlePointer_Thread( aObject );
    return ( handles != NULL );
    }













DMemSpyDriverOSAdaptionDProcess::DMemSpyDriverOSAdaptionDProcess( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


TUint DMemSpyDriverOSAdaptionDProcess::GetId( DProcess& aObject ) const
    {
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDProcess::GetId() - value: %d", aObject.iId ) );
    return aObject.iId;
    }


MemSpyObjectIx* DMemSpyDriverOSAdaptionDProcess::GetHandles( DProcess& aObject ) const
    {
    MemSpyObjectIx* handles = MemSpyObjectIx_GetHandlePointer_Process( aObject );
    return handles;
    }


TExitType DMemSpyDriverOSAdaptionDProcess::GetExitType( DProcess& aObject ) const
    {
    return static_cast< TExitType >( aObject.iExitType );
    }


DThread* DMemSpyDriverOSAdaptionDProcess::GetFirstThread( DProcess& aObject ) const
    {
    return aObject.FirstThread();
    }


TUint32 DMemSpyDriverOSAdaptionDProcess::GetSID( DProcess& aObject ) const
    {
    return GetSecurityInfo( aObject ).iSecureId;
    }


TUint DMemSpyDriverOSAdaptionDProcess::GetSecurityZone( DProcess& aObject ) const
    {
    return aObject.iSecurityZone;
    }


SSecurityInfo& DMemSpyDriverOSAdaptionDProcess::GetSecurityInfo( DProcess& aObject ) const
    {
    return aObject.iS;
    }


TInt DMemSpyDriverOSAdaptionDProcess::GetFlags( DProcess& aObject ) const
    {
    return aObject.iFlags;
    }


TInt DMemSpyDriverOSAdaptionDProcess::GetGeneration( DProcess& aObject ) const
    {
    return aObject.iGeneration;
    }


SDblQue& DMemSpyDriverOSAdaptionDProcess::GetThreadQueue( DProcess& aObject ) const
    {
    return aObject.iThreadQ;
    }


DThread* DMemSpyDriverOSAdaptionDProcess::GetThread( SDblQueLink* aLink ) const
    {
	DThread* ret = _LOFF( aLink, DThread, iProcessLink );
    return ret;
    }


void DMemSpyDriverOSAdaptionDProcess::SetSID( DProcess& aObject, TUint32 aSID ) const
    {
    GetSecurityInfo( aObject ).iSecureId = aSID;
    }


void DMemSpyDriverOSAdaptionDProcess::SetSecurityZone( DProcess& aObject, TUint aSecurityZone ) const
    {
    aObject.iSecurityZone = aSecurityZone;
    }


TBool DMemSpyDriverOSAdaptionDProcess::IsHandleIndexValid( DProcess& aObject ) const
    {
    MemSpyObjectIx* handles = MemSpyObjectIx_GetHandlePointer_Process( aObject );
    return ( handles != NULL );
    }


TUint DMemSpyDriverOSAdaptionDProcess::GetCreatorId( DProcess& aObject ) const
    {
    return aObject.iCreatorId;
    }


TInt DMemSpyDriverOSAdaptionDProcess::GetAttributes( DProcess& aObject ) const
    {
    return aObject.iAttributes;
    }


TInt DMemSpyDriverOSAdaptionDProcess::GetPriority( DProcess& aObject ) const
    {
    return aObject.iPriority;
    }


TUint8* DMemSpyDriverOSAdaptionDProcess::GetAddressOfOwningProcess( DProcess& aObject ) const
    {
    return (TUint8*)aObject.iOwningProcess;
    }


TUint8* DMemSpyDriverOSAdaptionDProcess::GetAddressOfDataBssStackChunk( DProcess& aObject ) const
    {
    return (TUint8*)aObject.iDataBssStackChunk;
    }




DMemSpyDriverOSAdaptionDChunk::DMemSpyDriverOSAdaptionDChunk( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


TInt DMemSpyDriverOSAdaptionDChunk::GetSize( DChunk& aObject ) const
    {
    return aObject.Size();
    }


TInt DMemSpyDriverOSAdaptionDChunk::GetMaxSize( DChunk& aObject ) const
    {
    return aObject.MaxSize();
    }


TUint8* DMemSpyDriverOSAdaptionDChunk::GetBase( DChunk& aObject ) const
    {
    return aObject.Base();
    }


DProcess* DMemSpyDriverOSAdaptionDChunk::GetOwningProcess( DChunk& aObject ) const
    {
    return aObject.OwningProcess();
    }


TUint DMemSpyDriverOSAdaptionDChunk::GetOwningProcessId( DChunk& aObject ) const
    {
    TUint ret = 0;
    //
    DProcess* process = GetOwningProcess( aObject );
    if  ( process )
        {
        ret = OSAdaption().DProcess().GetId( *process );
        }
    //
    return ret;
    }


TUint DMemSpyDriverOSAdaptionDChunk::GetControllingOwnerId( DChunk& aObject ) const
    {
    return aObject.iControllingOwner;
    }


TChunkType DMemSpyDriverOSAdaptionDChunk::GetType( DChunk& aObject ) const
    {
    return aObject.iChunkType;
    }


TInt DMemSpyDriverOSAdaptionDChunk::GetAttributes( DChunk& aObject ) const
    {
    return aObject.iAttributes;
    }


TUint8* DMemSpyDriverOSAdaptionDChunk::GetAddressOfOwningProcess( DChunk& aObject ) const
    {
    return (TUint8*)aObject.iOwningProcess;
    }


TInt DMemSpyDriverOSAdaptionDChunk::GetBottom( DChunk& aObject ) const
    {
    return aObject.Bottom();
    }


TInt DMemSpyDriverOSAdaptionDChunk::GetTop( DChunk& aObject ) const
    {
    return aObject.Top();
    }


TInt DMemSpyDriverOSAdaptionDChunk::GetStartPos( DChunk& aObject ) const
    {
    return aObject.iStartPos;
    }


TUint DMemSpyDriverOSAdaptionDChunk::GetRestrictions( DChunk& aObject ) const
    {
    return aObject.iRestrictions;
    }


TUint DMemSpyDriverOSAdaptionDChunk::GetMapAttr( DChunk& aObject ) const
    {
    return aObject.iMapAttr;
    }


void DMemSpyDriverOSAdaptionDChunk::GetNameOfOwningProcess( DChunk& aObject, TDes& aName ) const
    {
    if ( aObject.OwningProcess() )
        {
         aObject.OwningProcess()->FullName( aName );
        }
    }


















DMemSpyDriverOSAdaptionDServer::DMemSpyDriverOSAdaptionDServer( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


SDblQue& DMemSpyDriverOSAdaptionDServer::GetSessionQueue( DServer& aObject ) const
    {
    return aObject.iSessionQ;
    }


DSession* DMemSpyDriverOSAdaptionDServer::GetSession( SDblQueLink* aLink ) const
    {
	DSession* session = _LOFF( aLink, DSession, iServerLink );
    return session;
    }


TInt DMemSpyDriverOSAdaptionDServer::GetSessionCount( DServer& aObject ) const
    {
    TInt ret = 0;
    //
    SDblQueLink* anchor = &aObject.iSessionQ.iA;
    SDblQueLink* link = aObject.iSessionQ.First();
    //
    while( link != anchor)
	    {
 	    ++ret;
	    link = link->iNext;
	    }
    //
    return ret;
    }


DThread* DMemSpyDriverOSAdaptionDServer::GetOwningThread( DServer& aObject ) const
    {
    return aObject.iOwningThread;
    }


TUint DMemSpyDriverOSAdaptionDServer::GetOwningThreadId( DServer& aObject ) const
    {
    TUint ret = 0;
    //
    DThread* thread = GetOwningThread( aObject );
    if  ( thread )
        {
        ret = OSAdaption().DThread().GetId( *thread );
        }
    //
    return ret;
    }


TIpcSessionType DMemSpyDriverOSAdaptionDServer::GetSessionType( DServer& aObject ) const
    {
    return static_cast< TIpcSessionType >( aObject.iSessionType );
    }


TUint8* DMemSpyDriverOSAdaptionDServer::GetAddressOfOwningThread( DServer& aObject ) const
    {
    return (TUint8*)aObject.iOwningThread;
    }


void DMemSpyDriverOSAdaptionDServer::GetNameOfOwningThread( DServer& aObject, TDes& aName ) const
    {
    if ( aObject.iOwningThread )
        {
         aObject.iOwningThread->FullName( aName );
        }
    }












DMemSpyDriverOSAdaptionDSession::DMemSpyDriverOSAdaptionDSession( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


TIpcSessionType DMemSpyDriverOSAdaptionDSession::GetSessionType( DSession& aObject ) const
    {
    return static_cast< TIpcSessionType >( aObject.iSessionType );
    }


DServer* DMemSpyDriverOSAdaptionDSession::GetServer( DSession& aObject ) const
    {
    return aObject.iServer;
    }


TUint8* DMemSpyDriverOSAdaptionDSession::GetAddressOfServer( DSession& aObject ) const
    {
    return (TUint8*)aObject.iServer;
    }


TUint16 DMemSpyDriverOSAdaptionDSession::GetTotalAccessCount( DSession& aObject ) const
    {
    return aObject.iTotalAccessCount;
    }


TUint8 DMemSpyDriverOSAdaptionDSession::GetSrvSessionType( DSession& aObject ) const
    {
    return aObject.iSvrSessionType;
    }


TInt DMemSpyDriverOSAdaptionDSession::GetMsgCount( DSession& aObject ) const
    {
    return aObject.iMsgCount;
    }
    

TInt DMemSpyDriverOSAdaptionDSession::GetMsgLimit( DSession& aObject ) const
    {
    return aObject.iMsgLimit;
    }
















DMemSpyDriverOSAdaptionDCodeSeg::DMemSpyDriverOSAdaptionDCodeSeg( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


DCodeSeg* DMemSpyDriverOSAdaptionDCodeSeg::GetCodeSeg( SDblQueLink* aLink ) const
    {
    DCodeSeg* ret = _LOFF( aLink, DCodeSeg, iTempLink );
    return ret;
    }


DCodeSeg* DMemSpyDriverOSAdaptionDCodeSeg::GetCodeSeg( DLibrary& aLibrary ) const
    {
    return aLibrary.iCodeSeg;
    }


DCodeSeg* DMemSpyDriverOSAdaptionDCodeSeg::GetCodeSegFromHandle( TAny* aHandle ) const
    {
    DCodeSeg* ret = DCodeSeg::VerifyHandle( aHandle );
    return ret;
    }


TBool DMemSpyDriverOSAdaptionDCodeSeg::GetIsXIP( DCodeSeg& aCodeSeg ) const
    {
    TBool ret = ETrue;
    //
#ifdef __WINS__
    (void) aCodeSeg;
#else
    DEpocCodeSeg& epocCodeSegment = static_cast< DEpocCodeSeg& >( aCodeSeg );
    ret = ( epocCodeSegment.iXIP != 0 );
#endif
    //
    return ret;
    }


TInt DMemSpyDriverOSAdaptionDCodeSeg::GetCodeSegQueue( DProcess& aObject, SDblQue& aQueue ) const
    {
	const TInt count = aObject.TraverseCodeSegs( &aQueue, NULL, DCodeSeg::EMarkDebug, DProcess::ETraverseFlagAdd );
    return count;
    }


void DMemSpyDriverOSAdaptionDCodeSeg::EmptyCodeSegQueue( SDblQue& aQueue ) const
    {
	DCodeSeg::EmptyQueue( aQueue, DCodeSeg::EMarkDebug );
    }


TUint32 DMemSpyDriverOSAdaptionDCodeSeg::GetSize( DCodeSeg& aCodeSeg ) const
    {
    return aCodeSeg.iSize;
    }


void DMemSpyDriverOSAdaptionDCodeSeg::GetCreateInfo( DCodeSeg& aCodeSeg, TCodeSegCreateInfo& aInfo ) const
    {
    aCodeSeg.Info( aInfo );
    }


TUint8 DMemSpyDriverOSAdaptionDCodeSeg::GetState( DLibrary& aLibrary ) const
    {
    return aLibrary.iState;
    }


TInt DMemSpyDriverOSAdaptionDCodeSeg::GetMapCount( DLibrary& aLibrary ) const
    {
    return aLibrary.iMapCount;
    }

















DMemSpyDriverOSAdaptionDSemaphore::DMemSpyDriverOSAdaptionDSemaphore( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


TInt DMemSpyDriverOSAdaptionDSemaphore::GetCount( DSemaphore& aObject ) const
    {
    return aObject.iCount;
    }


TUint8 DMemSpyDriverOSAdaptionDSemaphore::GetResetting( DSemaphore& aObject ) const
    {
    return aObject.iResetting;
    }


















DMemSpyDriverOSAdaptionDMutex::DMemSpyDriverOSAdaptionDMutex( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


TInt DMemSpyDriverOSAdaptionDMutex::GetHoldCount( DMutex& aObject ) const
    {
    return aObject.iHoldCount;
    }


TInt DMemSpyDriverOSAdaptionDMutex::GetWaitCount( DMutex& aObject ) const
    {
    return aObject.iWaitCount;
    }


TUint8 DMemSpyDriverOSAdaptionDMutex::GetResetting( DMutex& aObject ) const
    {
    return aObject.iResetting;
    }


TUint8 DMemSpyDriverOSAdaptionDMutex::GetOrder( DMutex& aObject ) const
    {
    return aObject.iOrder;
    }









DMemSpyDriverOSAdaptionDLogicalDevice::DMemSpyDriverOSAdaptionDLogicalDevice( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


TInt DMemSpyDriverOSAdaptionDLogicalDevice::GetOpenChannels( DLogicalDevice& aObject ) const
    {
    return aObject.iOpenChannels;
    }


TVersion DMemSpyDriverOSAdaptionDLogicalDevice::GetVersion( DLogicalDevice& aObject ) const
    {
    return aObject.iVersion;
    }


TUint DMemSpyDriverOSAdaptionDLogicalDevice::GetParseMask( DLogicalDevice& aObject ) const
    {
    return aObject.iParseMask;
    }


TUint DMemSpyDriverOSAdaptionDLogicalDevice::GetUnitsMask( DLogicalDevice& aObject ) const
    {
    return aObject.iUnitsMask;
    }

















DMemSpyDriverOSAdaptionDPhysicalDevice::DMemSpyDriverOSAdaptionDPhysicalDevice( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


TVersion DMemSpyDriverOSAdaptionDPhysicalDevice::GetVersion( DPhysicalDevice& aObject ) const
    {
    return aObject.iVersion;
    }


TUint DMemSpyDriverOSAdaptionDPhysicalDevice::GetUnitsMask( DPhysicalDevice& aObject ) const
    {
    return aObject.iUnitsMask;
    }


TUint8* DMemSpyDriverOSAdaptionDPhysicalDevice::GetAddressOfCodeSeg( DPhysicalDevice& aObject ) const
    {
    return (TUint8*)aObject.iCodeSeg;
    }

















DMemSpyDriverOSAdaptionDChangeNotifier::DMemSpyDriverOSAdaptionDChangeNotifier( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


TUint DMemSpyDriverOSAdaptionDChangeNotifier::GetChanges( DChangeNotifier& aObject ) const
    {
    return aObject.iChanges;
    }


TUint8* DMemSpyDriverOSAdaptionDChangeNotifier::GetAddressOfOwningThread( DChangeNotifier& aObject ) const
    {
    return (TUint8*)aObject.iThread;
    }


void DMemSpyDriverOSAdaptionDChangeNotifier::GetNameOfOwningThread( DChangeNotifier& aObject, TDes& aName ) const
    {
    if ( aObject.iThread )
        {
         aObject.iThread->FullName( aName );
        }
    }
















DMemSpyDriverOSAdaptionDUndertaker::DMemSpyDriverOSAdaptionDUndertaker( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


TUint8* DMemSpyDriverOSAdaptionDUndertaker::GetAddressOfOwningThread( DUndertaker& aObject ) const
    {
    return (TUint8*)aObject.iOwningThread;
    }


void DMemSpyDriverOSAdaptionDUndertaker::GetNameOfOwningThread( DUndertaker& aObject, TDes& aName ) const
    {
    if ( aObject.iOwningThread )
        {
         aObject.iOwningThread->FullName( aName );
        }
    }

















DMemSpyDriverOSAdaptionDCondVar::DMemSpyDriverOSAdaptionDCondVar( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


TUint8 DMemSpyDriverOSAdaptionDCondVar::GetResetting( DCondVar& aObject ) const
    {
    return aObject.iResetting;
    }


TUint8* DMemSpyDriverOSAdaptionDCondVar::GetAddressOfMutex( DCondVar& aObject ) const
    {
    return (TUint8*)aObject.iMutex;
    }


void DMemSpyDriverOSAdaptionDCondVar::GetNameOfMutex( DCondVar& aObject, TDes& aName ) const
    {
    if ( aObject.iMutex )
        {
         aObject.iMutex->FullName( aName );
        }
    }


TInt DMemSpyDriverOSAdaptionDCondVar::GetWaitCount( DCondVar& aObject ) const
    {
    return aObject.iWaitCount;
    }


SDblQue& DMemSpyDriverOSAdaptionDCondVar::GetSuspendedQ( DCondVar& aObject ) const
    {
    return aObject.iSuspendedQ;
    }


DThread* DMemSpyDriverOSAdaptionDCondVar::GetThread( SDblQueLink* aLink ) const
    {
    DThread* thread = _LOFF( aLink, DThread, iWaitLink );
    return thread;
    }















DMemSpyDriverOSAdaptionDTimer::DMemSpyDriverOSAdaptionDTimer( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


TTimer::TTimerType DMemSpyDriverOSAdaptionDTimer::GetType( DTimer& aObject ) const
    {
    const TTimer::TTimerType ret = aObject.iTimer.Type();
    return ret;
    }


TTimer::TTimerState DMemSpyDriverOSAdaptionDTimer::GetState( DTimer& aObject ) const
    {
    const TTimer::TTimerState ret = static_cast<TTimer::TTimerState>( aObject.iTimer.iState );
    return ret;
    }














DMemSpyDriverOSAdaptionDPropertyRef::DMemSpyDriverOSAdaptionDPropertyRef( DMemSpyDriverOSAdaption& aOSAdaption )
:   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
    {
    }


TBool DMemSpyDriverOSAdaptionDPropertyRef::GetIsReady( DObject& aObject ) const
    {
    DMemSpyPropertyRef* prop = GetPropertyRef( aObject );
    return ( prop != NULL );
    }


RProperty::TType DMemSpyDriverOSAdaptionDPropertyRef::GetType( DObject& aObject ) const
    {
    RProperty::TType ret = RProperty::EInt;
    //
    DMemSpyPropertyRef* prop = GetPropertyRef( aObject );
    if  ( prop )
        {
        ret = (RProperty::TType) prop->iProp->iType;
        }
    //
    return ret;
    }


TUint DMemSpyDriverOSAdaptionDPropertyRef::GetCategory( DObject& aObject ) const
    {
    TUint ret = 0;
    //
    DMemSpyPropertyRef* prop = GetPropertyRef( aObject );
    if  ( prop )
        {
        ret = prop->iProp->iCategory;
        }
    //
    return ret;
    }


TUint DMemSpyDriverOSAdaptionDPropertyRef::GetKey( DObject& aObject ) const
    {
    TUint ret = 0;
    //
    DMemSpyPropertyRef* prop = GetPropertyRef( aObject );
    if  ( prop )
        {
        ret = prop->iProp->iKey;
        }
    //
    return ret;
    }


TInt DMemSpyDriverOSAdaptionDPropertyRef::GetRefCount( DObject& aObject ) const
    {
    TInt ret = 0;
    //
    DMemSpyPropertyRef* prop = GetPropertyRef( aObject );
    if  ( prop )
        {
        ret = prop->iProp->iRefCount;
        }
    //
    return ret;
    }


TUint DMemSpyDriverOSAdaptionDPropertyRef::GetThreadId( DObject& aObject ) const
    {
    TUint ret = 0;
    //
    DMemSpyPropertyRef* prop = GetPropertyRef( aObject );
    if  ( prop )
        {
        DThread* thread = prop->iClient;
        if  ( thread )
            {
            ret = OSAdaption().DThread().GetId( *thread );
            }
        }
    //
    return ret;
    }


TUint32 DMemSpyDriverOSAdaptionDPropertyRef::GetCreatorSID( DObject& aObject ) const
    {
    TUint32 ret = 0;
    //
    DMemSpyPropertyRef* prop = GetPropertyRef( aObject );
    if  ( prop )
        {
        ret = prop->iProp->iOwner;
        }
    //
    return ret;
    }


DMemSpyPropertyRef* DMemSpyDriverOSAdaptionDPropertyRef::GetPropertyRef( DObject& aObject ) const
    {
    DMemSpyPropertyRef* ret = NULL;
    //
    const TUint8 containerId = GetContainerID( aObject ) - 1;
    if ( containerId == EPropertyRef )
        {
        DMemSpyPropertyRef* prop = reinterpret_cast< DMemSpyPropertyRef* >( &aObject );
        if ( prop->iProp && prop->iClient )
            {
            ret = prop;
            }
        }
    //
    return ret;
    }















DMemSpyDriverOSAdaption::DMemSpyDriverOSAdaption( DMemSpyDriverDevice& aDevice )
:   iDevice( aDevice )
    {
    }


DMemSpyDriverOSAdaption::~DMemSpyDriverOSAdaption()
    {
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaption::~DMemSpyDriverOSAdaption() - START"));
    NKern::ThreadEnterCS();
    //
    delete iDThread;
    delete iDProcess;
    delete iDChunk;
    delete iDServer;
    delete iDSession;
    delete iDCodeSeg;
    delete iDSemaphore;
    delete iDMutex;
    delete iDLogicalDevice;
    delete iDPhysicalDevice;
    delete iDChangeNotifier;
    delete iDUndertaker;
    delete iDCondVar;
    delete iDTimer;
    delete iDPropertyRef;
    //
    NKern::ThreadLeaveCS();
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaption::~DMemSpyDriverOSAdaption() - END"));
    }


TInt DMemSpyDriverOSAdaption::Construct()
    {
    TRACE( Kern::Printf( "DMemSpyDriverOSAdaption::Construct() - START" ) );
    //
    NKern::ThreadEnterCS();
    //
    TInt error = KErrNoMemory;
    //
    iDThread = new DMemSpyDriverOSAdaptionDThread( *this );
    if  ( iDThread )
        {
        iDProcess = new DMemSpyDriverOSAdaptionDProcess( *this );
        if  ( iDProcess )
            {
            iDChunk = new DMemSpyDriverOSAdaptionDChunk( *this );
            if  ( iDChunk )
                {
                iDServer = new DMemSpyDriverOSAdaptionDServer( *this );
                if  ( iDServer )
                    {
                    iDSession = new DMemSpyDriverOSAdaptionDSession( *this );
                    if  ( iDSession )
                        {
                        iDCodeSeg = new DMemSpyDriverOSAdaptionDCodeSeg( *this );
                        if  ( iDCodeSeg )
                            {
                            iDSemaphore = new DMemSpyDriverOSAdaptionDSemaphore( *this );
                            if  ( iDSemaphore )
                                {
                                iDMutex = new DMemSpyDriverOSAdaptionDMutex( *this );
                                if  ( iDMutex )
                                    {
                                    iDLogicalDevice = new DMemSpyDriverOSAdaptionDLogicalDevice( *this );
                                    if  ( iDLogicalDevice )
                                        {
                                        iDPhysicalDevice = new DMemSpyDriverOSAdaptionDPhysicalDevice( *this );
                                        if  ( iDPhysicalDevice )
                                            {
                                            iDChangeNotifier = new DMemSpyDriverOSAdaptionDChangeNotifier( *this );
                                            if  ( iDChangeNotifier )
                                                {
                                                iDUndertaker = new DMemSpyDriverOSAdaptionDUndertaker( *this );
                                                if ( iDUndertaker )
                                                    {
                                                    iDCondVar = new DMemSpyDriverOSAdaptionDCondVar( *this );
                                                    if ( iDCondVar )
                                                        {
                                                        iDTimer = new DMemSpyDriverOSAdaptionDTimer( *this );
                                                        if  ( iDTimer )
                                                            {
                                                            iDPropertyRef = new DMemSpyDriverOSAdaptionDPropertyRef( *this );
                                                            if  ( iDPropertyRef )
                                                                {
                                                                error = KErrNone;
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    //
    NKern::ThreadLeaveCS();

    TRACE( Kern::Printf( "DMemSpyDriverOSAdaption::Construct() - END - error: %d", error ) );
    return error;
    }