diff -r 000000000000 -r c6b0df440bee dbgsrv/coredumpserver/test/crashapps/src/d_crashdriver_ldd.cpp --- /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 +//#include + +/** + * 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<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 + + + + + + + +