--- a/kernel/eka/debug/crashMonitor/src/crashlogwalker.cpp Wed Oct 20 13:58:28 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,535 +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\crashlogwalker.cpp
-// Class to allow us to traverse the crash log generated by System Crash Monitor
-//
-//
-
-/**
- @file
- @internalTechnology
-*/
-
-#ifndef __KERNEL_MODE__
-#include <e32std.h>
-#include <e32std_private.h>
-#include <e32base.h>
-#include <e32base_private.h>
-#endif
-
-#include "scmtrace.h"
-#include "crashlogwalker.h"
-
-namespace Debug
- {
- /**
- * Constructor for log walker
- * @param aBuffer The buffer containing the crash data
- */
- TCrashLogWalker::TCrashLogWalker(TDesC8& aBuffer) :
- iBuffer(aBuffer),
- iReader(const_cast<TUint8*>(iBuffer.Ptr()))
- {
- }
-
- /**
- * This reads in the crash header from the buffer from the given start point
- * @param aStartPoint Point to begin reading in buffer
- * @return One of the OS wide codes
- */
- TInt TCrashLogWalker::ReadLogHeader(const TInt aStartPoint)
- {
- iReader.SetPosition(aStartPoint);
-
- TInt err = iCrashHeader.Deserialize(iReader);
- if(err != KErrNone)
- {
- CLTRACE("(TCrashLogWalker::ReadLogHeader) - failed to read crash header");
- return KErrCorrupt;
- }
-
- err = iOffsets.Deserialize(iReader);
- if(err != KErrNone)
- {
- CLTRACE("(TCrashLogWalker::ReadLogHeader) - failed to read offsets");
- return KErrCorrupt;
- }
-
- TRegisterSet set;
- err = set.Deserialize(iReader);
- if(err != KErrNone)
- {
- CLTRACE("(TCrashLogWalker::ReadLogHeader) - failed to read register set");
- return KErrCorrupt;
- }
-
- for(TInt cnt = 0; cnt < set.iNumRegisters; cnt++)
- {
- TRegisterValue val;
- err = val.Deserialize(iReader);
- if(err != KErrNone)
- {
- CLTRACE1("(TCrashLogWalker::ReadLogHeader) - failed to read TRegisterValue cnt = %d", cnt);
- return KErrCorrupt;
- }
-
- HelpAssignRegisterToContext(val);
- }
-
- return VerifyHeader();
- }
-
- /**
- * Getter for the crash context - This is the CPU register set at the time of crash
- * @return Crash Context
- */
- const TRmdArmExcInfo& TCrashLogWalker::GetCrashContext() const
- {
- return iContext;
- }
-
- /**
- * Returns the crash size for the crash that has just been read, provided the
- * reading of the header was succesful.
- * @see ReadLogHeader
- * @return Crash Log size
- */
- TInt TCrashLogWalker::GetCrashSize() const
- {
- return iCrashHeader.iLogSize;
- }
-
- /**
- * Returns the crash ID for the crash that has just been read, provided the
- * reading of the header was succesful.
- * @see ReadLogHeader
- * @return Crash Log ID
- */
- TInt TCrashLogWalker::GetCrashId() const
- {
- return iCrashHeader.iCrashId;
- }
-
- /**
- * Looks at the member crash log header and checks that it is valid.
- * @see ReadLogHeader
- * @return one of the OS wide codes
- */
- TInt TCrashLogWalker::VerifyHeader()
- {
- if(iCrashHeader.iId == ESCMTCrashInfo)
- {
- CLTRACE("TCrashLogWalker::VerifyHeader() OK");
- return KErrNone;
- }
- else
- {
- CLTRACE("TCrashLogWalker::VerifyHeader() FAILED");
- return KErrCorrupt;
- }
- }
-
- /**
- * Updates the buffer being used by the crash walker and resets reader to use
- * the beginning of this
- * @param aBuffer New buffer
- */
- void TCrashLogWalker::UpdateBuffer(TDesC8& aBuffer)
- {
- iBuffer = aBuffer;
-
- //Read from start of this buffer
- iReader = TByteStreamReader(const_cast<TUint8*>(aBuffer.Ptr()));
- }
-
-#ifndef __KERNEL_MODE__
- /**
- * Gets the next data type from the buffer. If this is NULL it means the buffer was too small.
- * Call again with a larger buffer. It assumes the buffer contains valid data and leaves with KErrCorrupt
- * if it isnt. Note for raw data types, the data will be empty. This should be read with GetRawDataTypeL after reseting the reader to the
- * correct position. If you just want to skip a raw data type, move the buffer along the size of (contained in the returned struct)
- *
- * @see GetRawDataTypeL
- * @see UpdateBuffer
- * @param aPos Next position that will be read. If we return NULL, this is the position the next buffer should
- * begin from
- * @param aId ID of the MByteStreamSerializable returned
- * @param buffer size to be used the next time. Unchanged if the current buffer is ok
- * @return MByteStreamSerializable pointer. Ownership is passed to caller. NULL if failed
- * @leave KErrCorrupt if the buffer cant be read
- */
- MByteStreamSerializable* TCrashLogWalker::GetNextDataTypeL(TInt& aPos, SCMStructId& aId, TInt& aBufferSize)
- {
- MByteStreamSerializable* data = NULL;
-
- TInt roomInBuffer = iBuffer.Length() - iReader.CurrentPosition();
- //make sure we have at LEAST 4 bytes in the buffer
- if(roomInBuffer < (TInt)(sizeof(TInt)))
- {
- aBufferSize = sizeof(TInt);
- return NULL;
- }
-
- //this stores the required size in which to deserialize a structure - to make sure
- //there is room in the buffer
- TInt maxSize = 0;
- aPos = iReader.CurrentPosition();
- aBufferSize = iBuffer.Length();
-
- //all these data types are defined by their first byte
- aId = (SCMStructId)iBuffer.Ptr()[iReader.CurrentPosition()];
-
- //ensure we have a valid structure found
- if(aId <= 0 || aId >= ESCMLast)
- {
- //oddness is afoot and the mist of corruption reigns thick
- User::Leave(KErrCorrupt);
- }
-
- switch(aId)
- {
- case ESCMOffsetsHeader:
- {
- data = new TCrashOffsetsHeader();
- maxSize = TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize;
- break;
- }
- case ESCMTCrashInfo:
- {
- data = new TCrashInfoHeader();
- maxSize = TCrashInfoHeader::KSCMCrashInfoMaxSize;
- break;
- }
- case ESCMProcessData:
- {
- data = new TProcessData();
- maxSize = TProcessData::KSCMProcessDataMaxSize;
- break;
- }
- case ESCMThreadData:
- {
- data = new TThreadData();
- maxSize = TThreadData::KSCMThreadDataMaxSize;
- break;
- }
- case ESCMThreadStack:
- {
- data = new TThreadStack();
- maxSize = TThreadStack::KSCMThreadStackMaxSize;
- break;
- }
- case ESCMRegisterValue:
- {
- data = new TRegisterValue();
- maxSize = TRegisterValue::KSCMRegisterValueMaxSize;
- break;
- }
- case ESCMRegisterSet:
- {
- data = new TRegisterSet();
- maxSize = TRegisterSet::KSCMRegisterSetMaxSize;
- break;
- }
- case ESCMMemory:
- {
- data = new TMemoryDump();
- maxSize = TMemoryDump::KSCMMemDumpMaxSize;
- break;
- }
- case ESCMCodeSegSet:
- {
- data = new TCodeSegmentSet();
- maxSize = TCodeSegmentSet::KSCMCodeSegSetMaxSize;
- break;
- }
- case ESCMCodeSeg:
- {
- data = new TCodeSegment();
- maxSize = TCodeSegment::KMaxSegmentNameSize;
- break;
- }
- case ESCMLocks:
- {
- data = new TSCMLockData();
- maxSize = TSCMLockData::KSCMLockDataMaxSize;
- break;
- }
- case ESCMVariantData:
- {
- data = new TVariantSpecificData();
- maxSize = TVariantSpecificData::KSCMVarSpecMaxSize;
- break;
- }
- case ESCMRomHeader:
- {
- data = new TRomHeaderData();
- maxSize = TRomHeaderData::KSCMRomHdrMaxSize;
- break;
- }
- case ESCMRawData:
- {
- data = new TRawData();
-
- //This is a special case. The data in here can be any length, so we need to deserialise it
- //to find this length out. The MAX_SIZE of this class is the max size minus data
- //which is fine if we dont assign the TPtr8.
- if(TRawData::KSCMRawDataMaxSize > roomInBuffer )
- {
- aBufferSize = (maxSize > aBufferSize) ? maxSize : aBufferSize;
-
- if(data)
- delete data;
-
- return NULL;
- }
- else
- {
- data->Deserialize(iReader);
- maxSize = data->GetSize();
-
- aPos = iReader.CurrentPosition();
- return data;
- }
- }
- case ESCMTraceData:
- {
- data = new TTraceDump();
- maxSize = TTraceDump::KSCMTraceDumpMaxSize;
- break;
- }
- default :
- {
- User::Panic(_L("Unexpected Null. Unrecognised Data type from crash log."), KErrGeneral); //Programming error
- }
- }
-
- __ASSERT_ALWAYS((data != NULL), User::Panic(_L("Unexpected Null"), KErrGeneral));
-
- if(maxSize > roomInBuffer )
- {
- //Not enough room in buffer to read this. Tell caller where in the current buffer
- //we were via aPos, and what minimum size buffer should be used next time to allow reading
- aBufferSize = maxSize;
- if(data)
- {
- delete data;
- }
-
- return NULL;
- }
-
- if(!data)
- {
- CLTRACE("Unable to create data structure");
- User::Leave(KErrAbort);
- }
-
- data->Deserialize(iReader);
- aPos = iReader.CurrentPosition();
-
- return data;
- }
-
- /**
- * Assuming the next type in the buffer is a TRawData type, this will return the TRawData
- * types data pointer pointing to the buffer passed via aRawBuf.
- *
- * The difference between this call and GetNextDataTypeL is that GetNextDataTypeL only lets you move along the buffer
- * it doesnt allow you to specify a buffer in which to store the raw data.
- *
- * @see GetNextDataTypeL
- * @return TRawData* This is the TRawData object that holds the data via the buffer passed in. Ownership is passed to the caller
- * @param aPos position in buffer its been found. If we return NULL, this is the position the next buffer should
- * begin from
- * @param aBufferSize Should we return NULL, that means the descriptor passed in was not big enough and should be of at least aBufferSize bytes
- * @param aRawBuf The buffer to store the data refered to by the TRawData returned
- * @param aStartRawPosition The point in the raw data at which we will start to put it into the buffer
- * @leave One of the OS wide codes
- */
- TRawData* TCrashLogWalker::GetRawDataTypeL(TInt& aPos, TInt& aBufferSize, TDes8& aRawBuf, TInt aStartRawPosition)
- {
- //make sure we have at LEAST the size of the struct in the buffer
- if(iBuffer.Length() < TRawData::KSCMRawDataMaxSize)
- {
- aBufferSize = TRawData::KSCMRawDataMaxSize;
- return NULL;
- }
-
- //this stores the required size in which to deserialize a structure - to make sure
- //there is room in the buffer
- aPos = iReader.CurrentPosition();
- aBufferSize = iBuffer.Length();
-
- //all these data types are defined by their first byte
- TInt id = (SCMStructId)iBuffer.Ptr()[iReader.CurrentPosition()];
- if(id != ESCMRawData)
- {
- User::Leave(KErrCorrupt);
- }
-
- //Deserialise once to get the length (this will ignore the data in the absence of a Tptr)
- TRawData* data = new TRawData();
- data->Deserialize(iReader);
-
- //reset reader to where the raw data starts again
- iReader.SetPosition(aPos);
-
- //now we know we have room, deserialize into this descriptor
- aRawBuf.SetMax();
- data->iData.Set(aRawBuf.MidTPtr(0));
- User::LeaveIfError(data->Deserialize(aStartRawPosition, iReader));
-
- return data;
- }
-
-#endif
-
- /**
- * This is a helper function to convert between the two formats of register
- * @param aRegVal Resulting register values
- */
- void TCrashLogWalker::HelpAssignRegisterToContext(const TRegisterValue& aRegVal)
- {
- //only interested in core registers at the moment
- if(aRegVal.iClass != 0 || aRegVal.iSize != 2)
- {
- return;
- }
-
- //Is there a cleverer way to do this with bitmasks and FOFF ?
- switch(aRegVal.iType)
- {
- case 0x0 :
- {
- iContext.iR0 = aRegVal.iValue32;
- break;
- }
- case 0x100 :
- {
- iContext.iR1 = aRegVal.iValue32;
- break;
- }
- case 0x200 :
- {
- iContext.iR2 = aRegVal.iValue32;
- break;
- }
- case 0x300 :
- {
- iContext.iR3 = aRegVal.iValue32;
- break;
- }
- case 0x400 :
- {
- iContext.iR4 = aRegVal.iValue32;
- break;
- }
- case 0x500 :
- {
- iContext.iR5 = aRegVal.iValue32;
- break;
- }
- case 0x600 :
- {
- iContext.iR6 = aRegVal.iValue32;
- break;
- }
- case 0x700 :
- {
- iContext.iR7 = aRegVal.iValue32;
- break;
- }
- case 0x800 :
- {
- iContext.iR8 = aRegVal.iValue32;
- break;
- }
- case 0x900 :
- {
- iContext.iR9 = aRegVal.iValue32;
- break;
- }
- case 0xa00 :
- {
- iContext.iR10 = aRegVal.iValue32;
- break;
- }
- case 0xb00 :
- {
- iContext.iR11 = aRegVal.iValue32;
- break;
- }
- case 0xc00 :
- {
- iContext.iR12 = aRegVal.iValue32;
- break;
- }
- case 0xd00 :
- {
- iContext.iR13 = aRegVal.iValue32;
- break;
- }
- case 0xe00 :
- {
- iContext.iR14 = aRegVal.iValue32;
- break;
- }
- case 0xf00 :
- {
- iContext.iR15 = aRegVal.iValue32;
- break;
- }
- case 0x1000 :
- {
- iContext.iCpsr = aRegVal.iValue32;
- break;
- }
- case 0x1100 :
- {
- iContext.iR13Svc = aRegVal.iValue32;
- break;
- }
- case 0x1200 :
- {
- iContext.iR14Svc = aRegVal.iValue32;
- break;
- }
- default :
- {
- return;
- }
- }
- }
-
- /**
- * Getter for crash header
- * @return header
- */
- const TCrashInfoHeader& TCrashLogWalker::GetCrashHeader() const
- {
- return iCrashHeader;
- }
-
- /**
- * Getter for crash offsets header
- * @return header
- */
- const TCrashOffsetsHeader& TCrashLogWalker::GetOffsetsHeader() const
- {
- return iOffsets;
- }
-
- }
-//eof
-