crashanalysercmd/Libraries/Engine/CrashDebuggerLib/Parsers/State/Implementation/Stacks/StateThreadStacks.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 SymbianParserLib.Engine;
using SymbianParserLib.BaseStructures;
using CrashDebuggerLib.Structures.CodeSeg;
using CrashDebuggerLib.Structures.Thread;
using CrashDebuggerLib.Structures.Process;
using CrashDebuggerLib.Structures.KernelObjects;
using CrashDebuggerLib.Threading;
using SymbianParserLib.Elements;
using SymbianParserLib.Enums;

namespace CrashDebuggerLib.Parsers.State.Implementation
{
    internal class StateThreadStacks : State
    {
        #region Constructors
        public StateThreadStacks( CrashDebuggerParser aParser )
            : base( aParser )
        {
        }
        #endregion

        #region API
        public override void Prepare()
        {
            // First, we need to know which thread we're dealing with
            // so that means we must look for the thread info
            ParserParagraph para = new ParserParagraph( "STACK_THREAD_INFO" );
            //
            ParserLine l1 = ParserLine.NewSymFormat( "STACK DATA for thread at %8x" );
            l1.SetTargetMethod( this, "SetThreadAddress" );
            para.Add( l1 );
            ParserEngine.Add( para );
        }

        public override void Finalise()
        {
            if ( iCurrentThread != null )
            {
                if ( iCurrentThread.OwningProcess != null )
                {
                    iCurrentThread.OwningProcess.PrepareDebugView();
                }
                //
                iCurrentThread.StackInfoUser.Data.BuildCallStackAsync();
                iCurrentThread.StackInfoSupervisor.Data.BuildCallStackAsync();
            }
        }
        #endregion

        #region Properties
        #endregion

        #region Internal methods
        private void SetThreadAddress( uint aAddress )
        {
            // Look for the thread which we're about to process...
            iCurrentThread = CrashDebugger.ThreadByAddress( aAddress );
            if ( iCurrentThread != null )
            {
                // Next we must start to process code segments for this
                // thread. These lines contain additional information about
                // the run address of the code segments, relative to the process.
                ParserParagraph para = new ParserParagraph( "STACK_THREAD_INFO_CODESEGS" );
                //
                ParserLine l1 = ParserLine.NewSymFormat( "CodeSeg[%03d/%03d] @ %08x - %08X-%08X %S" );
                l1.ElementComplete += new ParserElementBase.ElementCompleteHandler( CodeSegmentLineComplete );
                //
                para.Add( l1 );
                ParserEngine.Add( para );
            }
        }

        void CodeSegmentLineComplete( ParserElementBase aElement )
        {
            System.Diagnostics.Debug.Assert( iCurrentThread != null );
            ParserLine line = (ParserLine) aElement;
            //
            int index = line[ 0 ].AsInt;
            int count = line[ 1 ].AsInt;
            uint codeSegAddress = line[ 2 ].AsUint;
            uint startAddress = line[ 3 ].AsUint;
            uint endAddress = line[ 4 ].AsUint;
            string fileName = line[ 5 ].AsString;
            //
            DProcess process = iCurrentThread.OwningProcess;
            if ( process != null )
            {
                ProcessCodeSegCollection codeSegs = process.CodeSegments;
                ProcessCodeSeg codeSeg = codeSegs[ codeSegAddress ];
                //
                if ( codeSeg == null )
                {
                    // The code seg is not directly part of the process handle list
                    // but it is some how mapped into the process?
                    //
                    // Try looking up the underlying code seg entry details from
                    // the crash debugger data itself. It should be part of the code
                    // seg listing so this should always work.
                    codeSeg = new ProcessCodeSeg( CrashDebugger, codeSegAddress, 0 );
                    process.CodeSegments.Add( codeSeg );
                }
                //
                codeSeg.ProcessLocalRunAddress = startAddress;
                codeSeg.Size = ( endAddress - startAddress );
            }
            //
            int remaining = count - index;
            if ( remaining == 0 )
            {
                // Queue up stack data...
                iHelperStack.CreateStackParagraphs( ParserEngine, iCurrentThread );
            }
            else
            {
                // So that we capture the next line
                aElement.SetRepetitions( 1 );
            }
        }
        #endregion

        #region Data members
        private DThread iCurrentThread = null;
        private Helpers.HelperStack iHelperStack = new CrashDebuggerLib.Parsers.State.Implementation.Helpers.HelperStack();
        #endregion
    }
}