--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/crashanalysercmd/Libraries/Engine/CrashItemLib/Crash/Stacks/CIStack.cs Thu Feb 11 15:50:58 2010 +0200
@@ -0,0 +1,354 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:
+*
+*/
+using System;
+using System.Text;
+using System.Collections.Generic;
+using SymbianUtils;
+using SymbianUtils.Range;
+using SymbianUtils.DataBuffer;
+using SymbianUtils.DataBuffer.Entry;
+using SymbianUtils.DataBuffer.Primer;
+using SymbianStackLib.Engine;
+using SymbianStackLib.Data.Source;
+using SymbianStackLib.Data.Output;
+using SymbianStackLib.Data.Output.Entry;
+using SymbianStructuresLib.Uids;
+using SymbianStructuresLib.Arm.Registers;
+using CrashItemLib.Crash;
+using CrashItemLib.Crash.Base;
+using CrashItemLib.Crash.Registers;
+using CrashItemLib.Crash.Threads;
+using CrashItemLib.Crash.Processes;
+using CrashItemLib.Crash.CodeSegs;
+using CrashItemLib.Crash.Messages;
+
+namespace CrashItemLib.Crash.Stacks
+{
+ public class CIStack : CIElement, IEnumerable<CIStackEntry>
+ {
+ #region Static constructors
+ public static CIStack NewStandAlone( CIRegisterList aRegisters, byte[] aData, uint aAddressOfFirstByte, AddressRange aRange )
+ {
+ CIStack ret = new CIStack( aRegisters, aData, aAddressOfFirstByte, aRange );
+ return ret;
+ }
+
+ internal static CIStack NewThreadStack( CIThread aThread, CIRegisterList aRegisters, byte[] aData, uint aAddressOfFirstByte, AddressRange aRange )
+ {
+ CIStack ret = new CIStack( aRegisters, aData, aAddressOfFirstByte, aRange );
+ return ret;
+ }
+ #endregion
+
+ #region Constructors
+ private CIStack( CIRegisterList aRegisters, byte[] aData, uint aAddressOfFirstByte, AddressRange aRange )
+ : base( aRegisters.Container )
+ {
+ base.AddSupportedChildType( typeof( CIStackEntry ) );
+ base.AddSupportedChildType( typeof( CIMessage ) );
+
+ iRegisters = aRegisters;
+ iStackAddressRange = aRange;
+
+ // Prepare data
+ DataBufferPrimer primer = new DataBufferPrimer( iStackData );
+ primer.Prime( aData, aAddressOfFirstByte );
+ }
+ #endregion
+
+ #region API
+ #endregion
+
+ #region Properties
+ public bool IsStackOutputAvailable
+ {
+ get { return iStackOutput != null; }
+ }
+
+ public bool IsThreadAvailable
+ {
+ get { return OwningThread != null; }
+ }
+
+ public bool IsProcessAvailable
+ {
+ get { return OwningProcess != null; }
+ }
+
+ public bool IsOverflow
+ {
+ get
+ {
+ bool ret = false;
+ //
+ bool pointerAvailable = this.Registers.Contains( TArmRegisterType.EArmReg_SP );
+ if ( pointerAvailable )
+ {
+ CIRegister regSP = this.Pointer;
+ AddressRange stackRange = this.Range;
+ //
+ ret = ( regSP <= stackRange.Min );
+ }
+ //
+ return ret;
+ }
+ }
+
+ public TArmRegisterBank Type
+ {
+ get { return Registers.Bank; }
+ }
+
+ public uint Base
+ {
+ // NB: CIStack stores addresses differently to the stack
+ // engine, but these are correct so no need to panic.
+ get
+ {
+ return iStackAddressRange.Min;
+ }
+ }
+
+ public uint Limit
+ {
+ // NB: CIStack stores addresses differently to the stack
+ // engine, but these are correct so no need to panic.
+ get
+ {
+ return iStackAddressRange.Max;
+ }
+ }
+
+ public uint Size
+ {
+ get
+ {
+ // The address range contains all-inclusive values.
+ //
+ // E.g. a range of 0x00 -> 0x10 would include the values...:
+ //
+ // 0x00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C, 0D, 0E, 0F, 0x10
+ //
+ // ...and therefore AddressRange.Size would return 17.
+ //
+ // Symbian OS treats the range as non-inclusive, so the value is one too large.
+ // Hence we subtract one
+ uint ret = iStackAddressRange.Size - 1;
+ return ret;
+ }
+ }
+
+ public int EntryCount
+ {
+ get { return iStackOutput.Count; }
+ }
+
+ public string Algorithm
+ {
+ get
+ {
+ string ret = "Unknown Algorithm";
+ if ( iStackOutput != null )
+ {
+ ret = iStackOutput.AlgorithmName;
+ }
+ return ret;
+ }
+ }
+
+ public byte[] RawStackData
+ {
+ get { return iStackData.ToArray(); }
+ }
+
+ public int RawDataLength
+ {
+ get { return iStackData.Count; }
+ }
+
+ public AddressRange RawDataRange
+ {
+ get { return iStackData.Range; }
+ }
+
+ public CIRegister Pointer
+ {
+ get
+ {
+ CIRegister ret = Registers[ TArmRegisterType.EArmReg_SP ];
+ return ret;
+ }
+ }
+
+ public uint PointerValue
+ {
+ get
+ {
+ uint ret = 0;
+
+ // We do it this way so as to avoid calling operator[] on the
+ // register list if the register does not exist. The default behaviour
+ // of the register list class is to create a new register in such a situation
+ // and we don't really want to do that.
+ CIRegisterList regs = this.Registers;
+ if ( regs.Contains( TArmRegisterType.EArmReg_SP ) )
+ {
+ ret = this.Pointer.Value;
+ }
+ //
+ return ret;
+ }
+ }
+
+ public AddressRange Range
+ {
+ get { return iStackAddressRange; }
+ set
+ {
+ iStackAddressRange = value;
+ }
+ }
+
+ public CIThread OwningThread
+ {
+ get { return iRegisters.OwningThread; }
+ }
+
+ public CIProcess OwningProcess
+ {
+ get
+ {
+ CIProcess ret = null;
+ //
+ if ( OwningThread != null )
+ {
+ ret = OwningThread.OwningProcess;
+ }
+ //
+ return ret;
+ }
+ }
+
+ public CICodeSegList CodeSegments
+ {
+ get
+ {
+ CICodeSegList list = null;
+ CIProcess process = OwningProcess;
+ if ( process != null )
+ {
+ list = process.CodeSegments;
+ }
+ return list;
+ }
+ }
+
+ public CIRegisterList Registers
+ {
+ get { return iRegisters; }
+ }
+
+ public StackOutputData RawOutputData
+ {
+ get { return iStackOutput; }
+ }
+
+ internal StackSourceData RawSourceData
+ {
+ get { return iStackData; }
+ }
+ #endregion
+
+ #region Internal methods
+ private void CreateEntries()
+ {
+ if ( iStackOutput != null )
+ {
+ int count = iStackOutput.Count;
+ //
+ for ( int i = 0; i < count; i++ )
+ {
+ StackOutputEntry dataOutputEntry = iStackOutput[ i ];
+ //
+ CIStackEntry entry = new CIStackEntry( this, dataOutputEntry );
+ base.AddChild( entry );
+ }
+ }
+ }
+ #endregion
+
+ #region From CIElement
+ internal override void OnFinalize( CIElementFinalizationParameters aParams )
+ {
+ try
+ {
+ base.OnFinalize( aParams );
+ }
+ finally
+ {
+ CIStackBuilder builder = new CIStackBuilder( this, aParams.DebugEngine );
+ builder.Build( TSynchronicity.ESynchronous );
+ //
+ iStackOutput = builder.StackEngine.DataOutput;
+ //
+ CreateEntries();
+ }
+ }
+ #endregion
+
+ #region From IEnumerable<CIStackEntry>
+ public new IEnumerator<CIStackEntry> GetEnumerator()
+ {
+ CIElementList<CIStackEntry> entries = base.ChildrenByType<CIStackEntry>();
+ return entries.GetEnumerator();
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ CIElementList<CIStackEntry> entries = base.ChildrenByType<CIStackEntry>();
+ return entries.GetEnumerator();
+ }
+ #endregion
+
+ #region From System.Object
+ public override string ToString()
+ {
+ StringBuilder ret = new StringBuilder();
+ if ( OwningThread != null )
+ {
+ ret.Append( "[Stack] " );
+ ret.Append( OwningThread.ToString() );
+ ret.Append( " " );
+ }
+ else
+ {
+
+ }
+ //
+ ret.Append( Registers.BankName );
+ return ret.ToString();
+ }
+ #endregion
+
+ #region Data members
+ private readonly CIRegisterList iRegisters;
+ private StackSourceData iStackData = new StackSourceData();
+ private AddressRange iStackAddressRange = new AddressRange();
+ private StackOutputData iStackOutput = null;
+ #endregion
+ }
+}