crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbolLib/Engines/ROFS/ROFSEngine.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) 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.IO;
using System.Collections;
using System.Collections.Generic;
using SymbolLib.CodeSegDef;
using SymbolLib.Engines.Common;
using SymbolLib.Sources.Map.Engine;
using SymbolLib.Sources.Map.Parser;
using SymbolLib.Sources.Map.File;
using SymbolLib.Sources.Symbol.Engine;
using SymbolLib.Sources.Symbol.Collection;
using SymbolLib.Sources.Symbol.File;
using SymbolLib.Generics;
using SymbianUtils;
using SymbianUtils.Range;
using SymbianUtils.Tracer;

namespace SymbolLib.Engines.ROFS
{
	public class ROFSEngine : SymbolEngineBase
	{
		#region Constructors
		internal ROFSEngine( ITracer aTracer )
            : base( aTracer )
		{
            iEngineMap = new MapFileEngineCollection( this );
            iEngineMap.Observer += new SymbianUtils.AsyncReaderBase.Observer( MapEngine_Observer );
        
            iEngineSymbol = new SymbolFileEngineCollection( this, SymbolFileEngine.TActivationType.EOnDemand, true );
			iEngineSymbol.Observer += new SymbianUtils.AsyncReaderBase.Observer( SymbolEngine_Observer );
		}
		#endregion

        #region API
        public static TFileType IsSupported( string aFileName )
        {
            TFileType ret = TFileType.EFileNotSupported;
            //
            try
            {
                string extension = Path.GetExtension( aFileName ).ToLower();
                if ( extension == ".symbol" )
                {
                    bool sawSomeValidContent = false;
                    //
                    SymbolFileEngine tempEngine = new SymbolFileEngine(null,  SymbolFileEngine.TActivationType.EOnDemand, true );
                    SymbolsForBinary symbols = tempEngine.ReadFirstCollection( aFileName, out sawSomeValidContent );

                    // For a valid ROFS symbol file, the first symbol should have an address of zero.
                    bool valid = ( symbols != null && symbols.Count > 0 && symbols[ 0 ].Address == 0 );
                    if ( valid )
                    {
                        ret = TFileType.EFileRofsSymbol;
                    }
                    else if ( sawSomeValidContent )
                    {
                        // Probably just a file containing data files rather than code, but that's okay.
                        ret = TFileType.EFileRofsSymbol;
                    }
                }
                else if ( extension == ".map" )
                {
                    ret = MapFileEngineCollection.IsSupported( aFileName );
                }
            }
            catch(Exception)
            {
            }
            //
            return ret;
        }
        #endregion

        #region Properties
        public CodeSegDefinitionParser DefinitionParser
        {
            get { return iEngineMap.CodeSegParser; }
        }

        public CodeSegResolver DefinitionResolver
        {
            get { return iEngineMap.CodeSegResolver; }
        }

        public SymbolFileEngineCollection SymbolFiles
        {
            get { return iEngineSymbol; }
        }

        public string[] SymbolFileNames
        {
            get
            {
                string[] ret = iEngineSymbol.SymbolFileNames;
                return ret;
            }
        }

        public string[] SymbolFileCollectionFileNames
		{
			get
			{
                string[] ret = iEngineSymbol.BinaryFileNames;
                return ret;
			}
		}

        public List<string> MapFileNames
        {
            get
            {
                List<string> ret = new List<string>();
                lock ( iEngineMap )
                {
                    ret.AddRange( iEngineMap.MapFileNames );
                }
                return ret;
            }
        }
        #endregion

        #region From SymbolEngineBase
        public override bool AddressInRange( long aAddress )
        {
            // Try map files first, then symbols (should be
            // quicker this way).
            bool ret = false;
            lock ( iEngineMap )
            {
                ret = iEngineMap.Range.Contains( aAddress );
            }
            if ( ret == false )
            {
                lock ( iEngineSymbol )
                {
                    ret = iEngineSymbol.Range.Contains( aAddress );
                }
            }
            //
            return ret;
        }

