crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbolLib/Sources/Map/Engine/MapFileEngineCollection.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.Text;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using SymbianUtils;
using SymbianUtils.Range;
using SymbianUtils.Tracer;
using SymbolLib.CodeSegDef;
using SymbolLib.Generics;
using SymbolLib.Engines;
using SymbolLib.Sources.Map.Symbol;
using SymbolLib.Sources.Map.File;
using SymbolLib.Sources.Map.Parser;

namespace SymbolLib.Sources.Map.Engine
{
    internal class MapFileEngineCollection : GenericSymbolEngine
    {
        #region Delegates & Events
        public event AsyncReaderBase.Observer Observer;
        #endregion

        #region Constructors & destructor
        internal MapFileEngineCollection( ITracer aTracer )
            : base( aTracer )
        {
            iCodeSegResolver = new CodeSegResolver( aTracer );
            iCodeSegParser = new CodeSegDefinitionParser( iCodeSegResolver );
        }
        #endregion

        #region API
        public static TFileType IsSupported( string aFileName )
        {
            TFileType ret = TFileType.EFileNotSupported;
            //
            try
            {
                using ( StreamReader reader = new StreamReader( aFileName ) )
                {
                    const int maxLines = 100;
                    //
                    bool foundHeader = false;
                    bool foundBody = false;
                    //
                    int lineCounter = 0;
                    string line = reader.ReadLine();
                    while ( line != null && !( foundHeader && foundBody ) && lineCounter < maxLines )
                    {
                        if ( line.StartsWith( "ARM Linker, RVCT" ) )
                        {
                            foundHeader = true;
                        }
                        else if ( line.Contains( "Symbol Name" ) && line.Contains( "Value" ) && line.Contains( "Object" ) && line.Contains( "Section" ) )
                        {
                            foundBody = true;
                        }

                        line = reader.ReadLine();
                        ++lineCounter;
                    }
                    //
                    if ( foundBody && foundHeader )
                    {
                        ret = TFileType.EFileMap;
                    }
                }
            }
            catch ( Exception )
            {
            }
            //
            return ret;
        }

        public MapFileEngine LoadFromFile( string aMapFileName, TSynchronicity aSynchronicity )
        {
            // Check if already exists
            MapFileEngine engine = null;
            //
            lock ( this )
            {
                engine = FindByMapFileName( aMapFileName );
                if ( engine != null )
                {
                    iFiles.Remove( engine );
                }

                engine = new MapFileEngine( this );
                engine.Observer += new AsyncReaderBase.Observer( MapEngine_ObserverProxy );
                engine.LoadFromFile( aMapFileName, aSynchronicity );
                iFiles.Add( engine );
            }

            return engine;
        }

        public bool Load( CodeSegDefinition aDefinition, TSynchronicity aSynchronicity )
        {
            bool ret = false;
            //
            if ( string.IsNullOrEmpty( aDefinition.MapFileName ) || !aDefinition.MapFileExists )
            {
            }
            else
            {
                // First pass - try to find map engine that matches the specified
                // PC file name. 
                string mapFileName = aDefinition.MapFileName;
                if ( aDefinition.MapFileExists )
                {
                    System.Diagnostics.Debug.WriteLine( "   LOAD {M}: " + aDefinition.ToString() );

                    MapFileEngine engine = FindByMapFileName( mapFileName );
                    if ( engine != null )
                    {
                        engine.Load( aDefinition );
                        ret = true;
                    }
                    else
                    {
                        // Map file engine doesn't exist for the specified code segment.
                        // Can we load it from file?
                        engine = LoadFromFile( aDefinition.MapFileName, aSynchronicity );
                        if ( engine != null )
                        {
                            engine.Load( aDefinition );
                            ret = true;
                        }
                    }
                }
            }
            //
            return ret;
        }

        public bool Unload( CodeSegDefinition aDefinition )
        {
            bool ret = false;
            //
            foreach ( MapFileEngine engine in iFiles )
            {
                if ( engine.Unload( aDefinition ) )
                {
                    ret = true;
                    break;
                }
            }
            //
            return ret;
        }

