// Copyright (c) 2007-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 <e32debug.h>
#include <rm_debug_api.h>
#include "testcrashdatasource.h"
#include <debuglogging.h>
CTestCrashDataSource::CTestCrashDataSource( )
{
RDebug::Printf( "test_crashdatasource.cpp::CTestCrashDataSource::CTestCrashDataSource()\n" );
}
// second-phase constructor
void CTestCrashDataSource::ConstructL()
{
RDebug::Printf( "test_crashdatasource.cpp::CTestCrashDataSource::ConstructL()\n" );
}
// destructor
CTestCrashDataSource::~CTestCrashDataSource()
{
RDebug::Printf( "test_crashdatasource.cpp::CTestCrashDataSource::~CTestCrashDataSource()\n" );
}
TInt CTestCrashDataSource::SetSimRegValues( const TUint32 aThreadId,
RRegisterList & aRegisterList )
{
RDebug::Print( _L("CTestCrashDataSource::SetSimRegValues()\n") );
if( aRegisterList.Count() > 0 )
{
TUint8 val8 = (TUint8)(KRegValue8 + aThreadId);
TUint16 val16 = (TUint16)(KRegValue16 + aThreadId);
TUint32 val32 = (TUint32)(KRegValue32 + aThreadId);
TUint64 val64 = (TUint64)(MAKE_TUINT64(0xFEDCBA98u,0x76543210u) + aThreadId);
for( TInt i = 0; i < aRegisterList.Count(); i ++ )
{
TRegisterData & reg = aRegisterList[i];
switch ( reg.iSize )
{
case 0:
reg.iValue8 = val8 + i;
RDebug::Printf( " Setting reg[%d] iValue8=0x%X\n", i, reg.iValue8 );
break;
case 1:
reg.iValue16 = val16+ i;
RDebug::Printf( " Setting reg[%d] iValue16=0x%X\n", i, reg.iValue16 );
break;
case 2:
reg.iValue32 = val32+ i;
RDebug::Printf( " Setting reg[%d] iValue32=0x%X\n", i, reg.iValue32 );
break;
case 3:
reg.iValue64 = val64+ i;
RDebug::Printf( " Setting reg[%d]=0x%X%X\n", i,
I64HIGH(reg.iValue64), I64LOW(reg.iValue64) );
break;
}
//reg.iAvailable = i%8 ? ETrue : EFalse;
/*
if ( 0 == ((i+1) % 8) )
{
RDebug::Printf( " setting reg[%d] as not available\n", i );
reg.iAvailable = EFalse;
}
*/
}
return KErrNone;
}
return KErrBadHandle;
}
void CTestCrashDataSource::PrintRegs( RRegisterList & aRegisterList )
{
RDebug::Printf( "CTestCrashDataSource::PrintRegs()\n" );
if( aRegisterList.Count() > 0 )
{
for( TInt i = 0; i < aRegisterList.Count(); i ++ )
{
TRegisterData & reg = aRegisterList[i];
RDebug::Printf( " reg[%d] iRegClass=%d, iId=%d, iSubId=%d, iSize=%d, iAvailable=",
i, reg.iRegClass, reg.iId, reg.iSubId, reg.iSize );
if(reg.iAvailable)
RDebug::Printf( "ETrue\n" );
else
RDebug::Printf( "EFalse\n" );
switch ( reg.iSize )
{
case 0:
RDebug::Printf( " iValue8=0x%X\n", reg.iValue8 ); break;
case 1:
RDebug::Printf( " iValue16=0x%X\n", reg.iValue16 ); break;
case 2:
RDebug::Printf( " iValue32=0x%X\n", reg.iValue32 ); break;
case 3:
RDebug::Printf( " iValue64=0x%X%X\n",
I64HIGH(reg.iValue64), I64LOW(reg.iValue64) );
break;
}
}
}
else
{
RDebug::Printf( " No registers to print\n" );
}
}
void CTestCrashDataSource::GetRegisterListL( RRegisterList & aRegisterList )
{
LOG_MSG("CTestCrashDataSource::GetRegisterListL()\n");
TFunctionalityRegister ids[] = {ERegisterR0,
ERegisterR1,
ERegisterR2,
ERegisterR3,
ERegisterR4,
ERegisterR5,
ERegisterR6,
ERegisterR7,
ERegisterR8,
ERegisterR9,
ERegisterR10,
ERegisterR11,
ERegisterR12,
ERegisterR13,
ERegisterR14,
ERegisterR15,
ERegisterCpsr,
ERegisterR13Svc,
ERegisterR14Svc,
ERegisterSpsrSvc,
ERegisterR13Abt,
ERegisterR14Abt,
ERegisterSpsrAbt,
ERegisterR13Und,
ERegisterR14Und,
ERegisterSpsrUnd,
ERegisterR13Irq,
ERegisterR14Irq,
ERegisterSpsrIrq,
ERegisterR8Fiq,
ERegisterR9Fiq,
ERegisterR10Fiq,
ERegisterR11Fiq,
ERegisterR12Fiq,
ERegisterR13Fiq,
ERegisterR14Fiq,
ERegisterSpsrFiq,
ERegisterLast
};
aRegisterList.Reset();
TRegisterData reg;
//core regs
const TFunctionalityRegister* r;
for(r = ids; *r != ERegisterLast; ++r)
{
reg.iRegClass = 0; //Core
reg.iId = *r; // R0, ...
reg.iSubId = 0; // not used for Core Regs
reg.iSize = 2;
reg.iAvailable = ETrue;
aRegisterList.AppendL( reg );
}
//copro regs
for(TInt i = 0; i < KCoProRegsCount; ++i)
{
reg.iRegClass = 1; //CoPro
reg.iId = i; // R0, ...
reg.iSubId = KRegSubId + i;
reg.iSize = i%4;
reg.iAvailable = i < KCoProRegsCount/2 ? ETrue : EFalse; //half not available
aRegisterList.AppendL( reg );
}
}
void CTestCrashDataSource::ReadRegistersL( const TUint64 aThreadId, RRegisterList &aRegisterList )
{
//RDebug::Print( _L("CTestCrashDataSource::ReadRegisters( threadId=0x%X)\n"), I64LOW(aThreadId) );
if( aRegisterList.Count() )
{
RDebug::Printf( "Register list already supplied\n" );
User::LeaveIfError(SetSimRegValues( aThreadId, aRegisterList ));
}
else
{
RDebug::Printf( "Creating register list\n" );
GetRegisterListL( aRegisterList );
User::LeaveIfError(SetSimRegValues( aThreadId, aRegisterList ));
}
PrintRegs( aRegisterList );
}
void CTestCrashDataSource::ReadMemoryL(
const TUint64 aThreadId,
const TUint32 aAddress,
const TUint32 aLength,
TDes8 & aData )
{
RDebug::Print( _L("CCrashDataSource::ReadMemory( tId=0x%X, addr=0x%X, len=0x%X)\n"),
aThreadId, aAddress, aLength );
for( TUint32 i = 0; i < aLength; i++ )
{
aData.Append((TUint8*)&i, 1);
RDebug::Printf( " Memory[%d]=0x%X\n", i, aData[i] );
}
}
void CTestCrashDataSource::GetProcessListL( RProcessPointerList & aProcList,
TUint & aTotalProcessListDescSize )
{
RDebug::Print( _L("CTestCrashDataSource::GetProcessList( )\n") );
CProcessInfo *processInfo = CProcessInfo::NewL(KCrashPid, KCrashFileName );
TInt err = aProcList.Append( processInfo );
if(err != KErrNone)
{
delete processInfo;
User::Leave(err);
}
}
void CTestCrashDataSource::GetExecutableListL( RExecutablePointerList & aExecutableList,
TUint & aTotalExecutableListDescSize )
{
RDebug::Print( _L("CTestCrashDataSource::GetExecutableList( )\n") );
CExecutableInfo *executableInfo = CExecutableInfo::NewL(KCrashFileName, EFalse, EFalse );
TInt err = aExecutableList.Append( executableInfo );
if(err != KErrNone)
{
delete executableInfo;
User::Leave(err);
}
}
void CTestCrashDataSource::GetThreadListL( const TUint64 aProcessId,
RThreadPointerList & aThreadList,
TUint & aTotalThreadListDescSize )
{
GetThreadListL( I64LOW( aProcessId ), aThreadList, aTotalThreadListDescSize );
}
void CTestCrashDataSource::GetThreadListL( const TUint32 aProcessId,
RThreadPointerList & aThreadList,
TUint & aTotalThreadListDescSize )
{
RDebug::Print( _L("CTestCrashDataSource::GetThreadList( pId=0x%X)\n"), aProcessId );
LOG_MSG2( "CTestCrashDataSource::GetThreadListL( pId=0x%X)\n", aProcessId );
aThreadList.ResetAndDestroy();
aTotalThreadListDescSize = 0;
for(TInt i =0; i < KCrashThreadsCount; ++i)
{
CThreadInfo *thread = CThreadInfo::NewL( KCrashTid + i,
KCrashThreadName,
KCrashPid,
KCrashThreadPriority + i,
KCrashSvcStackPtr + i,
KCrashSvcStackAddr + i,
KCrashSvcStackSize + i,
KCrashUsrStackAddr + i,
KCrashUsrStackSize + i);
aThreadList.Append(thread);
//delete thread;
}
}
void CTestCrashDataSource::GetCodeSegmentsL( const TUint64 aTid, RCodeSegPointerList &aCodeSegs, TUint &aTotalCodeSegListDescSize )
{
RDebug::Printf( "CTestCrashDataSource::GetExecutableInfo(pId=0x%X)\n", aTid );
TInt err;
TCodeSegInfo *segInfo;
if(KCrashXIP)
RDebug::Printf( " Exec info XIP == ETrue\n" );
else
RDebug::Printf( " Exec info XIP == EFalse\n" );
segInfo = new(ELeave) TCodeSegInfo;
segInfo->iName = KCrashFileName;
segInfo->iXIP = ETrue;
segInfo->iCodeSize = KCrashCodeSize + aTid;
segInfo->iCodeRunAddr = KCrashCodeRunAddr + aTid;
segInfo->iCodeLoadAddr = KCrashCodeLoadAddr + aTid;
segInfo->iRoDataSize = KCrashRODataSize + aTid;
segInfo->iRoDataRunAddr = KCrashRODataRunAddr + aTid;
segInfo->iRoDataLoadAddr = KCrashRODataLoadAddr + aTid;
segInfo->iDataSize = KCrashDataSize + aTid;
segInfo->iDataRunAddr = KCrashDataRunAddr + aTid;
segInfo->iDataLoadAddr = KCrashDataLoadAddr + aTid;
segInfo->iType = EExeCodeSegType;
err = aCodeSegs.Append(segInfo);
if(err != KErrNone)
{
delete segInfo;
User::Leave(err);
}
aTotalCodeSegListDescSize += sizeof(TCodeSegInfo);
segInfo = new(ELeave) TCodeSegInfo;
segInfo->iName = KLibName1;
segInfo->iXIP = ETrue;
segInfo->iCodeSize = KCrashCodeSize + aTid + 1;
segInfo->iCodeRunAddr = KCrashCodeRunAddr + aTid + 1;
segInfo->iCodeLoadAddr = KCrashCodeLoadAddr + aTid + 1;
segInfo->iRoDataSize = KCrashRODataSize + aTid + 1;
segInfo->iRoDataRunAddr = KCrashRODataRunAddr + aTid + 1;
segInfo->iRoDataLoadAddr = KCrashRODataLoadAddr + aTid + 1;
segInfo->iDataSize = KCrashDataSize + aTid + 1;
segInfo->iDataRunAddr = KCrashDataRunAddr + aTid + 1;
segInfo->iDataLoadAddr = KCrashDataLoadAddr + aTid + 1;
segInfo->iType = EDllCodeSegType;
err = aCodeSegs.Append(segInfo);
if(err != KErrNone)
{
delete segInfo;
User::Leave(err);
}
aTotalCodeSegListDescSize += sizeof(TCodeSegInfo);
segInfo = new(ELeave) TCodeSegInfo;
segInfo->iName = KLibName2;
segInfo->iXIP = EFalse;
segInfo->iCodeSize = KCrashCodeSize + aTid + 2;
segInfo->iCodeRunAddr = KCrashCodeRunAddr + aTid + 2;
segInfo->iCodeLoadAddr = KCrashCodeLoadAddr + aTid + 2;
segInfo->iRoDataSize = KCrashRODataSize + aTid + 2;
segInfo->iRoDataRunAddr = KCrashRODataRunAddr + aTid + 2;
segInfo->iRoDataLoadAddr = KCrashRODataLoadAddr + aTid + 2;
segInfo->iDataSize = KCrashDataSize + aTid + 2;
segInfo->iDataRunAddr = KCrashDataRunAddr + aTid + 2;
segInfo->iDataLoadAddr = KCrashDataLoadAddr + aTid + 2;
segInfo->iType = EDllCodeSegType;
err = aCodeSegs.Append(segInfo);
if(err != KErrNone)
{
delete segInfo;
User::Leave(err);
}
aTotalCodeSegListDescSize += sizeof(TCodeSegInfo);
}
void CTestCrashDataSource::ReadTraceBufferL(TDes8 &aTraceData )
{
User::Leave(KErrNotSupported);
}
void CTestCrashDataSource::GetLocksL(TSCMLockData& aLockData)
{
User::Leave(KErrNotSupported);
}
void CTestCrashDataSource::GetROMBuildInfoL(TRomHeaderData& aRomHeader)
{
User::Leave(KErrNotSupported);
}
TUint CTestCrashDataSource::GetExceptionStackSizeL(const Debug::TArmProcessorModes aMode)
{
User::Leave(KErrNotSupported);
return 0;
}
void CTestCrashDataSource::GetExceptionStackL(const Debug::TArmProcessorModes aMode, TDes8& aStack, TUint aStartReadPoint)
{
User::Leave(KErrNotSupported);
}
TInt CTestCrashDataSource::GetDataSourceFunctionality(TDes8& aFuncBuffer)
{
return KErrNotSupported;
}
TInt CTestCrashDataSource::GetDataSourceFunctionalityBufSize(TUint& aBufSize)
{
return KErrNotSupported;
}
TVersion CTestCrashDataSource::GetVersion() const
{
TVersion ver(2,0,0);
return ver;
}
TInt CTestCrashDataSource::GetVariantSpecificDataSize(TUint& aDataSize)
{
aDataSize = 0;
return KErrNotSupported;
}
TInt CTestCrashDataSource::GetVariantSpecificData(TDes8& aVarSpecData)
{
(void)aVarSpecData;
return KErrNotSupported;
}
//eof