os/kernelhwsrv/kernel/eka/debug/crashMonitor/src/crashlogwalker.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32\debug\crashMonitor\src\crashlogwalker.cpp
sl@0
    15
// Class to allow us to traverse the crash log generated by System Crash Monitor
sl@0
    16
// 
sl@0
    17
//
sl@0
    18
sl@0
    19
/**
sl@0
    20
 @file
sl@0
    21
 @internalTechnology
sl@0
    22
*/
sl@0
    23
sl@0
    24
#ifndef __KERNEL_MODE__
sl@0
    25
#include <e32std.h>
sl@0
    26
#include <e32std_private.h> 
sl@0
    27
#include <e32base.h>
sl@0
    28
#include <e32base_private.h> 
sl@0
    29
#endif
sl@0
    30
sl@0
    31
#include "scmtrace.h"
sl@0
    32
#include "crashlogwalker.h"
sl@0
    33
sl@0
    34
namespace Debug
sl@0
    35
	{	
sl@0
    36
	/**
sl@0
    37
	 * Constructor for log walker
sl@0
    38
	 * @param aBuffer The buffer containing the crash data
sl@0
    39
	 */
sl@0
    40
	TCrashLogWalker::TCrashLogWalker(TDesC8& aBuffer) : 
sl@0
    41
		iBuffer(aBuffer),
sl@0
    42
		iReader(const_cast<TUint8*>(iBuffer.Ptr()))
sl@0
    43
		{
sl@0
    44
		}
sl@0
    45
	
sl@0
    46
	/**
sl@0
    47
	 * This reads in the crash header from the buffer from the given start point
sl@0
    48
	 * @param aStartPoint Point to begin reading in buffer
sl@0
    49
	 * @return One of the OS wide codes
sl@0
    50
	 */
sl@0
    51
	TInt TCrashLogWalker::ReadLogHeader(const TInt aStartPoint)
sl@0
    52
		{		
sl@0
    53
		iReader.SetPosition(aStartPoint);
sl@0
    54
		
sl@0
    55
		TInt err = iCrashHeader.Deserialize(iReader);
sl@0
    56
		if(err != KErrNone)
sl@0
    57
			{
sl@0
    58
			CLTRACE("(TCrashLogWalker::ReadLogHeader) - failed to read crash header");
sl@0
    59
			return KErrCorrupt;
sl@0
    60
			}
sl@0
    61
		
sl@0
    62
		err = iOffsets.Deserialize(iReader);
sl@0
    63
		if(err != KErrNone)
sl@0
    64
			{
sl@0
    65
			CLTRACE("(TCrashLogWalker::ReadLogHeader) - failed to read offsets");
sl@0
    66
			return KErrCorrupt;
sl@0
    67
			}
sl@0
    68
		
sl@0
    69
		TRegisterSet set;
sl@0
    70
		err = set.Deserialize(iReader);
sl@0
    71
		if(err != KErrNone)
sl@0
    72
			{
sl@0
    73
			CLTRACE("(TCrashLogWalker::ReadLogHeader) - failed to read register set");
sl@0
    74
			return KErrCorrupt;
sl@0
    75
			}
sl@0
    76
		
sl@0
    77
		for(TInt cnt = 0; cnt < set.iNumRegisters; cnt++)
sl@0
    78
			{
sl@0
    79
			TRegisterValue val;
sl@0
    80
			err = val.Deserialize(iReader);
sl@0
    81
			if(err != KErrNone)
sl@0
    82
				{
sl@0
    83
				CLTRACE1("(TCrashLogWalker::ReadLogHeader) - failed to read TRegisterValue cnt = %d", cnt);
sl@0
    84
				return KErrCorrupt;
sl@0
    85
				}
sl@0
    86
						
sl@0
    87
			HelpAssignRegisterToContext(val);
sl@0
    88
			}
sl@0
    89
		
sl@0
    90
		return VerifyHeader();
sl@0
    91
		}
sl@0
    92
	
sl@0
    93
	/**
sl@0
    94
	 * Getter for the crash context - This is the CPU register set at the time of crash
sl@0
    95
	 * @return Crash Context
sl@0
    96
	 */
sl@0
    97
	const TRmdArmExcInfo& TCrashLogWalker::GetCrashContext() const
sl@0
    98
		{
sl@0
    99
		return iContext;
sl@0
   100
		}
sl@0
   101
	
sl@0
   102
	/**
sl@0
   103
	 * Returns the crash size for the crash that has just been read, provided the
sl@0
   104
	 * reading of the header was succesful. 
sl@0
   105
	 * @see ReadLogHeader
sl@0
   106
	 * @return Crash Log size
sl@0
   107
	 */
sl@0
   108
	TInt TCrashLogWalker::GetCrashSize() const
sl@0
   109
		{
sl@0
   110
		return iCrashHeader.iLogSize;
sl@0
   111
		}
sl@0
   112
	
sl@0
   113
	/**
sl@0
   114
	 * Returns the crash ID for the crash that has just been read, provided the
sl@0
   115
	 * reading of the header was succesful. 
sl@0
   116
	 * @see ReadLogHeader
sl@0
   117
	 * @return Crash Log ID
sl@0
   118
	 */
sl@0
   119
	TInt TCrashLogWalker::GetCrashId() const
sl@0
   120
		{
sl@0
   121
		return iCrashHeader.iCrashId;
sl@0
   122
		}
sl@0
   123
	
sl@0
   124
	/**
sl@0
   125
	 * Looks at the member crash log header and checks that it is valid.
sl@0
   126
	 * @see ReadLogHeader 
sl@0
   127
	 * @return one of the OS wide codes
sl@0
   128
	 */
sl@0
   129
	TInt TCrashLogWalker::VerifyHeader()
sl@0
   130
		{
sl@0
   131
		if(iCrashHeader.iId == ESCMTCrashInfo)
sl@0
   132
			{			
sl@0
   133
			CLTRACE("TCrashLogWalker::VerifyHeader() OK");
sl@0
   134
			return KErrNone;
sl@0
   135
			}
sl@0
   136
		else
sl@0
   137
			{
sl@0
   138
			CLTRACE("TCrashLogWalker::VerifyHeader() FAILED");
sl@0
   139
			return KErrCorrupt;
sl@0
   140
			}
sl@0
   141
		}
sl@0
   142
	
sl@0
   143
	/**
sl@0
   144
	 * Updates the buffer being used by the crash walker and resets reader to use 
sl@0
   145
	 * the beginning of this
sl@0
   146
	 * @param aBuffer New buffer
sl@0
   147
	 */
sl@0
   148
	void TCrashLogWalker::UpdateBuffer(TDesC8& aBuffer)
sl@0
   149
		{
sl@0
   150
		iBuffer = aBuffer;		
sl@0
   151
		
sl@0
   152
		//Read from start of this buffer		
sl@0
   153
		iReader = TByteStreamReader(const_cast<TUint8*>(aBuffer.Ptr()));
sl@0
   154
		}
sl@0
   155
	
sl@0
   156
#ifndef __KERNEL_MODE__
sl@0
   157
	/**
sl@0
   158
	 * Gets the next data type from the buffer. If this is NULL it means the buffer was too small.
sl@0
   159
	 * Call again with a larger buffer. It assumes the buffer contains valid data and leaves with KErrCorrupt 
sl@0
   160
	 * 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 
sl@0
   161
	 * correct position. If you just want to skip a raw data type, move the buffer along the size of (contained in the returned struct)
sl@0
   162
	 * 
sl@0
   163
	 * @see GetRawDataTypeL
sl@0
   164
	 * @see UpdateBuffer
sl@0
   165
	 * @param aPos Next position that will be read. If we return NULL, this is the position the next buffer should
sl@0
   166
	 * 			begin from
sl@0
   167
	 * @param aId ID of the MByteStreamSerializable returned	 
sl@0
   168
	 * @param buffer size to be used the next time. Unchanged if the current buffer is ok
sl@0
   169
	 * @return MByteStreamSerializable pointer. Ownership is passed to caller. NULL if failed
sl@0
   170
	 * @leave KErrCorrupt if the buffer cant be read
sl@0
   171
	 */
sl@0
   172
	MByteStreamSerializable* TCrashLogWalker::GetNextDataTypeL(TInt& aPos, SCMStructId& aId, TInt& aBufferSize)
sl@0
   173
		{
sl@0
   174
		MByteStreamSerializable* data = NULL;
sl@0
   175
		
sl@0
   176
		TInt roomInBuffer = iBuffer.Length() - iReader.CurrentPosition();
sl@0
   177
		//make sure we have at LEAST 4 bytes in the buffer
sl@0
   178
		if(roomInBuffer < (TInt)(sizeof(TInt)))
sl@0
   179
			{
sl@0
   180
			aBufferSize = sizeof(TInt);
sl@0
   181
			return NULL;
sl@0
   182
			}
sl@0
   183
		
sl@0
   184
		//this stores the required size in which to deserialize a structure - to make sure 
sl@0
   185
		//there is room in the buffer
sl@0
   186
		TInt maxSize = 0;
sl@0
   187
		aPos = iReader.CurrentPosition();
sl@0
   188
		aBufferSize = iBuffer.Length();		
sl@0
   189
		
sl@0
   190
		//all these data types are defined by their first byte
sl@0
   191
		aId = (SCMStructId)iBuffer.Ptr()[iReader.CurrentPosition()];		
sl@0
   192
		
sl@0
   193
		//ensure we have a valid structure found
sl@0
   194
		if(aId <= 0 || aId >= ESCMLast)
sl@0
   195
			{
sl@0
   196
			//oddness is afoot and the mist of corruption reigns thick
sl@0
   197
			User::Leave(KErrCorrupt);
sl@0
   198
			}					
sl@0
   199
		
sl@0
   200
		switch(aId)
sl@0
   201
			{
sl@0
   202
			case ESCMOffsetsHeader:
sl@0
   203
				{
sl@0
   204
				data = new TCrashOffsetsHeader();	
sl@0
   205
				maxSize = TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize;
sl@0
   206
				break;
sl@0
   207
				}
sl@0
   208
			case ESCMTCrashInfo:
sl@0
   209
				{
sl@0
   210
				data = new TCrashInfoHeader();
sl@0
   211
				maxSize = TCrashInfoHeader::KSCMCrashInfoMaxSize;
sl@0
   212
				break;
sl@0
   213
				}
sl@0
   214
			case ESCMProcessData:
sl@0
   215
				{
sl@0
   216
				data = new TProcessData();
sl@0
   217
				maxSize = TProcessData::KSCMProcessDataMaxSize;
sl@0
   218
				break;
sl@0
   219
				}
sl@0
   220
			case ESCMThreadData:
sl@0
   221
				{
sl@0
   222
				data = new TThreadData();
sl@0
   223
				maxSize = TThreadData::KSCMThreadDataMaxSize;
sl@0
   224
				break;
sl@0
   225
				}
sl@0
   226
			case ESCMThreadStack:
sl@0
   227
				{
sl@0
   228
				data = new TThreadStack();
sl@0
   229
				maxSize = TThreadStack::KSCMThreadStackMaxSize;
sl@0
   230
				break;
sl@0
   231
				}
sl@0
   232
			case ESCMRegisterValue:
sl@0
   233
				{
sl@0
   234
				data = new TRegisterValue();
sl@0
   235
				maxSize = TRegisterValue::KSCMRegisterValueMaxSize;
sl@0
   236
				break;
sl@0
   237
				}
sl@0
   238
			case ESCMRegisterSet:
sl@0
   239
				{
sl@0
   240
				data = new TRegisterSet();
sl@0
   241
				maxSize = TRegisterSet::KSCMRegisterSetMaxSize;
sl@0
   242
				break;
sl@0
   243
				}
sl@0
   244
			case ESCMMemory:
sl@0
   245
				{
sl@0
   246
				data = new TMemoryDump();
sl@0
   247
				maxSize = TMemoryDump::KSCMMemDumpMaxSize;
sl@0
   248
				break;
sl@0
   249
				}
sl@0
   250
			case ESCMCodeSegSet:
sl@0
   251
				{
sl@0
   252
				data = new TCodeSegmentSet();
sl@0
   253
				maxSize = TCodeSegmentSet::KSCMCodeSegSetMaxSize;
sl@0
   254
				break;
sl@0
   255
				}
sl@0
   256
			case ESCMCodeSeg:
sl@0
   257
				{
sl@0
   258
				data = new TCodeSegment();
sl@0
   259
				maxSize = TCodeSegment::KMaxSegmentNameSize;
sl@0
   260
				break;
sl@0
   261
				}	
sl@0
   262
			case ESCMLocks:
sl@0
   263
				{
sl@0
   264
				data = new TSCMLockData();
sl@0
   265
				maxSize = TSCMLockData::KSCMLockDataMaxSize;	
sl@0
   266
				break;
sl@0
   267
				}
sl@0
   268
			case ESCMVariantData:
sl@0
   269
				{
sl@0
   270
				data = new TVariantSpecificData();
sl@0
   271
				maxSize = TVariantSpecificData::KSCMVarSpecMaxSize;	
sl@0
   272
				break;
sl@0
   273
				}				
sl@0
   274
			case ESCMRomHeader:
sl@0
   275
				{
sl@0
   276
				data = new TRomHeaderData();
sl@0
   277
				maxSize = TRomHeaderData::KSCMRomHdrMaxSize;	
sl@0
   278
				break;
sl@0
   279
				}				
sl@0
   280
			case ESCMRawData:
sl@0
   281
				{
sl@0
   282
				data = new TRawData();
sl@0
   283
				
sl@0
   284
				//This is a special case. The data in here can be any length, so we need to deserialise it
sl@0
   285
				//to find this length out. The MAX_SIZE of this class is the max size minus data
sl@0
   286
				//which is fine if we dont assign the TPtr8.				
sl@0
   287
				if(TRawData::KSCMRawDataMaxSize > roomInBuffer )
sl@0
   288
					{					
sl@0
   289
					aBufferSize = (maxSize > aBufferSize) ? maxSize : aBufferSize;
sl@0
   290
					
sl@0
   291
					if(data)
sl@0
   292
						delete data;
sl@0
   293
					
sl@0
   294
					return NULL;
sl@0
   295
					}
sl@0
   296
				else
sl@0
   297
					{
sl@0
   298
					data->Deserialize(iReader);
sl@0
   299
					maxSize = data->GetSize();
sl@0
   300
					
sl@0
   301
					aPos = iReader.CurrentPosition();
sl@0
   302
					return data;
sl@0
   303
					}
sl@0
   304
				}
sl@0
   305
			case ESCMTraceData:
sl@0
   306
				{
sl@0
   307
				data = new TTraceDump();
sl@0
   308
				maxSize = TTraceDump::KSCMTraceDumpMaxSize;
sl@0
   309
				break;
sl@0
   310
				}
sl@0
   311
			default :
sl@0
   312
				{
sl@0
   313
				User::Panic(_L("Unexpected Null. Unrecognised Data type from crash log."), KErrGeneral); //Programming error				
sl@0
   314
				}							
sl@0
   315
			}
sl@0
   316
		
sl@0
   317
		__ASSERT_ALWAYS((data != NULL), User::Panic(_L("Unexpected Null"), KErrGeneral));
sl@0
   318
		
sl@0
   319
		if(maxSize > roomInBuffer )
sl@0
   320
			{
sl@0
   321
			//Not enough room in buffer to read this. Tell caller where in the current buffer
sl@0
   322
			//we were via aPos, and what minimum size buffer should be used next time to allow reading
sl@0
   323
			aBufferSize = maxSize;
sl@0
   324
			if(data)
sl@0
   325
				{
sl@0
   326
				delete data;
sl@0
   327
				}
sl@0
   328
			
sl@0
   329
			return NULL;
sl@0
   330
			}
sl@0
   331
		
sl@0
   332
		if(!data)
sl@0
   333
			{
sl@0
   334
			CLTRACE("Unable to create data structure");
sl@0
   335
			User::Leave(KErrAbort);
sl@0
   336
			}
sl@0
   337
		
sl@0
   338
		data->Deserialize(iReader);			
sl@0
   339
		aPos = iReader.CurrentPosition();
sl@0
   340
		
sl@0
   341
		return data;
sl@0
   342
		}
sl@0
   343
	
sl@0
   344
	/**
sl@0
   345
	 * Assuming the next type in the buffer is a TRawData type, this will return the TRawData
sl@0
   346
	 * types data pointer pointing to the buffer passed via aRawBuf.
sl@0
   347
	 *  
sl@0
   348
	 * The difference between this call and GetNextDataTypeL is that GetNextDataTypeL only lets you move along the buffer
sl@0
   349
	 * it doesnt allow you to specify a buffer in which to store the raw data.
sl@0
   350
	 * 
sl@0
   351
	 * @see GetNextDataTypeL
sl@0
   352
	 * @return TRawData* This is the TRawData object that holds the data via the buffer passed in. Ownership is passed to the caller
sl@0
   353
	 * @param aPos position in buffer its been found. If we return NULL, this is the position the next buffer should
sl@0
   354
	 * 			begin from
sl@0
   355
	 * @param aBufferSize Should we return NULL, that means the descriptor passed in was not big enough and should be of at least aBufferSize bytes
sl@0
   356
	 * @param aRawBuf The buffer to store the data refered to by the TRawData returned
sl@0
   357
	 * @param aStartRawPosition The point in the raw data at which we will start to put it into the buffer
sl@0
   358
	 * @leave One of the OS wide codes
sl@0
   359
	 */
sl@0
   360
	TRawData* TCrashLogWalker::GetRawDataTypeL(TInt& aPos, TInt& aBufferSize, TDes8& aRawBuf, TInt aStartRawPosition)
sl@0
   361
		{								
sl@0
   362
		//make sure we have at LEAST the size of the struct in the buffer
sl@0
   363
		if(iBuffer.Length() < TRawData::KSCMRawDataMaxSize)
sl@0
   364
			{
sl@0
   365
			aBufferSize = TRawData::KSCMRawDataMaxSize;
sl@0
   366
			return NULL;
sl@0
   367
			}
sl@0
   368
		
sl@0
   369
		//this stores the required size in which to deserialize a structure - to make sure 
sl@0
   370
		//there is room in the buffer
sl@0
   371
		aPos = iReader.CurrentPosition();
sl@0
   372
		aBufferSize = iBuffer.Length();
sl@0
   373
		
sl@0
   374
		//all these data types are defined by their first byte
sl@0
   375
		TInt id = (SCMStructId)iBuffer.Ptr()[iReader.CurrentPosition()];
sl@0
   376
		if(id != ESCMRawData)
sl@0
   377
			{
sl@0
   378
			User::Leave(KErrCorrupt);
sl@0
   379
			}		
sl@0
   380
		
sl@0
   381
		//Deserialise once to get the length (this will ignore the data in the absence of a Tptr)
sl@0
   382
		TRawData* data = new TRawData();
sl@0
   383
		data->Deserialize(iReader);
sl@0
   384
		
sl@0
   385
		//reset reader to where the raw data starts again
sl@0
   386
		iReader.SetPosition(aPos);
sl@0
   387
		
sl@0
   388
		//now we know we have room, deserialize into this descriptor	
sl@0
   389
		aRawBuf.SetMax();	
sl@0
   390
		data->iData.Set(aRawBuf.MidTPtr(0));
sl@0
   391
		User::LeaveIfError(data->Deserialize(aStartRawPosition, iReader));
sl@0
   392
		
sl@0
   393
		return data;
sl@0
   394
		}
sl@0
   395
	
sl@0
   396
#endif
sl@0
   397
	
sl@0
   398
	/**
sl@0
   399
	 * This is a helper function to convert between the two formats of register
sl@0
   400
	 * @param aRegVal Resulting register values
sl@0
   401
	 */
sl@0
   402
	void TCrashLogWalker::HelpAssignRegisterToContext(const TRegisterValue& aRegVal)
sl@0
   403
		{
sl@0
   404
		//only interested in core registers at the moment
sl@0
   405
		if(aRegVal.iClass != 0 || aRegVal.iSize != 2)
sl@0
   406
			{
sl@0
   407
			return;
sl@0
   408
			}
sl@0
   409
		
sl@0
   410
		//Is there a cleverer way to do this with bitmasks and FOFF ?
sl@0
   411
		switch(aRegVal.iType)
sl@0
   412
			{
sl@0
   413
			case 0x0 :
sl@0
   414
				{
sl@0
   415
				iContext.iR0 = aRegVal.iValue32;
sl@0
   416
				break;
sl@0
   417
				}
sl@0
   418
			case 0x100 :
sl@0
   419
				{
sl@0
   420
				iContext.iR1 = aRegVal.iValue32;
sl@0
   421
				break;
sl@0
   422
				}
sl@0
   423
			case 0x200 :
sl@0
   424
				{
sl@0
   425
				iContext.iR2 = aRegVal.iValue32;
sl@0
   426
				break;
sl@0
   427
				}
sl@0
   428
			case 0x300 :
sl@0
   429
				{
sl@0
   430
				iContext.iR3 = aRegVal.iValue32;
sl@0
   431
				break;
sl@0
   432
				}
sl@0
   433
			case 0x400 :
sl@0
   434
				{
sl@0
   435
				iContext.iR4 = aRegVal.iValue32;
sl@0
   436
				break;
sl@0
   437
				}
sl@0
   438
			case 0x500 :
sl@0
   439
				{
sl@0
   440
				iContext.iR5 = aRegVal.iValue32;
sl@0
   441
				break;
sl@0
   442
				}
sl@0
   443
			case 0x600 :
sl@0
   444
				{
sl@0
   445
				iContext.iR6 = aRegVal.iValue32;
sl@0
   446
				break;
sl@0
   447
				}
sl@0
   448
			case 0x700 :
sl@0
   449
				{
sl@0
   450
				iContext.iR7 = aRegVal.iValue32;
sl@0
   451
				break;
sl@0
   452
				}
sl@0
   453
			case 0x800 :
sl@0
   454
				{
sl@0
   455
				iContext.iR8 = aRegVal.iValue32;
sl@0
   456
				break;
sl@0
   457
				}
sl@0
   458
			case 0x900 :
sl@0
   459
				{
sl@0
   460
				iContext.iR9 = aRegVal.iValue32;
sl@0
   461
				break;
sl@0
   462
				}
sl@0
   463
			case 0xa00 :
sl@0
   464
				{
sl@0
   465
				iContext.iR10 = aRegVal.iValue32;
sl@0
   466
				break;
sl@0
   467
				}
sl@0
   468
			case 0xb00 :
sl@0
   469
				{
sl@0
   470
				iContext.iR11 = aRegVal.iValue32;
sl@0
   471
				break;
sl@0
   472
				}
sl@0
   473
			case 0xc00 :
sl@0
   474
				{
sl@0
   475
				iContext.iR12 = aRegVal.iValue32;
sl@0
   476
				break;
sl@0
   477
				}
sl@0
   478
			case 0xd00 :
sl@0
   479
				{
sl@0
   480
				iContext.iR13 = aRegVal.iValue32;				
sl@0
   481
				break;
sl@0
   482
				}
sl@0
   483
			case 0xe00 :
sl@0
   484
				{
sl@0
   485
				iContext.iR14 = aRegVal.iValue32;
sl@0
   486
				break;
sl@0
   487
				}
sl@0
   488
			case 0xf00 :
sl@0
   489
				{
sl@0
   490
				iContext.iR15 = aRegVal.iValue32;
sl@0
   491
				break;
sl@0
   492
				}
sl@0
   493
			case 0x1000 :
sl@0
   494
				{
sl@0
   495
				iContext.iCpsr = aRegVal.iValue32;
sl@0
   496
				break;
sl@0
   497
				}
sl@0
   498
			case 0x1100 :
sl@0
   499
				{
sl@0
   500
				iContext.iR13Svc = aRegVal.iValue32;
sl@0
   501
				break;
sl@0
   502
				}
sl@0
   503
			case 0x1200 :
sl@0
   504
				{
sl@0
   505
				iContext.iR14Svc = aRegVal.iValue32;
sl@0
   506
				break;
sl@0
   507
				}
sl@0
   508
			default :
sl@0
   509
				{
sl@0
   510
				return;
sl@0
   511
				}				
sl@0
   512
			}
sl@0
   513
		}
sl@0
   514
	
sl@0
   515
	/**
sl@0
   516
	 * Getter for crash header
sl@0
   517
	 * @return header
sl@0
   518
	 */
sl@0
   519
	const TCrashInfoHeader& TCrashLogWalker::GetCrashHeader() const
sl@0
   520
		{
sl@0
   521
		return iCrashHeader;
sl@0
   522
		}
sl@0
   523
	
sl@0
   524
	/**
sl@0
   525
	 * Getter for crash offsets header
sl@0
   526
	 * @return header
sl@0
   527
	 */
sl@0
   528
	const TCrashOffsetsHeader& TCrashLogWalker::GetOffsetsHeader() const
sl@0
   529
		{
sl@0
   530
		return iOffsets;
sl@0
   531
		}			
sl@0
   532
		
sl@0
   533
	}
sl@0
   534
//eof
sl@0
   535