crashanalysercmd/Libraries/Engine/CrashDebuggerLib/Parsers/State/Implementation/Info/StateInfoUserContextTable.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.Scheduler;
using CrashDebuggerLib.Structures.Register;
using CrashDebuggerLib.Structures.UserContextTable;
using SymbianParserLib.Elements;
using SymbianParserLib.Enums;

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

        #region API
        public override void Prepare()
        {
            ParserParagraph para = new ParserParagraph( "USERCONTEXTTABLE_INFO" );
            
            // The format of the actual entry specification is the same for each
            // line
            StringBuilder lineFormat = new StringBuilder(  );
            int count = UserContextTable.EntryCount;
            for( int i=0; i<count; i++ )
            {
                lineFormat.Append( "[%02x, %02x]" );
            }

            // Create one line per table
            int tableCount = CrashDebugger.UserContextTableManager.Count;
            for( int i=0; i<tableCount; i++ )
            {
                // Create line based upon dynamic format string
                string format = String.Format( KTablePrefixFormat, i, lineFormat.ToString() );
                ParserLine line = ParserLine.NewSymFormat( format );

                // Save the context table type - we need this in the callback later on
                line.Tag = (TUserContextType) i;

                // Make sure each field stores it's value internally, so that we can extract it
                // ourselves in the callback.
                line.SetTargetObject();

                // Get a callback when all fields are ready.
                line.ElementComplete += new ParserElementBase.ElementCompleteHandler( LineComplete );

                para.Add( line );
            }

            ParserEngine.Add( para );
        }

        public override void Finalise()
        {
            // Go through each field
            CrashDebugger.UserContextTableManager.Dump();
        }
        #endregion

        #region Properties
        #endregion

        #region Internal methods
        void LineComplete( ParserElementBase aElement )
        {
            ParserLine line = (ParserLine) aElement;
            TUserContextType tableType = (TUserContextType) line.Tag;
            UserContextTable table = CrashDebugger.UserContextTableManager[ tableType ];

            // Each line should have a known number of entries stored within it's field collection.
            int expectedCount = UserContextTable.EntryCount * 2; // 2 fields per table entry
            int actualCount = line.Count;

            if ( expectedCount == actualCount )
            {
                for ( int i = 0; i < expectedCount; i += 2 )
                {
                    ParserField fieldType = line[ i + 0 ];
                    ParserField fieldValue = line[ i + 1 ];
                    //
                    if ( fieldType.IsUint && fieldValue.IsUint )
                    {
                        UserContextTable.TArmRegisterIndex reg = (UserContextTable.TArmRegisterIndex) ( i / 2 );
                        UserContextTableEntry entry = table[ reg ];
                        //
                        UserContextTableEntry.TType type = (UserContextTableEntry.TType) fieldType.AsUint;
                        byte value = (byte) fieldValue.AsUint;
                        //
                        entry.Type = type;
                        entry.Offset = value;
                    }
                }
            }
            else
            {
                throw new Exception( "User Context Table Corruption" );
            }
        }
        #endregion

        #region Internal constants
        private const string KTablePrefixFormat = "Table[{0:d2}] = {1}";
        #endregion

        #region Data members
        private List<ParserLine> iLines = new List<ParserLine>();
        #endregion
    }
}