--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dbgsrv/coredumpserver/test/automatictests/tcds_kernel/src/cds/t_process_crash.cpp Tue Mar 02 10:33:16 2010 +0530
@@ -0,0 +1,2792 @@
+// Copyright (c) 2008-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:
+//
+
+/**
+ @file t_process_crash.cpp
+ @internalTechnology
+*/
+
+#include <bautils.h>
+
+#include "t_process_crash.h"
+
+using namespace Debug;
+
+//Names of functions to be tested - referenced from script file
+_LIT(KProcessCrashNewL, "NewL");
+_LIT(KReadCrashInfo, "ReadCrashInfo");
+_LIT(KDeleteAllCrash, "DeleteAllCrashes");
+_LIT(KLoadPlugins, "LoadPlugins");
+_LIT(KUnLoadPlugins, "UnLoadPlugins");
+_LIT(KConfigurePlugins, "ConfigurePlugins");
+_LIT(KConfigureSCMZeroPriority, "ConfigureSCMZeroPriority");
+_LIT(KCheckMultipleCrashes, "CheckMultipleCrashes");
+_LIT(KValidateSingleELFFile, "ValidateSingleELFFile");
+_LIT(KValidateMultipleSELFFile, "ValidateMultipleSELFFile");
+_LIT(KValidateSelfCPUId, "ValidateSelfCPUID");
+_LIT(KValidateHeapSELFFile, "ValidateHeapSELFFile");
+_LIT(KValidateTraceSELFFile, "ValidateTraceSELFFile");
+_LIT(KPerformanceMeasureSELFFile, "PerformanceMeasureSELFFile");
+_LIT(KValidateCorruptCrash, "ValidateCorruptCrash");
+_LIT(KValidateAsyncProcessCrashLog, "ValidateAsyncProcessCrashLog");
+_LIT(KValidateAsyncProcessAndLiveCrash, "ValidateAsyncProcessAndLiveCrash");
+
+//list of exception to check for
+enum TCheckExecption
+ {
+ ETestDataAbort = 24
+ };
+
+//Max String Read out from the SELF file String scetion
+const TInt KMaxStringLength = 200;
+
+//Minimum amount of crashes we need for multi crash tests
+const TInt KMinimumAcceptableCrashNumber = 2;
+
+// crash type
+enum TCrashType
+ {ECrashException, ECrashKill};
+
+/**
+ * Constructor for test wrapper
+ */
+CProcessCrashWrapper::CProcessCrashWrapper()
+ {
+ }
+
+/**
+ * Destructor
+ */
+CProcessCrashWrapper::~CProcessCrashWrapper()
+ {
+ iCrashList.ResetAndDestroy();
+ iCoreDumpSession.Disconnect();
+ iFsSession.Close();
+ iThreadCrashed.Close();
+ }
+
+/**
+ * Two phase constructor for CProcessCrashWrapper
+ * @return CProcessCrashWrapper object
+ * @leave
+ */
+CProcessCrashWrapper* CProcessCrashWrapper::NewL()
+ {
+ CProcessCrashWrapper* ret = new (ELeave) CProcessCrashWrapper();
+ CleanupStack::PushL(ret);
+ ret->ConstructL();
+ CleanupStack::Pop(ret);
+ return ret;
+ }
+
+/**
+ * Safe construction
+ * @leave
+ */
+void CProcessCrashWrapper::ConstructL()
+ {
+ User::LeaveIfError(iFsSession.Connect());
+ iFsSession.SetSessionPath(KDir);
+ }
+
+/**
+ * Assign the object
+ *
+ * @param aObject TAny* to the object to test
+ * @leave
+ */
+void CProcessCrashWrapper::SetObjectL(TAny* aObject)
+ {}
+
+/**
+ * Runs a test preamble
+ */
+void CProcessCrashWrapper::PrepareTestL()
+ {
+ SetBlockResult(EPass);
+
+ //Delete any crash files from previous tests
+ TBuf<KMaxFileName> name;
+ name.Append(KDir);
+ name.Append(KCrashWildCard);
+ BaflUtils::DeleteFile(iFsSession, name);
+ }
+
+/**
+ * Handle a command invoked from the script
+ *
+ * @param aCommand Is the name of the command
+ * for a TBuf
+ * @param aSection Is the .ini file section where parameters to the command
+ * are located
+ * @param aAsyncErrorIndex Is used by the TEF Block framework to handle
+ * asynchronous commands.
+ */
+
+TBool CProcessCrashWrapper::DoCommandL(const TTEFFunction& aCommand,
+ const TTEFSectionName& aSection, const TInt aAsyncErrorIndex)
+ {
+
+ //__UHEAP_MARK;
+
+ PrepareTestL();
+
+ if (KProcessCrashNewL() == aCommand)
+ {
+ DoCmdNewL();
+ }
+ else if (KReadCrashInfo() == aCommand)
+ {
+ DoCmdReadCrashInfoL();
+ }
+ else if (KCheckMultipleCrashes() == aCommand)
+ {
+ DoCmdCheckMultipleCrashesL();
+ }
+ else if (KDeleteAllCrash() == aCommand)
+ {
+ DoCmdDeleteAllCrashL();
+ }
+ else if (KLoadPlugins() == aCommand)
+ {
+ DoCmdLoadPluginsL();
+ }
+ else if (KUnLoadPlugins() == aCommand)
+ {
+ DoCmdUnLoadPluginsL();
+ }
+ else if (KConfigurePlugins() == aCommand)
+ {
+ DoCmdConfigurePluginsL(KCrashFileName);
+ }
+ else if (KConfigureSCMZeroPriority() == aCommand)
+ {
+ DoCmdConfigureSCMZeroPriorityL();
+ }
+ else if (KValidateSingleELFFile() == aCommand)
+ {
+ DoCmdValidateSingleELFFileL();
+ }
+ else if (KValidateMultipleSELFFile() == aCommand)
+ {
+ DoCmdValidateMultipleELFFileL();
+ }
+ else if (KValidateSelfCPUId() == aCommand)
+ {
+ DoCmdValidateCpuIDL();
+ }
+ else if (KValidateHeapSELFFile() == aCommand)
+ {
+ DoCmdValidateHeapSELFFileL();
+ }
+ else if (KValidateTraceSELFFile() == aCommand)
+ {
+ DoCmdValidateTraceSELFFileL();
+ }
+ else if (KPerformanceMeasureSELFFile() == aCommand)
+ {
+ DoCmdPerformanceMeasureSELFFileL();
+ }
+ else if (KValidateCorruptCrash() == aCommand)
+ {
+ DoCmdValidateCorruptCrashL();
+ }
+ else if (KValidateAsyncProcessCrashLog() == aCommand)
+ {
+ DoCmdValidateAsyncProcessCrashLogL();
+ }
+ else if (KValidateAsyncProcessAndLiveCrash() == aCommand)
+ {
+ DoCmdValidateAsyncProcessAndLiveCrashCrashLogL(aSection);
+ }
+ else
+ {
+ INFO_PRINTF1(_L("NOT ** Inside Command"));
+ return EFalse;
+ }
+
+ //__UHEAP_MARKEND;
+
+ return ETrue;
+ }
+
+/**
+ * The initailization function wherein the sessions to Core Dump Server is established
+ */
+void CProcessCrashWrapper::DoCmdNewL()
+ {
+ INFO_PRINTF1(_L("CProcessCrashWrapper::DoCmdNewL"));
+
+ TInt err = iCoreDumpSession.Connect();
+ if (err != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::DoCmdNewL: iCoreDumpSession->Connect() failed!, err:%d\n"),
+ err);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+
+ }
+
+/**
+ * Reads all the crash information present in the flash
+ */
+void CProcessCrashWrapper::DoCmdReadCrashInfoL()
+ {
+ INFO_PRINTF1(_L("CProcessCrashWrapper:: DoCmdReadCrashInfoL\n"));
+
+ //Do list all the Crash Information here
+ TRAPD(err, iCoreDumpSession.ListCrashesInFlashL(iCrashList));
+ if (err != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::DoCmdReadCrashInfoL: Could not read Crashes in the Flash! err:%d\n"),
+ err);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+
+ INFO_PRINTF2(_L("Number of crash information present: %d"),
+ iCrashList.Count());
+
+ for (TInt i = 0; i < iCrashList.Count(); i++)
+ {
+ INFO_PRINTF3(_L("Crash no: %d, CrashId %d"), i, iCrashList[i]->iCrashId);
+ INFO_PRINTF3(_L("Crash no: %d, Type %ld"), i, iCrashList[i]->iType);
+ INFO_PRINTF3(_L("Crash no: %d, Time %ld"), i, iCrashList[i]->iTime);
+ INFO_PRINTF3(_L("Crash no: %d, Thread ID %ld"), i, iCrashList[i]->iTid);
+ }
+ }
+
+/**
+ * Test case specific to DT-coredump-monitor-010
+ * Reads all the crash information present
+ * Checks for exactly four crashed present
+ * Process the crash without any plugins
+ */
+void CProcessCrashWrapper::DoCmdCheckMultipleCrashesL()
+ {
+ INFO_PRINTF1(_L("CProcessCrashWrapper:: DoCmdCheckMultipleCrashesL"));
+
+ //reads all the crash information present in the flash
+ DoCmdReadCrashInfoL();
+
+ //check for exactly four crashes present in the flash
+ if (iCrashList.Count() < KMinimumAcceptableCrashNumber)
+ {
+ ERR_PRINTF1(_L("CProcessCrashWrapper::DoCmdCheckMultipleCrashesL Could not find multiple crashes"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ INFO_PRINTF1(_L("Verified that there are multiple crashes present"));
+ INFO_PRINTF1(_L("CProcessCrashWrapper:: Procesing the crashes!!!"));
+
+ for (TInt i = 0; i < iCrashList.Count(); i++)
+ {
+ //process teh crash log for each of the crashes present
+ TRAPD(error, iCoreDumpSession.ProcessCrashLogL(iCrashList[i]->iCrashId));
+ if (error != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ProcessCrashLogL: Could not process crash! err:%d\n"),
+ error);
+ SetBlockResult(EFail);
+ User::Leave(error);
+ }
+ }
+ }
+
+/**
+ * Deletes all crashes in the flash
+ * Always called after Reading all crash information present
+ * by CProcessCrashWrapper::DoCmdReadCrashInfoL()
+ */
+void CProcessCrashWrapper::DoCmdDeleteAllCrashL()
+ {
+ INFO_PRINTF1(_L("CProcessCrashWrapper:: DoCmdDeleteAllCrashL deleting all the crashes"));
+
+ TRAPD(err, iCoreDumpSession.DeleteCrashPartitionL());
+ if (err != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::DoCmdDeleteAllCrashL: Could not delete crash! err:%d\n"),
+ err);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+
+ INFO_PRINTF1(_L("Successfully deleted all the crashes"));
+ }
+
+/**
+ * Loads the SELF Formatter and the File Writer plugin
+ */
+void CProcessCrashWrapper::DoCmdLoadPluginsL()
+ {
+ INFO_PRINTF1(_L("CProcessCrashWrapperloading SELF Formatter and File Writer!!!"));
+
+ TPluginRequest loadSELFReq;
+ loadSELFReq.iPluginType = TPluginRequest::EFormatter;
+ loadSELFReq.iLoad = ETrue;
+ loadSELFReq.iUid = KUidELFFormatterV2;
+
+ TPluginRequest loadWriterReq;
+ loadWriterReq.iPluginType = TPluginRequest::EWriter;
+ loadWriterReq.iLoad = ETrue;
+ loadWriterReq.iUid = KUidFileWriter;
+
+ // loading Symbian ELF formatter
+ TRAPD(ret, iCoreDumpSession.PluginRequestL(loadSELFReq));
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::DoCmdLoadPluginsL: Could not load SELF plugin!, err:%d\n"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ // loading Symbian File writer
+ TRAP(ret, iCoreDumpSession.PluginRequestL(loadWriterReq));
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::DoCmdLoadPluginsL: Could not load writer plugin!, err:%d\n"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ //intend to check for the loaded SELF formatter and File Writer
+ RPluginList pluginLists;
+ CleanupClosePushL(pluginLists);
+
+ TRAP(ret, iCoreDumpSession.GetPluginListL(pluginLists));
+
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::DoCmdLoadPluginsL: Could not get plugin list!, err:%d\n"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ //Now we look through the list, until we find our plugin, its a fail
+
+ for (TInt i = 0; i < pluginLists.Count(); i++)
+ {
+ if (pluginLists[i].iUid == KUidELFFormatterV2 && !(pluginLists[i].iLoaded))
+ {
+ ERR_PRINTF1(
+ _L("SELF Plugin Not loaded !\n"));
+ SetBlockResult(EFail);
+ User::Leave(KErrNotFound);
+ }
+ }
+
+ for (TInt i = 0; i < pluginLists.Count(); i++)
+ {
+ if (pluginLists[i].iUid == KUidFileWriter && !(pluginLists[i].iLoaded))
+ {
+ ERR_PRINTF1(
+ _L("Writer Plugin Not loaded !\n"));
+ SetBlockResult(EFail);
+ User::Leave(KErrNotFound);
+ }
+ }
+
+ INFO_PRINTF1(_L("SELF Formatter and File Writer loaded successfully \n"));
+ CleanupStack::PopAndDestroy();//pluginLists
+ }
+
+/**
+ * UnLoads the SELF Formatter and the File Writer plugin
+ */
+void CProcessCrashWrapper::DoCmdUnLoadPluginsL()
+ {
+ INFO_PRINTF1(_L("CProcessCrashWrapper DoCmdUnLoadPluginsL unloading SELF Formatter and File Writer"));
+
+ TPluginRequest unloadSELFReq;
+ unloadSELFReq.iPluginType = TPluginRequest::EFormatter;
+ unloadSELFReq.iLoad = EFalse;
+ unloadSELFReq.iUid = KUidELFFormatterV2;
+
+ TPluginRequest unloadWriterReq;
+ unloadWriterReq.iPluginType = TPluginRequest::EWriter;
+ unloadWriterReq.iLoad = EFalse;
+ unloadWriterReq.iUid = KUidFileWriter;
+
+ TRAPD(ret, iCoreDumpSession.PluginRequestL(unloadSELFReq));
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::DoCmdLoadPluginsL: Could not unload SELF plugin!, err:%d\n"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ TRAPD(err, iCoreDumpSession.PluginRequestL(unloadWriterReq));
+ if (err != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::DoCmdLoadPluginsL: Could not unload writer plugin!, err:%d\n"),
+ err);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+
+ INFO_PRINTF1(_L("Successful unloading SELF Formatter and File Writer"));
+ }
+
+/**
+ * Configuring the SCM to have minimal information the flash
+ * Done inorder to incorporate more crashes in the flash
+ */
+void CProcessCrashWrapper::DoCmdConfigureSCMZeroPriorityL()
+ {
+ INFO_PRINTF1(_L("CProcessCrashWrapper::DoCmdConfigureSCMZeroPriority setting all SCM configurations to zero priority"));
+
+ TInt noConfigParams = 0;
+ // this will ultimateley read the config
+ TRAPD(err, noConfigParams = iCoreDumpSession.GetNumberConfigParametersL());
+ if(err != KErrNone)
+ {
+ ERR_PRINTF1(_L("COULD not read number of config params"));
+ User::Leave(KErrGeneral);
+ SetBlockResult(EFail);
+ }
+ else
+ {
+
+ INFO_PRINTF2(_L("CProcessCrashWrapper::DoCmdConfigureSCMZeroPriority found %d config params"), noConfigParams);
+ for (TInt i = 0; i < noConfigParams; i++)
+ {
+ TInt priority = 1;//setting priority to one for all
+
+ COptionConfig* conf = iCoreDumpSession.GetConfigParameterL(i);
+ CleanupStack::PushL(conf);
+
+ if (conf->Source()== COptionConfig::ESCMConfig)
+ {
+ TConfigItem::TSCMDataType dataType = (TConfigItem::TSCMDataType) conf->Instance();
+
+// INFO_PRINTF3(_L("CProcessCrashWrapper::DoCmdConfigureSCMZeroPriority found config data type %d priority %d")
+// , dataType, conf->Value());
+
+ if(dataType == TConfigItem::EKernelHeap || dataType == TConfigItem::EThreadsUsrStack || dataType == TConfigItem::EThreadsSvrStack )
+ {
+ priority = 0;
+ INFO_PRINTF3(_L("CProcessCrashWrapper::DoCmdConfigureSCMZeroPriority modifying data type %d with priority %d")
+ , dataType, priority);
+ }
+
+ // set the value
+ conf->Value(priority);
+ TRAP(err, iCoreDumpSession.SetConfigParameterL(*conf));
+ if (err != KErrNone)
+ {
+ ERR_PRINTF3(
+ _L("CProcessCrashWrapper::DoCmdConfigureSCMZeroPriority for SCM Configurations failed error code is %d changing param for run no: %d"),
+ err, i);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+ }
+
+ CleanupStack::PopAndDestroy(conf);
+ }
+
+ }
+
+ INFO_PRINTF1(_L("SCM Configuration successful"));
+ }
+
+/**
+ * Tests that the SELF plugin can handle invalid configuration
+ */
+void CProcessCrashWrapper::DoCmdConfigureSELFPluginWithInvalidnessL()
+ {
+ INFO_PRINTF1(_L("CProcessCrashWrapper::DoCmdConfigureSELFPluginWithInvalidnessL configuring the Core dump server and File Writer plugin"));
+
+ TUint numConfigParams = 0;
+ TRAPD(err, numConfigParams = iCoreDumpSession.GetNumberConfigParametersL());
+ if(KErrNone != err)
+ {
+ ERR_PRINTF2(_L("Unable to get the number of config parameters. Returned %d"), err);
+ SetBlockResult(EFail);
+ return;
+ }
+
+ INFO_PRINTF2(_L("Found %d params"), numConfigParams);
+
+ for (TInt i = 0; i < numConfigParams; i++)
+ {
+ COptionConfig* conf;
+ conf = iCoreDumpSession.GetConfigParameterL(i);
+ CleanupStack::PushL(conf);
+
+ if(conf->Source() == COptionConfig::EFormatterPlugin)
+ {
+ //Try to configure with the old invalidity
+ switch(conf->Type())
+ {
+ }
+ }
+
+ CleanupStack::PopAndDestroy(conf);
+
+ }
+
+ }
+
+/**
+ * Configuring the Core Dump Server and the File Writer
+ * @param aSELFFileName is the SELF File Name configuring the File Writer plugin
+ */
+void CProcessCrashWrapper::DoCmdConfigurePluginsL(const TDesC& aSELFFileName)
+ {
+ INFO_PRINTF1(_L("CProcessCrashWrapper DoCmdConfigurePlugins configuring the Core dump server and File Writer plugin"));
+
+ //Configuring the Core Dump Server
+ TRAPD(ret, DoConfigureL(2, KCDSUid.iUid, COptionConfig::ECoreDumpServer,
+ COptionConfig::ETUInt, KPostCrashEventActionPrompt, 1, KNullDesC,
+ 4, KNullDesC, 0));
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::DoConfigureL for CDS Error %d changing param"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ //Configuring the file writer plugin to have a specified crash file name
+ TRAPD(err, DoConfigureL((TInt)(CCrashDataSave::ECoreFilePath),
+ KUidFileWriter.iUid, COptionConfig::EWriterPlugin,
+ COptionConfig::ETFileName, KFilePathPrompt, 1, KNullDesC, 0,
+ aSELFFileName, 0));
+
+ if (err != KErrNone)
+ {
+ ERR_PRINTF2(_L("CProcessCrashWrapper::DoConfigureL for File Writer Error %d changing param"),
+ err);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+
+ }
+/**
+ * @return void
+ * @param aIndex Internal index to the component that owns the object
+ * @param aUID UID of the component that owns the object
+ * @param aSource Type of component that owns the object
+ * @param aType Type of parameter
+ * @param aPrompt Prompt to present to user
+ * @param aNumOptions Number of options that the parameter can be set to. Only applies if type is ETMultiEntryEnum.
+ * @param aOptions Comma separated list of options. Applies to ETMultiEntryEnum and ETBool
+ * @param aVal Integer value. Applies to ETInt, ETUInt, ETBool
+ * @param aStrValue String value. Applies to ETString, ETFileName, ETMultiEntry, ETBool
+ */
+void CProcessCrashWrapper::DoConfigureL(const TUint32& aIndex,
+ const TUint32& aUID, const COptionConfig::TParameterSource& aSource,
+ const COptionConfig::TOptionType& aType, const TDesC& aPrompt,
+ const TUint32& aNumOptions, const TDesC& aOptions, const TInt32& aVal,
+ const TDesC& aStrValue, const TUint aInstance)
+ {
+ COptionConfig * config;
+
+ config = COptionConfig::NewL(aIndex, aUID, aSource, aType, aPrompt,
+ aNumOptions, aOptions, aVal, aStrValue);
+
+ CleanupStack::PushL(config);
+
+ config->Instance(aInstance);
+
+ //Configure now...
+ iCoreDumpSession.SetConfigParameterL(*config);
+
+ CleanupStack::PopAndDestroy(config);
+ }
+
+void CProcessCrashWrapper::DoCmdValidateCpuIDL()
+ {
+ LOG_MSG(_L("CProcessCrashWrapper::DoCmdValidateCpuIDL()"));
+
+ //expects one crash information to be present in the flash otherwise complain
+ if (iCrashList.Count() != 1)
+ {
+ ERR_PRINTF1(_L("More than one crash information present"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ GenerateElfFileL(iCrashList[0]->iCrashId);
+
+ //open the SELF File for processing
+ TInt err = iSELFFile.Open(iFsSession, iSELFFileName, EFileStream|EFileRead);
+ if (err != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ProcessELFFile Error opening the SELF File %d"),
+ err);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+
+ //Parse start of ELF file
+ ValidateHeaderELFFileL();
+ ValidateProgramHeaderELFFileL();
+ ValidateSymInfoSectionELFFileL();
+
+ //Validate the CPU Id
+ RDebug::Printf("Looking at CPU ID");
+ ValidateThreadInfoSectionELFFileL(ETrue, KThreadKernelCrash, ETrue);
+
+ TBuf<KMaxFileName> fileName;
+ iSELFFile.Name(fileName);
+
+ INFO_PRINTF2(_L("Finished with %S So im sharking it"), &fileName);
+ iSELFFile.Close();
+ iFsSession.Delete(fileName);
+ }
+/**
+ * Generate the SELF File and search for the generated file
+ * aCrashId = crash id
+ * aTiming (default value is False) determines the timing measurement
+ */
+void CProcessCrashWrapper::GenerateElfFileL(TUint aCrashId, TBool aTiming)
+ {
+ if(aTiming) HelpStartTestTimer();
+
+ //process the crash with configured SELF formatter and file writer
+ TRAPD(ret, iCoreDumpSession.ProcessCrashLogL(aCrashId));
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(_L("CProcessCrashWrapper::ProcessCrashLogL for CDS Error %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ MonitorProgressL();
+
+ if(aTiming) HelpStopTestTimer();
+
+ INFO_PRINTF1(_L("ProcessCrashLogL Successful"));
+
+ //Use wildcard utilities to search for the SELF FIle Created
+ TBuf<32> buf;
+ buf = KDir;
+ TUidType uid1;
+ TUidType uid2(uid1.MostDerived());
+
+ CFindFileByType* obj = new(ELeave) CFindFileByType(iFsSession);
+ CleanupStack::PushL(obj);
+
+ ret = obj->FindFirst(KCrashWildCard, buf, uid2);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("GenerateElfFileL Error finding the SELF File %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ iSELFFileName = obj->Entry().iName;
+
+ CleanupStack::PopAndDestroy(); //CFindFileByType
+ INFO_PRINTF2(_L("The SELF File Found is E:\\%S "), &iSELFFileName);
+ }
+
+/**
+ * Generate the SELF File and Validate the Symbian INFO and executable sections
+ */
+void CProcessCrashWrapper::DoCmdValidateSingleELFFileL()
+ {
+ INFO_PRINTF1(_L("CProcessCrashWrapper DoCmdSingleValidateELFFileL"));
+
+ //expects one crash information to be present in the flash otherwise complain
+ if (iCrashList.Count() != 1)
+ {
+ ERR_PRINTF1(_L("More than one crash information present"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ //generate the SELF File by calling ProcessCrashLogL
+ GenerateElfFileL(iCrashList[0]->iCrashId);
+
+ //open the SELF File for processing
+ TInt err = iSELFFile.Open(iFsSession, iSELFFileName, EFileStream|EFileRead);
+ if (err != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ProcessELFFile Error opening the SELF File %d"),
+ err);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+
+ //validate the SELF Header Format
+ ValidateHeaderELFFileL();
+
+ //validate the Program Header and store information about the string section Sections
+ ValidateProgramHeaderELFFileL();
+
+ //validate the Symbian Info section
+ ValidateSymInfoSectionELFFileL();
+
+ //validate Thread name that crashed
+ ValidateThreadInfoSectionELFFileL(EFalse, KThreadKernelCrash, ETrue);
+
+ //do the necessary clean up
+ CleanupMethod(iSELFFileName);
+ }
+
+/**
+ * Process the crash log using the asynchrnous API ProcessCrashLog
+ */
+void CProcessCrashWrapper::DoCmdValidateAsyncProcessCrashLogL()
+ {
+
+ INFO_PRINTF1(_L("CProcessCrashWrapper DoCmdValidateAsyncProcessCrashLogL"));
+
+ //expects one crash information to be present in the flash otherwise complain
+ if (iCrashList.Count() != 1)
+ {
+ ERR_PRINTF1(_L("More than one crash information present"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ //create the Active Object to process the crash log asynchrnously
+ CAsyncProcessCrash* asyncProcessCrash = CAsyncProcessCrash::NewL(this);
+ CleanupStack::PushL(asyncProcessCrash);
+
+ asyncProcessCrash->IssueProcessCrashRequest(iCrashList[0]->iCrashId);
+
+ CActiveScheduler::Start();// Doesn’t return until it is explicitly
+
+ RDebug::Printf("After CActiveScheduler::Start");
+ CleanupStack::PopAndDestroy();
+ INFO_PRINTF1(_L("DoCmdValidateAsyncProcessCrashLogL Successful with processing the crash log asynchrnouly"));
+
+ }
+
+/**
+ * Process the crash log using the asynchrnous API ProcessCrashLog whilst a user side crash
+ */
+void CProcessCrashWrapper::DoCmdValidateAsyncProcessAndLiveCrashCrashLogL(const TDesC& aSection)
+ {
+
+ INFO_PRINTF1(_L("CProcessCrashWrapper DoCmdValidateAsyncProcessAndLiveCrashCrashLogL"));
+
+ //expects one crash information to be present in the flash otherwise complain
+ if (iCrashList.Count() != 1)
+ {
+ ERR_PRINTF1(_L("More than one crash information present"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ //generate a live crash using the test application crashapp.exe
+ GenerateLiveCrashL(aSection);
+
+ //start processing the crash log in the flash
+ TRequestStatus asyncSystemCrash;
+ iCoreDumpSession.ProcessCrashLog( (iCrashList[0]->iCrashId), asyncSystemCrash);
+ User::WaitForRequest(asyncSystemCrash);
+
+ //This user after is to ensure the live crash has completed before analysis
+ User::After(3000000);
+
+ //process the two SELF files created
+ DoProcessSELFLiveandKernelL();
+
+ }
+
+/**
+ * Generates a user side crash using the crashapp
+ */
+void CProcessCrashWrapper::GenerateLiveCrashL(const TDesC& aSection)
+ {
+
+ TPtrC crashAppParam;
+ //read from the INI for crashapp paramemters
+ if(!GetStringFromConfig(aSection, KTe_CrashAppParam, crashAppParam))
+ {
+ ERR_PRINTF1(_L("Failed to get data from ini file"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ INFO_PRINTF2(_L("The CrashApp Parameters are: crashapp %S, "), &crashAppParam); // print it to check
+ //Start the process that we intend to crash....
+ RProcess crashProcess;
+ CleanupClosePushL(crashProcess);
+
+ TInt ret = crashProcess.Create( KCrashAppFileName, crashAppParam);
+ if(ret != KErrNone)
+ {
+ INFO_PRINTF2(_L("Error %d from RProcess .Create(z:\\sys\\bin\\crashapp.exe)/n"), ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ INFO_PRINTF1(_L("Started userside crash app"));
+
+ // Observe the process and wait for a crash
+ TRAP(ret, iCoreDumpSession.ObservationRequestL( KCrashAppFileName, KCrashAppFileName, ETrue) );
+ if(ret != KErrNone)
+ {
+ INFO_PRINTF2(_L("Error %d iCoreDumpSession.ObservationRequestL(z:\\sys\\bin\\crashapp.exe)\n"), ret);
+ SetBlockResult(EFail);
+ User::Leave( ret );
+ }
+
+ //start the crash process which should go ahead a create a crash
+ crashProcess.Resume();
+ CleanupStack::PopAndDestroy(&crashProcess); //this is for crashProcess
+
+ }
+
+/**
+ * Complete the processing the SELF file generated after the async ProcessCrashLog
+ * called from RunL
+ */
+void CProcessCrashWrapper::ProcessSELFFileCreatedL()
+ {
+
+ INFO_PRINTF1(_L("CProcessCrashWrapper ProcessSELFFileCreatedL called after RunL"));
+
+ //Use wildcard utilities to search for the SELF FIle Created
+ TBuf<32> buf;
+ buf = KDir;
+ TUidType uid1;
+ TUidType uid2(uid1.MostDerived());
+
+ CFindFileByType* obj = new(ELeave) CFindFileByType(iFsSession);
+ CleanupStack::PushL(obj);
+
+ TInt ret = obj->FindFirst(KCrashWildCard, buf, uid2);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(_L("GenerateElfFileL Error finding the SELF File %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ iSELFFileName = obj->Entry().iName;
+ CleanupStack::PopAndDestroy();//CFindFileByType* obj
+
+ INFO_PRINTF2(_L("The SELF File Found is E:\\%S "), &iSELFFileName);
+
+ //open the SELF File for processing
+ TInt err = iSELFFile.Open(iFsSession, iSELFFileName, EFileStream|EFileRead);
+ if (err != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ProcessSELFFileCreatedL Error opening the SELF File %d"),
+ err);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+
+ //validate the SELF Header Format
+ ValidateHeaderELFFileL();
+
+ //validate the Program Header and store information about the string section Sections
+ ValidateProgramHeaderELFFileL();
+
+ //validate the Symbian Info section
+ ValidateSymInfoSectionELFFileL();
+
+ //validate Thread name that crashed
+ ValidateThreadInfoSectionELFFileL(EFalse, KThreadKernelCrash, ETrue);
+
+ //do the necessary clean up
+ CleanupMethod(iSELFFileName);
+
+ }
+
+/**
+ * Process the two SELF files created for user and kernel side crashes
+ */
+void CProcessCrashWrapper::DoProcessSELFLiveandKernelL()
+ {
+ INFO_PRINTF1(_L("CProcessCrashWrapper DoProcessSELFLiveandKernel about process user and kernel crashes"));
+
+ TBool systemcrash = EFalse;
+
+ //Use wildcard utilities to search for the two SELF File Created
+ TBuf<32> buf;
+ buf = KDir;
+ TUidType uid1;
+ TUidType uid2(uid1.MostDerived());
+
+ CFindFileByType* obj = new(ELeave) CFindFileByType(iFsSession);
+ CleanupStack::PushL(obj);
+
+ TInt ret = obj->FindFirst(KCrashWildCard, buf, uid2);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("DoProcessSELFLiveandKernelL Error finding the SELF File %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ iSELFFileName = obj->Entry().iName;
+ INFO_PRINTF2(_L("The SELF File Found is E:\\%S "), &iSELFFileName);
+
+ ret = iSELFFile.Open(iFsSession, iSELFFileName, EFileStream|EFileRead);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("DoProcessSELFLiveandKernelL Error opening the SELF File %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ //validate the SELF Header Format
+ ValidateHeaderELFFileL();
+
+ //validate the Program Header and store information about the string section Sections
+ ValidateProgramHeaderELFFileL();
+
+ //validate the Symbian Info section
+ ValidateSymInfoSectionELFFileL();
+
+ //validate the Register Info Section also verifies the CPSR to check on the type of the crash
+ ValidateRegisterInfoSectionELFFileL();
+
+ if(iSystemCrash)//if it is a System Crash
+ {
+ //checking this SELF file for the kernel crash
+ ValidateThreadInfoSectionELFFileL(EFalse, KThreadKernelCrash, ETrue);
+ }
+ else
+ {
+ //checking this one for user crash
+ ValidateThreadInfoSectionELFFileL(EFalse, KThreadUserCrash, ETrue);
+ }
+
+ systemcrash = iSystemCrash;
+ //do the necessary clean up
+ CleanupMethod(iSELFFileName);
+
+ //Find the next SELF file
+ ret = obj->FindNext();
+
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF1(
+ _L("DoProcessSELFLiveandKernelL Expecting Two SELF files to be created"));
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ iSELFFileName = obj->Entry().iName;
+ INFO_PRINTF2(_L("The SELF File Found is E:\\%S "), &iSELFFileName);
+
+ CleanupStack::PopAndDestroy(); //CFindFileByType
+
+ //open the SELF File for processing
+ ret = iSELFFile.Open(iFsSession, iSELFFileName, EFileStream|EFileRead);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("DoProcessSELFLiveandKernelL Error opening the SELF File %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ //validate the SELF Header Format
+ ValidateHeaderELFFileL();
+
+ //validate the Program Header and store information about the string section Sections
+ ValidateProgramHeaderELFFileL();
+
+ //validate the Symbian Info section
+ ValidateSymInfoSectionELFFileL();
+
+ //validate the Register Info Section also verifies the CPSR to check on the type of the crash
+ ValidateRegisterInfoSectionELFFileL();
+
+ if(iSystemCrash == systemcrash)
+ {
+ ERR_PRINTF1( _L("Expecting to have two different types of crashes one User side and the other one as System Crash"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ if(iSystemCrash)//if it is a System Crash
+ {
+ //checking this SELF file for the kernel crash
+ ValidateThreadInfoSectionELFFileL(EFalse, KThreadKernelCrash, ETrue);
+ }
+ else
+ {
+ //checking this one for user crash
+ ValidateThreadInfoSectionELFFileL(EFalse, KThreadUserCrash, ETrue);
+ }
+
+ //do the necessary clean up
+ CleanupMethod(iSELFFileName);
+
+ }
+/**
+ * Generate multiple SELF File and Validate the Symbian INFO and executable sections
+ */
+void CProcessCrashWrapper::DoCmdValidateMultipleELFFileL()
+ {
+ INFO_PRINTF1(_L("CProcessCrashWrapper::DoCmdValidateMultipleELFFileL parsing multiple SELF files"));
+
+ //expects MULTIPLECRASHNUMBERCHECK to be present in the flash otherwise complain
+ if (iCrashList.Count() < KMinimumAcceptableCrashNumber)
+ {
+ ERR_PRINTF1(_L("Did not find multiple crashes"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ for (TInt i = 0; i < iCrashList.Count(); i++)
+ {
+ //generate the SELF File(s) by calling ProcessCrashLogL
+ GenerateElfFileL(iCrashList[i]->iCrashId);
+
+ TInt err = iSELFFile.Open(iFsSession, iSELFFileName, EFileStream|EFileRead);
+ if (err != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ProcessELFFile Error opening the SELF File %d"),
+ err);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+
+ //validate the SELF Header Format
+ ValidateHeaderELFFileL();
+
+ //validate the Program Header and store information about the string section Sections
+ ValidateProgramHeaderELFFileL();
+
+ //validate the Symbian Info section
+ ValidateSymInfoSectionELFFileL();
+
+ //validate Thread name that crashed
+ ValidateThreadInfoSectionELFFileL(EFalse, KThreadKernelCrash, ETrue);
+
+ //do the necessary clean up
+ CleanupMethod(iSELFFileName);
+
+ }
+
+/*
+ * code to check on multiple files in the directory and storing them
+ * commented for future reference
+ * RBuf selfname;
+ selfname.CreateL(obj->Entry().iName);
+ selfname.SetMax();
+
+ TBufC<100> selfnamebuffer = obj->Entry().iName;
+ HBufC* selfname = selfnamebuffer.AllocL();
+
+ iArray.Append(selfname);
+
+ INFO_PRINTF2(_L("The SELF File Found is E:\\%S "), &iArray[0]);
+
+ for (TInt i = 0; i < iCrashList.Count() - 1; i++)
+ {
+
+ ret = obj->FindNext();
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::CFindFileByType Error finding the SELF File %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ RBuf selfname2;
+ selfname2.CreateL(obj->Entry().iName);
+ selfname2.SetMax();
+
+ TBufC<100> selfnamebuffer2 = obj->Entry().iName;
+ HBufC* selfname2 = selfnamebuffer2.AllocL();
+
+ iArray.Append(selfname2);// no close
+
+ INFO_PRINTF2(_L("The SELF File Found is E:\\%S "), &iArray[i]);
+ */
+
+ }
+
+/**
+ * Validates the presence of the heap data in the SELF file
+ */
+void CProcessCrashWrapper::DoCmdValidateHeapSELFFileL()
+ {
+ INFO_PRINTF1(_L("\nDoCmdValidateHeapSELFFileL intend to validate the Heap Section of SELF File"));
+
+ //expects one crash information to be present in the flash otherwise complain
+ if (iCrashList.Count() != 1)
+ {
+ ERR_PRINTF1(_L("More than one crash information present"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ /*
+ * POSITIVE TEST CASE
+ * Test for the positive case let the Heap Section be present
+ */
+
+ //configuring the SELF Formatter to have the date segment
+ ConfigureSELF(ETrue, EHeap);
+
+ //generate the SELF File by calling ProcessCrashLogL
+ GenerateElfFileL(iCrashList[0]->iCrashId);
+
+ //open the SELF File for processing
+ TInt err = iSELFFile.Open(iFsSession, iSELFFileName, EFileStream|EFileRead);
+ if (err != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ProcessELFFile Error opening the SELF File %d"),
+ err);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+
+ //validate the SELF Header Format
+ ValidateHeaderELFFileL();
+
+ //validate the Program Header and store information about the string section Sections
+ ValidateProgramHeaderELFFileL();
+
+ //validate the Symbian Info section
+ ValidateSymInfoSectionELFFileL();
+
+ //validate Thread name that crashed
+ ValidateThreadInfoSectionELFFileL(EFalse, KThreadKernelCrash, ETrue);
+
+ //validate the heap section to be present
+ ValidateHeapSectionELFFileL(ETrue);
+
+ //clean up of the generated SELF file
+ iSELFFile.Close();
+ TInt ret = iFsSession.Delete(iSELFFileName);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::SELF File delete returned error %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ INFO_PRINTF1(_L("Validation of the Positive Heap Test Case Successful!!!\n\n"));
+
+ /*
+ * NEGATIVE TEST CASE
+ * Test for the negative test case let the Heap Section be NOT present
+ */
+
+ //configuring the SELF NOT to have data segment/heap
+ ConfigureSELF(EFalse, EHeap);
+
+ //generate the SELF File by calling ProcessCrashLogL
+ GenerateElfFileL(iCrashList[0]->iCrashId);
+
+ //open the SELF File for processing
+ err = iSELFFile.Open(iFsSession, iSELFFileName, EFileStream|EFileRead);
+ if (err != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ProcessELFFile Error opening the SELF File %d"),
+ err);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+
+ //validate the SELF Header Format
+ ValidateHeaderELFFileL();
+
+ //validate the Program Header and store information about the string section Sections
+ ValidateProgramHeaderELFFileL();
+
+ //validate the Symbian Info section
+ ValidateSymInfoSectionELFFileL();
+
+ //validate Thread name that crashed
+ ValidateThreadInfoSectionELFFileL(EFalse, KThreadKernelCrash, ETrue);
+
+ //validate the heap section NOT to be present this time
+ ValidateHeapSectionELFFileL(EFalse);
+
+ //do necessary clean up
+ CleanupMethod(iSELFFileName);
+
+ INFO_PRINTF1(_L("Validation of the Negative Heap Test Case Successful!!!\n\n"));
+ }
+
+/**
+ * Validates the presence of the trace data in the SELF file
+ */
+void CProcessCrashWrapper::DoCmdValidateTraceSELFFileL()
+ {
+ INFO_PRINTF1(_L("\nDoCmdValidateTraceSELFFileL intend to validate the Trace Section of SELF File"));
+
+ //expects one crash information to be present in the flash otherwise complain
+ if (iCrashList.Count() != 1)
+ {
+ ERR_PRINTF1(_L("More than one crash information present"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ /*
+ * POSITIVE TEST CASE
+ * Test for the positive case let the Trace Section be present
+ */
+
+ //configuring the SELF Formatter to have the trace segment
+ ConfigureSELF(ETrue, ETrace);
+
+ //generate the SELF File by calling ProcessCrashLogL
+ GenerateElfFileL(iCrashList[0]->iCrashId);
+
+ //open the SELF File for processing
+ TInt err = iSELFFile.Open(iFsSession, iSELFFileName, EFileStream|EFileRead);
+ if (err != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ProcessELFFile Error opening the SELF File %d"),
+ err);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+
+ //validate the SELF Header Format
+ ValidateHeaderELFFileL();
+
+ //validate the Program Header and store information about the string section Sections
+ ValidateProgramHeaderELFFileL();
+
+ //validate the Symbian Info section
+ ValidateSymInfoSectionELFFileL();
+
+ //validate Thread name that crashed
+ ValidateThreadInfoSectionELFFileL(EFalse, KThreadKernelCrash, ETrue);
+
+ //validate the trace section to be present
+ ValidateTraceSectionELFFileL(ETrue);
+
+ //clean up of the generated SELF file
+ iSELFFile.Close();
+ TInt ret = iFsSession.Delete(iSELFFileName);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::SELF File delete returned error %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ INFO_PRINTF1(_L("Validation of the Positive Test Case Successful!!!\n\n"));
+
+ /*
+ * NEGATIVE TEST CASE
+ * Test for the negative test case let the Trace Section be NOT present
+ */
+
+ //configuring the SELF NOT to have trace segment
+ ConfigureSELF(EFalse, ETrace);
+
+ //generate the SELF File by calling ProcessCrashLogL
+ GenerateElfFileL(iCrashList[0]->iCrashId);
+
+ //open the SELF File for processing
+ err = iSELFFile.Open(iFsSession, iSELFFileName, EFileStream|EFileRead);
+ if (err != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ProcessELFFile Error opening the SELF File %d"),
+ err);
+ SetBlockResult(EFail);
+ User::Leave(err);
+ }
+
+ //validate the SELF Header Format
+ ValidateHeaderELFFileL();
+
+ //validate the Program Header and store information about the string section Sections
+ ValidateProgramHeaderELFFileL();
+
+ //validate the Symbian Info section
+ ValidateSymInfoSectionELFFileL();
+
+ //validate Thread name that crashed
+ ValidateThreadInfoSectionELFFileL(EFalse, KThreadKernelCrash, ETrue);
+
+ //validate the heap section NOT to be present this time
+ ValidateTraceSectionELFFileL(EFalse);
+
+ //do necessary clean up
+ CleanupMethod(iSELFFileName);
+
+ INFO_PRINTF1(_L("Validation of the Negative Test Case Successful!!!\n\n"));
+
+ }
+
+/**
+ * Benchmark test of SELF files
+ */
+void CProcessCrashWrapper::DoCmdPerformanceMeasureSELFFileL()
+ {
+ INFO_PRINTF1(_L("CProcessCrashWrapper::DoCmdPerformanceMeasureSELFFileL performing Performance measurement on various SELF file(s)"));
+
+ //expects one crash information to be present in the flash otherwise complain
+ if (iCrashList.Count() != 1)
+ {
+ ERR_PRINTF1(_L("More than one crash information present"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ /*
+ * WITH OR WITHOUT HEAP DATA
+ */
+
+ //configuring SELF to have the Heap section
+ ConfigureSELF(ETrue, EHeap);
+
+ //Generate the SELF File keeping a record of the time
+ GenerateElfFileL(iCrashList[0]->iCrashId , ETrue);
+
+ INFO_PRINTF1(_L("SELF File has Heap Data"));
+ ValidatePerformanceELFFile();
+
+ //configuring SELF NOT to have the Heap section
+ ConfigureSELF(EFalse, EHeap);
+
+ //Generate the SELF File keeping a record of the time
+ GenerateElfFileL(iCrashList[0]->iCrashId , ETrue);
+
+ INFO_PRINTF1(_L("SELF File has NO Heap Data"));
+ ValidatePerformanceELFFile();
+
+ /*
+ * WITH OR WITHOUT CODE SEGEMENT
+ */
+
+ //configuring SELF to have the Code Segment
+ ConfigureSELF(ETrue, ECode);
+ //putting back the heap data as well
+ ConfigureSELF(ETrue, EHeap);
+
+ //Generate the SELF File keeping a record of the time
+ GenerateElfFileL(iCrashList[0]->iCrashId , ETrue);
+
+ INFO_PRINTF1(_L("SELF File has Code Segement"));
+ ValidatePerformanceELFFile();
+
+ //configuring SELF NOT to have the Code segment
+ ConfigureSELF(EFalse, ECode);
+
+ //Generate the SELF File keeping a record of the time
+ GenerateElfFileL(iCrashList[0]->iCrashId , ETrue);
+
+ INFO_PRINTF1(_L("SELF File has NO Code Segement"));
+ ValidatePerformanceELFFile();
+
+ /*
+ * WITH OR WITHOUT THREAD SEGEMENT
+ */
+
+ //configuring SELF to have the Thread Segment
+ ConfigureSELF(ETrue, EThread);
+ //putting back the code segement as well
+ ConfigureSELF(ETrue, ECode);
+
+ //Generate the SELF File keeping a record of the time
+ GenerateElfFileL(iCrashList[0]->iCrashId , ETrue);
+
+ INFO_PRINTF1(_L("SELF File has Thread Segement"));
+ ValidatePerformanceELFFile();
+
+ //configuring SELF NOT to have the Thread segment
+ ConfigureSELF(EFalse, EThread);
+
+ //Generate the SELF File keeping a record of the time
+ GenerateElfFileL(iCrashList[0]->iCrashId , ETrue);
+
+ INFO_PRINTF1(_L("SELF File has NO Thread Segement"));
+ ValidatePerformanceELFFile();
+
+ INFO_PRINTF1(_L("Benchmarking of SELF files successful"));
+ }
+
+/**
+ * Validates the Corrupted Crash Information
+ * Part of neagtive test on ProcessCrashLog
+ */
+void CProcessCrashWrapper::DoCmdValidateCorruptCrashL()
+ {
+ LOG_MSG(_L("CProcessCrashWrapper::DoCmdValidateCorruptCrashL() validating the Corrupted Crash"));
+
+ //reads all the crash information present in the flash
+ DoCmdReadCrashInfoL();
+
+ //expects one crash information to be present in the flash otherwise complain
+ if (iCrashList.Count() != 1)
+ {
+ ERR_PRINTF1(_L("More than one crash information present"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ INFO_PRINTF1(_L("Able to read crash log now start processing the crash"));
+
+ TRAPD(error, iCoreDumpSession.ProcessCrashLogL(iCrashList[0]->iCrashId));
+ if (error == KErrCorrupt)
+ {
+ INFO_PRINTF2(_L("Success!!! The crash information is corrupted returns error %d\n"), error);
+ }
+ else
+ {
+ ERR_PRINTF2(
+ _L("Returns error %d which is NOT KErrCorrupt\n"),
+ error);
+ SetBlockResult(EFail);
+ User::Leave(error);
+ }
+ }
+
+/**
+ * Validates the Header Format Elf32_Ehdr for the SELF file
+ */
+void CProcessCrashWrapper::ValidateHeaderELFFileL()
+ {// Elf32_Ehdr
+ INFO_PRINTF1(_L("CProcessCrashWrapper::ValidateHeaderELFFileL validating Elf32_Ehdr"));
+ RDebug::Printf("Validating the ELF file");
+
+ TInt sizeofELFHeader = sizeof(Elf32_Ehdr); //size of Elf32_Ehdr structure
+
+ // allocate buffer Elf32_Ehdr
+ TUint8* SELFHeader = new TUint8[sizeofELFHeader];
+ TPtr8 elfHeaderPointer(SELFHeader, sizeofELFHeader, sizeofELFHeader);
+ CleanupStack::PushL(SELFHeader);
+
+ //read the SELF file for Elf32_Ehdr
+ TInt ret = iSELFFile.Read(0, elfHeaderPointer, sizeofELFHeader);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ValidateHeaderELFFile Error reading the SELF Header Elf32_Ehdr %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+ //
+ Elf32_Ehdr* eh=(Elf32_Ehdr *)SELFHeader;
+
+ //VALIDATE THE Elf32_Ehdr
+
+ if (eh->e_ident[EI_MAG0] !=0x7f || eh->e_ident[EI_MAG1] != 0x45
+ || eh->e_ident[EI_MAG2] !=0x4c || eh->e_ident[EI_MAG3] != 0x46)
+ {
+ // EI_MAG0 to EI_MAG3 - A files' first 4 bytes hold a 'magic number', identifying the file as an ELF object file.
+ ERR_PRINTF1(_L("Error: is not a valid ELF file"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+ if (eh->e_ident[EI_DATA] == 2)
+ {
+ // ELF Header size should be 52 bytes or converted into Big-Endian system 13312
+ if (eh->e_ehsize != 13312)
+ {
+ ERR_PRINTF1(_L("Error: ELF Header contains invalid file typ"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+ // e_ident[EI_DATA] specifies the data encoding of the processor-specific data in the object file.
+ ERR_PRINTF1(_L("Error: Data encoding ELFDATA2MSB (Big-Endian) not supported"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+ if (eh->e_ehsize != 52)
+ {
+ // ELF Header size should be 52 bytes
+ ERR_PRINTF1(_L("Error: ELF Header contains invalid file type"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ //Number of entries in the program header table
+ if ((eh->e_phnum) == 0)
+ {
+ ERR_PRINTF1(_L("Error: ELF Header contains zero program headers"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ //store number of program header entries
+ iPHEntries = eh->e_phnum;
+ INFO_PRINTF2(_L("Program header entries:%d"), iPHEntries);
+
+ //Offset in bytes from the start of the file to the section header table
+ if ((eh->e_phoff) == 0)
+ {
+ ERR_PRINTF1(_L("Error: ELF Header contains zero offset to the section header table"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ //store program header offset
+ iPHOffset = eh->e_phoff;
+ INFO_PRINTF2(_L("Program header offsett:%d"), iPHOffset);
+
+ CleanupStack::PopAndDestroy(SELFHeader);
+
+ INFO_PRINTF1(_L("Validation of Elf32_Ehdr successful"));
+ }
+
+/**
+ * Validates the Program Header Entries Elf32_Phdr of the SELF file
+ */
+void CProcessCrashWrapper::ValidateProgramHeaderELFFileL()
+ {//Elf32_Phdr
+ INFO_PRINTF1(_L("CProcessCrashWrapper::ValidateProgramHeaderELFFileL validating the program header Entries"));
+
+ TInt sizeofELFProgramHeader = sizeof(Elf32_Phdr); //size of Elf32_Phdr
+ TInt totalsizeofELFProgramHeader = iPHEntries * sizeofELFProgramHeader;
+
+ //allocate buffer Elf32_Phdr
+ iSELFPHHeader = new TUint8[totalsizeofELFProgramHeader];
+ TPtr8 elfPHHeaderPointer(iSELFPHHeader, totalsizeofELFProgramHeader,
+ totalsizeofELFProgramHeader);
+
+ //read the SELF for the whole Program Header Table
+ TInt ret = iSELFFile.Read(iPHOffset, elfPHHeaderPointer,
+ totalsizeofELFProgramHeader);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ValidateProgramHeaderELFFileL Error reading the SELF Header Elf32_Phdr %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ Elf32_Phdr* phdr = (Elf32_Phdr*) iSELFPHHeader;//Elf32_Phdr Program Header
+
+ //Prepare for each of the DHDR buffers
+ TInt sizeofDhdr = sizeof(Sym32_dhdr);
+
+ //loop through the program headers to find out more information on the String section
+ for (TInt i = 0; i < iPHEntries; i++)
+ {
+ //allocate DHDR buffers Sym32_dhdr
+ iDHDRBuffer[i] = new TUint8[sizeofDhdr];
+ TPtr8 dhdrPointer(iDHDRBuffer[i], sizeofDhdr, sizeofDhdr);
+
+ //read SELF file for the Sym32_dhdr
+ TInt ret = iSELFFile.Read(phdr[i].p_offset, dhdrPointer, sizeofDhdr);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ValidateHeaderELFFile Error reading the SELF Header Sym32_dhdr %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ idhdr[i] = (Sym32_dhdr*) iDHDRBuffer[i];//array of Sym32_dhdr store it
+
+ //find information about the String Info section
+ if (phdr[i].p_type == PT_NOTE)
+ {
+ // Intend to store information about the string section ESYM_NOTE_STR
+ //the srting section is to be accessed for all sectiosn to be parsed
+ if (idhdr[i]->d_type == ESYM_NOTE_STR)
+ {
+ INFO_PRINTF2(_L("ESYM_NOTE_STR Header offset %d"),
+ phdr[i].p_offset);
+ INFO_PRINTF2(
+ _L("ESYM_NOTE_STR Size of single descriptor element %d "),
+ idhdr[i]->d_descrsz);
+
+ iOffsetStringSection = phdr[i].p_offset + sizeof(Sym32_dhdr);
+ iSizeofStringSection = idhdr[i]->d_descrsz;
+
+ }//if ESYM_NOTE_STR
+ }//if PT_NOTE
+ }//for loop
+
+ }//end of function
+
+/**
+ * Validates the Symbian Info Section Sym32_syminfod of the SELF file
+ */
+void CProcessCrashWrapper::ValidateSymInfoSectionELFFileL()
+ {//Sym32_syminfod
+ INFO_PRINTF1(_L("CProcessCrashWrapper::ValidateSymInfoSection validating the Symbian Info Section"));
+
+ Elf32_Phdr* phdr = (Elf32_Phdr*) iSELFPHHeader;//Elf32_Phdr Program Header
+
+ //loop through the program headers to get information about the Symbian Info section
+ for (TInt i = 0; i < iPHEntries; i++)
+ {
+ if (phdr[i].p_type == PT_NOTE)
+ {
+ if (idhdr[i]->d_type == ESYM_NOTE_SYM) //SYMBIAN INFO SEGMENT
+ {
+ if (sizeof(Sym32_syminfod) != (idhdr[i]->d_descrsz))
+ {
+ ERR_PRINTF1(_L("CProcessCrashWrapper::ValidateProgramHeaderELFFileL sizeof(Sym32_syminfod)is different from descriptor size") );
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+ TInt sizeofsyminfo = sizeof(Sym32_syminfod);
+ INFO_PRINTF2(_L("ESYM_NOTE_SYM Header offset %d"), phdr[i].p_offset);
+ INFO_PRINTF2(_L("ESYM_NOTE_SYM Size of single descriptor element %d"),
+ idhdr[i]->d_descrsz);
+
+ TInt offsettosyminfod = phdr[i].p_offset + sizeof(Sym32_dhdr);
+
+ //allocate buffer for Sym32_syminfod
+ TUint8* symbianInfoSection = new TUint8[sizeofsyminfo];
+ CleanupStack::PushL(symbianInfoSection);
+
+ TPtr8 ptrSymbianInfoSection(symbianInfoSection, sizeofsyminfo,
+ sizeofsyminfo);
+
+ TInt ret = iSELFFile.Read(offsettosyminfod, ptrSymbianInfoSection, sizeofsyminfo);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ValidateProgramHeaderELFFileL Error reading the SELF Header Sym32_syminfod %d"), ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+ Sym32_syminfod *syminfod = (Sym32_syminfod*) symbianInfoSection; //Symbian Info Section Sym32_syminfod
+
+ // Validation Phase of the Symbian Info section
+ INFO_PRINTF2(_L("Executable Crc32 %X"), syminfod->sd_execid.exec_crc);
+ INFO_PRINTF2(_L("Crashed Thread %ld"), syminfod->sd_thread_id);
+ INFO_PRINTF2(_L("Owning Process %ld"), syminfod->sd_proc_id);
+
+ iCrashedThreadId = syminfod->sd_thread_id;
+ if (ECrashException == syminfod->sd_exit_type)
+ {
+ INFO_PRINTF2(_L("Hardware Exception Number:%d"),
+ syminfod->sd_exit_reason);
+ ValidateExceptionL(syminfod->sd_exit_reason, ETestDataAbort, EFalse); //print the exception string
+ }
+ else
+ if (ECrashKill == syminfod->sd_exit_type)
+ {
+ INFO_PRINTF2(_L("Exit Type\t\t\t:%d"),
+ syminfod->sd_exit_reason);
+ switch (syminfod->sd_exit_reason)
+ {
+ case 0:
+ INFO_PRINTF1(_L(":EExitKill\n"));
+ break;
+ case 1:
+ INFO_PRINTF1(_L(":EExitTerminate\n"));
+ break;
+ case 2:
+ INFO_PRINTF1(_L(":EExitPanic\n"));
+ break;
+ case 3:
+ INFO_PRINTF1(_L(":EExitPending\n"));
+ break;
+ default:
+ INFO_PRINTF1(_L(":Unknown\n"));
+ break;
+ }
+ }
+ else
+ {
+ INFO_PRINTF1(_L("\tUnknown Crash Type\n"));
+ }
+
+ CleanupStack::PopAndDestroy(symbianInfoSection);
+
+ }//if ESYM_NOTE_SYM
+
+ if (idhdr[i]->d_type == ESYM_NOTE_EXEC) //EXECUTABLE INFO SEGMENT
+ {
+ if (sizeof(Sym32_execinfod) != (idhdr[i]->d_descrsz))
+ {
+ ERR_PRINTF1(_L("CProcessCrashWrapper::ValidateProgramHeaderELFFileL sizeof(Sym32_execinfod))is different from descriptor size") );
+ User::Leave(KErrGeneral);
+ }
+
+ TInt sizeofsymexecinfo = sizeof(Sym32_execinfod);
+ INFO_PRINTF2(_L("ESYM_NOTE_EXEC Header offset %d"),
+ phdr[i].p_offset);
+ INFO_PRINTF2(
+ _L("ESYM_NOTE_EXEC Size of single descriptor element %d"),
+ idhdr[i]->d_descrsz);
+
+ //Sym32_execinfod *execinfod = ADDR(Sym32_execinfod,eh,data+sizeof(Sym32_dhdr));
+ TInt offsettosymexecinfod = phdr[i].p_offset
+ + sizeof(Sym32_dhdr);
+
+ TUint8* symbianExecInfoSection = new TUint8[sizeofsymexecinfo];
+ CleanupStack::PushL(symbianExecInfoSection);
+
+ TPtr8 ptrSymbianExecInfoSection(symbianExecInfoSection,
+ sizeofsymexecinfo, sizeofsymexecinfo);
+
+ TInt ret = iSELFFile.Read(offsettosymexecinfod,
+ ptrSymbianExecInfoSection, sizeofsymexecinfo);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ValidateProgramHeaderELFFileL Error reading the SELF Header Sym32_execinfod %d"),
+ ret);
+ User::Leave(ret);
+ }
+ Sym32_execinfod *execinfod =
+ (Sym32_execinfod*) symbianExecInfoSection; //Symbian Info Section Sym32_syminfod
+
+ TBufC<30> nameToCheck(KCrashAppFileName);
+
+ ValidateStringL(EValExecutable, execinfod->ed_name, nameToCheck, EFalse);
+
+ CleanupStack::PopAndDestroy();
+ }//if ESYM_NOTE_EXEC
+
+ }//if PT_NOTE
+
+ }//for loop PHEntries
+ INFO_PRINTF1(_L("Sym_Info validated"));
+ }
+
+/**
+ * Validates the Symbian Thread Section Sym32_thrdinfod of the SELF file
+ * @param aValidateCpuId If this is true, this test will fail if all the CPU Id's are not the same
+ */
+void CProcessCrashWrapper::ValidateThreadInfoSectionELFFileL(TBool aValidateCpuId, const TDesC& aThreadCrashed, TBool aCheck)
+ {
+ INFO_PRINTF1(_L("Validating the Symbian Thread Info Section"));
+
+ Elf32_Phdr* phdr = (Elf32_Phdr*) iSELFPHHeader;//Elf32_Phdr Program Header
+ TInt cpuId = -1;
+
+ //loop through the program headers to get information about the Symbian Info section
+ for (TInt i = 0; i < iPHEntries; i++)
+ {
+ if (phdr[i].p_type == PT_NOTE)
+ {
+ if (idhdr[i]->d_type == ESYM_NOTE_THRD) //SYMBIAN INFO SEGMENT
+ {
+ if (sizeof(Sym32_thrdinfod) != (idhdr[i]->d_descrsz))
+ {
+ ERR_PRINTF1(_L("CProcessCrashWrapper::ValidateThreadInfoSectionELFFileL sizeof(Sym32_thrdinfod) %d is different from descriptor size") );
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ TInt sizeofthreadinfo = sizeof(Sym32_thrdinfod);
+ INFO_PRINTF2(_L("ESYM_NOTE_THRD Header offset %d"), phdr[i].p_offset);
+ INFO_PRINTF2(_L("ESYM_NOTE_THRD Size of single descriptor element %d"),
+ idhdr[i]->d_descrsz);
+ INFO_PRINTF2(_L("ESYM_NOTE_THRD Number of elements %d"), idhdr[i]->d_elemnum);
+
+ TInt offsettothreadinfod = phdr[i].p_offset + sizeof(Sym32_dhdr);
+ TInt newoffsettothreadinfod = offsettothreadinfod;
+
+ //allocate buffer for Sym32_thrdinfod
+ TUint8* symbianThreadSection = new TUint8[sizeofthreadinfo];
+ CleanupStack::PushL(symbianThreadSection);
+
+ TPtr8 ptrSymbianThreadSection(symbianThreadSection, sizeofthreadinfo,
+ sizeofthreadinfo);
+
+ TInt ret = iSELFFile.Read(offsettothreadinfod, ptrSymbianThreadSection, sizeofthreadinfo);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ValidateThreadInfoSectionELFFileL Error reading the SELF Header Sym32_thrdinfod %d"), ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+ Sym32_thrdinfod *thrdinfod = (Sym32_thrdinfod*) symbianThreadSection; //Symbian Info Section Sym32_syminfod
+
+ for(int thrIdx = 0; thrIdx < idhdr[i]->d_elemnum; thrIdx++ )
+ {
+ //valid checking fo thread id
+
+ if (iCrashedThreadId == thrdinfod->td_id)
+ {
+ INFO_PRINTF2(_L("Owning process %ld"), thrdinfod->td_owning_process);
+ INFO_PRINTF2(_L("Thread Priority %d"), thrdinfod->td_priority);
+ INFO_PRINTF2(_L("Heap Adress 0x%X"), thrdinfod->td_heap_add);
+ INFO_PRINTF2(_L("Heap Size %d"), thrdinfod->td_heap_sz);
+ //storing the heap address and the Heap Siz for future verification
+ iHeapBase = thrdinfod->td_heap_add;
+ iHeapSize = thrdinfod->td_heap_sz;
+
+ ValidateStringL(EValThread, thrdinfod->td_name, aThreadCrashed, aCheck);
+
+ }
+
+ if(aValidateCpuId)
+ {
+ //If its the first, set the CPU ID to be this
+ if(cpuId < 0)
+ {
+ cpuId = thrdinfod->td_last_cpu_id;
+ }
+ else
+ {
+ //Otherwise, the current CPU ID should be the same as the previous
+ if(thrdinfod->td_last_cpu_id != cpuId)
+ {
+ ERR_PRINTF3(_L("CProcessCrashWrapper::ValidateThreadInfoSectionELFFileL CPU ID Not as expected. Current is not the same as previous. Current = [%d] Previous = [%d]"), thrdinfod->td_last_cpu_id, cpuId);
+ SetBlockResult(EFail);
+ User::Leave(KErrCorrupt);
+ }
+ cpuId = thrdinfod->td_last_cpu_id;
+ }
+ }
+
+ newoffsettothreadinfod = newoffsettothreadinfod + sizeofthreadinfo;
+
+ ret = iSELFFile.Read(newoffsettothreadinfod, ptrSymbianThreadSection, sizeofthreadinfo);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ValidateThreadInfoSectionELFFileL Error reading the SELF Header Sym32_thrdinfod %d"), ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ thrdinfod = (Sym32_thrdinfod*) symbianThreadSection;
+
+ }
+
+ CleanupStack::PopAndDestroy();
+ }//if ESYM_NOTE_THRD
+
+ }//if PT_NOTE
+
+ }//for PHEntries
+
+ }
+
+/**
+ * Validates the Register Info Section
+ * Reads the CPSR value to determine the type of the crash (user/system)
+ */
+void CProcessCrashWrapper::ValidateRegisterInfoSectionELFFileL()
+ {
+
+ INFO_PRINTF1(_L("CProcessCrashWrapper::ValidateRegisterInfoSectionELFFileL validating the regsiter Section"));
+
+ TBool matchfound = EFalse;
+ Elf32_Phdr* phdr = (Elf32_Phdr*) iSELFPHHeader;//Elf32_Phdr Program Header
+
+ //loop through the program headers to get information about the Symbian Info section
+ for (TInt i = 0; (i < iPHEntries) && !matchfound; i++)
+ {
+ if (phdr[i].p_type == PT_NOTE)
+ {
+ if (idhdr[i]->d_type == ESYM_NOTE_REG) //SYMBIAN REGISTER INFO SEGEMENT
+ {
+
+ TInt sizeofreginfo = sizeof(Sym32_reginfod);
+ TInt offsettoreginfod = phdr[i].p_offset + sizeof(Sym32_dhdr);
+
+ //allocate buffer for Sym32_reginfod
+ TUint8* symbianRegSection = new TUint8[sizeofreginfo];
+ CleanupStack::PushL(symbianRegSection);
+
+ TPtr8 ptrSymbianRegSection(symbianRegSection, sizeofreginfo,
+ sizeofreginfo);
+
+ TInt ret = iSELFFile.Read(offsettoreginfod, ptrSymbianRegSection, sizeofreginfo);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ValidateRegisterInfoSectionELFFileL Error reading the SELF Header Sym32_thrdinfod %d"), ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+ Sym32_reginfod *reginfod = (Sym32_reginfod*) symbianRegSection; //Symbian Register Info Section Sym32_reginfod
+
+ if(reginfod->rid_thread_id == iCrashedThreadId)
+ {
+
+ INFO_PRINTF2(_L("Crashed Thread id %ld"), iCrashedThreadId);
+ INFO_PRINTF2(_L("Thread ID %ld"), reginfod->rid_thread_id);
+
+ TInt offsettoregdatad = offsettoreginfod + sizeofreginfo;
+
+ for( TInt i = 0; (i < reginfod->rid_num_registers) && !matchfound; i++ )
+ {
+ //Sym32_regdatad immediately following the Register Info descriptor header
+ TInt sizeofregdatad = sizeof (Sym32_regdatad);
+ offsettoregdatad = offsettoregdatad + sizeofreginfo;
+
+ TUint8* symbianRegDatad = new TUint8[sizeofregdatad];
+ CleanupStack::PushL(symbianRegDatad);
+
+ TPtr8 ptrSymbianRegDatad(symbianRegDatad, sizeofregdatad,
+ sizeofregdatad);
+
+ TInt ret = iSELFFile.Read(offsettoregdatad, ptrSymbianRegDatad, sizeofregdatad);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ValidateRegisterInfoSectionELFFileL Error reading the SELF Header Sym32_thrdinfod %d"), ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ Sym32_regdatad *regdatad = (Sym32_regdatad*) symbianRegDatad; //Symbian Register Info Section Sym32_regdatad
+
+ if( (ESYM_REG_CORE == reginfod->rid_class) && (ESYM_REG_32 == reginfod->rid_repre) && (KCPSRReg == regdatad->rd_id) )
+ {
+ //we have found the CPSR value for the crashed thread, now read the register value
+ TInt sizeofELF32Word = sizeof(Elf32_Word);
+ TUint8* rd_data_cpsr = new TUint8[sizeofELF32Word];
+ CleanupStack::PushL(rd_data_cpsr);
+
+ TPtr8 ptrSymbianRdDataCpsr(rd_data_cpsr, sizeofELF32Word,
+ sizeofELF32Word);
+
+ TInt ret = iSELFFile.Read(regdatad->rd_data , ptrSymbianRdDataCpsr, sizeofELF32Word);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ValidateRegisterInfoSectionELFFileL Error reading the SELF Header Sym32_thrdinfod %d"), ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ Elf32_Word * val32 = (Elf32_Word*) rd_data_cpsr;
+
+ TUint cpsrval = *val32;
+
+ if(cpsrval & KModeBitCPSR) //checking on the M[4:0] mode bits of the CPSR
+ {
+ INFO_PRINTF2(_L("System Crash CPSR value: 0x%X\n"), cpsrval );
+ iSystemCrash = ETrue; //system crash
+ }
+ else
+ {
+ INFO_PRINTF2(_L("User Side Crash CPSR value: 0x%X\n"), cpsrval );
+ iSystemCrash = EFalse; //user crash
+ }
+
+ matchfound = ETrue;
+
+ CleanupStack::PopAndDestroy();//rd_data_cpsr CPSR data value
+ }
+
+ CleanupStack::PopAndDestroy();//Sym32_regdatad symbianRegDatad
+ }// for loop reginfod->rid_num_registers
+
+ }//if iCrashedThreadId
+
+ CleanupStack::PopAndDestroy();
+
+ }
+ }
+ }
+
+ }
+
+/**
+ * Validates the Heap Section of the SELF file
+ */
+void CProcessCrashWrapper::ValidateHeapSectionELFFileL(TBool aHeapCheck)
+ {
+
+ INFO_PRINTF1(_L("CProcessCrashWrapper::ValidateHeapSectionELFFileL validating the Heap Section"));
+
+ Elf32_Phdr* phdr = (Elf32_Phdr*) iSELFPHHeader;//Elf32_Phdr Program Header
+
+ TBool matchfound = EFalse;
+ //loop through the program headers to get information about the Symbian Info section
+ for (TInt i = 0; i < iPHEntries; i++)
+ {
+ if (phdr[i].p_type == PT_LOAD)
+ {
+ if(phdr[i].p_vaddr == iHeapBase && phdr[i].p_filesz == iHeapSize )
+ {
+ if(phdr[i].p_filesz == 0) //if the heap size is zero just complain
+ {
+ ERR_PRINTF1(
+ _L("CProcessCrashWrapper::ValidateHeapSectionELFFileL Error Heap Size found to be zero"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+ matchfound = ETrue;
+ INFO_PRINTF2(_L("Heap section found at PHDR offset %d"), phdr[i].p_offset);
+ break;
+ }
+
+ }
+ }
+ if(!aHeapCheck && matchfound )
+ {
+ ERR_PRINTF1(
+ _L("CProcessCrashWrapper::ValidateHeapSectionELFFileL Error found heap section when there shouldnt be one"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+ if(aHeapCheck && !matchfound )
+ {
+ ERR_PRINTF1(
+ _L("CProcessCrashWrapper::ValidateHeapSectionELFFileL Error did not find the heap section"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ }
+
+/**
+ * Validates the Trace Section Sym32_tracedata of the SELF file
+ */
+void CProcessCrashWrapper::ValidateTraceSectionELFFileL(TBool aTraceCheck)
+ {
+
+ INFO_PRINTF1(_L("CProcessCrashWrapper::ValidateTraceSectionELFFileL validating the Trace Section"));
+
+ Elf32_Phdr* phdr = (Elf32_Phdr*) iSELFPHHeader;//Elf32_Phdr Program Header
+
+ TBool dataPresent = EFalse;
+ //loop through the program headers to get information about the Symbian Info section
+ for (TInt i = 0; i < iPHEntries; i++)
+ {
+ if (phdr[i].p_type == PT_NOTE)
+ {
+ if (idhdr[i]->d_type == ESYM_NOTE_TRACE) //Trace Info
+ {
+ TInt sizeoftraceinfo = sizeof(Sym32_tracedata);
+ INFO_PRINTF2(_L("ESYM_NOTE_TRACE Size of trace section %d"), sizeoftraceinfo);
+ INFO_PRINTF2(_L("ESYM_NOTE_TRACE Header offset %d"), phdr[i].p_offset);
+ INFO_PRINTF2(_L("ESYM_NOTE_TRACE Size of single descriptor element %d"),
+ idhdr[i]->d_descrsz);
+ INFO_PRINTF2(_L("ESYM_NOTE_TRACE Number of elements %d"), idhdr[i]->d_elemnum);
+
+ if (sizeof(Sym32_tracedata) != (idhdr[i]->d_descrsz))
+ {
+ ERR_PRINTF1(_L("CProcessCrashWrapper::ValidateTraceSectionELFFileL sizeof(Sym32_tracedata) %d is different from descriptor size") );
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ TInt offsettotraceinfod = phdr[i].p_offset + sizeof(Sym32_dhdr);
+ //allocate buffer for Sym32_tracedata
+ TUint8* symbianTraceSection = new TUint8[sizeoftraceinfo];
+ CleanupStack::PushL(symbianTraceSection);
+
+ TPtr8 ptrSymbianTraceSection(symbianTraceSection, sizeoftraceinfo,
+ sizeoftraceinfo);
+
+ TInt ret = iSELFFile.Read(offsettotraceinfod, ptrSymbianTraceSection, sizeoftraceinfo);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ValidateTraceSectionELFFileL Error reading the SELF Header Sym32_thrdinfod %d"), ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ Sym32_tracedata *traceInfo =
+ (Sym32_tracedata*) symbianTraceSection;
+
+ INFO_PRINTF2(_L("Size of trace buffer: %d"), traceInfo->tr_size);
+ INFO_PRINTF2(_L("Offset of trace buffer:%d"), traceInfo->tr_data);
+
+ //checking for the presence of trace data
+ if(traceInfo->tr_size != 0)//trace data present
+ {
+ dataPresent = ETrue;
+ //read the trace buffer
+ //unsigned char* data = ADDR(unsigned char, aElfHdr, aTraceData->tr_data);
+
+ RBuf8 tracebufferString;
+ tracebufferString.CleanupClosePushL();
+
+ tracebufferString.CreateL(traceInfo->tr_size);//READING 200 characters assuming strings to be not more than 200 characters
+
+ TInt ret = iSELFFile.Read(traceInfo->tr_data, tracebufferString, traceInfo->tr_size);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ValidateTraceSectionELFFileL Error reading the Trace Information %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ INFO_PRINTF1(_L("Validate the trace buffer now"));
+ ValidateTraceBufferL(tracebufferString);
+
+ CleanupStack::PopAndDestroy();//tracebufferString
+ CleanupStack::PopAndDestroy();//symbianTraceSection
+ break;
+ }
+ else //expecting trace data to be present otherwise complain
+ {
+ ERR_PRINTF1(
+ _L("CProcessCrashWrapper::ValidateTraceSectionELFFileL Error found trace size to be zero"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+
+ }
+ }
+ }
+
+ }
+
+ if(!aTraceCheck && dataPresent )
+ {
+ ERR_PRINTF1(
+ _L("CProcessCrashWrapper::ValidateTraceSectionELFFileL Error found trace section when there shouldnt be one"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+ if(aTraceCheck && !dataPresent )
+ {
+ ERR_PRINTF1(
+ _L("CProcessCrashWrapper::ValidateTraceSectionELFFileL Error did not find the trace section"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ }
+
+/**
+ * @return void
+ * This method monitors the RProperty for the crash progress. There are several states of this but we are
+ * only interested in the start and finish of these properties
+ */
+void CProcessCrashWrapper::MonitorProgressL()
+ {
+ RProperty crashProgress;
+ User::LeaveIfError(crashProgress.Attach(KCoreDumpServUid, ECrashProgress));
+
+ TBuf<50> crashProg;
+
+ TRequestStatus status;
+ crashProgress.Subscribe(status);
+ User::WaitForRequest(status);
+ //Subscribe for next one again...
+ crashProgress.Subscribe(status);
+
+ //First one should be the start string = "-"
+ User::LeaveIfError(crashProgress.Get(crashProg ));
+ if(crashProg != KStartOfSELFProc)
+ {
+ INFO_PRINTF1(_L("SELF formatter has not started processing the data"));
+ }
+
+ INFO_PRINTF1(_L("SELF formatters have started processing the data"));
+ INFO_PRINTF1(_L("Waiting to be notified of the timeout of the processing. A timeout here is a fail"));
+ //Now we wait until its finished
+ do
+ {
+ User::WaitForRequest(status);
+ crashProgress.Subscribe(status);
+
+ User::LeaveIfError(crashProgress.Get(crashProg ));
+ }
+ while(crashProg != KEndOfProcessing);
+
+ INFO_PRINTF1(_L("SELF formatter has finished processing the data"));
+
+ }
+/**
+ * Utility Function to print and validate the exception type
+ * @param aException exception number
+ * @param acheckException exception to check for
+ * @param aCheck whether to validate the exception or not
+ */
+void CProcessCrashWrapper::ValidateExceptionL(TInt aException, TInt acheckException, TBool aCheck)
+ {
+ INFO_PRINTF2(_L("Hardware Exception of type: %d"), aException);
+ switch (aException)
+ {
+ case 0:
+ INFO_PRINTF1(_L(":EExcGeneral"));
+ break;
+ case 1:
+ INFO_PRINTF1(_L(":EExcIntegerDivideByZero"));
+ break;
+ case 2:
+ INFO_PRINTF1(_L(":EExcSingleStep"));
+ break;
+ case 3:
+ INFO_PRINTF1(_L(":EExcBreakPoint"));
+ break;
+ case 4:
+ INFO_PRINTF1(_L(":EExcIntegerOverflow"));
+ break;
+ case 5:
+ INFO_PRINTF1(_L(":EExcBoundsCheck"));
+ break;
+ case 6:
+ INFO_PRINTF1(_L(":EExcInvalidOpCode"));
+ break;
+ case 7:
+ INFO_PRINTF1(_L(":EExcDoubleFault"));
+ break;
+ case 8:
+ INFO_PRINTF1(_L(":EExcStackFault"));
+ break;
+ case 9:
+ INFO_PRINTF1(_L(":EExcAccessViolation"));
+ break;
+ case 10:
+ INFO_PRINTF1(_L(":EExcPrivInstruction"));
+ break;
+ case 11:
+ INFO_PRINTF1(_L(":EExcAlignment"));
+ break;
+ case 12:
+ INFO_PRINTF1(_L(":EExcPageFault"));
+ break;
+ case 13:
+ INFO_PRINTF1(_L(":EExcFloatDenormal"));
+ break;
+ case 14:
+ INFO_PRINTF1(_L(":EExcFloatDivideByZero"));
+ break;
+ case 15:
+ INFO_PRINTF1(_L(":EExcFloatInexactResult"));
+ break;
+ case 16:
+ INFO_PRINTF1(_L(":EExcFloatInvalidOperation"));
+ break;
+ case 17:
+ INFO_PRINTF1(_L(":EExcFloatOverflow"));
+ break;
+ case 18:
+ INFO_PRINTF1(_L(":EExcFloatStackCheck"));
+ break;
+ case 19:
+ INFO_PRINTF1(_L(":EExcFloatUnderflow"));
+ break;
+ case 20:
+ INFO_PRINTF1(_L(":EExcAbort"));
+ break;
+ case 21:
+ INFO_PRINTF1(_L(":EExcKill"));
+ break;
+ case 22:
+ INFO_PRINTF1(_L(":EExcUserInterrupt"));
+ break;
+ case 23:
+ INFO_PRINTF1(_L(":EExcDataAbort"));
+ break;
+ case 24:
+ INFO_PRINTF1(_L(":EExcCodeAbort"));
+ break;
+ case 25:
+ INFO_PRINTF1(_L(":EExcMaxNumber"));
+ break;
+ case 26:
+ INFO_PRINTF1(_L(":EExcInvalidVector"));
+ break;
+ default:
+ ERR_PRINTF1(_L("Unknown Exception"));
+ break;
+ }
+
+ if(aCheck)
+ {
+ if( aException != acheckException )
+ {
+ ERR_PRINTF1(
+ _L("CProcessCrashWrapper::ValidateExceptionL is not the valid type"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ INFO_PRINTF1(_L("Hardware Exception matched successful!"));
+ }
+
+ }
+/**
+ * Utility Function to print and validate a string
+ * Reads the String section and searches for a NULL character to find the right string
+ * @param aIndex index to the string section
+ * @param aStingToMatch string to be matched
+ * @param aCheck whether to validate the string or not
+ */
+void CProcessCrashWrapper::ValidateStringL(TValidateString aType, TInt aIndex, const TDesC& aStingToMatch, TBool aCheck)
+ {
+ INFO_PRINTF2(_L("CProcessCrashWrapper::ValidateStringL Index %d"), aIndex);
+
+ RBuf8 bufferString;
+ bufferString.CleanupClosePushL();
+ bufferString.CreateL(KMaxStringLength);//Reading 200 characters assuming strings to be not more than 200 characters
+
+ //going to the string in the string node
+ TInt offsetString = iOffsetStringSection + aIndex;
+ TInt ret = iSELFFile.Read(offsetString, bufferString, KMaxStringLength);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::PrintStringL Error reading the String Information %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ //trying to find a NULL terminating character
+ TInt nullPos = -1;
+ TInt loop = 0;
+ while ((nullPos = bufferString.Locate(NULL)) > KErrNotFound)
+ {
+ loop++;
+ if (loop > KMaxStringLength)
+ {
+ ERR_PRINTF1(_L("CProcessCrashWrapper::ValidateStringL Error reading NULL character from the string"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+ else
+ {
+ //found the NULL character exit the loop
+ INFO_PRINTF2(_L("ValidateStringL postion of NULL character %d"), nullPos);
+ break;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(); //bufferString
+
+ //create a new actual string to hold the value we want
+ RBuf8 printString;
+ printString.CreateL(nullPos+2);
+ printString.CleanupClosePushL();
+
+ ret = iSELFFile.Read(offsetString, printString, nullPos);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::ValidateStringL Error reading reading the String Information %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ //create a NULL terminated string for printing on serial output
+ char* clPrompt = (char*) printString.PtrZ();
+ RDebug::Printf("String printed %s", clPrompt);
+
+ RBuf bigString;
+ bigString.CreateL(KMaxFileName);
+ bigString.CleanupClosePushL();
+
+ bigString.Copy(printString); //8 to 16 bit conversion
+
+ if(aType == EValExecutable)
+ {
+ INFO_PRINTF2(_L("Crashed Executable name: %S"), &bigString);
+
+ }
+
+ else if(aType == EValThread)
+ {
+ if(!aCheck) //NOT to check on the thread name
+ {
+ //just happy printing the name of the thread
+ INFO_PRINTF2(_L("Crashed Thread name: %S"), &bigString);
+ }
+ else
+ {
+ // check with the thread name passed
+ RBuf stringtoCheck;
+ stringtoCheck.Create(aStingToMatch);
+ stringtoCheck.CleanupClosePushL();
+
+ bigString.SetLength(stringtoCheck.Length()); //reducing the length
+
+ INFO_PRINTF2(_L("Crashed Thread name Verified : %S"), &bigString);
+
+ if(bigString.Compare(stringtoCheck) != 0)
+ {
+ ERR_PRINTF1(
+ _L("CProcessCrashWrapper::ValidateStringL Application name does not match "));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ INFO_PRINTF1( _L("CProcessCrashWrapper::ValidateStringL Crashed Application Match Successful ! "));
+
+ CleanupStack::PopAndDestroy();//stringtoCheck
+
+ }
+
+ }
+ CleanupStack::PopAndDestroy();//bigString
+ CleanupStack::PopAndDestroy(); //printString
+
+ }
+
+/**
+ * Utility Function to do trace data verification
+ */
+void CProcessCrashWrapper::ValidateTraceBufferL(const TDesC8& aBuffer)
+{
+ INFO_PRINTF2(_L("CDataTranslator::ValidateTraceBufferL: size: %d"), aBuffer.Length());
+
+ const TUint8* tracePtr = aBuffer.Ptr();
+ TInt traceSize = aBuffer.Length();
+
+/* TUint8 recSize = 0;
+ TUint8 flags = 0;*/
+ TUint8 category = 0;
+/* TUint8 subCategory = 0;*/
+ TInt count = 0;
+
+ const TUint8* endPtr = tracePtr+traceSize;
+ while(tracePtr < endPtr)
+ {
+ count++;
+ category = 0;
+
+ /*recSize = flags = subCategory = 0;
+ recSize = tracePtr[BTrace::ESizeIndex];
+ flags = tracePtr[BTrace::EFlagsIndex];
+ subCategory = tracePtr[BTrace::ESubCategoryIndex];*/
+
+ //read trace header
+ category = tracePtr[BTrace::ECategoryIndex];
+
+ //check the parameter Category
+ if(category != KTraceCategory)
+ {
+ ERR_PRINTF1(
+ _L("CProcessCrashWrapper::ValidateTraceBufferL Category 200 did not match with the trace buffer"));
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ tracePtr = BTrace::NextRecord((TAny*)tracePtr);
+ }
+
+ INFO_PRINTF2(_L("Number of trace packets found: %d"), count);
+}
+
+/**
+ * Reports performance metrics from all the tests
+ */
+void CProcessCrashWrapper::ValidatePerformanceELFFile()
+ {
+
+ TInt ticks = HelpGetTestTicks();
+ TInt nkTicksPerSecond = HelpTicksPerSecond();
+
+ TInt actualtimeinseconds = ticks/nkTicksPerSecond;
+
+ INFO_PRINTF3(_L("SELF File Creation E:\\%S took: %d seconds\n") , &iSELFFileName, ticks/nkTicksPerSecond);
+
+ if (actualtimeinseconds > KMAXTIMEOUT)
+ {
+ ERR_PRINTF2(
+ _L("SELF File Creation had exceeded TIME OUT of %d secs "), KMAXTIMEOUT);
+ SetBlockResult(EFail);
+ User::Leave(KErrGeneral);
+ }
+
+ //clean up routine for the file created
+ TInt ret = iFsSession.Delete(iSELFFileName);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::SELF File delete returned error %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+ iStartTick = iStopTick = 0;//reset the timer ticks
+
+ }
+/**
+ * Utility Function to do SELF Configurations
+ */
+void CProcessCrashWrapper::ConfigureSELF(TBool aPresent, TInt aSegment)
+ {
+
+ INFO_PRINTF3(_L("CProcessCrashWrapper::ConfigureSELF confiugring SELF for segment %d to present %d"), aSegment, aPresent);
+
+ if(EHeap == aSegment)
+ {//heap segment is configured through the data segemnts in the SELF file
+ if(aPresent)
+ {//configure to have data segments
+ DoConfigureL(2, KUidELFFormatterV2.iUid, COptionConfig::EFormatterPlugin,
+ COptionConfig::ETBool, KDataSegmentPrompt,
+ 1, KTrueFalseOpt, 1, KTrueOpt, 0);
+
+ }
+ else
+ {//configure NOT to have data segments
+ DoConfigureL(2, KUidELFFormatterV2.iUid, COptionConfig::EFormatterPlugin,
+ COptionConfig::ETBool, KDataSegmentPrompt,
+ 1, KTrueFalseOpt, 0, KFalseOpt, 0);
+ }
+ }
+
+ if(ETrace == aSegment)
+ {//trace segment configured here
+ if(aPresent)
+ {//configure to have trace segments upto have 10KB data
+ DoConfigureL(8, KUidELFFormatterV2.iUid, COptionConfig::EFormatterPlugin,
+ COptionConfig::ETInt, KCreateTraceData,
+ 1, KNullDesC, 10, KNullDesC, 0);
+
+ }
+ else
+ {//configure NOT to have trace segments
+ DoConfigureL(8, KUidELFFormatterV2.iUid, COptionConfig::EFormatterPlugin,
+ COptionConfig::ETInt, KCreateTraceData,
+ 1, KNullDesC, 0, KNullDesC, 0);
+ }
+ }
+
+ if(ECode == aSegment)
+ {//code segment configured here
+ if(aPresent)
+ {//configure to have Code Segements
+ DoConfigureL(3, KUidELFFormatterV2.iUid, COptionConfig::EFormatterPlugin,
+ COptionConfig::ETBool, KCodeSegmentPrompt,
+ 1, KTrueFalseOpt, 1, KTrueOpt, 0);
+ }
+ else
+ {//configure NOT to have Code Segments
+ DoConfigureL(3, KUidELFFormatterV2.iUid, COptionConfig::EFormatterPlugin,
+ COptionConfig::ETBool, KCodeSegmentPrompt,
+ 1, KTrueFalseOpt, 0, KFalseOpt, 0);
+ }
+ }
+
+ if(EThread == aSegment)
+ {//thread segment configured here
+ if(aPresent)
+ {//configure to have Thread Segments
+ DoConfigureL(4, KUidELFFormatterV2.iUid, COptionConfig::EFormatterPlugin,
+ COptionConfig::ETBool, KThreadSegmentPrompt,
+ 1, KTrueFalseOpt, 1, KTrueOpt, 0);
+ }
+ else
+ {//configure NOT to have Thread Segments
+ DoConfigureL(4, KUidELFFormatterV2.iUid, COptionConfig::EFormatterPlugin,
+ COptionConfig::ETBool, KThreadSegmentPrompt,
+ 1, KTrueFalseOpt, 0, KFalseOpt, 0);
+ }
+ }
+
+ }
+
+/**
+ * Utility Function to do cleanup activities
+ */
+void CProcessCrashWrapper::CleanupMethod(const TDesC& aDes)
+ {
+ RBuf fileDelete;
+ fileDelete.CreateL(aDes);
+ fileDelete.SetMax();
+ fileDelete.CleanupClosePushL();
+ INFO_PRINTF2(_L("Entered deletion routine for file %S"), &fileDelete);
+
+ //close the file
+ iSELFFile.Close();
+
+ TInt ret = iFsSession.Delete(fileDelete);
+ if (ret != KErrNone)
+ {
+ ERR_PRINTF2(
+ _L("CProcessCrashWrapper::SELF File delete returned error %d"),
+ ret);
+ SetBlockResult(EFail);
+ User::Leave(ret);
+ }
+
+ CleanupStack::PopAndDestroy();//fileDelete
+
+ //delete the buffers
+ if (iSELFPHHeader)
+ {
+ delete [] iSELFPHHeader;
+ iSELFPHHeader = NULL;
+ }
+
+ for (TInt i = 0; i < iPHEntries; i++)
+ {
+ delete [] iDHDRBuffer[i];
+ }
+
+ INFO_PRINTF1(_L("Cleanup Done of the SELF File\n"));
+ }
+
+/**
+ * Returns the number of nanokernel ticks in one second
+ * @return Number of nanokernel ticks. 0 if unsuccesful
+ */
+TInt CProcessCrashWrapper::HelpTicksPerSecond(void)
+ {
+ TInt nanokernel_tick_period;
+ HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+
+ ASSERT(nanokernel_tick_period != 0);
+
+ static const TInt KOneMillion = 1000000;
+
+ return KOneMillion/nanokernel_tick_period;
+ }
+
+/**
+ *Prints the error condition for TEF log/output
+ */
+void CProcessCrashWrapper::PrintErrorCondition(TInt aError)
+ {
+ //print out the error and put the result as failure
+ ERR_PRINTF2(_L("Oops!!! error %d"),aError);
+ SetBlockResult(EFail);
+ }
+/*
+ * class CAsyncProcessCrash Implementation
+ */
+
+/**
+ * Two phase constructor for CAsyncProcessCrash
+ * @return CAsyncProcessCrash object
+ * @leave
+ */
+CAsyncProcessCrash* CAsyncProcessCrash::NewL(CProcessCrashWrapper* aProcessCrashWrapper)
+ {
+ CAsyncProcessCrash* ret = new (ELeave) CAsyncProcessCrash(aProcessCrashWrapper);
+ CleanupStack::PushL(ret);
+ ret->ConstructL();
+ CleanupStack::Pop(ret);
+ return ret;
+ }
+
+/**
+ * Safe construction
+ * @leave
+ */
+void CAsyncProcessCrash::ConstructL()
+ {
+ }
+
+/*
+ * Constructor for the CActive derived object
+ */
+CAsyncProcessCrash::CAsyncProcessCrash(CProcessCrashWrapper* aProcessCrashWrapper)
+ : CActive(CActive::EPriorityStandard),
+ iProcessCrashWrapper(aProcessCrashWrapper),
+ iCrashId(0)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+/*
+ * Function that issues request to the Core Dump Server
+ * @param aCrashId is the crash id
+ * to process crash log
+ */
+void CAsyncProcessCrash::IssueProcessCrashRequest(TUint aCrashId)
+ {
+ RDebug::Printf("CAsyncProcessCrash::IssueProcessCrashRequest");
+
+ iCrashId = aCrashId;
+
+ ASSERT(!IsActive());
+
+ // Actually issue the request
+ iProcessCrashWrapper->iCoreDumpSession.ProcessCrashLog( iCrashId, iStatus);
+
+ // Tell the framework that a request is pending but
+ // do it after the async request in case it Leaves
+ SetActive();
+ }
+
+/*
+ * RunL from CActive when the asynchronous request completes
+ *
+ */
+void CAsyncProcessCrash::RunL()
+ {
+ RDebug::Printf("CAsyncProcessCrash::RunL %d", iStatus.Int());
+ // that errors are handled in RunError()
+ User::LeaveIfError(iStatus.Int());
+
+ // request-handling code
+ iProcessCrashWrapper->ProcessSELFFileCreatedL();
+
+ CActiveScheduler::Stop();
+ }
+
+/*
+ * RunError from CActive called when RunL leaves
+ */
+TInt CAsyncProcessCrash::RunError(TInt aError)
+ {
+ RDebug::Printf("CAsyncProcessCrash::RunError");
+
+ iProcessCrashWrapper->PrintErrorCondition(aError);
+
+ CActiveScheduler::Stop();
+
+ return KErrNone; // error handled
+ }
+
+/*
+ * Destructor for clean up purposes
+ */
+CAsyncProcessCrash::~CAsyncProcessCrash()
+ {
+ RDebug::Printf("CAsyncProcessCrash::~CAsyncProcessCrash");
+ //cancel any outstanding request
+ Cancel();
+
+ }
+
+/*
+ * Destructor for clean up purposes
+ */
+void CAsyncProcessCrash::DoCancel()
+ {
+ RDebug::Printf("CAsyncProcessCrash::DoCancel");
+ //cancel the processing the crashlog
+ iProcessCrashWrapper->iCoreDumpSession.CancelProcessCrashLog(iCrashId);
+ }
+
+//eof