        public void UnloadAll()
        {
            foreach ( MapFileEngine engine in iFiles )
            {
                engine.UnloadAll();
            }
        }

        public bool IsLoaded( CodeSegDefinition aDefinition )
        {
            bool ret = false;
            //
            foreach ( MapFileEngine engine in iFiles )
            {
                if ( engine.IsLoaded( aDefinition ) )
                {
                    ret = true;
                    break;
                }
            }
            //
            return ret;
        }

        public string MapFileName( int aIndex )
        {
            return iFiles[ aIndex ].MapFileName;
        }
        #endregion

        #region Properties
        public int MapFileCount
        {
            get { return iFiles.Count; }
        }

        public CodeSegResolver CodeSegResolver
        {
            get { return iCodeSegResolver; }
        }

        public CodeSegDefinitionParser CodeSegParser
        {
            get { return iCodeSegParser; }
        }

        public GenericSymbolEngine MapFileEngineAt( int aIndex )
        {
            return iFiles[ aIndex ];
        }

        public string[] BinaryFileNames
        {
            get
            {
                List<string> fileNames = new List<string>( iFiles.Count );
                //
                foreach ( MapFileEngine engine in iFiles )
                {
                    // Map files only contain symbols for one binary
                    fileNames.Add( engine[ 0 ].HostBinaryFileName );
                }
                //
                return fileNames.ToArray();
            }
        }

        public string[] MapFileNames
        {
            get
            {
                List<string> fileNames = new List<string>( iFiles.Count );
                //
                foreach ( MapFileEngine engine in iFiles )
                {
                    fileNames.Add( engine.MapFileName );
                }
                //
                return fileNames.ToArray();
            }
        }
        #endregion

        #region From GenericSymbolEngine
        public override void Reset()
        {
            iFiles.Clear();
            iCodeSegResolver.Clear();
        }

        public override bool IsLoaded( string aFileName )
        {
            MapFileEngine engine = FindByMapFileName( aFileName );
            return engine != null;
        }

        public override bool IsReady
        {
            get
            {
                int readyCount = 0;
                //
                foreach ( MapFileEngine engine in iFiles )
                {
                    if ( engine.IsReady )
                    {
                        ++readyCount;
                    }
                }
                //
                return ( readyCount == iFiles.Count );
            }
        }

        public override GenericSymbolCollection this[ int aIndex ]
        {
            get
            {
                // Map files contain only a single symbol collection;
                GenericSymbolCollection ret = iFiles[ aIndex ][ 0 ];
                return ret;
            }
        }

        public override AddressRange Range
        {
            get
            {
                AddressRange ret = new AddressRange();
                //
                foreach ( MapFileEngine engine in iFiles )
                {
                    ret.Update( engine.Range );
                }
                //
                return ret;
            }
        }

        internal override void UnloadUntagged()
        {
        }
        #endregion

        #region From IGenericSymbolCollectionStatisticsInterface
        public override int NumberOfCollections
        {
            get
            {
                // Map files contain only a single symbol collection
                int count = iFiles.Count;
                return count;
            }
        }
        #endregion

        #region Event handlers
        private void MapEngine_ObserverProxy( SymbianUtils.AsyncReaderBase.TEvent aEvent, SymbianUtils.AsyncReaderBase aSender )
        {
            if ( Observer != null )
            {
                Observer( aEvent, aSender );
            }
        }
        #endregion

        #region Internal methods
        private MapFileEngine FindByMapFileName( string aFileName )
        {
            MapFileEngine ret = null;
            //
            foreach ( MapFileEngine engine in iFiles )
            {
                if ( engine.MapFileName.ToLower() == aFileName.ToLower() )
                {
                    ret = engine;
                    break;
                }
            }
            //
            return ret;
        }
        #endregion

        #region Data members
        private readonly CodeSegResolver iCodeSegResolver;
        private readonly CodeSegDefinitionParser iCodeSegParser;
        private List<MapFileEngine> iFiles = new List<MapFileEngine>();
        #endregion
    }
}