diff -r 0659d0e1a03c -r 94f2adf59133 kernel/eka/debug/crashMonitor/src/crashlogwalker.cpp --- 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 -#include -#include -#include -#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(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(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 -