diff -r 000000000000 -r a41df078684a kerneltest/e32test/rm_debug/t_rmdebug_app.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/rm_debug/t_rmdebug_app.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,328 @@ +// 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 the License "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 +#include +#include +#include +#include +#include +#include "t_rmdebug_app.h" + +IMPORT_C extern void RMDebug_BranchTst2(); + +LOCAL_C void ParseCommandLineL(TInt32& aFunctionType, TUint& aDelay, TUint& aExtraThreads) + { + // get the length of the command line arguments + TInt argc = User::CommandLineLength(); + + // allocate a buffer for the command line arguments and extract the data to it + HBufC* commandLine = HBufC::NewLC(argc); + TPtr commandLineBuffer = commandLine->Des(); + User::CommandLine(commandLineBuffer); + + // create a lexer and read through the command line + TLex lex(*commandLine); + while (!lex.Eos()) + { + // expecting the first character to be a '-' + if (lex.Get() == '-') + { + TChar arg = lex.Get(); + switch (arg) + { + case 'f': + // the digits following '-f' give the function type + User::LeaveIfError(lex.Val(aFunctionType)); + break; + case 'd': + // the digits following '-d' give the delay + User::LeaveIfError(lex.Val(aDelay)); + break; + case 'e': + // the digits following '-e' give the number of extra threads to launch + User::LeaveIfError(lex.Val(aExtraThreads)); + break; + default: + // unknown argument so leave + User::Leave(KErrArgument); + } + lex.SkipSpace(); + } + else + { + // unknown argument so leave + User::Leave(KErrArgument); + } + } + + // do clean up + CleanupStack::PopAndDestroy(commandLine); + } + +typedef void (*TPfun)(); + +// test function to call corresponding to EPrefetchAbortFunction +void PrefetchAbort() + { + TPfun f = NULL; + f(); + } + +// test function to call corresponding to EUserPanicFunction +void UserPanic() + { + User::Panic(KUserPanic, KUserPanicCode); + } + +// calls self repeatedly until stack is used up. Slightly convoluted to prevent UREL optimising this out... +TUint32 StackOverFlowFunction(TUint32 aInt=0) + { + TUint32 unusedArray[150]; + for(TInt i=0; i<150; i++) + { + unusedArray[i] = StackOverFlowFunction(i); + } + return unusedArray[0]; + } + +void DataAbort() + { + TInt* r = (TInt*) 0x1000; + *r = 0x42; + } + +void UndefInstruction() + { + TUint32 undef = 0xE6000010; + TPfun f = (TPfun) &undef; + f(); + } + +TInt DataRead() + { + TInt* r = (TInt*) 0x1000; + TInt rr = (TInt)*r; + //include the following line to ensure that rr doesn't get optimised out + RDebug::Printf("Shouldn't see this being printed out: %d", rr); + + // Stop compilation warning. Should not get here anyway. + rr++; + return rr; + } + +void DataWrite() + { + TInt* r = (TInt*) 0x1000; + *r = 0x42; + } + +void UserException() + { + User::RaiseException(EExcGeneral); + } + +void SpinForeverWithBreakPoint() + { + + // finding the process t_rmdebug2/t_rmdebug2_oem/t_rmdebug2_oem2 + // we find the process.SID to attach to the property + _LIT(KThreadWildCard, "t_rmdebug2*"); + + TInt err = KErrNone; + TUid propertySid = KNullUid; + TFindThread find(KThreadWildCard); + TFullName name; + TBool found = EFalse; + while(find.Next(name)==KErrNone && !found) + { + RThread thread; + err = thread.Open(find); + if (err == KErrNone) + { + RProcess process; + thread.Process(process); + TFullName fullname = thread.FullName(); + //RDebug::Printf("SID Search Match Found Name %lS Process ID%ld Thread Id %ld", &fullname, process.Id().Id(), thread.Id().Id()); + found = ETrue; + //SID saved so that the property can be attached to + propertySid = process.SecureId(); + process.Close(); + } + thread.Close(); + } + + //attach to the property to publish the address of the RMDebug_BranchTst2 with the correct SID value + RProperty integerProperty; + err = integerProperty.Attach(propertySid, EMyPropertyInteger, EOwnerThread); + if(KErrNone != err) + RDebug::Printf("Error Attach to the property %d", err); + + TInt address = (TInt)&RMDebug_BranchTst2; + + // publish the address where the breakpoint would be set + err = integerProperty.Set(address); + if(KErrNone != err) + RDebug::Printf("Error Set of the property %d", err); + integerProperty.Close(); + + //open semaphore to signal the fact we have reached the point where we have to set the property + RSemaphore globsem; + globsem.OpenGlobal(_L("RMDebugGlobSem")); + globsem.Signal(); + globsem.Close(); + + RProcess thisProcess; + TFileName thisProcessName = thisProcess.FileName(); + RDebug::Printf("App Process Name %lS process id %ld thread id %ld", &thisProcessName, thisProcess.Id().Id(), RThread().Id().Id()); + + TInt i=0; + RThread::Rendezvous(KErrNone); + while(i<0xffffffff) + { + RMDebug_BranchTst2(); + User::After(10000); + } + } +void SpinForever() + { + TInt i=0; + RThread::Rendezvous(KErrNone); + while(i<0xffffffff) + { + User::After(10000); + } + } + +void LaunchThreads(TUint aNumber) + { + _LIT(KDebugThreadName, "DebugThread"); + const TUint KDebugThreadDefaultHeapSize=0x10000; + for(TInt i=0; i\n\t: delay in microseconds before calling target function\n"); + RDebug::Printf("\t-f\n\t: enumerator from TDebugFunctionType representing function to call\n"); + RDebug::Printf("\t-e\n\t: number of extra threads to launch, these threads run endlessly\n"); + } + +TInt E32Main() + { + // setup heap checking and clean up trap + __UHEAP_MARK; + CTrapCleanup* cleanup=CTrapCleanup::New(); + RThread().SetPriority(EPriorityNormal); + RProcess::Rendezvous(KErrNone); + + // read arguments from command line + TUint delay = 0; + TInt32 functionTypeAsTInt32 = (TInt32)EDefaultDebugFunction; + TUint extraThreads = 0; + TRAPD(err, ParseCommandLineL(functionTypeAsTInt32, delay, extraThreads)); + + if(KErrNone == err) + { + // if the command line arguments were successfully read then call the appropriate function + CallFunction((TDebugFunctionType)functionTypeAsTInt32, delay, extraThreads); + } + + // perform clean up and return any error which was recorded + delete cleanup; + __UHEAP_MARKEND; + return err; + } +