        public override int FileNameCount
        {
            get
            {
				int count = 0;
				//
                lock ( iEngineSymbol )
                {
                    count += iEngineSymbol.SymbolFileCount;
                }
                lock ( iEngineMap )
                {
                    count += iEngineMap.NumberOfCollections;
                }
				//
                return count;
            }
        }

        public override string FileName( int aIndex )
        {
            string ret = string.Empty;
            //
            lock ( iEngineMap )
            {
                lock ( iEngineSymbol )
                {
                    int countSymbolFiles = iEngineSymbol.SymbolFileCount;
                    int countMapFiles = iEngineMap.NumberOfCollections;
                    //
                    if ( aIndex < countSymbolFiles )
                    {
                        ret = iEngineSymbol.SymbolFileName( aIndex );
                    }
                    else
                    {
                        // Must be a map index
                        aIndex -= countSymbolFiles;
                        //
                        if ( aIndex >= 0 && aIndex < iEngineMap.NumberOfCollections )
                        {
                            ret = iEngineMap.MapFileName( aIndex );
                        }
                    }
                }
            }
            //            
            return ret;
        }

        public override void LoadFromFile( string aFileName, TSynchronicity aSynchronicity )
        {
            if ( SymbolFileEngine.IsSymbolFile( aFileName ) )
            {
                iEngineSymbol.LoadFromFile( aFileName, aSynchronicity );
            }
            else if ( MapFileEngine.IsMapFile( aFileName ) )
            {
                iEngineMap.LoadFromFile( aFileName, aSynchronicity );
            }
            else
            {
                throw new NotSupportedException();
            }
        }

        public override bool LoadFromDefinition( CodeSegDefinition aDefinition, TSynchronicity aSynchronicity )
        {
            // Try Symbol file first
            bool wasActivated = false;

            lock ( this )
            {
                wasActivated = iEngineSymbol.Load( aDefinition );
                if ( wasActivated == false )
                {
                    wasActivated = iEngineMap.Load( aDefinition, aSynchronicity );
                }
            }

            return wasActivated;
        }

        public override void UnloadAll()
        {
            lock ( iEngineMap )
            {
                iEngineMap.UnloadAll();
            }
            lock ( iEngineSymbol )
            {
                iEngineSymbol.UnloadAll();
            }
        }

        public override bool Unload( CodeSegDefinition aDefinition )
        {
            bool ret = false;
            lock ( this )
            {
                ret = iEngineMap.Unload( aDefinition );

                // Try with the Symbol engine if it wasn't a loaded map codeseg
                if ( ret == false )
                {
                    ret = iEngineSymbol.Unload( aDefinition );
                }
            }

            return ret;
        }

        public override bool IsLoaded( CodeSegDefinition aDefinition )
        {
            bool ret = false;
            lock ( iEngineMap )
            {
                ret = iEngineMap.IsLoaded( aDefinition );
            }
            if ( ret == false )
            {
                // Try with the Symbol engine if it wasn't a loaded map codeseg
                lock( iEngineSymbol )
                {
                    ret = iEngineSymbol.IsLoaded( aDefinition );
                }
            }

            return ret;
        }
        #endregion

        #region From GenericSymbolEngine
        public override bool IsReady
        {
            get
            {
                bool mapReady = false;
                lock( iEngineMap )
                {
                    mapReady = iEngineMap.IsReady;
                }
                //
                bool symbolReady = false;
                lock ( iEngineSymbol )
                {
                    symbolReady = iEngineSymbol.IsReady;
                }
                //
                bool ret = ( mapReady && symbolReady );
                return ret;
            }
        }

        public override void Reset()
        {
            lock ( iEngineMap )
            {
                iEngineMap.Reset();
            }
            lock( iEngineSymbol )
            {
                iEngineSymbol.Reset();
            }
        }

