diff -r 000000000000 -r 818e61de6cd1 crashanalysercmd/Libraries/Engine/CrashItemLib/Crash/Stacks/CIStackBuilder.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crashanalysercmd/Libraries/Engine/CrashItemLib/Crash/Stacks/CIStackBuilder.cs Thu Feb 11 15:50:58 2010 +0200 @@ -0,0 +1,211 @@ +/* +* 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 SymbianDebugLib.Engine; +using SymbianStackLib.Engine; +using SymbianStackLib.Exceptions; +using CrashItemLib.Engine.Operations; +using CrashItemLib.Crash; +using CrashItemLib.Crash.Base; +using CrashItemLib.Crash.Symbols; +using CrashItemLib.Crash.Registers; +using CrashItemLib.Crash.Processes; +using CrashItemLib.Crash.CodeSegs; +using CrashItemLib.Crash.Messages; +using CrashItemLib.Engine; + +namespace CrashItemLib.Crash.Stacks +{ + internal class CIStackBuilder + { + #region Constructors + public CIStackBuilder( CIStack aStack, DbgEngine aDebugEngine ) + { + iStack = aStack; + iStackEngine = new StackEngine( aDebugEngine ); + iStackEngine.AddressInfo.Pointer = aStack.PointerValue; + iStackEngine.AddressInfo.Range = aStack.Range; + iStackEngine.Registers = aStack.Registers; + iStackEngine.DataSource = aStack.RawSourceData; + + // Get the code segments for the process + bool isThreadStack = aStack.IsThreadAvailable; + if ( isThreadStack ) + { + CIProcess process = OwningProcess; + System.Diagnostics.Debug.Assert( process != null ); + + // Seed stack engine with relevant code segments + iStackEngine.CodeSegments = process.CodeSegments; + } + } + #endregion + + #region API + public void Build( TSynchronicity aSynchronicity ) + { + StackEventsSubscribe(); + iStackEngine.Reconstruct( aSynchronicity ); + } + #endregion + + #region Properties + public bool IsReady + { + get { return iIsReady; } + private set + { + lock ( this ) + { + iIsReady = value; + } + } + } + + public CIProcess OwningProcess + { + get + { + CIProcess ret = iStack.OwningProcess; + return ret; + } + } + + public StackEngine StackEngine + { + get { return iStackEngine; } + } + #endregion + + #region Event handlers + private void StackEngine_EventHandler( StackEngine.TEvent aEvent, StackEngine aEngine ) + { + if ( aEvent == StackEngine.TEvent.EStackBuildingComplete ) + { + StackEventsUnsubscribe(); + IsReady = true; + } + } + + private void StackEngine_ExceptionHandler( Exception aException, StackEngine aEngine ) + { + // Operation failed, but we must mark ourselves as ready or else UI clients will block forever... + IsReady = true; + + // We'll deal with the public exceptions ourselves. Any kind of exception we cannot handle + // will just get treated as a generic error. + string msg = string.Empty; + bool recognized = false; + // + if ( aException is StackAddressException ) + { + recognized = true; + StackAddressException exception = (StackAddressException) aException; + switch ( exception.Type ) + { + case StackAddressException.TType.ETypePointerIsNull: + msg = LibResources.CIStackBuilder_AddressInfoException_PointerMissing; + break; + case StackAddressException.TType.ETypePointerOutOfBounds: + msg = LibResources.CIStackBuilder_AddressInfoException_PointerOutOfBounds; + break; + case StackAddressException.TType.ETypeBaseAddressBeforeTopAddress: + msg = LibResources.CIStackBuilder_AddressInfoException_BaseAddressBeforeTopAddress; + break; + case StackAddressException.TType.ETypeTopAddressAfterBaseAddress: + msg = LibResources.CIStackBuilder_AddressInfoException_TopAddressAfterBaseAddress; + break; + default: + recognized = false; + break; + } + } + + // Not recognized? Unfortunately have to leak the original underlying .NET exception details + if ( recognized == false ) + { + msg = aException.Message; + } + + if ( string.IsNullOrEmpty( msg ) == false ) + { + // Treat exceptions as fatal errors + CIMessageError error = new CIMessageError( iStack.Container, LibResources.CIStackBuilder_Error_Title ); + error.AddLine( msg ); + iStack.AddChild( error ); + } + } + + private void StackEngine_MessageHandler( StackEngine.TMessageType aType, string aMessage, StackEngine aEngine ) + { + switch ( aType ) + { + default: + break; + case StackEngine.TMessageType.ETypeError: + { + CIMessageError error = new CIMessageError( iStack.Container, LibResources.CIStackBuilder_Error_Title ); + error.AddLine( aMessage ); + iStack.AddChild( error ); + break; + } + case StackEngine.TMessageType.ETypeWarning: + { + CIMessageWarning warning = new CIMessageWarning( iStack.Container, LibResources.CIStackBuilder_Warning_Title ); + warning.AddLine( aMessage ); + iStack.AddChild( warning ); + break; + } + } + } + #endregion + + #region Internal methods + private void StackEventsSubscribe() + { + StackEngine.MessageHandler += new StackEngine.StackEngineMessageHandler( StackEngine_MessageHandler ); + StackEngine.EventHandler += new StackEngine.StackEngineEventHandler( StackEngine_EventHandler ); + StackEngine.ExceptionHandler += new StackEngine.StackEngineExceptionHandler( StackEngine_ExceptionHandler ); + } + + private void StackEventsUnsubscribe() + { + StackEngine.MessageHandler -= new StackEngine.StackEngineMessageHandler( StackEngine_MessageHandler ); + StackEngine.EventHandler -= new StackEngine.StackEngineEventHandler( StackEngine_EventHandler ); + StackEngine.ExceptionHandler -= new StackEngine.StackEngineExceptionHandler( StackEngine_ExceptionHandler ); + } + #endregion + + #region From System.Object + public override string ToString() + { + StringBuilder ret = new StringBuilder(); + ret.AppendFormat( "CIStackBuilder_{0}_{1}", iStack.Id, iStack.Name ); + return ret.ToString(); + } + #endregion + + #region Data members + private readonly CIStack iStack; + private readonly StackEngine iStackEngine; + private bool iIsReady = false; + #endregion + } +}