First public contribution.
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
17 #include <e32base_private.h>
19 #include <e32cmn_private.h>
21 #include <e32property.h>
22 #include "t_rmdebug_app.h"
24 IMPORT_C extern void RMDebug_BranchTst2();
26 LOCAL_C void ParseCommandLineL(TInt32& aFunctionType, TUint& aDelay, TUint& aExtraThreads)
28 // get the length of the command line arguments
29 TInt argc = User::CommandLineLength();
31 // allocate a buffer for the command line arguments and extract the data to it
32 HBufC* commandLine = HBufC::NewLC(argc);
33 TPtr commandLineBuffer = commandLine->Des();
34 User::CommandLine(commandLineBuffer);
36 // create a lexer and read through the command line
37 TLex lex(*commandLine);
40 // expecting the first character to be a '-'
43 TChar arg = lex.Get();
47 // the digits following '-f' give the function type
48 User::LeaveIfError(lex.Val(aFunctionType));
51 // the digits following '-d' give the delay
52 User::LeaveIfError(lex.Val(aDelay));
55 // the digits following '-e' give the number of extra threads to launch
56 User::LeaveIfError(lex.Val(aExtraThreads));
59 // unknown argument so leave
60 User::Leave(KErrArgument);
66 // unknown argument so leave
67 User::Leave(KErrArgument);
72 CleanupStack::PopAndDestroy(commandLine);
75 typedef void (*TPfun)();
77 // test function to call corresponding to EPrefetchAbortFunction
84 // test function to call corresponding to EUserPanicFunction
87 User::Panic(KUserPanic, KUserPanicCode);
90 // calls self repeatedly until stack is used up. Slightly convoluted to prevent UREL optimising this out...
91 TUint32 StackOverFlowFunction(TUint32 aInt=0)
93 TUint32 unusedArray[150];
94 for(TInt i=0; i<150; i++)
96 unusedArray[i] = StackOverFlowFunction(i);
98 return unusedArray[0];
103 TInt* r = (TInt*) 0x1000;
107 void UndefInstruction()
109 TUint32 undef = 0xE6000010;
110 TPfun f = (TPfun) &undef;
116 TInt* r = (TInt*) 0x1000;
118 //include the following line to ensure that rr doesn't get optimised out
119 RDebug::Printf("Shouldn't see this being printed out: %d", rr);
121 // Stop compilation warning. Should not get here anyway.
128 TInt* r = (TInt*) 0x1000;
134 User::RaiseException(EExcGeneral);
137 void SpinForeverWithBreakPoint()
140 // finding the process t_rmdebug2/t_rmdebug2_oem/t_rmdebug2_oem2
141 // we find the process.SID to attach to the property
142 _LIT(KThreadWildCard, "t_rmdebug2*");
145 TUid propertySid = KNullUid;
146 TFindThread find(KThreadWildCard);
148 TBool found = EFalse;
149 while(find.Next(name)==KErrNone && !found)
152 err = thread.Open(find);
156 thread.Process(process);
157 TFullName fullname = thread.FullName();
158 //RDebug::Printf("SID Search Match Found Name %lS Process ID%ld Thread Id %ld", &fullname, process.Id().Id(), thread.Id().Id());
160 //SID saved so that the property can be attached to
161 propertySid = process.SecureId();
167 //attach to the property to publish the address of the RMDebug_BranchTst2 with the correct SID value
168 RProperty integerProperty;
169 err = integerProperty.Attach(propertySid, EMyPropertyInteger, EOwnerThread);
171 RDebug::Printf("Error Attach to the property %d", err);
173 TInt address = (TInt)&RMDebug_BranchTst2;
175 // publish the address where the breakpoint would be set
176 err = integerProperty.Set(address);
178 RDebug::Printf("Error Set of the property %d", err);
179 integerProperty.Close();
181 //open semaphore to signal the fact we have reached the point where we have to set the property
183 globsem.OpenGlobal(_L("RMDebugGlobSem"));
187 RProcess thisProcess;
188 TFileName thisProcessName = thisProcess.FileName();
189 RDebug::Printf("App Process Name %lS process id %ld thread id %ld", &thisProcessName, thisProcess.Id().Id(), RThread().Id().Id());
192 RThread::Rendezvous(KErrNone);
195 RMDebug_BranchTst2();
202 RThread::Rendezvous(KErrNone);
209 void LaunchThreads(TUint aNumber)
211 _LIT(KDebugThreadName, "DebugThread");
212 const TUint KDebugThreadDefaultHeapSize=0x10000;
213 for(TInt i=0; i<aNumber; i++)
217 threadName.Create(KDebugThreadName().Length()+10); // the 10 is for appending i to the end of the name
218 threadName.Append(KDebugThreadName());
219 threadName.AppendNum(i);
220 TInt err = thread.Create(threadName, (TThreadFunction)SpinForever, KDefaultStackSize, KDebugThreadDefaultHeapSize, KDebugThreadDefaultHeapSize, NULL);
223 RDebug::Printf("Couldn't create thread %d", err);
228 thread.SetPriority(EPriorityNormal);
229 TRequestStatus status;
230 thread.Rendezvous(status);
232 User::WaitForRequest(status);
238 void WaitFiveSecondsThenExit(void)
240 // wait for 5 seconds
241 User::After(5000000);
244 // call the function corresponding to aFunctionType
245 LOCAL_C void CallFunction(TDebugFunctionType aFunctionType, TUint aDelay, TUint aExtraThreads)
247 // pause for aDelay microseconds
250 // launch the extra threads
251 LaunchThreads(aExtraThreads);
253 // call appropriate function
254 switch( aFunctionType )
256 case EPrefetchAbortFunction:
259 case EUserPanicFunction:
262 case EStackOverflowFunction:
263 StackOverFlowFunction();
265 case EDataAbortFunction:
268 case EUndefInstructionFunction:
271 case EDataReadErrorFunction:
274 case EDataWriteErrorFunction:
277 case EUserExceptionFunction:
280 case EWaitFiveSecondsThenExit:
281 WaitFiveSecondsThenExit();
286 case ESpinForeverWithBreakPoint:
287 SpinForeverWithBreakPoint();
289 case EDefaultDebugFunction:
297 RDebug::Printf("Invoke with arguments:\n");
298 RDebug::Printf("\t-d<delay>\n\t: delay in microseconds before calling target function\n");
299 RDebug::Printf("\t-f<function-number>\n\t: enumerator from TDebugFunctionType representing function to call\n");
300 RDebug::Printf("\t-e<number>\n\t: number of extra threads to launch, these threads run endlessly\n");
305 // setup heap checking and clean up trap
307 CTrapCleanup* cleanup=CTrapCleanup::New();
308 RThread().SetPriority(EPriorityNormal);
309 RProcess::Rendezvous(KErrNone);
311 // read arguments from command line
313 TInt32 functionTypeAsTInt32 = (TInt32)EDefaultDebugFunction;
314 TUint extraThreads = 0;
315 TRAPD(err, ParseCommandLineL(functionTypeAsTInt32, delay, extraThreads));
319 // if the command line arguments were successfully read then call the appropriate function
320 CallFunction((TDebugFunctionType)functionTypeAsTInt32, delay, extraThreads);
323 // perform clean up and return any error which was recorded