        public override bool IsLoaded( string aFileName )
        {
            bool loaded = false;
            lock ( iEngineMap )
            {
                loaded = iEngineMap.IsLoaded( aFileName );
            }
            if ( loaded == false )
            {
                lock ( iEngineSymbol )
                {
                    loaded = iEngineSymbol.IsLoaded( aFileName );
                }
            }
            //
            return loaded;
        }

        public override GenericSymbolCollection this[ int aIndex ]
        {
            get
            {
                GenericSymbolCollection ret = null;
                //
                lock ( iEngineMap )
                {
                    lock ( iEngineSymbol )
                    {
                        int mapCount = iEngineMap.NumberOfCollections;
                        if ( aIndex >= 0 && aIndex < mapCount )
                        {
                            ret = iEngineMap[ aIndex ];
                        }
                        else
                        {
                            int symbolBaseIndex = ( aIndex - mapCount );
                            int symbolCount = iEngineSymbol.NumberOfCollections;
                            if ( symbolBaseIndex >= 0 && symbolBaseIndex < symbolCount )
                            {
                                ret = iEngineSymbol[ symbolBaseIndex ];
                            }
                        }
                    }
                }
                //
                return ret;
            }
        }

        public override AddressRange Range
        {
            get
            {
                AddressRange ret = new AddressRange();
                //
                lock ( iEngineMap )
                {
                    ret.Update( iEngineMap.Range );
                }
                lock ( iEngineSymbol )
                {
                    ret.Update( iEngineSymbol.Range );
                }
                //
                return ret;
            }
        }

        internal override void UnloadUntagged()
        {

        }
        #endregion

        #region From IGenericSymbolCollectionStatisticsInterface
        public override int NumberOfCollections
        {
            get
            {
                int count = 0;
                //
                lock ( iEngineMap )
                {
                    count += iEngineMap.NumberOfCollections;
                }
                lock ( iEngineSymbol )
                {
                    count += iEngineSymbol.NumberOfCollections;
                }
                //
                return count;
            }
        }
        #endregion
        
        #region Event handlers
        private void MapEngine_Observer( SymbianUtils.AsyncReaderBase.TEvent aEvent, SymbianUtils.AsyncReaderBase aSender )
        {
            System.Diagnostics.Debug.Assert( aSender.Tag is MapFileEngine );
            MapFileEngine engine = (MapFileEngine) aSender.Tag;
            //
            switch( aEvent )
            {
            case SymbianUtils.AsyncReaderBase.TEvent.EReadingStarted:
                OnParsingStarted( engine.MapFileName );
                break;
            case SymbianUtils.AsyncReaderBase.TEvent.EReadingProgress:
                OnParsingProgress( engine.MapFileName, aSender.Progress );
                break;
            case SymbianUtils.AsyncReaderBase.TEvent.EReadingComplete:
                OnParsingCompleted( engine.MapFileName );
                break;
            }
        }

        private void MapEngine_MapLoaded( CodeSegDefinition aLoadedEntry, MapFile aMapFile )
        {
            OnCollectionCreated( aMapFile );
        }

        private void SymbolEngine_Observer( SymbianUtils.AsyncReaderBase.TEvent aEvent, SymbianUtils.AsyncReaderBase aSender )
        {
            System.Diagnostics.Debug.Assert( aSender.Tag is SymbolFileEngine );
            SymbolFileEngine engine = (SymbolFileEngine) aSender.Tag;
            //
            switch( aEvent )
            {
            case SymbianUtils.AsyncReaderBase.TEvent.EReadingStarted:
                OnParsingStarted( engine.SymbolFileName );
                break;
            case SymbianUtils.AsyncReaderBase.TEvent.EReadingProgress:
                OnParsingProgress( engine.SymbolFileName, aSender.Progress );
                break;
            case SymbianUtils.AsyncReaderBase.TEvent.EReadingComplete:
                OnParsingCompleted( engine.SymbolFileName );
                break;
            }
        }
        #endregion

        #region Internal methods
        #endregion

        #region Data members
        private readonly MapFileEngineCollection iEngineMap;
        private readonly SymbolFileEngineCollection iEngineSymbol;
        #endregion
    }
}