--- 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*)®Set;
-
- 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*)(®s);
-
- 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
-