crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbolLib/Sources/Map/Engine/MapFileEngine.cs
author Jussi Ryoma <ext-jussi.s.ryoma@nokia.com>
Fri, 27 Aug 2010 12:21:46 +0300
changeset 3 045ade241ef5
parent 0 818e61de6cd1
permissions -rw-r--r--
Version 1.0.13. The most important changes are: -detailed defect hash added -panic descriptions updated -release build is working -simple command line usage added

/*
* 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.Text;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using SymbolLib.CodeSegDef;
using SymbolLib.Generics;
using SymbolLib.Engines;
using SymbolLib.Sources.Map.File;
using SymbolLib.Sources.Map.Parser;
using SymbolLib.Sources.Map.Symbol;
using SymbianUtils;
using SymbianUtils.Range;
using SymbianUtils.Tracer;

namespace SymbolLib.Sources.Map.Engine
{
	internal class MapFileEngine : GenericSymbolEngine, SymbolEntryCreator
    {
		#region Events
        public event AsyncReaderBase.Observer Observer;
        #endregion

        #region Constructor & destructor
        public MapFileEngine( ITracer aTracer )
            : base( aTracer )
		{
		}
		#endregion

		#region API
        public static bool IsMapFile( string aFileName )
        {
            string extension = Path.GetExtension( aFileName ).ToLower();
            return ( extension == CodeSegDefinition.KMapFileExtension );
        }

        internal bool IsLoaded( CodeSegDefinition aDefinition )
        {
            bool ret = iMapFile.HostBinaryFileName == aDefinition.ImageFileNameAndPath;
            return ret;
        }

        internal void LoadFromFile( string aMapFileName, TSynchronicity aSynchronicity )
        {
            iMapFileName = aMapFileName;
            iMapFile = MapFile.NewByHostMapFileName( aMapFileName );
            //
            iParser = new MapFileParser( this, aMapFileName, this );
            iParser.Tag = this;
            iParser.iObserver += new SymbianUtils.AsyncReaderBase.Observer( Parser_Observer );
            iParser.SymbolCreated += new MapFileParser.SymbolCreatedHandler( Parser_SymbolCreated );
            iParser.BaseAddressHandler += new MapFileParser.MapFileBaseAddressHandler( Parser_BaseAddressHandler );
            iParser.Read( aSynchronicity );
        }

        internal void Load( CodeSegDefinition aDefinition )
        {
            iMapFile.Fixup( aDefinition );
        }

        internal bool Unload( CodeSegDefinition aDefinition )
        {
            return true;
        }

        internal void UnloadAll()
        {
        }
		#endregion

        #region Properties
        public MapFile MapFile
        {
            get { return iMapFile; }
        }

        public string MapFileName
        {
            get { return iMapFileName; }
        }
        #endregion

        #region From GenericSymbolEngine
        public override void Reset()
		{
            // Do nothing - we cannot unload our only file. This is taken
            // care of by parent class.
            iMapFile = null;
            iParser = null;
            iMapFileName = string.Empty;
        }

        public override bool IsReady
        {
            get
            {
                return true;
            }
        }

        public override bool IsLoaded( string aFileName )
        {
            bool ret = MapFileName == aFileName;
            return ret;
        }

        public override GenericSymbolCollection this[ int aIndex ]
        {
            get
            {
                return iMapFile;
            }
        }

        public override AddressRange Range
        {
            get
            {
                return iMapFile.AddressRange;
            }
        }

        internal override void UnloadUntagged()
        {

        }
        #endregion

        #region From IGenericSymbolCollectionStatisticsInterface
        public override int NumberOfCollections
        {
            get
			{
				return 1;
			}
        }
        #endregion

        #region From SymbolEntryCreator
        public MapSymbol CreateSymbol()
        {
            return MapSymbol.New( iMapFile );
        }
        #endregion

		#region Map file parser observer
        private void Parser_Observer( SymbianUtils.AsyncReaderBase.TEvent aEvent, SymbianUtils.AsyncReaderBase aSender )
        {
            if ( Observer != null )
            {
                Observer( aEvent, aSender );
            }

            if ( aEvent == SymbianUtils.AsyncReaderBase.TEvent.EReadingComplete )
            {
                iMapFile.EnsureAllEntriesHaveSize();
                iMapFile.Sort();

                int x = 0;
                if ( x != 0 )
                {
                    iMapFile.Dump();
                }

                iParser = null;
            }
        }

        private void Parser_SymbolCreated( MapSymbol aSymbol )
        {
            bool addItem = true;
            
            if ( iMapFile.Count > 0 )
            {
                int lastEntryIndex = iMapFile.Count - 1;
                MapSymbol lastEntry = (MapSymbol) iMapFile[ lastEntryIndex ];
                //
                long lastEntrySize = lastEntry.Size;
                long newEntrySize = aSymbol.Size;
                //
                if ( lastEntry.Address == aSymbol.Address )
                {
                    if ( lastEntrySize == 0 && newEntrySize > 0 )
                    {
                        // Remove an entry with zero size to replace it with a better definition...
                        iMapFile.RemoveAt( lastEntryIndex );
                    }
                    else if ( newEntrySize == 0 && lastEntrySize > 0 )
                    {
                        // Don't replace an entry with zero size when we already
                        // have a good item.
                        addItem = false;
                    }
                }
            }
         
            if ( addItem )
            {
                iMapFile.Add( this, aSymbol );
            }
        }

        private void Parser_BaseAddressHandler( uint aBaseAddress )
        {
            iMapFile.GlobalBaseAddress = aBaseAddress;
        }
        #endregion

		#region Internal methods
		#endregion

        #region Data members
        private MapFile iMapFile = null;
        private MapFileParser iParser = null;
        private string iMapFileName = string.Empty;
        #endregion
    }
}