/** * Given a thread ID, return a handle to the corresponding DThread. If the returned * pointer is non-NULL, it is the responsibility of the caller to close the handle. * * @pre caller must be in thread critical section * @post if a non-NULL value is returned then a handle to the thread has been * opened on the callers behalf * @param aThreadId ID of the thread to return a handle for * @return a DThread* to the appropriate thread, or NULL if a handle could not be * opened to the specified thread */ DThread* DebugUtils::OpenThreadHandle(TUint64 aThreadId) { __ASSERT_CRITICAL; LOG_MSG2("DebugUtils::OpenThreadHandle(0x%lx)", aThreadId); DObjectCon& threads = *Kern::Containers()[EThread]; // Get containing holding threads threads.Wait(); // Obtain the container mutex so the list does get changed under us DThread* thread = Kern::ThreadFromId(aThreadId); // Open a handle to the thread so that it doesn't exit while we are processing if (thread) { // if opening a handle fails then set thread to NULL if(KErrNone != thread->Open()) { LOG_MSG2("\tCould not open handle to thread %d", (TUint32)aThreadId); thread = NULL; } } else { LOG_MSG2("\tThread with ID %d is NULL", (TUint32)aThreadId); } threads.Signal(); // Release the container mutex return thread; }
// RunL() completes a previously issued Observe call void CTargetObserver::RunL() { LOG_MSG2("->CTargetObserver::RunL(status:%d)", iStatus.Int()); User::LeaveIfError(iStatus.Int()); //something bad happened iCrashEventInfo.iEventTime.UniversalTime(); //not 100% exact time of the crash, but as soon as we are notified about it Observe(); RThread thread; LOG_MSG2("CTargetObserver::RunL() - opening handle to crashed thread:%Lu\n", iCrashEventInfo.iThreadId); TInt err = thread.Open(iCrashEventInfo.iThreadId); if(err != KErrNone) { LOG_MSG2("CTargetObserver::RunL - unable to open thread handle! err:%d\n", err); User::Leave(err); } CleanupClosePushL(thread); if( (iThreadList.Count() == 0) || (HasThread(thread.FullName())) ) { //crash event of the whole process or thread that we observe LOG_MSG("CTargetObserver::RunL() -> HandleCrashEventL()"); iHandler.HandleCrashEventL(iCrashEventInfo); } else //crash event of thread that we don't care about { LOG_MSG("CTargetObserver::RunL() - resuming crashed thread"); iSecSess.ResumeThread(iCrashEventInfo.iThreadId); } CleanupStack::PopAndDestroy(); //thread }
/** * Given a process ID, return a handle to the corresponding DProcess. If the returned * pointer is non-NULL, it is the responsibility of the caller to close the handle. * * @post if a non-NULL value is returned then a handle to the process has been * opened on the callers behalf * @param aProcessId ID of the process to return a handle for * @return a DProcess* to the appropriate process, or NULL if a handle could not be * opened to the specified process */ DProcess* DebugUtils::OpenProcessHandle(const TUint64 aProcessId) { // Commenting out this message as it gets printed out every time a RDebug::Printf statement is caught by the driver, // which makes looking at the serial cable output irritating. Replaced it with LOG_MSG statements below to indicate if // something amiss happened. By default then this function prints nothing out. //LOG_MSG("DebugUtils::OpenProcessHandle()"); NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex DObjectCon& processes = *Kern::Containers()[EProcess]; // Get containing holding threads processes.Wait(); // Obtain the container mutex so the list does get changed under us DProcess* process = Kern::ProcessFromId(aProcessId); // Open a handle to the process so that it doesn't exit while we are processing if (process) { // if opening a handle fails then set process to NULL if(KErrNone != process->Open()) { LOG_MSG2("DebugUtils::OpenProcessHandle(): Could not open handle for 0x%lx", aProcessId); process = NULL; } } else { LOG_MSG2("DebugUtils::OpenProcessHandle(): Could not find process for 0x%lx", aProcessId); } processes.Signal(); // Release the container mutex NKern::ThreadLeaveCS(); // End of critical section return process; }
// // DTrkXtiChannel::DoControl // TInt DTrkXtiChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2) { LOG_MSG("DTrkXtiChannel::DoControl()"); TInt err = KErrNone; switch(aFunction) { case RTrkXtiDriver::EControlWrite: { //lock the Semaphore so that write doesn't happen when a write is already in progress. Kern::SemaphoreWait(*iLock); err = DoWrite((TUint32)a1, a2); Kern::SemaphoreSignal(*iLock); break; } default: { return KErrGeneral; } } if (KErrNone != err) { LOG_MSG2("Error %d from control function", err); } return err; }
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 CServerCrashDataSource::GetExecutableListL( RExecutablePointerList & aExecutableList, TUint & aTotalExecutableListDescSize ) { LOG_MSG( "CServerCrashDataSource::GetExecutableListL()\n" ); // Delete any objects in the array, since we will replace them. aExecutableList.ResetAndDestroy(); aTotalExecutableListDescSize = 0; if( iExecutableListBuffer.Size() != iLastExecutableListSize ) { LOG_MSG2( " iExecutableListBuffer.ReAlloc( %d)\n", iLastExecutableListSize ); iExecutableListBuffer.ReAllocL( iLastExecutableListSize ); } DoGetListL( EExecutables, (TUint)(-1), (TUint)(-1), iExecutableListBuffer, iLastExecutableListSize ); iLastExecutableListSize = iExecutableListBuffer.Size(); TUint8* ptr = (TUint8*)( iExecutableListBuffer.Ptr() ); const TUint8* ptrEnd = ptr + iLastExecutableListSize; //LOG_MSG3( " Data start,end=(0x%x, 0x%x)\n", ptr, ptrEnd ); while( ptr < ptrEnd ) { TExecutablesListEntry *entry = (TExecutablesListEntry*)ptr; if( !entry ) { LOG_MSG( " ERROR !* : TExecutablesListEntry is NULL\n" ); User::Leave(KErrBadHandle); } if( entry->iNameLength == 0 ) { LOG_MSG( " Skipping executable : entry->iNameLength=0" ); ptr += Align4( entry->GetSize() ); continue; } TPtrC entryName(&(entry->iName[0]), entry->iNameLength); CExecutableInfo *executableInfoPtr = CExecutableInfo::NewL(entryName, entry->iIsActivelyDebugged, entry->iIsPassivelyDebugged ); TInt err = aExecutableList.Append( executableInfoPtr ); if(err != KErrNone) { delete executableInfoPtr; User::Leave(err); } aTotalExecutableListDescSize += executableInfoPtr->Size(); ptr += Align4( entry->GetSize() ); } }
void CServerCrashDataSource::DoGetListL(const TListId aListId, const TThreadId aThreadId, const TProcessId aProcessId, RBuf8 & aBuffer, TUint32 & aSize ) { LOG_MSG5( "->CServerCrashDataSource::DoGetList(aListId=%d, aThredId=%Lu, aProcessId=%Lu, aSize=%d\n", aListId, aThreadId.Id(), aProcessId.Id(), aSize ); TInt ret; TListLevel listLevel; if( ((TUint)-1 == (TUint)aThreadId) && ((TUint)-1 == (TUint)aProcessId) ) { listLevel = EListGlobal; ret = iSecSess.GetList( aListId, aBuffer, aSize ); } else if( ((TUint)-1 != (TUint)aThreadId) && ((TUint)-1 == (TUint)aProcessId) ) { listLevel = EListThread; LOG_MSG("CServerCrashDataSource::DoGetList - EListThread"); ret = iSecSess.GetList( aThreadId, aListId, aBuffer, aSize ); } else { listLevel = EListProcess; LOG_MSG("CServerCrashDataSource::DoGetList - EListProcess"); ret = iSecSess.GetList( aProcessId, aListId, aBuffer, aSize ); } while( KErrTooBig == ret ) { LOG_MSG2( "CServerCrashDataSource::DoGetListL - list too big, new size=%d\n", aSize ); // Too big, and aSize should have been modified to the required new size // Since the list could have increased in size between calls, give it an // extra margin. aSize += 256; aBuffer.ReAllocL( aSize ); if( EListGlobal == listLevel ) { ret = iSecSess.GetList( aListId, aBuffer, aSize ); } else if( EListThread == listLevel ) { ret = iSecSess.GetList( aThreadId, aListId, aBuffer, aSize ); } else { ret = iSecSess.GetList( aProcessId, aListId, aBuffer, aSize ); } } User::LeaveIfError(ret); }
void CTargetObserver::DoCancel() { LOG_MSG( "CTargetObserver::DoCancel -> CancelGetEvent\n"); TInt err = iSecSess.CancelGetEvent( iTargetName ); if(err != KErrNone) { LOG_MSG2( "CTargetObserver::DoCancel - iSecSess.DetachExecutable returned:%d!", err); //panic client?? close DSS session?? } LOG_MSG("CTargetObserver::DoCancel -> iSecSess.DetachExecutable\n"); err = iSecSess.DetachExecutable( iTargetName ); if(err != KErrNone) { LOG_MSG2( "CTargetObserver::DoCancel iSecSess.DetachExecutable returned:%d!\n", err); //panic client?? close DSS session?? } }
void CProcessPair::ConstructL(const TDesC& aProcessName, const TProcessId aProcessId) { //allocate the process name buffer and fill with aProcessName iProcessName = aProcessName.Alloc(); if(iProcessName == NULL) User::Leave(KErrNoMemory); LOG_MSG2( "CProcessPair::ConstructL() process name: %S", &TPtr8((TUint8*)iProcessName->Ptr(), 2*iProcessName->Length(), 2*iProcessName->Length()) ); //set process id iProcessId = aProcessId; }
int main( int argc, char* argv[] ) { int nResult = INVALID_RESULT; START_FUNCTION(); if( argc < 2 ) { LOG_ERROR( "Message should not be empty" ); usage(); } string sMessage = argv[ 1 ], sTitle = szDefaultTitle; size_t nSeverity = nDefaultSeverity; string sServer = szDefaultServer, sPluginPath = szDefaultPluginPath; for( int idx = 2; idx < argc; ++idx ) { const char* szParam = argv[ idx ]; if( *szParam == '-' || *szParam == '/' ) { switch( szParam[1] ) { case 's': if( ++idx == argc ) usage(); sServer = argv[ idx ]; break; case 'p': if( ++idx == argc ) usage(); sPluginPath = argv[ idx ]; break; case 't': if( ++idx == argc ) usage(); sTitle = argv[ idx ]; break; case 'e': if( ++idx == argc ) usage(); nSeverity = atol( argv[ idx ] ); break; } } } if( nSeverity <= 0 || nSeverity > 3 ) nSeverity = 1; string sHttpQuery; FormatString( sHttpQuery, szFormat, sServer.c_str(), sPluginPath.c_str(), HttpUtils::HttpEncode(sMessage).c_str(), HttpUtils::HttpEncode(sTitle).c_str(), nSeverity ); string sResponse; if( !HttpUtils::DownloadPage(sHttpQuery, sResponse) ) break; LOG_MSG2( "%s", sResponse.c_str() ); END_FUNCTION_RET( nResult ); }
GLDEF_C TInt E32Main() { LOG_MSG("ENTER: Multi_agent_launcher E32Main()"); __UHEAP_MARK; CTrapCleanup* trap = CTrapCleanup::New(); if (!trap) return KErrNoMemory; TRAPD(err, MainL()); LOG_MSG2("Multi_agent_launcher: returning from MainL(), err = %d", err); delete trap; LOG_MSG("EXIT: Multi_agent_launcher E32Main()"); __UHEAP_MARKEND; return err; }
/* * Symbian OS 2nd stage construction. Called from CCoreDumpServer::NewLC() */ void CCoreDumpServer::ConstructL() { //LOG_MSG("->CCoreDumpServer::ConstructL()\n" ); TInt err = iSecSess.Connect( securityServerVersion ); if( KErrNone != err ) { _LIT( KDssStartErrorMsg ,"Core Dump Server: Unable to Start/Connect to Debug Security Server"); User::InfoPrint( KDssStartErrorMsg ); LOG_MSG2("CCoreDumpServer::ConstructL() - unable to open security server session! err:%d\n", err); User::Leave(err); } err = iSecSess.ShareAuto(); StartL( KCoreDumpServerName ); }
void CServerCrashDataSource::ReadRegistersL( const TUint64 aThreadId, RRegisterList & aRegisterList ) { LOG_MSG2("CServerCrashDataSource::ReadRegistersL(aThreadId=%Lu)\n", aThreadId); if( aRegisterList.Count() ) { LOG_MSG("CServerCrashDataSource::ReadRegistersL - register list already supplied\n" ); SetRegValuesL( aThreadId, aRegisterList ); } else { LOG_MSG("CServerCrashDataSource::ReadRegistersL - suppliying register list\n" ); GetRegisterListL( aRegisterList ); SetRegValuesL( aThreadId, aRegisterList ); } //PrintRegs( aRegisterList ); }
/** * Launch a process * @param aProcess the RProcess object used for creating the process * @param aExeName the name of the executable to run * @param aCommandLine command line parameters to pass when creating the process * @return KErrNone on success, or one of the other system wide error codes */ TInt LaunchProcess(RProcess& aProcess, TDesC& aExeName, TDesC& aCommandLine ) { LOG_MSG("ENTER: t_multi_agent_launcher: launchProcess"); LOG_MSG2("aExeName %S ", &TPtr8((TUint8*)aExeName.Ptr(), 2*aExeName.Length(), 2*aExeName.Length())); LOG_MSG2("aCommandLine %S", &TPtr8((TUint8*)aCommandLine.Ptr(), 2*aCommandLine.Length(), 2*aCommandLine.Length())); TInt err = aProcess.Create( aExeName, aCommandLine ); LOG_MSG2("t_multi_agent_launcher launchProcess, aProcess.Create err = %d", err); // check that there was no error raised if(err != KErrNone) { return err; } // rendezvous with process TRequestStatus status = KRequestPending; aProcess.Rendezvous(status); if(KRequestPending != status.Int()) { // startup failed so kill the process LOG_MSG2("t_multi_agent_launcher: launchProcess: RProcess Rendezvous() failed with %d. Killing process", status.Int()); aProcess.Kill(KErrNone); return status.Int(); } else { aProcess.Resume(); User::WaitForRequest(status); LOG_MSG2("t_multi_agent_launcher: launchProcess: RProcess Resume() Rendezvous successful %d: ", status.Int()); if(KErrNone != status.Int()) { LOG_MSG2("t_multi_agent_launcher: RProcess Resume() failed with %d. Killing process", status.Int()); aProcess.Kill(KErrNone); } LOG_MSG("EXIT: t_multi_agent_launcher launchProcess"); return status.Int(); } }
void CServerCrashDataSource::GetProcessListL( RProcessPointerList & aProcessList, TUint & aTotalProcessListDescSize ) { //LOG_MSG( "CServerCrashDataSource::GetProcessListL()\n" ); // Delete any objects in the array, since we will replace them. aProcessList.ResetAndDestroy(); aTotalProcessListDescSize = 0; if( iProcListBuffer.Size() != iLastProcListSize ) { LOG_MSG2( " iProcListBuffer.ReAlloc( %d)\n", iLastProcListSize ); iProcListBuffer.ReAllocL( iLastProcListSize ); } DoGetListL( EProcesses, (TUint)(-1), (TUint)(-1), iProcListBuffer, iLastProcListSize ); iLastProcListSize = iProcListBuffer.Size(); TUint8* ptr = (TUint8*)( iProcListBuffer.Ptr() ); const TUint8* ptrEnd = ptr + iLastProcListSize; //LOG_MSG3( " Data start,end=(0x%x, 0x%x)\n", ptr, ptrEnd ); while( ptr < ptrEnd ) { TProcessListEntry *entry = (TProcessListEntry*)ptr; if( !entry ) { LOG_MSG( " ERROR !* : TProcessListEntry is NULL\n" ); User::Leave(KErrBadHandle); } TUint64 id = entry->iProcessId; if( entry->iFileNameLength == 0 ) { LOG_MSG4( " Skipping process 0x%X%X : entry->iFileNameLength=%d", I64HIGH(entry->iProcessId), I64LOW(entry->iProcessId), entry->iFileNameLength ); ptr += Align4( entry->GetSize() ); continue; } /* LOG_MSG4( " process 0x%X%X has iFileNameLength=%d", I64HIGH(entry->iProcessId), I64LOW(entry->iProcessId), entry->iFileNameLength ); */ TPtrC entryName(&(entry->iNames[0]), entry->iFileNameLength); CProcessInfo *procInfoPtr = CProcessInfo::NewL(id, entryName ); TInt err = aProcessList.Append( procInfoPtr ); if(err != KErrNone) { delete procInfoPtr; User::Leave(err); } aTotalProcessListDescSize += procInfoPtr->Size(); ptr += Align4( entry->GetSize() ); } }
const TDesC& CTargetObserver::Thread(TInt aIndex) const { LOG_MSG2("CTargetObserver::Thread(%d)\n", aIndex); return *iThreadList[aIndex]; }
TBool CConfigureCDSDialog::OkToExitL(TInt aButtonId) { LOG_MSG( "-> CConfigureCDSDialog::OkToExitL" ); TBool ret = ETrue; TInt err; RPointerArray<CEikEdwin> edwins; CEikEdwin *edwin = static_cast<CEikEdwin*>(Control(EEdwin1)); edwins.Append(edwin); edwin = static_cast<CEikEdwin*>(Control(EEdwin2)); edwins.Append(edwin); edwin = static_cast<CEikEdwin*>(Control(EEdwin3)); edwins.Append(edwin); edwin = static_cast<CEikEdwin*>(Control(EEdwin4)); edwins.Append(edwin); edwin = static_cast<CEikEdwin*>(Control(EEdwin5)); edwins.Append(edwin); edwin = static_cast<CEikEdwin*>(Control(EEdwin6)); edwins.Append(edwin); edwin = static_cast<CEikEdwin*>(Control(EEdwin7)); edwins.Append(edwin); switch (aButtonId) { case EEikBidCancel: { //RDebug::Print(_L("CConfigureCDSDialog::OkToExitL: Cancel pressed")); } break; case EBidCDSConfigure: { //RDebug::Print(_L("CConfigureCDSDialog::OkToExitL: iConfs.Count() == %d"), iConfs.Count()); for (TInt i = 0; ( i < iConfs.Count() ) && ret; i++) { err = KErrNone; HBufC *input = NULL; if (edwins[i]->TextLength() > 0) { input = edwins[i]->GetTextInHBufL(); } if ( ! input ) { LOG_MSG2( " NULL input for param %d" , i ); continue; } //RDebug::Print(_L("CConfigureCDSDialog::OkToExitL: iConfs[i]->Type() == %d"), iConfs[i]->Type()); switch (iConfs[i]->Type()) { case COptionConfig::ETInt: case COptionConfig::ETUInt: { TLex opts(*input); TInt32 conf; err = opts.Val(conf); if ( err ) { LOG_MSG(" error from opts.Val(conf) -> CConfigureCDSDialog::CEikonEnv::Static()->InfoMsg;" ); CEikonEnv::Static()->InfoMsg(_L("Value must be an integer")); break; } //RDebug::Print(_L("CConfigureCDSDialog::OkToExitL: conf == %d"), conf); iConfs[i]->Value(conf); TRAP( err, iCoreDumpSession.SetConfigParameterL( *iConfs[i]) ); } break; case COptionConfig::ETFileName: case COptionConfig::ETString: case COptionConfig::ETSingleEntryEnum: case COptionConfig::ETMultiEntryEnum: { TRAP( err, iConfs[i]->ValueL(*input) ); if ( KErrNone == err ) { TRAP( err, iCoreDumpSession.SetConfigParameterL( *iConfs[i]) ); } } break; case COptionConfig::ETBool: if (input->CompareF(_L("True"))== 0) { iConfs[i]->Value(ETrue); iConfs[i]->ValueL(_L("True")); } else if (input->CompareF(_L("False"))== 0) { iConfs[i]->Value(EFalse); iConfs[i]->ValueL(_L("False")); } else { err = KErrCorrupt; } if ( KErrNone == err ) { TRAP( err, iCoreDumpSession.SetConfigParameterL( *iConfs[i]) ); } break; default: CEikonEnv::Static()->InfoMsg(_L("Error with parameter type")); LOG_MSG( "CConfigureCDSDialog::OkToExitL: none of the above" ); err = KErrCorrupt; break; }//switch if ( err ) { RBuf errorString; CleanupClosePushL( errorString ); errorString.CreateL( 128 ); errorString.Append( _L("CDS Error ") ); errorString.AppendNum( err ); errorString.Append( _L(" setting parameter number ") ); errorString.AppendNum( i ); CEikonEnv::InfoWinL( errorString, KNullDesC ); CleanupStack::PopAndDestroy( &errorString ); ret = EFalse; } if(input) { delete input; input = NULL; } } } break; default: break; } edwins.Close(); return ret; }
LOCAL_C void processConfigL() { // Create a CCrashConfig object, the configuration client-side // object of the CoreDump Server . RCoreDumpSession coredumpinterface; TInt ret = coredumpinterface.Connect(); if( KErrNone != ret ) { LOG_MSG2( "requestConfigLoadL():: Could not create a Core Dump configuration object, error=%d", ret ); User::Leave( ret ); } TUint crashes = 1; TInt argc = User::CommandLineLength(); TPtrC configFile(KNullDesC); HBufC* args = NULL; if(argc > 0) { args = HBufC::NewLC(User::CommandLineLength()); TPtr argv = args->Des(); User::CommandLine(argv); TLex lex(*args); while(!lex.Eos()) { if(lex.Get() == '-') { TChar c = lex.Get(); if(c == '-') { TPtrC16 token = lex.NextToken(); c = token[0]; } lex.SkipSpace(); switch(c) { case 'c': lex.Val(crashes); break; case 'f': configFile.Set(lex.NextToken()); break; default: User::Leave(KErrArgument); } } lex.SkipSpace(); } } TRAPD(err, coredumpinterface.LoadConfigL( configFile )); if(err != KErrNone) { LOG_MSG2("unable to load config file! err:%d\n", err ); coredumpinterface.Disconnect(); User::Leave(err); } LOG_MSG2( "Will wait for %u crashes\n", crashes ); RProperty crashCountProperty; User::LeaveIfError( crashCountProperty.Attach( KCoreDumpServUid, ECrashCount ) ); TInt crashCount = 0; do { User::After(5000000); ret = crashCountProperty.Get( crashCount ); LOG_MSG2( " crashCountProperty.Get( crashCount )=%d\n", crashCount ); if ( KErrNone != ret ) { break; } } while( crashes > crashCount ); crashCountProperty.Close(); if(args) { CleanupStack::PopAndDestroy(args); } coredumpinterface.Disconnect(); LOG_MSG( " returned from CleanupStack::PopAndDestroy( cmd );" ); }
void CServerCrashDataSource::GetCodeSegmentsL( const TUint64 aTid, RCodeSegPointerList &aCodeSegList, TUint & aTotalCodeSegListDescSize ) { LOG_MSG2("->CServerCrashDataSource::GetCodeSegmentsL(aTid=%Lu)\n", aTid ); aCodeSegList.ResetAndDestroy(); aTotalCodeSegListDescSize = 0; TUint32 size = KMaxFileName; RBuf8 buffer; buffer.CreateL(KMaxFileName); CleanupClosePushL(buffer); DoGetListL( ECodeSegs, aTid, (TUint)-1, buffer, size ); LOG_MSG2( " DoGetListL( ECodeSegs ) returned buffer.Size()=0x%X\n", buffer.Size() ); TUint8* ptr = (TUint8*)buffer.Ptr(); const TUint8* ptrEnd = ptr + size; while(ptr < ptrEnd) { TCodeSegListEntry* entry = (TCodeSegListEntry*)ptr; LOG_MSG4( " entry->CodeBase=0x%X, CodeSize=0x%X, ConstDataSize=0x%X\n", entry->iCodeBase, entry->iCodeSize, entry->iConstDataSize ); LOG_MSG4( " InitDataBase=0x%X, InitDataSize=0x%X, UnintDataSize=0x%X\n", entry->iInitialisedDataBase, entry->iInitialisedDataSize, entry->iUninitialisedDataSize ); LOG_MSG3( " IsXip=0x%X, CodeSegType=0x%X\n", entry->iIsXip, entry->iCodeSegType ); TCodeSegInfo *codeSeg = new(ELeave) TCodeSegInfo; TPtr name(&(entry->iName[0]), entry->iNameLength, entry->iNameLength); codeSeg->iName = name; codeSeg->iType = entry->iCodeSegType; codeSeg->iXIP = entry->iIsXip; codeSeg->iCodeSize = entry->iCodeSize; codeSeg->iCodeRunAddr = entry->iCodeBase; if( codeSeg->iXIP ) { codeSeg->iCodeLoadAddr = codeSeg->iCodeRunAddr; } else { codeSeg->iCodeLoadAddr = 0; //TODO } codeSeg->iRoDataSize = entry->iConstDataSize; codeSeg->iRoDataRunAddr = entry->iCodeBase + entry->iCodeSize; if( codeSeg->iXIP ) { codeSeg->iRoDataLoadAddr = codeSeg->iRoDataRunAddr; } else { codeSeg->iRoDataLoadAddr = 0; //TODO } codeSeg->iDataSize = entry->iInitialisedDataSize + entry->iUninitialisedDataSize; codeSeg->iDataRunAddr = entry->iInitialisedDataBase; if( codeSeg->iXIP ) { codeSeg->iDataLoadAddr = codeSeg->iDataRunAddr; } else { codeSeg->iDataLoadAddr = 0; //TODO } TInt err = aCodeSegList.Append(codeSeg); if(err != KErrNone) { delete codeSeg; User::Leave(err); } aTotalCodeSegListDescSize += sizeof(TCodeSegInfo); ptr += Align4(entry->GetSize()); } CleanupStack::PopAndDestroy(&buffer); }
/** Obtain the thread list. If aProcessId is negative, we obtain the entire system thread list. If aProcessId is positive we get the thread list for that process */ void CServerCrashDataSource::GetThreadListL( const TUint64 aProcessId, RThreadPointerList & aThreadList, TUint & aTotalThreadListDescSize ) { LOG_MSG2( "->CServerCrashDataSource::GetThreadListL(aProcessId=%Lu)\n", aProcessId); // Delete any objects in the array, since we will replace them. aThreadList.ResetAndDestroy(); aTotalThreadListDescSize = 0; if( iThreadListBuffer.Size() != iLastThreadListSize ) { LOG_MSG2("CServerCrashDataSource::GetThreadListL -> iThreadListBuffer.ReAlloc(%d)\n", iLastThreadListSize ); iThreadListBuffer.ReAllocL( iLastThreadListSize ); } LOG_MSG( "CServerCrashDataSource::GetThreadListL -> DoGetListL()\n" ); DoGetListL( EThreads, (TUint)-1, aProcessId, iThreadListBuffer, iLastThreadListSize ); iLastThreadListSize = iThreadListBuffer.Size(); CThreadInfo * threadInfoPtr; RThread thread; TThreadStackInfo stackInfo; TThreadListEntry * entry; TUint usrStackSize; TLinAddr usrStackAddr; TLinAddr svcStackPtr; TLinAddr svcStackBase; TUint svcStackSize; TUint priority; TUint8* ptr = (TUint8*)( iThreadListBuffer.Ptr() ); const TUint8* ptrEnd = ptr + iLastThreadListSize; //LOG_MSG3( " Data start,end=(0x%x, 0x%x)\n", ptr, ptrEnd ); while( ptr < ptrEnd ) { entry = (TThreadListEntry*)ptr; if( !entry ) { LOG_MSG( " ERROR !* : TThreadListEntry is NULL\n" ); User::Leave(KErrBadHandle); } if( entry->iNameLength == 0 ) { LOG_MSG4( " Skipping Thread 0x%X%X : entry->iNameLength=%d", I64HIGH(entry->iThreadId), I64LOW(entry->iThreadId), entry->iNameLength ); ptr += Align4( entry->GetSize() ); continue; } //LOG_MSG3( " entry &=0x%X, size=%d\n", &(entry->iThreadId), entry->GetSize() ); //LOG_MSG3( " entry->iThreadId= 0x%X%X\n", I64HIGH(entry->iThreadId), I64LOW(entry->iThreadId) ); //LOG_MSG3( " found tid=%d, pid=%d\n", I64LOW(entry->iThreadId), I64LOW(entry->iProcessId) ); if( entry->iSupervisorStackPtrValid ) { svcStackPtr = entry->iSupervisorStackPtr; } else { svcStackPtr = 0; } if( entry->iSupervisorStackBaseValid ) { svcStackBase = entry->iSupervisorStackBase; } else { svcStackBase = 0; } if( entry->iSupervisorStackSizeValid ) { svcStackSize = entry->iSupervisorStackSize; } else { svcStackSize = 0; } if( KErrNone == thread.Open( entry->iThreadId ) ) { priority = (TUint)(thread.Priority()); if( KErrNone == thread.StackInfo( stackInfo ) ) { usrStackAddr = stackInfo.iLimit; usrStackSize = stackInfo.iBase - stackInfo.iLimit; } else { usrStackSize = 0; usrStackAddr = 0; } thread.Close(); } else { usrStackSize = 0; usrStackAddr = 0; priority = 0; } /* LOG_MSG3( " entry->iNameLength=%d, &(entry->iName[0])=0x%X\n", entry->iNameLength, &(entry->iName[0]) ); */ TPtrC entryName( &(entry->iName[0]), entry->iNameLength ); //LOG_MSG2( " -> threadInfoPtr = CThreadInfo::NewL( name.Size()=%d)\n", entryName.Size() ); threadInfoPtr = CThreadInfo::NewL( entry->iThreadId, entryName, entry->iProcessId, (TUint)priority, svcStackPtr, svcStackBase, svcStackSize, usrStackAddr, usrStackSize ); /* LOG_MSG3( " threadInfoPtr->iSvcStackAddr=0x%X, threadInfoPtr->iSvcStackSize=0x%X\n", threadInfoPtr->SvcStackAddr(), threadInfoPtr->SvcStackSize() ); */ TInt err = aThreadList.Append( threadInfoPtr ); if( err != KErrNone ) { // We use this id so as not to use Push(), AppendL(), Pop() delete threadInfoPtr; User::Leave( err ); } aTotalThreadListDescSize += threadInfoPtr->Size(); /* LOG_MSG3( " aTotalThreadListDescSize = %d after adding %d\n", aTotalThreadListDescSize, threadInfoPtr->Size() ); RBuf rPrintBuf; rPrintBuf.Create( threadInfoPtr->Name()); RDebug::Printf( " <- rPrintBuf.Create(), rPrintBuf.Length()=%d\n", rPrintBuf.Length() ); char* cl = (char*) rPrintBuf.Collapse().PtrZ(); RDebug::Printf(" name=%s\n", cl ); rPrintBuf.Close(); */ ptr += Align4( entry->GetSize() ); //LOG_MSG2( " ptr += Align4(entry->GetSize()) = 0x%X\n", ptr ); } // while }
// second-phase constructor void CServerCrashDataSource::ConstructL() { LOG_MSG("->CServerCrashDataSource::ConstructL()\n" ); // Get the debug func block and make appropriate changes to our structures TInt err; TUint32 bufsize = 0; LOG_MSG( " -> iSecSess->GetDebugFunctionalityBufSize( &bufsize )\n" ); err = iSecSess.GetDebugFunctionalityBufSize( &bufsize ); if( (err != KErrNone) || (0 == bufsize) ) { // No debug functionality block, cannot do much without that. LOG_MSG2("CServerCrashDataSource::ConstructL() - unable to get debug functionality block! err:%d\n", err); User::Leave( KErrNotSupported ); } RBuf8 DFBlock; DFBlock.CreateL(bufsize); DFBlock.CleanupClosePushL(); LOG_MSG2( " -> HBufC8::NewLC( bufsize=%d )\n", bufsize ); LOG_MSG("CServerCrashDataSource::ConstrucL -> GetDebugFunctionality()\n" ); err = iSecSess.GetDebugFunctionality(DFBlock); if( KErrNone != err ) { LOG_MSG( "CServerCrashDataSource::ConstructL() : ERROR !* : Could not retrieve debug functionality block\n" ); User::Leave( KErrNotSupported ); } LOG_MSG( " -> GetDebugHeader( EDF_TagHdrId_RegistersCore )\n" ); TTagHeader * hdr = GetDebugHeader( ETagHeaderIdRegistersCore, DFBlock ); if( hdr == NULL ) { LOG_MSG( "Could not retrieve ETagHeaderIdRegistersCore register debug block\n" ); } else if( 0 == hdr->iNumTags ) { LOG_MSG( "Zero tags found for ETagHeaderIdRegistersCore register debug block\n" ); } else { iRegisterList.ReserveL( (TInt)hdr->iNumTags ); // Skip the header to get to the tags TUint8 * ptr = ((TUint8 *) hdr) + sizeof( TTagHeader ); TTag * tag = (TTag *) ptr; TRegisterData regData; TRegisterData * reg = ®Data; // Process all the register tags for( TInt regIdx = 0; regIdx < hdr->iNumTags; regIdx ++ ) { reg->iRegClass = 0; // Core = 0 reg->iId = tag->iTagId; // reg->iSubId = 0; // reg->iSize = 2; // Should all be 32 bits == 2. reg->iAvailable = ETrue; reg->iValue64 = 0; iRegisterList.Append( *reg ); tag++; } } hdr = GetDebugHeader( ETagHeaderIdMemory, DFBlock ); if( hdr == NULL ) { LOG_MSG( "Could not retrieve ETagHeaderIdMemory. Cannot read memory\n" ); iMaxMemReadSize = 0; } else if( 0 == hdr->iNumTags ) { LOG_MSG( "Zero tags found for ETagHeaderIdMemory register debug block\n" ); iMaxMemReadSize = 0; } else { TTag* tag = GetTag( hdr, EMemoryMaxBlockSize ); if( tag ) { //LOG_MSG2( " EMemoryMaxBlockSize =0x%X\n", tag->iValue ); iMaxMemReadSize = tag->iValue; } } iLastThreadListSize = 1; iLastProcListSize = 1; iLastRegListSize = 1; CleanupStack::PopAndDestroy(&DFBlock); }
/** * Read command line parameters and control the launching of the agents. */ void MainL() { LOG_MSG( "ENTER: t_multi_agent_launcher MainL()"); TInt ret = KErrNone; TInt numAgents = KNumAgents; TInt numTargets = KNumTargets; TInt numTestRuns = KNumTestRuns; TInt argc = User::CommandLineLength(); HBufC* commandLine = NULL; LOG_MSG2("t_multi_agent_launcher: MainL(): argc=%d", argc); if(argc) { commandLine = HBufC::NewLC(argc); TPtr commandLineBuffer = commandLine->Des(); User::CommandLine(commandLineBuffer); RBuf printCommandLine; CleanupClosePushL( printCommandLine ); printCommandLine.CreateL( commandLine->Des().Length() ); printCommandLine.Copy( commandLine->Des() ); printCommandLine.Collapse(); LOG_MSG2("t_multi_agent_launcher: command line = %S", &printCommandLine); CleanupStack::PopAndDestroy( &printCommandLine ); // create a lexer and read through the command line TLex lex(*commandLine); while (!lex.Eos()) { // only look for options with first character '-' if (lex.Get() == '-') { TChar arg = lex.Get(); switch ( arg ) { case 'n': lex.Val( numAgents ); LOG_MSG2("t_multi_agent_launcher: parsed numAgents as %d", numAgents); break; case 'm': lex.Val( numTargets ); LOG_MSG2("t_multi_agent_launcher: parsed numTargets as %d", numTargets); break; case 't': lex.Val( numTestRuns ); LOG_MSG2("t_multi_agent_launcher: parsed numTestRuns as %d", numTestRuns); break; default: LOG_MSG("t_multi_agent_launcher: unknown argument ignoring it"); break; } } } } // Note: below is a workaround to overcome an issue with RTest server crashing // when writing to the windows console from different agents (on different CPUs // at the same time). To overcome this we get signaled by the agents when they have // completed their tests so that we can do a RTest complete RSemaphore launchSemaphore; CleanupClosePushL(launchSemaphore); ret = launchSemaphore.CreateGlobal(KLaunchSemaphoreName, 0); LOG_MSG2( ">Target Launcher : RSemaphore.CreateGlobal ret %d", ret); User::LeaveIfError( ret ); ret = launchSemaphore.OpenGlobal(KLaunchSemaphoreName); LOG_MSG2( ">Target Launcher : RSemaphore.OpenGlobal ret %d", ret); User::LeaveIfError( ret ); //Now launch the requested number of apps for the requested number of test runs for( TInt j = 0; j < numTestRuns; j++ ) { for( TInt i = 0; i < numAgents; i++ ) { RBuf targetName; targetName.CleanupClosePushL(); targetName.CreateL(KAgentExe()); RProcess aProc; CleanupClosePushL(aProc); RBuf launcherOptions; CleanupClosePushL(launcherOptions); const TInt additionalWords = 2; launcherOptions.CreateL( KAgentOptions().Length() + additionalWords ); // Apply offset: launcherOptions.Format( .., .., i * numTargets, ..) // workaround to ensure we have the same binary for multiple agents. // e.g. So if offset = 0, agent attaches to app1, app2, app3, app4, app5 // if offset = 5, agent attached to app6, app7, app8, app9, app10 etc. // Note: apps need to be in rom otherwise the agent will fail on an assert // (with KErrNotFound) launcherOptions.Format( KAgentOptions(), (TUint)numTargets, i * numTargets, 0); ret = LaunchProcess( aProc, targetName, launcherOptions ); CleanupStack::PopAndDestroy(3,&targetName); User::LeaveIfError(ret); } } // Wait for all agents to do their testing before checking the semaphore User::After(12000000); LOG_MSG( ">Target Launcher: Semaphore wait"); for (TInt i = 0; i < numAgents; i ++) { //We need this delay just in case an agent crashes and never signals the sem ret = launchSemaphore.Wait(100000); if( ret != KErrNone ) { LOG_MSG3("launchSemaphore.Wait ret %d for agent %d", ret, i); break; } } LOG_MSG2( "testing for Semaphore ret %d", ret); // We only want to have one RTest instance at any one time since otherwise RTest can panic RTest test(_L("T_MULTI_AGENT_LAUNCHER")); test.Start(_L("t_multi_agent_launcher Check for agents finishing correctly")); test(ret == KErrNone); test.End(); test.Close(); CleanupStack::PopAndDestroy(&launchSemaphore); // launchSemaphore if( commandLine ) CleanupStack::PopAndDestroy(commandLine); LOG_MSG("EXIT: t_multi_agent_launcher MainL()"); }
void CServerCrashDataSource::SetRegValuesL( const TUint64 aThreadId, RRegisterList &aRegisterList ) { LOG_MSG2("->CServerCrashDataSource::SetRegValuesL(aThreadId=%Lu)\n", aThreadId); TInt numberOfRegisters = aRegisterList.Count(); RBuf8 ids; ids.CreateL( numberOfRegisters * sizeof(TFunctionalityRegister) ); ids.CleanupClosePushL(); TInt totalByteSize = 0; // Keeps track of the number of bytes that we are requesting for( TInt i=0; i < numberOfRegisters; i++ ) { TRegisterInfo reg = (TRegisterInfo)( aRegisterList[i].iId ); // iSize = (0 == 1 byte); (3 == 8 bytes) TInt byteSize = (aRegisterList[i].iSize) << 1; totalByteSize += byteSize; ids.Append( reinterpret_cast<const TUint8*>(®), sizeof(TRegisterInfo) ); } RBuf8 registerValues; registerValues.CreateL( totalByteSize ); registerValues.CleanupClosePushL(); RBuf8 registerFlags; registerFlags.CreateL( numberOfRegisters ); registerFlags.CleanupClosePushL(); LOG_MSG("CServerCrashDataSource::SetRegValuesL - reading registers\n"); User::LeaveIfError(iSecSess.ReadRegisters( aThreadId, ids, registerValues, registerFlags )); // Now copy the values back to the array and mark the availability from the flags TUint8* valuePtr = (TUint8*) registerValues.Ptr(); for( TInt i=0; i < numberOfRegisters; i++ ) { TRegisterData & reg = aRegisterList[i]; switch( reg.iSize ) { case 0: reg.iValue8 = *((TUint8 *)valuePtr); valuePtr += 1; break; case 1: reg.iValue16 = *((TUint16 *)valuePtr); valuePtr += 2; break; case 2: reg.iValue32 = *((TUint32 *)valuePtr); valuePtr += 4; break; case 3: reg.iValue64 = *((TUint64 *)valuePtr); valuePtr += 8; break; } if( EValid == registerFlags[i] ) { reg.iAvailable = ETrue; } else { reg.iAvailable = EFalse; } } CleanupStack::PopAndDestroy(®isterFlags); CleanupStack::PopAndDestroy(®isterValues); CleanupStack::PopAndDestroy(&ids); }