--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dbgsrv/coredumpserver/test/crashapps/src/d_crashdriver_ldd.cpp Tue Mar 02 10:33:16 2010 +0530
@@ -0,0 +1,593 @@
+// Copyright (c) 2003-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 "t_crashdriver_drv.h"
+#include "d_crashdriver_ldd.h"
+#include "crash.h"
+#include <arm_types.h>
+//#include <scmonitor.h>
+
+/**
+ * Utility method to append a string to a kernel side descriptor
+ */
+void AppendString(TDes8& aDes, const char* aFmt, ...)
+ {
+ VA_LIST list;
+ VA_START(list,aFmt);
+ Kern::AppendFormat(aDes,aFmt,list);
+ }
+
+/**
+ * DCrashDriverFactory
+ * Standard export function for LDDs. This creates a DLogicalDevice derived object,
+ * in this case, our DCrashDriverFactory
+ */
+DECLARE_STANDARD_LDD()
+ {
+ return new DCrashDriverFactory;
+ }
+
+/**
+ * Constructor
+ */
+DCrashDriverFactory::DCrashDriverFactory()
+ {
+ // Set version number for this device
+ iVersion=RKernelCrashDrv::VersionRequired();
+ }
+
+
+/**
+ Destructor
+*/
+DCrashDriverFactory::~DCrashDriverFactory()
+ {
+ }
+
+/**
+ Second stage constructor for DKernelCrashAppFactory.
+ This must at least set a name for the driver object.
+
+ @return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DCrashDriverFactory::Install()
+ {
+ return SetName(&RKernelCrashDrv::Name());
+ }
+
+/**
+ Return the drivers capabilities.
+ Called in the response to an RDevice::GetCaps() request.
+
+ @param aDes Descriptor into which capabilities information is to be written.
+*/
+void DCrashDriverFactory::GetCaps(TDes8& aDes) const
+ {
+ // Create a capabilities object
+ RKernelCrashDrv::TCaps caps;
+ caps.iVersion = iVersion;
+ // Write it back to user memory
+ Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps));
+ }
+
+
+/**
+ Called by the kernel's device driver framework to create a Logical Channel.
+ This is called in the context of the user thread (client) which requested the creation
+ of the Logical Channel (e.g. through a call to RBusLogicalChannel::DoCreate).
+ The thread is in a critical section.
+
+ @param aChannel Set to point to the created Logical Channel
+
+ @return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DCrashDriverFactory::Create(DLogicalChannelBase*& aChannel)
+ {
+ aChannel=new DCrashDriverChannel;
+ if(!aChannel)
+ return KErrNoMemory;
+
+ return KErrNone;
+ }
+
+
+//
+// Logical Channel
+//
+
+/**
+ Constructor
+*/
+DCrashDriverChannel::DCrashDriverChannel() :
+ iDfcQ(NULL)
+ {
+ // Get pointer to client thread's DThread object
+ iClient=&Kern::CurrentThread();
+
+ // Open a reference on client thread so its control block can't disappear until
+ // this driver has finished with it.
+ // Note, this call to Open() can't fail since it is the thread we are currently running in.
+ iClient->Open();
+ recurseCount = 0;
+ }
+
+
+/**
+ Destructor
+*/
+DCrashDriverChannel::~DCrashDriverChannel()
+ {
+ if(iDfcQ)
+ iDfcQ->Destroy();
+
+ // Cancel all processing that we may be doing
+ //DoCancel(RKernelCrashApp::EAllRequests); not needed as of now check while debugging - praveenc
+ //Close our reference on the client thread
+ Kern::SafeClose((DObject*&)iClient,NULL);
+ }
+
+
+/**
+ Second stage constructor called by the kernel's device driver framework.
+ This is called in the context of the user thread (client) which requested the creation
+ of the Logical Channel (e.g. through a call to RBusLogicalChannel::DoCreate())
+ The thread is in a critical section.
+
+ @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate()
+ @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate()
+ @param aVer The version argument supplied by the client to RBusLogicalChannel::DoCreate()
+
+ @return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DCrashDriverChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
+ {
+ if(!Kern::CurrentThreadHasCapability(ECapability_None,__PLATSEC_DIAGNOSTIC_STRING("Checked by crashdriver")))
+ return KErrPermissionDenied;
+
+ // Check version
+ if (!Kern::QueryVersionSupported(RKernelCrashDrv::VersionRequired(),aVer))
+ return KErrNotSupported;
+
+ // Setup LDD for receiving client messages.
+ TInt err = Kern::DynamicDfcQCreate(iDfcQ, 25, RKernelCrashDrv::Name());
+ if(err != KErrNone)
+ {
+ Kern::Printf("Creating Dfc queue failed.");
+ }
+ SetDfcQ(iDfcQ);
+ iMsgQ.Receive();
+
+ return KErrNone;
+ }
+
+
+/**
+ Called when a user thread requests a handle to this channel.
+*/
+TInt DCrashDriverChannel::RequestUserHandle(DThread* aThread, TOwnerType aType)
+ {
+ // Make sure that only our client can get a handle
+ if (aType!=EOwnerThread || aThread!=iClient)
+ {
+ return KErrAccessDenied;
+ }
+ return KErrNone;
+ }
+
+
+/**
+ Process a message for this logical channel.
+ This function is called in the context of a DFC thread.
+
+ @param aMessage The message to process.
+ The iValue member of this distinguishes the message type:
+ iValue==ECloseMsg, channel close message
+ iValue==KMaxTInt, a 'DoCancel' message
+ iValue>=0, a 'DoControl' message with function number equal to iValue
+ iValue<0, a 'DoRequest' message with function number equal to ~iValue
+*/
+void DCrashDriverChannel::HandleMsg(TMessageBase* aMsg)
+ {
+ TThreadMessage& m=*(TThreadMessage*)aMsg;//needs checking -praveenc
+
+ // Get message type
+ TInt id=m.iValue;
+
+ // Decode the message type and dispatch it to the relevent handler function...
+ if (id==(TInt)ECloseMsg) //check later praveenc
+ {
+ // Channel Close
+ m.Complete(KErrNone, EFalse);
+ return;
+ }
+
+ if (id<0)
+ {
+ TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
+ TInt r=DoRequest(~id,pS,m.Ptr1(), m.Ptr2());
+ if (r==KErrNone)
+ Kern::RequestComplete(iClient,pS,r);
+ m.Complete(KErrNone,ETrue);
+ }
+ }
+
+/**
+ * Loop thread - infinite loop so we have a thread in a known state
+ * @param aPtr
+ * @return One of the symbian wide return codes
+ */
+TInt Loop(TAny* aPtr)
+ {
+ TInt32 array[3];
+ array[0] = 0xDEADDEAD;
+ array[1] = 0xF000BEEF;
+ array[2] = 0xBEEBEE00;
+
+ //set registers for known state for testing
+ SetRegs();
+
+ //go into infinite loop
+ InfLoop();
+
+ return array[0]; //to avoid warning - will never get here anyway
+ }
+
+TInt StartInfLoop()
+ {
+ //set registers for known state for testing
+ SetUpperRegs();
+
+ //Launch another kernel thread
+ SThreadCreateInfo info;
+ info.iType = EThreadSupervisor;
+ info.iFunction = Loop;
+ info.iPtr = NULL;
+ info.iSupervisorStack=NULL;
+ info.iSupervisorStackSize=0; // zero means use default value
+ info.iInitialThreadPriority= 25;
+ info.iName.Set(_L("cdsknownthread"));
+ info.iTotalSize = sizeof(info);
+
+ NKern::ThreadEnterCS();
+ TInt err = Kern::ThreadCreate(info);
+ NKern::ThreadLeaveCS();
+
+ if(err != KErrNone)
+ return err;
+
+ DThread* kernTh = (DThread*)info.iHandle;
+ Kern::ThreadResume(*kernTh);
+
+ NKern::Sleep(NKern::TimerTicks(3000)); //wait 3 seconds to ensure our other thread has been scheduled
+
+ return KErrNone;
+ }
+
+/**
+ Process asynchronous requests
+*/
+TInt DCrashDriverChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
+ {
+
+
+ Kern::Printf("DCrashDriverChannel::DoRequest");
+
+ TInt err = KErrNone;
+
+ switch(aReqNo)
+ {
+ case RKernelCrashDrv::EPrefetchAbort:
+ {
+ err = StartInfLoop();
+ if(err != KErrNone)
+ return err;
+ PrefetchAbort();
+ break;
+ }
+ case RKernelCrashDrv::EDataRead:
+ {
+ err = StartInfLoop();
+ if(err != KErrNone)
+ return err;
+ DataRead();
+ break;
+ }
+ case RKernelCrashDrv::EDataWrite:
+ {
+ err = StartInfLoop();
+ if(err != KErrNone)
+ return err;
+ DataWrite();
+ break;
+ }
+ case RKernelCrashDrv::EUndefInst:
+ {
+ err = StartInfLoop();
+ if(err != KErrNone)
+ return err;
+ UndefinedInst();
+ break;
+ }
+ case RKernelCrashDrv::EDivByZero:
+ {
+ err = StartInfLoop();
+ if(err != KErrNone)
+ return err;
+ DivByZero();
+ break;
+ }
+ case RKernelCrashDrv::EStackOverflow:
+ {
+ err = StartInfLoop();
+ if(err != KErrNone)
+ return err;
+ StackOverFlow();
+ break;
+ }
+ case RKernelCrashDrv::ETestSCMConfigInsertMethod:
+ {
+ //read the argmuents
+ HBuf8* tmp = HBuf8::New(KMaxBufferSize);
+
+ TInt err = Kern::ThreadDesRead(iClient, a2, *tmp, 0, 0 );
+ if (err != KErrNone || tmp->MaxLength() < KMaxBufferSize)
+ {
+ Kern::Printf("Unable to read argument or buffer too small");
+
+ // We could not read information from the user, so the a2 argument is probably wrong
+ Kern::RequestComplete(iClient, aStatus, KErrArgument);
+ return KErrArgument;
+ }
+
+ //run the test and gather the results
+ TBool pass;
+
+ //run test
+ //TestConfigInsertL(pass, *tmp);
+
+ //write the results back to client thread
+ err = Kern::ThreadRawWrite(iClient, a1, (TUint8*)&pass, sizeof(TBool), iClient);
+ if(err != KErrNone)
+ {
+ Kern::Printf("Unable to write data back to client");
+
+ // We could not read information from the user, so the a2 argument is probably wrong
+ Kern::RequestComplete(iClient, aStatus, KErrArgument);
+ return err;
+ }
+
+ //and write the buffer back...
+ err = Kern::ThreadDesWrite(iClient, a2, *tmp, 0, 0, iClient);
+ if(err != KErrNone)
+ {
+ Kern::Printf("Unable to write data back to client");
+
+ // We could not read information from the user, so the a2 argument is probably wrong
+ Kern::RequestComplete(iClient, aStatus, KErrArgument);
+ return err;
+ }
+
+ break;
+ }
+ default:
+ {
+ err=KErrNotSupported;
+ break;
+ }
+ }
+
+ return err;
+ }
+
+
+/**
+ Process cancelling of asynchronous requests //need later -praveenc
+*/
+void DCrashDriverChannel::DoCancel(TUint aMask)
+ {
+ //give definition later - praveenc
+ //if(aMask&(1<<RKernelCrashApp::ESendData))
+ // SendDataCancel();
+ //if(aMask&(1<<RKernelCrashApp::EReceiveData))
+ // ReceiveDataCancel();
+ }
+
+/**
+ * Method to cause board to crash with a prefetch abort
+ */
+void DCrashDriverChannel::PrefetchAbort()
+ {
+ Tfunc f = NULL;
+ f();
+ }
+
+/**
+ * Method to cause board to read from a location we arent allowed
+ */
+void DCrashDriverChannel::DataRead()
+ {
+ Kern::Printf("Causing a data read crash");
+ TInt* r = (TInt*) 0x1000;
+ TInt rr = (TInt)*r;
+
+ // Stop compilation warning. Should not get here anyway.
+ rr++;
+
+ }
+
+/**
+ * Method to cause board to crash from writing to a location we are not allowed
+ */
+void DCrashDriverChannel::DataWrite()
+ {
+ Kern::Printf("Causing a data write crash");
+ TInt* r = (TInt*) 0x1000;
+ *r = 0x42;
+ }
+
+/**
+ * Method to cause board to crash from executing an undefined instruction
+ */
+void DCrashDriverChannel::UndefinedInst()
+ {
+ Kern::Printf("Executing an undefined instruction");
+ TUint32 undef = 0xE6000010;
+ Tfunc f = (Tfunc) &undef;
+ f();
+ }
+
+/**
+ * Method to cause board to crash with a division by zero
+ */
+void DCrashDriverChannel::DivByZero()
+ {
+ Kern::Printf("\tDivision By zero crash...");
+ int x = 5;
+ int y = 5;
+ for(y = 5; y>0; --y)
+ {
+ //this is to avoid compiler errors
+ }
+ x = x/y;
+ }
+
+/**
+ * Method to cause board to crash with a stack overflow
+ */
+void DCrashDriverChannel::StackOverFlow()
+ {
+ Kern::Printf("\tAbout to cause a stackoverflow");
+ TUint32 array[128];
+ array[0] = ++recurseCount;
+ StackOverFlow();
+ TUint warnRem = array[0];
+ array[0] = warnRem;
+ }
+
+// Testing methods for SCMConfig //
+
+/**
+ * This tests we can succesfully enter and retrieve items from our config class
+ *//*
+void DCrashDriverChannel::TestConfigInsertL(TBool& aPass, TDes8& aResult)
+ {
+ //create our config object (We want a fresh one every time)
+ SCMConfiguration* config = new SCMConfiguration();
+
+ TInt32 highPriority = 200;
+ TInt32 highishPriority = 150;
+ TInt32 mediumPriority = 100;
+ TInt32 lowishPriority = 50;
+ TInt32 lowPriority = 10;
+
+ TUint8 numbytes1 = 20;
+ TUint8 numbytes2 = 30;
+ TUint8 numbytes3 = 40;
+ TUint8 numbytes4 = 50;
+ TUint8 numbytes5 = 60;
+ TUint8 numbytes6 = 10;
+
+ config->SetConfigItem(SCMConfiguration::ECrashedProcessMetaData, highishPriority, numbytes2);
+ config->SetConfigItem(SCMConfiguration::ECrashedThreadMetaData, lowPriority, numbytes5);
+ config->SetConfigItem(SCMConfiguration::ECrashedThreadUsrRegisters, highPriority, numbytes1);
+ config->SetConfigItem(SCMConfiguration::EExceptionStacks, mediumPriority, numbytes3);
+ config->SetConfigItem(SCMConfiguration::EThreadsSvrStack, lowishPriority, numbytes4);
+ config->SetConfigItem(SCMConfiguration::EProcessMetaData, lowishPriority, numbytes6);
+
+ //now we make sure they come back in the right order
+ TInt32 size = 0;
+ SCMConfiguration::TSCMDataType type;
+
+ //for each item, ensure that the expected size and type is correct
+ type = config->GetNextItemToDump(size);
+ aPass = (type == SCMConfiguration::ECrashedThreadUsrRegisters ) && (size == numbytes1);
+
+ if(!aPass)
+ {
+ delete config;
+ AppendString(aResult, "Expected ECrashedThreadUsrRegisters but got %d and expected size to be %d but got %d", type, numbytes1, size );
+ return;
+ }
+
+ type = config->GetNextItemToDump(size);
+ aPass = (type == SCMConfiguration::ECrashedProcessMetaData ) && (size == numbytes2);
+
+ if(!aPass)
+ {
+ delete config;
+ AppendString(aResult, "Expected ECrashedProcessMetaData but got %d and expected size to be %d but got %d", type, numbytes2, size );
+ return;
+ }
+
+ type = config->GetNextItemToDump(size);
+ aPass = (type == SCMConfiguration::EExceptionStacks ) && (size == numbytes3);
+
+ if(!aPass)
+ {
+ delete config;
+ AppendString(aResult, "Expected EExceptionStacks but got %d and expected size to be %d but got %d", type, numbytes3, size);
+ return;
+ }
+
+ //these next 2 went in at the same priority but the last one that goes in will be retrieved first
+ type = config->GetNextItemToDump(size);
+ aPass = (type == SCMConfiguration::EProcessMetaData ) && (size == numbytes6);
+
+ if(!aPass)
+ {
+ delete config;
+ AppendString(aResult, "Expected EProcessMetaData but got %d and expected size to be %d but got %d", type, numbytes6, size);
+ return;
+ }
+
+ type = config->GetNextItemToDump(size);
+ aPass = (type == SCMConfiguration::EThreadsSvrStack ) && (size == numbytes4);
+
+ if(!aPass)
+ {
+ delete config;
+ AppendString(aResult, "Expected EThreadsSvrStack but got %d and expected size to be %d but got %d", type, numbytes4, size);
+ return;
+ }
+
+ type = config->GetNextItemToDump(size);
+ aPass = (type == SCMConfiguration::ECrashedThreadMetaData ) && (size == numbytes5);
+
+ if(!aPass)
+ {
+ delete config;
+ AppendString(aResult, "Expected ECrashedThreadMetaData but got %d and expected size to be %d but got %d", type, numbytes5, size);
+ return;
+ }
+
+ //if we get here, test has passed
+ aResult.Zero();
+ aResult.SetLength(50);
+ AppendString(aResult, "TestConfigInsertL passed");
+ aPass = ETrue;
+
+
+ delete config;
+ }*/
+
+//eof d_crashdriver_ldd.cpp
+
+
+
+
+
+
+
+