kernel/eka/debug/crashMonitor/src/scmdatasave.cpp
changeset 296 94f2adf59133
parent 293 0659d0e1a03c
child 297 b2826f67641f
--- a/kernel/eka/debug/crashMonitor/src/scmdatasave.cpp	Wed Oct 20 13:58:28 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1266 +0,0 @@
-// 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 the License "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-// e32\debug\crashMonitor\src\scmdatasave.cpp
-// 
-//
-
-#define __INCLUDE_REG_OFFSETS__  // for SP_R13U in nk_plat.h
-
-#include <omap_dbg.h>
-#include "arm_mem.h"
-#include "nk_plat.h"
-#include <omap_assp.h>
-#include <scmonitor.h>
-#include <scmdatasave.h> 
-
-/**
- * @file
- * @internal technology
- */
-
-/**
- * SCMDataSave constructor
- * @param aMonitor - the monitor which has caught the syetem crash this object is saving data for 
- * @param aFlash - the flash memory data will be written to, note the CrashFlash interface is
- * 				   rather limited and does not support partial block writes
- * @param aFlashInfo - data describing the structure of the flash data
- */
-EXPORT_C SCMDataSave::SCMDataSave(Monitor* aMonitor, CrashFlash* aFlash)
-	: iMonitor(aMonitor)
-		,iFlash(aFlash)
-		,iByteCount(0)	
-#ifdef SCM_COMM_OUTPUT	
-		,iWriteSelect(EWriteComm)  // write data to debug port	
-#else	
-		,iWriteSelect(EWriteFlash)  // write data to flash
-#endif
-		,iPerformChecksum(ETrue)			 // checksum data 
-		,iStartingPointForCrash(0)
-	{  		
-	const TInt KCacheSize = 128;
-	iFlashCache = HBuf8::New(KCacheSize);
-	CLTRACE1("(SCMDataSave) Creating writer with cache size = %d", KCacheSize);
-	iWriter = new TCachedByteStreamWriter(const_cast<TUint8*>(iFlashCache->Ptr()), KCacheSize);
-	iWriter->SetWriterImpl(this);
-	}
-
-/**
- * Destructor
- */
-SCMDataSave::~SCMDataSave()
-	{
-	delete iFlashCache;
-	}
-
-/**
- * Getter for the current byte count. This is the amount of data that has currently 
- * been written to given media for this crash log
- * @return The number of bytes written already to given media
- */
-TInt SCMDataSave::GetByteCount()
-	{
-	return iByteCount;
-	}
-
-/**
- * Logs the user stack for a given DThread object if it is available
- * @param aThread - thread whose stack we wish to log
- * @param aSizeDumped Holds the size of the data dumped
- * @return one of the OS codes
- */
-TInt SCMDataSave::LogThreadUserStack(DThread* aThread, TBool aFullStack, TUint& aSizeDumped)
-	{
-	LOG_CONTEXT
-	aSizeDumped = 0;
-	TUint memDumped = 0;	
-	
-	TUint svSp, usrSp;
-	iMonitor->GetStackPointers(&(aThread->iNThread), svSp, usrSp );	
-	
-	//first we check for a user stack...
-	if (aThread->iUserStackRunAddress && aThread->iUserStackSize)
-		{		
-		//Get data together
-		TThreadStack usrStack;
-		usrStack.iStackType = TThreadStack::EUsrStack;
-		usrStack.iThreadId = (TUint64)aThread->iId;					
-				
-		//map in the user stack
-		TUint8* usrStart = (TUint8*)iMonitor->MapAndLocateUserStack(aThread); //What about Demand paging??
-		TUint8* usrEnd = (TUint8*)(usrStart + aThread->iUserStackSize);
-		if(usrStart) 
-			{
-			TUint8* stackPointer = (TUint8*)usrSp;			
-			
-			//check the stack pointer is in the range of the stack...
-			if (stackPointer < usrStart || stackPointer >= usrEnd)
-				{
-				stackPointer = usrStart;
-				}
-			
-			//log the size of the stack we are dumping
-			usrStack.iStackSize = aFullStack || (stackPointer == usrStart) ? usrEnd - usrStart : usrEnd - stackPointer;
-			TUint8* dumpFrom = aFullStack ? usrStart : stackPointer;
-			
-			//write the stack
-			aSizeDumped+= usrStack.GetSize();
-			usrStack.Serialize(*iWriter);					
-			
-			//now we dump the actual stack
-			//if there is a memErr when we read, there isnt much we can do - possibly a bit in the struct to say available/not available?
-			//-1 because we dont want to write the byte at usrEnd			
-			MTRAPD(memErr, LogMemory(dumpFrom, usrStack.iStackSize, aThread, memDumped));			
-			if(KErrNone != memErr)
-				{
-				CLTRACE("Failed to log usr stack");
-				}
-			
-			aSizeDumped+= memDumped;					
-			}
-		else
-			{
-			//write the struct
-			aSizeDumped+=usrStack.GetSize();
-			usrStack.Serialize(*iWriter);
-			}
-		}	
-	return KErrNone;
-	}
-
-/**
- * Logs the supervisor stack for a given DThread object
- * @param aThread - thread whose stack we wish to log
- * @param aSizeDumped Holds the size of the data dumped
- * @return one of the system wide codes
- */
-TInt SCMDataSave::LogThreadSupervisorStack(DThread* aThread, TBool aFullStack, TUint& aSizeDumped)
-	{	
-	LOG_CONTEXT
-	aSizeDumped = 0;
-	TUint memDumped = 0;
-	
-	TUint svSp, usrSp;
-	iMonitor->GetStackPointers(&(aThread->iNThread), svSp, usrSp );
-	
-	//now we dump the supervisor stack
-	TThreadStack svrStack;
-	svrStack.iStackType = TThreadStack::ESvrStack;
-	svrStack.iThreadId = (TUint64)aThread->iId;
-	
-	if (aThread->iSupervisorStack && aThread->iSupervisorStackSize)
-		{
-		TUint8* svrStart = (TUint8*)aThread->iSupervisorStack;
-		TUint8* svrEnd = (TUint8*)(svrStart + aThread->iSupervisorStackSize);
-		TUint8* svrStackPointer = (TUint8*)svSp;
-		
-		//size of stack we are to dump
-		svrStack.iStackSize = aFullStack ? svrEnd - svrStart  : svrEnd - svrStackPointer;					
-		
-		if(svrStart)
-			{
-			//check the stack pointer is in the range of the stack...
-			if (svrStackPointer < svrStart || svrStackPointer >= svrEnd)
-				{
-				svrStackPointer = svrStart;
-				}
-
-			//write struct to flash
-			aSizeDumped += svrStack.GetSize();
-			svrStack.Serialize(*iWriter);
-			
-			//now we dump the actual stack
-			//if there is a memErr when we read, there isnt much we can do - possibly a bit in the struct to say available/not available?
-			MTRAPD(memErr, LogMemory(svrStart, svrStack.iStackSize, aThread, memDumped));
-			aSizeDumped += memDumped;
-			
-			if(KErrNone != memErr)
-				{
-				CLTRACE("Failed to log supervisor stack");
-				}						
-			}
-		else
-			{
-			//write the struct
-			aSizeDumped += svrStack.GetSize();
-			svrStack.Serialize(*iWriter);
-			}
-		}
-	
-	return KErrNone;
-	}
-
-/**
- * Takes a DProcess kernel object and logs its corrosponding code segments
- * @param aProcess
- * @param aSizeDumped Holds the size of the data dumped
- * @return one of the OS wide error codes
- */
-TInt SCMDataSave::LogCodeSegments(DProcess* aProc, TUint& aSizeDumped)
-	{	
-	LOG_CONTEXT
-	aSizeDumped = 0;	
-	
-	//the code segment set for this process
-	TCodeSegmentSet segSet;
-	segSet.iPid = (TUint64)aProc->iId;
-	
-	//make sure list mutex is ok
-	if(Kern::CodeSegLock()->iHoldCount)
-		{
-		return KErrCorrupt;
-		}
-	
-	//get code seg list
-	SDblQue queue;		
-	aProc->TraverseCodeSegs(&queue, NULL, DCodeSeg::EMarkDebug, DProcess::ETraverseFlagAdd);
-	
-	//iterate through the list
-	TInt codeSegCnt = 0;
-	for(SDblQueLink* codeSegPtr= queue.First(); codeSegPtr!=(SDblQueLink*) (&queue); codeSegPtr=codeSegPtr->iNext)
-		{
-		//get the code seg
-		DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iTempLink);
-		
-		if(codeSeg)
-			{
-			codeSegCnt++;
-			}
-		}
-	
-	if(codeSegCnt == 0)
-		{
-		return KErrNone;
-		}	
-	
-	segSet.iNumSegs = codeSegCnt;
-	segSet.Serialize(*iWriter);	
-	aSizeDumped+=segSet.GetSize();
-	
-	TModuleMemoryInfo memoryInfo;
-	
-	//now we write each code segment
-	for(SDblQueLink* codeSegPtr= queue.First(); codeSegPtr!=(SDblQueLink*) (&queue); codeSegPtr=codeSegPtr->iNext)
-		{
-		//get the code seg
-		DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iTempLink);
-		
-		if(codeSeg)
-			{			
-			TCodeSegment seg;									
-			seg.iXip = (codeSeg->iXIP) ? ETrue : EFalse;
-			
-			//Get the code seg type
-			if(codeSeg->IsExe())
-				{
-				seg.iCodeSegType = EExeCodeSegType;
-				}
-			else if(codeSeg->IsDll())
-				{
-				seg.iCodeSegType = EDllCodeSegType;
-				}
-			
-			TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL);
-			if(KErrNone == err)
-				{
-				seg.iCodeSegMemInfo = memoryInfo;
-				}
-			else
-				{
-				seg.iCodeSegMemInfo.iCodeSize = 0; 
-
-				// Still need to indicate it wasnt available somehow
-				}
-			
-			//Get filename			
-			seg.iNameLength = codeSeg->iFileName->Length();
-			seg.iName = *(codeSeg->iFileName);
-			
-			aSizeDumped+=seg.GetSize();
-			seg.Serialize(*iWriter);						
-			}
-		}
-	
-	//Empty this queue and clear marks
-	DCodeSeg::EmptyQueue(queue, DCodeSeg::EMarkDebug);
-	
-	return KErrNone;
-	}
-
-/**
- * This logs the rom version and header information to the crash media
- * @param aSizeDumped amount of data occupied
- * @return one of the OS wide codes
- */
-TInt SCMDataSave::LogRomInfo(TUint& aSizeDumped)	
-	{
-	aSizeDumped = 0;
-	
-	TRomHeaderData romData;
-	
-	TRomHeader rHdr = Epoc::RomHeader();
-	
-	romData.iMajorVersion = rHdr.iVersion.iMajor;
-	romData.iMinorVersion = rHdr.iVersion.iMinor;
-	romData.iBuildNumber = rHdr.iVersion.iBuild;
-	romData.iTime = rHdr.iTime;
-	
-	TInt err = romData.Serialize(*iWriter);
-	if(KErrNone != err)
-		{
-		return err;
-		}
-	
-	aSizeDumped += romData.GetSize();
-	
-	return KErrNone;
-	}
-
-/**
- * Takes a DProcess kernel object and logs to flash
- * @param aProc
- * @param aSizeDumped Holds the size of the data dumped
- * @return one of the OS wide error codes
- */
-TInt SCMDataSave::LogProcessData(DProcess* aProc, TUint& aSizeDumped)
-	{	
-	LOG_CONTEXT
-	aSizeDumped = 0;	
-	
-	TProcessData procData;
-	DCodeSeg* codeSeg = aProc->iCodeSeg;
-
-	procData.iPriority = aProc->iPriority;
-	procData.iPid = (TUint64)aProc->iId;
-	
-	//the code segment is not always available
-	if(codeSeg)
-		{
-		procData.iNamesize = codeSeg->iFileName->Length();
-		procData.iName = *(codeSeg->iFileName);
-		}
-	
-	aSizeDumped += procData.GetSize();
-	procData.Serialize(*iWriter);
-	
-	return KErrNone;
-	}
-
-/**
- * Creates meta data about the crash such as time of crash, exit reason etc. to be logged
- * later on when we have log size.
- * @param aCategory - crash category
- * @param aReason - crash reason
- * @param aSizeDumped Holds the size of the data dumped
- * @return one of the OS wide codes
- */
-TInt SCMDataSave::LogCrashHeader(const TDesC8& aCategory, TInt aReason, TInt aCrashId, TUint& aSizeDumped)
-	{
-	LOG_CONTEXT
-	aSizeDumped = 0;
-	
-	//the thread that crashed is the context in which we are running
-	DThread* crashedThread = &Kern::CurrentThread();
-	
-	iCrashInf.iPid = crashedThread->iOwningProcess->iId; 
-	iCrashInf.iTid = crashedThread->iId;
-	iCrashInf.iCrashTime = CrashTime();
-	iCrashInf.iExitType = 0; // Not yet done: Exception or Fault - should be in category
-	iCrashInf.iExitReason = aReason;
-	iCrashInf.iFlashAlign = KFlashAlignment; //record the flash alignment (word aligned for now)
-	iCrashInf.iCachedWriterSize = iWriter->GetCacheSize();
-	
-	iCrashInf.iCategorySize = aCategory.Length();
-	iCrashInf.iCategory = aCategory;	
-	iCrashInf.iCrashId = aCrashId;
-	
-	iCrashInf.iFlashBlockSize = KCrashLogBlockSize;;
-	iCrashInf.iFlashPartitionSize = KCrashLogSize;;
-	
-	TSuperPage& sp=Kern::SuperPage();
-	iCrashInf.iExcCode = sp.iKernelExcId;
-
-	//These will be updated with more info at end of crash
-	aSizeDumped+=iCrashInf.GetSize();
-	iCrashInf.Serialize(*iWriter);
-	
-	aSizeDumped+=iHdr.GetSize();
-	iHdr.Serialize(*iWriter);		
-
-	CLTRACE1("(SCMDataSave::LogCrashHeader) finished bytes written= %d", iWriter->GetBytesWritten());
-	return KErrNone;
-	}
-
-/**
- * Logs meta data about a given DThread object
- * @param aThread Thread to dump
- * @param aSizeDumped Holds the size of the data dumped
- * @return
- */
-TInt SCMDataSave::LogThreadData(DThread* aThread, TUint& aSizeDumped)
-	{
-	LOG_CONTEXT
-	aSizeDumped = 0;	
-	
-	//struct to hold data that gets written to flash
-	TThreadData threadData;
-	
-	threadData.iTid = (TUint64)aThread->iId;
-	threadData.iOwnerId = (TUint64)aThread->iOwningProcess->iId;
-	threadData.iPriority = aThread->iThreadPriority;
-	
-	//Get the stack pointers	
-	TUint svSp, usrSp;
-	iMonitor->GetStackPointers(&(aThread->iNThread), svSp, usrSp );
-	threadData.iUsrSP = usrSp;
-	threadData.iSvcSP = svSp;
-		
-	//supervisor and user stack details
-	threadData.iSvcStack = (TInt32)aThread->iSupervisorStack;
-	threadData.iSvcStacksize = aThread->iSupervisorStackSize;
-	threadData.iUsrStack = aThread->iUserStackRunAddress;
-	threadData.iUsrStacksize = aThread->iUserStackSize;	
-	
-	//currently we can only get the kernels heap
-	if(aThread == &Kern::CurrentThread())
-		{
-		TInt32 heapLoc = 0;
-		TInt32 heapSz = 0;
-		TInt err = FindKernelHeap(heapLoc,heapSz);
-		if(KErrNone == err)
-			{
-			threadData.iSvcHeap = heapLoc;
-			threadData.iSvcHeapSize = heapSz;
-			}
-		else
-			{
-			CLTRACE("\tError: Unable to get kernel heap");
-			}
-		}	
-	
-	//get filename	
-	TFileName filename;
-	aThread->TraceAppendFullName(filename, EFalse);
-	
-	threadData.iName.Copy(filename);
-	threadData.iNamesize = threadData.iName.Length();
-	
-		
-#ifdef __INCLUDE_NTHREADBASE_DEFINES__
-	threadData.iLastCpu = aThread->iNThread.iLastCpu;
-#else	
-	threadData.iLastCpu = aThread->iNThread.iSpare3;	
-#endif	
-	
-	threadData.Serialize(*iWriter);
-	aSizeDumped+=threadData.GetSize();
-	
-	return KErrNone;
-	}
-
-/**
- * Logs the arm exception stacks 
- * @param aSizeDumped Holds the size of the data dumped 
- * @return one of the OS wide codes
- */
-TInt SCMDataSave::LogExceptionStacks(TUint& aSizeDumped)
-	{
-	LOG_CONTEXT
-	aSizeDumped = 0;
-	TUint memDumped = 0;
-	
-	#if defined(__EPOC32__) && !defined(__CPU_X86)
-
-	TStackInfo& stackInfo = Kern::SuperPage().iStackInfo;
-
-	TThreadStack irqStack;
-	irqStack.iStackType = TThreadStack::EIRQStack;
-	irqStack.iStackSize = stackInfo.iIrqStackSize;
-	
-	aSizeDumped+=irqStack.GetSize();
-	irqStack.Serialize(*iWriter);
-	
-	//now dump the IRQ memory - not much we can do in the event of an error
-	MTRAPD(irqErr, LogMemory((TUint8*)stackInfo.iIrqStackBase, stackInfo.iIrqStackSize, &Kern::CurrentThread(), memDumped));	
-	
-	if(KErrNone != irqErr)
-		{
-		CLTRACE("*****Failed to log IRQ stack");
-		}
-	aSizeDumped+=memDumped;
-	
-	//Next, we do the FIQ stack
-	TThreadStack fiqStack;
-	fiqStack.iStackType = TThreadStack::EFIQStack;
-	fiqStack.iStackSize = stackInfo.iFiqStackSize;
-	
-	aSizeDumped+=fiqStack.GetSize();
-	fiqStack.Serialize(*iWriter);
-	
-	//Now dump the stack itself
-	MTRAPD(fiqErr, LogMemory((TUint8*)stackInfo.iFiqStackBase, stackInfo.iFiqStackSize, &Kern::CurrentThread(), memDumped));
-	
-	if(KErrNone != fiqErr )
-		{
-		CLTRACE("*****Failed to log FIQ stack");
-		}
-	aSizeDumped+=memDumped;
-
-	#endif
-	
-	return KErrNone;
-	}
-
-/**
- * Logs the CPU Registers at the time of crash
- * @param aSizeDumped Holds the size of the data dumped
- * @return system wide OS code
- */
-TInt SCMDataSave::LogCPURegisters(TUint& aSizeDumped)
-	{
-	LOG_CONTEXT
-	aSizeDumped = 0;
-	
-	TInt32 fullSet = 37;
-	
-	//meta data about the thread set
-	TRegisterSet threadSet;
-	threadSet.iNumRegisters = fullSet;
-	
-	aSizeDumped+=threadSet.GetSize();
-	threadSet.Serialize(*iWriter);
-		
-	SFullArmRegSet regSet;
-	ReadCPURegisters(regSet);
-	TArmReg* regs = (TArmReg*)&regSet;
-		
-	TInt32 cnt = 0;
-	for(cnt = 0; cnt < fullSet; cnt++)
-		{			
-		//this is the struct to store the register value in
-		TRegisterValue regVal;
-		regVal.iType = cnt * 0x100;
-		regVal.iValue32 = regs[cnt];
-		regVal.iOwnId = Kern::CurrentThread().iId;
-		
-		aSizeDumped+=regVal.GetSize();
-		regVal.Serialize(*iWriter);
-		}
-
-	return KErrNone;	
-	}
-
-/**
- * This logs the registers for a given thread to the flash memory
- * @param aThread - thread whose registers we want
- * @param aRegType - type of register set required such as user, supervisor etc
- * @param aSizeDumped Holds the size of the data dumped
- * @return one of the OS return codes
- */
-TInt SCMDataSave::LogRegisters(DThread* aThread, const TRegisterSetType& aRegType, TUint& aSizeDumped)
-	{
-	LOG_CONTEXT
-	aSizeDumped = 0;
-	
-	TArmRegSet regs;
-	TUint32 availableRegs;
-	TInt err;
-	
-	//for the current thread we do things differently
-	if(aThread == &Kern::CurrentThread() && aRegType == EFullCPURegisters)
-		{
-		err = LogCPURegisters(aSizeDumped);
-		return err;
-		} 
-	else if(aThread == &Kern::CurrentThread())
-		{
-		//only do full cpu reg for the current thread
-		return KErrNotSupported;
-		}
-	
-	//Read the appropriate registers
-	switch(aRegType)
-		{
-		case EUserRegisters :
-			{
-			err = ReadUserRegisters(aThread, regs, availableRegs);
-			break;
-			}
-		case ESupervisorRegisters :
-			{
-			err = ReadSystemRegisters(aThread, regs, availableRegs);
-			break;			
-			}
-		default : return KErrNotSupported;
-		}
-	
-	if(err != KErrNone)
-		{
-		return err;
-		}	
-		
-	//meta data about the thread set
-	TRegisterSet threadSet;
-	
-	//to get the number of registers in advance, we need to count the number of times 1 is set in the bit field of availableRegs
-	TUint numR = 0;
-	for(TInt cnt =0; cnt< 8*sizeof(availableRegs); cnt++) //cycle through 1 bit at a time
-		{
-		if(0x1 & (availableRegs>>cnt))
-			numR++;
-		}
-	
-	threadSet.iNumRegisters = numR;
-	
-	if(numR == 0)
-		return KErrNone;
-	
-	threadSet.Serialize(*iWriter);
-	aSizeDumped += threadSet.GetSize();
-	
-	TInt32 currentRegister = 1;
-	TArmReg* reg = (TArmReg*)(&regs);	
-	
-	for(TInt32 cnt = 0; cnt < KArmRegisterCount; cnt++)
-		{		
-		//look at the unavailable bitmask to see current register is available
-		//only write the registers we have values for
-		if(currentRegister & availableRegs)
-			{
-			//this is the struct to store the register value in
-			TRegisterValue regVal;
-						
-			//get register type as per symbian elf docs
-			TUint32 registerType;
-			err = GetRegisterType(aRegType, cnt, registerType);
-			if(err != KErrNone)
-				{
-				continue;
-				}
-			regVal.iType = registerType;
-			regVal.iOwnId = aThread->iId;
-			
-			//set value
-			regVal.iValue32 = reg[cnt];
-			
-			aSizeDumped+=regVal.GetSize();
-			regVal.Serialize(*iWriter);
-			}
-		
-		currentRegister<<=1; 
-		}
-	
-	return KErrNone;
-	}
-
-/**
- * This logs memory in the specified area
- * @param aStartAddress - address to start from
- * @param aEndAddress - address to finish
- * @param aThread - process whose memory this is in
- * @param aSizeDumped Holds the size of the data dumped
- * @return one of the system wide codes
- */
-TInt SCMDataSave::LogMemory(const TUint8* aStartAddress, TInt aLength, const DThread* aThread, TUint& aSizeDumped)
-	{
-	LOG_CONTEXT
-	aSizeDumped = 0;	
-	
-	if(aThread->iOwningProcess != &Kern::CurrentProcess())
-		{
-		TInt err = iMonitor->SwitchAddressSpace(aThread->iOwningProcess, ETrue);
-		if(KErrNone != err)
-			{
-			return err;
-			}
-		}
-	
-	TMemoryDump memDump;
-	memDump.iStartAddress = (TUint32)aStartAddress;
-	memDump.iLength = aLength;
-	memDump.iPid = aThread->iOwningProcess->iId;
-	
-	aSizeDumped+=memDump.GetSize();
-	memDump.Serialize(*iWriter);	
-	
-	if(!aStartAddress)
-		{
-		return KErrArgument;
-		}
-	
-	TRawData theMemory;
-	theMemory.iData.Set(const_cast<TUint8*>(aStartAddress), aLength, aLength);
-	
-	theMemory.Serialize(*iWriter);
-	aSizeDumped+=theMemory.GetSize();
-	
-	return KErrNone;	
-	}
-
-/**
- * This logs the locks held by system at time of crash
- * @param aSizeDumped Holds the size of the data dumped
- * @return one of the system wide codes
- */
-TInt SCMDataSave::LogLocks(TUint& aSizeDumped)
-	{
-	LOG_CONTEXT
-	aSizeDumped = 0;
-	
-	// get the mutex logs & waits & log via a TLockData object		
-	TSCMLockData lockData;
-
-	const TInt KMaxLockCheck = 20; // so no possibility of infinite loop
-		
-	TInt lockCount = 0;
-	// check for kernel locks - 	
-	for(TInt i=0;i<KMaxLockCheck;i++)
-		{		
-		TBool locked = NKern::KernelLocked(i);	
-		if(!locked)
-			{
-			lockData.SetLockCount(lockCount);
-			break;		
-			}
-		// found a valid lock for value i increment the clock counter
-		lockCount++;
-		}
-	
-	// now mutexes
-	DMutex* mutex = Kern::CodeSegLock();
-	if(mutex)
-		{
-		lockData.SetMutexHoldCount(mutex->iHoldCount);
-		lockData.SetMutexThreadWaitCount(mutex->iWaitCount);
-		}
-	else
-		{
-		// no mutex held set to -1
-		lockData.SetMutexHoldCount(0);
-		lockData.SetMutexThreadWaitCount(0);		
-		}
-
-	aSizeDumped+=lockData.GetSize();
-	TInt err = lockData.Serialize(*iWriter);
-	
-	return err;
-	}
-
-/**
- * Writes the SCM Configuration to the start of the media
- * @param aScmConfig Configuration to write
- * @return one of the system wide codes
- */
-TInt SCMDataSave::LogConfig(SCMConfiguration& aScmConfig)
-	{
-	iWriter->SetPosition(0);
-	
-	TInt err = aScmConfig.Serialize(*iWriter);
-	
-	if( err != KErrNone)
-		{
-		CLTRACE1("SCMDataSave::LogConfig failed err = %d", err);
-		}
-
-	return err;
-	}
-
-/**
- * Reads the SCM Configuration from the media
- * @param aScmConfig
- * @return one of the system wide codes
- */
-TInt SCMDataSave::ReadConfig(SCMConfiguration& aScmConfig)
-	{		
-	const TInt KBufSize = 135; //Not yet done: Put in header, beside config defn
-
-	if( KBufSize < aScmConfig.GetSize())
-		{
-		CLTRACE2("(SCMDataSave::ReadConfig) ** ERROR Inadequate buffer actual = %d req = %d"
-				, KBufSize,  aScmConfig.GetSize());	
-		}
-	
-	// try and read the configuration
-	TBuf8<KBufSize> buf;
-	buf.SetLength(KBufSize);
-		
-	iFlash->SetReadPos(0); // config always at 0
-	iFlash->Read(buf);
-	 
-	TByteStreamReader reader(const_cast<TUint8*>(buf.Ptr()));		
-	TInt err = aScmConfig.Deserialize(reader);	
-	if(err == KErrNotReady)
-		{
-		CLTRACE("(SCMDataSave::ReadConfig) no config saved - use default");
-		}	
-	else if(err == KErrNone)	
-		{
-		CLTRACE("(SCMDataSave::ReadConfig) Config read ok"); 		
-		}
-	else
-		{
-		CLTRACE1("(SCMDataSave::ReadConfig) error reading config err = %d", err); 
-		}
-	
-	return err;
-	}
-
-/**
- * This is a look up table to map the register type and number to the symbian elf definition 
- * of register type
- * @param aSetType this is the register set type - user, supervisor etc
- * @param aRegNumber this is the number of the register as per TArmRegisters in arm_types.h
- * @param aSizeDumped Holds the size of the data dumped
- * @return One of the OS wide codes
- */
-TInt SCMDataSave::GetRegisterType(const TRegisterSetType& aSetType, TInt32& aRegNumber, TUint32& aRegisterType)
-	{	
-	//validate arguments
-	if(aRegNumber < EArmR0 || aRegNumber > EArmFlags)
-		{
-		return KErrArgument;
-		}
-	
-	//look at what type we are using
-	switch(aSetType)
-		{
-		case EUserRegisters :
-			{
-			aRegisterType = aRegNumber * 0x100; //for R0 to R16 (CPSR) it just increments in 0x100 from 0x0 to 0x1000
-			break;
-			}
-		case ESupervisorRegisters :
-			{
-			//same as EUserRegisters except R13 and R14 are different
-			if(aRegNumber == EArmSp)
-				{
-				aRegisterType = 0x1100;
-				break;
-				}
-			else if(aRegNumber == EArmLr)
-				{
-				aRegisterType = 0x1200;
-				break;
-				}
-			else
-				{
-				aRegisterType = aRegNumber * 0x100;
-				break;
-				}		
-			}
-		default : return KErrNotSupported;
-		}
-	
-	return KErrNone;
-	}
-
-/**
- * Writes the trace buffer to the crash log. 
- * @param aSizeToDump Number of bytes to dump. If this is zero we attempt to write the entire buffer
- * @param aSizeDumped Holds the size of the data dumped
- * @return One of the OS wide codes
- */
-TInt SCMDataSave::LogTraceBuffer(TInt aSizeToDump, TUint& aSizeDumped)
-	{
-	LOG_CONTEXT
-	aSizeDumped = 0;
-	TUint memDumped = 0;
-	
-	TBool dumpAll = (aSizeToDump == 0) ? ETrue : EFalse;
-	
-	//Because the btrace buffer is a circular one, we need to save it in two parts
-	//this corrosponds to how we read it	
-	TUint8* data;
-	TUint sizeOfPartRead;
-	TInt spaceRemaining = aSizeToDump;
-	
-	//This structure will be filled after the first pass and cached so by the time we ARE writing it will
-	//contain the data we want 
-	aSizeDumped+=iTrace.GetSize();
-	iTrace.Serialize(*iWriter);
-	
-	//read first part
-	TInt err = BTrace::Control(BTrace::ECtrlCrashReadFirst,&data,&sizeOfPartRead);
-	
-	while(KErrNone == err && sizeOfPartRead > 0)
-		{
-		TUint rawSize = 0; //how much of this read data want we to dump
-		
-		if(dumpAll)
-			{
-			rawSize = sizeOfPartRead;
-			}
-		else	//Otherwise see what room is left for dumpage
-			{
-			rawSize  = ((sizeOfPartRead + iTrace.iSizeOfMemory) > aSizeToDump) ? spaceRemaining : sizeOfPartRead;
-			}		
-		
-		//Only relevant if restricting the dump
-		if(spaceRemaining <= 0 && !dumpAll)
-			break;
-		
-		TPtrC8 ptr(data, rawSize);
-		err = LogRawData(ptr, memDumped);
-		if(KErrNone != err)
-			{
-			CLTRACE1("Logging Raw data failed - [%d]", err);
-			err = BTrace::Control(BTrace::ECtrlCrashReadNext,&data,&sizeOfPartRead);
-			continue;
-			}
-		
-		aSizeDumped+=memDumped;
-		
-		iTrace.iSizeOfMemory += rawSize;
-		iTrace.iNumberOfParts++;
-		spaceRemaining -= rawSize;		
-		
-		err = BTrace::Control(BTrace::ECtrlCrashReadNext,&data,&sizeOfPartRead);
-		}
-	
-	return KErrNone;
-	}
-
-/**
- * Logs the data in a TRawData struct
- * @param aData 
- * @param aSizeDumped Holds the size of the data dumped
- * @return One of the OS wide codes
- */
-TInt SCMDataSave::LogRawData(const TDesC8& aData, TUint& aSizeDumped)
-	{
-	TRawData theData;
-	theData.iLength = aData.Length();
-	theData.iData.Set(const_cast<TUint8*>(aData.Ptr()), aData.Length(), aData.Length());
-	
-	aSizeDumped+=theData.GetSize();
-	return theData.Serialize(*iWriter);	
-	}
-
-
-/**
- * Logs the kernels heap and returns the size dumped via aSizeDumped
- * @param aSizeDumped Holds the size of the data dumped
- * @return
- */
-TInt SCMDataSave::LogKernelHeap(TUint& aSizeDumped)
-	{
-	LOG_CONTEXT
-	
-	TInt32 heapLoc = 0;
-	TInt32 heapSize = 0;
-	TInt32 err = FindKernelHeap(heapLoc, heapSize);
-	if(KErrNone == err)
-		{
-		return LogMemory((TUint8*)heapLoc, heapSize, &Kern::CurrentThread(), aSizeDumped);
-		}
-	
-	CLTRACE1("\tCouldnt find the kernel heap: [%d]", err);
-	return err;
-	}
-
-/**
- * Iterates the object containers and finds the kernel heap
- * @param aHeapLocation Contains the memory location of the kernel heap
- * @param aHeapSize Contains the size of the Heap
- * @return One of the OS wide codes
- */
-TInt SCMDataSave::FindKernelHeap(TInt32& aHeapLocation, TInt32& aHeapSize)
-	{
-	LOG_CONTEXT
-	
-	//Get process object container
-	DObjectCon* objectContainer = Kern::Containers()[EProcess];
-	if(objectContainer == NULL)
-		{		
-		CLTRACE("\tFailed to get object container for the processes");
-		return KErrNotFound;
-		}
-	
-	//Must check the mutex on this is ok otherwise the data will be in an inconsistent state
-	if(objectContainer->Lock()->iHoldCount)
-		{
-		CLTRACE("\tChunk Container is in an inconsistant state");
-		return KErrCorrupt;
-		}
-	
-	TInt numObjects = objectContainer->Count();	
-	
-	DProcess* kernelProcess = NULL;
-	for(TInt cnt = 0; cnt < numObjects; cnt ++)
-		{		
-		DProcess* candidateProcess = (DProcess*)(*objectContainer)[cnt];
-		
-		//Get the objects name
-		TBuf8<KMaxKernelName> name;
-		candidateProcess->TraceAppendFullName(name,EFalse);		
-		if(name == KKernelProcessName)
-			{
-			kernelProcess = candidateProcess;
-			}
-		}
-	if (!kernelProcess)
-		return KErrNotFound;
-
-	//Get chunk object container
-	objectContainer = Kern::Containers()[EChunk];
-	if(objectContainer == NULL)
-		{		
-		CLTRACE("\tFailed to get object container for the chunks");
-		return KErrNotFound;
-		}
-	
-	//Must check the mutex on this is ok otherwise the data will be in an inconsistent state
-	if(objectContainer->Lock()->iHoldCount)
-		{
-		CLTRACE("\tChunk Container is in an inconsistant state");
-		return KErrCorrupt;
-		}	
-	
-	numObjects = objectContainer->Count();
-	for(TInt cnt = 0; cnt < numObjects; cnt ++)
-		{		
-		DChunk* candidateHeapChunk = (DChunk*)(*objectContainer)[cnt];
-		
-		//Get the objects name
-		TBuf8<KMaxKernelName> name;
-		candidateHeapChunk->TraceAppendFullName(name,EFalse);
-		
-		if(name == KKernelHeapChunkName)
-			{
-			aHeapLocation = (TInt32)candidateHeapChunk->Base(kernelProcess);
-			aHeapSize = candidateHeapChunk->iSize;
-			return KErrNone;
-			}
-		}
-	
-	return KErrNotFound;
-	}
-
-/**
- * This logs the variant specific descriptor data to the crash log
- * @param aSizeDumped records how much was dumped by this function
- * @return one of the OS wide codes
- */
-TInt SCMDataSave::LogVariantSpecificData(TUint& aSizeDumped)
-	{
-	LOG_CONTEXT
-	
-	aSizeDumped = 0;
-	
-	//Change this descriptor as required for your needs
-	_LIT(KVariantSpecificData, "This is the variant specific data. Put your own here");
-	
-	TVariantSpecificData varData;
-	varData.iSize = KVariantSpecificData().Size(); 
-	
-	TInt err = varData.Serialize(*iWriter);
-	if(KErrNone != err)
-		{
-		CLTRACE1("\tLogging variant specific data failed with code [%d]", err);
-		return err;
-		}
-	aSizeDumped+=varData.GetSize();
-	
-	TUint rawDataSize = 0;
-	err = LogRawData(KVariantSpecificData(), rawDataSize);
-	if(KErrNone != err)
-		{
-		CLTRACE1("\tLogging variant specific data failed with code [%d]", err);
-		return err;
-		}
-	
-	aSizeDumped+=rawDataSize;
-	
-	return KErrNone;
-	}
-
-
-/**
- * This method is the callback used by MPhysicalWriterImpl interface
- * if the TCachedByteStreamWriter is configured to use this interface
- * the callback avoids the need for temp buffers & can interface directly with the
- * flash writer methods
- * @param aData - data to write
- * @param aLen	- length of data to write
- * @param aPos  - writers internal position   
- */
-void SCMDataSave::DoPhysicalWrite(TAny* aData, TInt aPos, TInt aLen)
-	{	
-	if(iPerformChecksum)
-		{
-		iChecksum.ChecksumBlock((TUint8*)aData, aLen);
-		}
-	
-	if( this->iWriteSelect == EWriteComm)
-		{	
-		WriteUart((TUint8*)aData, aLen);		
-		}
-	else  // EWriteFlash
-		{			
-		Write(aData, aLen);
-		}
-	}
-
-/**
- * Writes data to Flash
- * @param aSomething Pointer to the data
- * @param aSize Size of the data
- */
-void SCMDataSave::Write(const TAny* aSomething, TInt aSize)
-	{		
-	TPtrC8 data((const TUint8 *)aSomething, aSize);
-	
-	TInt written = 0;
-	
-	WriteCrashFlash(iByteCount, written, data);
-	iByteCount+= written;	
-	}
-
-/**
- * Writes a descriptor to the crash flash
- * @param aPos Position in flash to write
- * @param aSize Holds the size of the data written after the call
- * @param aBuffer Descriptor to write
- */
-void SCMDataSave::WriteCrashFlash(TInt aPos, TInt& aSize, const TDesC8& aBuffer)
-	{	
-	//Set write position in the flash
-	iFlash->SetWritePos(aPos);	
-	iFlash->Write(aBuffer);
-	
-	//get bytes written
-	aSize += iFlash->BytesWritten();
-	
-	if(aSize != aBuffer.Length())
-		{
-		CLTRACE2("(SCMDataSave::WriteCrashFlash) Over the limit aSize = %d aBuffer.Length() = %d",
-				aSize,  aBuffer.Length());
-		}
-	}
-	
-/**
- * Writes a descriptor via serial
- * @param aDes Descriptor to write
- */
-void SCMDataSave::WriteUart(const TDesC8& aDes)
-	{
-	WriteUart(aDes.Ptr(), aDes.Length());	
-	}
-
-/**
- * Writes data via serial
- * @param aData Data to write
- * @param aSize Size of data to write
- */
-void SCMDataSave::WriteUart(const TUint8* aData, TInt aSize)
-	{
-	OMAP* assp = ((OMAP*)Arch::TheAsic());
-	TOmapDbgPrt* dbg = assp->DebugPort();
-		
-	if (dbg)
-		{
-		for(TInt i=0;i<aSize;i++)
-			{
-			dbg->DebugOutput(*(aData+i));			
-			}
-		}
-	else
-		{
-		CLTRACE("SCMDataSave::WriteUart ERROR - dbg was null");		
-		}
-	}
-
-/**
- * Setter for the current number of bytes written for this crash log
- * If aByte is not word aligned, it will be rounded up to be so
- * @param aByte Current bytes written
- */
-void SCMDataSave::SetByteCount(TInt aByte)
-	{
-	//ensure aligned
-	if(aByte % iWriter->GetCacheSize() == 0)
-		{
-		iByteCount = aByte;
-		}
-	else
-		{
-		iByteCount = aByte + (iWriter->GetCacheSize() - (aByte % iWriter->GetCacheSize()));
-		}		
-	}
-
-/**
- * Gets the output target selection
- * @return TScmWriteSelect output target selection
- * @param void
- */	
-SCMDataSave::TWriteSelect SCMDataSave::GetWriteSelect()
-	{
-	return iWriteSelect;
-	}
-
-/**
- * Sets the output target selection
- * @return void
- * @param TScmWriteSelect aWriteSelect output target selection
- */
-void SCMDataSave::SetWriteSelect(SCMDataSave::TWriteSelect aWriteSelect)
-	{
-	iWriteSelect = aWriteSelect;
-	}
-
-/**
- * Gets the amount of space remaining for the media of choice
- * @return
- */
-TUint SCMDataSave::SpaceRemaining()
-	{
-	TInt currentPosition = iWriter->GetBytesWritten() + iStartingPointForCrash;
-	
-	return MaxLogSize() - currentPosition; 
-	}
-
-/**
- * To find the max size of a log for a given media
- * @return the max size of a log for a given media
- */
-TUint SCMDataSave::MaxLogSize()
-	{
-	//see what write media is being used
-	switch(GetWriteSelect())
-		{
-		case EWriteFlash:
-			{
-			return KMaxCrashLogSize; 
-			}
-		case EWriteComm:
-			{
-			return 0xFFFFFFFF;
-			}
-		default:
-			{
-			return 0;
-			}
-		} 
-	}
-
-/**
- * Records the offset in the flash partition where this crash begins
- * @param aStart Offset in flash
- */
-void SCMDataSave::SetCrashStartingPoint(TUint32 aStart)
-	{
-	iStartingPointForCrash = aStart;
-	}
-
-//eof
-