crashanalysercmd/Libraries/Engine/CrashDebuggerLib/Structures/Thread/ThreadStackBuilder.cs
author Matti Laitinen <matti.t.laitinen@nokia.com>
Thu, 11 Feb 2010 15:50:58 +0200
changeset 0 818e61de6cd1
permissions -rw-r--r--
Add initial version of Crash Analyser cmdline under EPL

/*
* Copyright (c) 2004-2008 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.Collections.Generic;
using System.Text;
using CrashDebuggerLib.Threading;
using SymbianStructuresLib.Debug.Symbols;
using SymbianStructuresLib.Arm.Registers;
using SymbianStructuresLib.CodeSegments;
using SymbianUtils.DataBuffer;
using SymbianUtils.DataBuffer.Entry;
using SymbianUtils.DataBuffer.Primer;
using SymbianDebugLib.Engine;
using SymbianUtils.Utilities;
using CrashDebuggerLib.Structures.KernelObjects;
using CrashDebuggerLib.Structures.Common;
using CrashDebuggerLib.Structures.Process;
using CrashDebuggerLib.Structures.CodeSeg;
using CrashDebuggerLib.Structures.Register;
using CrashDebuggerLib.Structures.Cpu;
using SymbianStackLib.Engine;
using SymbianStackLib.Data.Output;

namespace CrashDebuggerLib.Structures.Thread
{
    internal class ThreadStackBuilder : AsyncOperation
    {
        #region Constructors
        public ThreadStackBuilder( ThreadStackData aInfo )
        {
            iInfo = aInfo;
            this.DoWork += new System.ComponentModel.DoWorkEventHandler( ThreadStackBuilder_DoWork );
        }
        #endregion

        #region API
        public void BuildSync()
        {
            PrimeStackEngine();
            iStackEngine.ReconstructSync();
        }
        #endregion

        #region Properties
        public bool CallStackConstructed
        {
            get
            {
                return iIsReady;
            }
        }

        public StackOutputData CallStackElements
        {
            get
            {
                StackOutputData ret = new StackOutputData();
                //
                if ( iStackEngine != null )
                {
                    ret = iStackEngine.DataOutput;
                }
                //
                return ret;
            }
        }
        #endregion

        #region Internal methods
        private void PrimeStackEngine()
        {
            // Create new engine (resets old data)
            iStackEngine = new StackEngine( iInfo.CrashDebugger.DebugEngine );

            // Not yet ready
            iIsReady = false;

            // Get the data source
            DThread thread = iInfo.Info.Thread;
            string threadName = thread.Name.ToLower();
            //
            DataBuffer dataSource = iInfo.Data;
            if ( dataSource.Count > 0 )
            {
                // Prime stack engine with data & current stack pointer
                iStackEngine.Primer.Prime( dataSource );
                iStackEngine.AddressInfo.Pointer = iInfo.Info.StackPointer;

                // Set us up so we know when the process finishes
                iStackEngine.EventHandler += new StackEngine.StackEngineEventHandler( StackEngine_EventHandler );

                // Set up registers. First update them taking into account the
                // curent CPU regs.
                RegisterCollection.TType requiredType = RegisterCollection.TType.ETypeUser;
                if ( iInfo.Info.Type == ThreadStackInfo.TType.ETypeSupervisor )
                {
                    requiredType = RegisterCollection.TType.ETypeSupervisor;
                }

                RegisterCollection registers = thread.NThread.GetRegisters( requiredType );
                iStackEngine.Registers = registers;

                // Get code segs
                DProcess process = thread.OwningProcess;
                if ( process != null )
                {
                    iStackEngine.CodeSegments = process.GetCodeSegDefinitions();
                }
            }
            else
            {
            }
        }

        void ThreadStackBuilder_DoWork( object sender, System.ComponentModel.DoWorkEventArgs aArgs )
        {
            PrimeStackEngine();

            // Only reconstruct if we have some data
            if ( iStackEngine.DataSource.Count > 0 )
            {
                iStackEngine.ReconstructSync();
            }
        }
        #endregion

        #region Stack Engine event handler
        private void StackEngine_EventHandler( StackEngine.TEvent aEvent, StackEngine aEngine )
        {
            if ( aEvent == StackEngine.TEvent.EStackBuildingComplete )
            {
                iIsReady = true;
            }
        }
        #endregion

        #region Data members
        private readonly ThreadStackData iInfo;
        private StackEngine iStackEngine = null;
        private bool iIsReady = false;
        #endregion
    }
}