crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbolLib/Sources/Symbol/Engine/SymbolFileEngine.cs
changeset 0 818e61de6cd1
equal deleted inserted replaced
-1:000000000000 0:818e61de6cd1
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 * 
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 using System;
       
    18 using System.IO;
       
    19 using System.Text;
       
    20 using System.Threading;
       
    21 using System.Collections;
       
    22 using System.Collections.Generic;
       
    23 using SymbianUtils;
       
    24 using SymbianUtils.Range;
       
    25 using SymbianUtils.Tracer;
       
    26 using SymbianUtils.FileSystem;
       
    27 using SymbianUtils.FileSystem.Utilities;
       
    28 using SymbolLib.Generics;
       
    29 using SymbolLib.CodeSegDef;
       
    30 using SymbolLib.Sources.Symbol.Symbol;
       
    31 using SymbolLib.Sources.Symbol.File;
       
    32 using SymbolLib.Sources.Symbol.Parser;
       
    33 using SymbolLib.Sources.Symbol.Collection;
       
    34 
       
    35 namespace SymbolLib.Sources.Symbol.Engine
       
    36 {
       
    37     internal class SymbolFileEngine : GenericSymbolEngine, SymbolCollectionCreator, SymbolEntryCreator
       
    38 	{
       
    39 		#region Events
       
    40 		public event AsyncReaderBase.Observer Observer;
       
    41 		#endregion
       
    42 
       
    43         #region Enumerations
       
    44         public enum TActivationType
       
    45         {
       
    46             EImmediate,
       
    47             EOnDemand
       
    48         }
       
    49         #endregion
       
    50 
       
    51 		#region Constructors
       
    52         public SymbolFileEngine( ITracer aTracer, TActivationType aActivationType, bool aAllowNonRomSymbols )
       
    53             : base( aTracer )
       
    54 		{
       
    55             iAllowNonRomSymbols = aAllowNonRomSymbols;
       
    56             iActivationType = aActivationType;
       
    57 		}
       
    58 		#endregion
       
    59 
       
    60 		#region API
       
    61         public static bool IsSymbolFile( string aFileName )
       
    62         {
       
    63             string extension = Path.GetExtension( aFileName ).ToLower();
       
    64             return ( extension == KSymbolFileExtensionPrimary );
       
    65         }
       
    66 
       
    67         public SymbolsForBinary ReadFirstCollection( string aFileName )
       
    68         {
       
    69             bool isValid = false;
       
    70             return ReadFirstCollection( aFileName, out isValid );
       
    71         }
       
    72 
       
    73         public SymbolsForBinary ReadFirstCollection( string aFileName, out bool aIsSymbolFile )
       
    74         {
       
    75             iCurrentBinary = null;
       
    76             iSymbolFileName = aFileName;
       
    77             //
       
    78             iParser = new SymbolFileParser( this, this, aFileName, this );
       
    79             iParser.CollectionCompleted += new SymbolLib.Sources.Symbol.Parser.SymbolFileParser.CollectionCompletedHandler( Parser_CollectionCompletedSingleOnly );
       
    80             iParser.SymbolCreated += new SymbolLib.Sources.Symbol.Parser.SymbolFileParser.SymbolCreatedHandler( Parser_SymbolCreated );
       
    81             iParser.Read( TSynchronicity.ESynchronous );
       
    82             //
       
    83             SymbolsForBinary ret = null;
       
    84             if ( iAllSymbols.Count > 0 )
       
    85             {
       
    86                 ret = iAllSymbols[ 0 ];
       
    87                 aIsSymbolFile = true;
       
    88             }
       
    89 
       
    90             // Did we see any collections whatsoever (all be they data or code?)
       
    91             aIsSymbolFile = iParser.ContainedAtLeastOneCollectionFileName;
       
    92 
       
    93             return ret;
       
    94         }
       
    95 
       
    96         public void LoadFromFile( string aSymbolFileName, TSynchronicity aSynchronicity )
       
    97         {
       
    98 			iSymbolFileName = aSymbolFileName;
       
    99 			//
       
   100             iParser = new SymbolFileParser( this, this, aSymbolFileName, this );
       
   101             iParser.Tag = this;
       
   102 			iParser.iObserver += new SymbianUtils.AsyncReaderBase.Observer( ParserEventHandler );
       
   103             iParser.CollectionCompleted += new SymbolLib.Sources.Symbol.Parser.SymbolFileParser.CollectionCompletedHandler( Parser_CollectionCompleted );
       
   104             iParser.SymbolCreated += new SymbolLib.Sources.Symbol.Parser.SymbolFileParser.SymbolCreatedHandler( Parser_SymbolCreated );
       
   105             iParser.Read( aSynchronicity );
       
   106         }
       
   107 
       
   108         public bool IsLoaded( CodeSegDefinition aDefinition )
       
   109         {
       
   110             // In ROM, variation might mean that the file name
       
   111             // doesn't match the definition name from the actual run-time code
       
   112             // segments loaded by a process...
       
   113             //
       
   114             // If we don't find a file name match, but we do find an address match
       
   115             // then we'll treat it as "good enough"
       
   116             bool activated = false;
       
   117             string searchingFor = aDefinition.ImageFileName.ToLower();
       
   118             string searchingForWithoutExtension = FSUtilities.StripAllExtensions( searchingFor );
       
   119 
       
   120             // Try to promote a symbol 
       
   121             foreach ( SymbolsForBinary file in iActivatedSymbols )
       
   122             {
       
   123                 string entryName = System.IO.Path.GetFileName( file.HostBinaryFileName ).ToLower();
       
   124                 if ( entryName == searchingFor )
       
   125                 {
       
   126                     activated = true;
       
   127                     break;
       
   128                 }
       
   129                 else if ( file.AddressRangeStart == aDefinition.AddressStart && file.AddressRangeEnd == aDefinition.AddressEnd )
       
   130                 {
       
   131                     // E.g: ROM.symbol says:         "From    \epoc32\release\armv5\urel\xxx.22.dll"
       
   132                     //      runtime code seg says:   "xxx.dll"
       
   133                     // We must use the base address instead...
       
   134 
       
   135                     activated = true;
       
   136                     break;
       
   137                 }
       
   138                 else
       
   139                 {
       
   140                     // Try a fuzzy match
       
   141                     string entryNameWithoutExtension = FSUtilities.StripAllExtensions( entryName );
       
   142                     if ( entryNameWithoutExtension.Contains( searchingForWithoutExtension ) )
       
   143                     {
       
   144                         // Also make sure the base addresses are the same
       
   145                         if ( file.AddressRangeStart == aDefinition.AddressStart )
       
   146                         {
       
   147                             // Fuzzy match
       
   148                             activated = true;
       
   149                             break;
       
   150                         }
       
   151                     }
       
   152                 }
       
   153             }
       
   154 
       
   155             return activated;
       
   156         }
       
   157 
       
   158         public bool Load( CodeSegDefinition aDefinition )
       
   159         {
       
   160             bool activated = false;
       
   161             string searchingFor = aDefinition.EnvironmentFileName.ToLower();
       
   162             if ( string.IsNullOrEmpty( searchingFor ) )
       
   163             {
       
   164                 // Try to use on-target name instead, if valid
       
   165                 searchingFor = aDefinition.ImageFileName.ToLower();
       
   166             }
       
   167 
       
   168             // Try to promote a symbol 
       
   169             foreach( SymbolsForBinary file in iIdleSymbols )
       
   170             {
       
   171                 string entryName = System.IO.Path.GetFileName( file.HostBinaryFileName ).ToLower();
       
   172                 if  ( entryName == searchingFor )
       
   173                 {
       
   174 #if DEBUG
       
   175                     System.Diagnostics.Debug.WriteLine( "   LOAD {S}: " + aDefinition.ToString() );
       
   176 #endif
       
   177 
       
   178                     // Fix up the symbols in this collection
       
   179                     file.Fixup( aDefinition.AddressStart );
       
   180 					
       
   181                     // Update ranges
       
   182                     iRange.UpdateMin( file.AddressRangeStart );
       
   183                     iRange.UpdateMax( file.AddressRangeEnd );
       
   184 
       
   185                     // Housekeeping
       
   186                     iActivatedSymbols.Add( file );
       
   187                     iIdleSymbols.Remove( file );
       
   188                     iActivatedSymbols.Sort();
       
   189 
       
   190                     // Even though the symbols for this binary may not be explicitly referenced
       
   191                     // they are definitely required by the callee, therefore we tag them
       
   192                     // immediately.
       
   193                     file.Tagged = true;
       
   194 
       
   195                     // Indicate we loaded the code seg from a symbol file
       
   196                     aDefinition.Source = CodeSegDefinition.TSourceType.ESourceWasSymbolFile;
       
   197 
       
   198                     activated = true;
       
   199                     break;
       
   200                 }
       
   201             }
       
   202 
       
   203             return activated;
       
   204         }
       
   205 
       
   206         public bool Unload( CodeSegDefinition aDefinition )
       
   207         {
       
   208             bool suspended = false;
       
   209             string searchingFor = aDefinition.EnvironmentFileName.ToLower();
       
   210 
       
   211             // Try to promote a symbol 
       
   212             foreach( SymbolsForBinary file in iActivatedSymbols )
       
   213             {
       
   214                 string entryName = System.IO.Path.GetFileName( file.HostBinaryFileName ).ToLower();
       
   215                 if  ( entryName == searchingFor )
       
   216                 {
       
   217 #if DEBUG
       
   218                     System.Diagnostics.Debug.WriteLine( " UNLOAD {S}: " + aDefinition.ToString() );
       
   219 #endif
       
   220                     //
       
   221                     iActivatedSymbols.Remove( file );
       
   222                     iIdleSymbols.Add( file );
       
   223                     //
       
   224                     iRange.UpdateMin( file.AddressRangeStart );
       
   225                     iRange.UpdateMax( file.AddressRangeEnd );
       
   226                     //
       
   227                     suspended = true;
       
   228 
       
   229                     // NB: We don't untag the file since it was obviously needed at
       
   230                     // some point.
       
   231                     break;
       
   232                 }
       
   233             }
       
   234 
       
   235             return suspended;
       
   236         }
       
   237 
       
   238 		public void UnloadAll()
       
   239 		{
       
   240 			iActivatedSymbols.Clear();
       
   241 			iIdleSymbols.Clear();
       
   242 			//
       
   243 			foreach( SymbolsForBinary file in iAllSymbols )
       
   244 			{
       
   245 				iIdleSymbols.Add( file );
       
   246 			}
       
   247 		}
       
   248 		#endregion
       
   249 
       
   250         #region Properties
       
   251 		public string SymbolFileName
       
   252 		{
       
   253 			get { return iSymbolFileName; }
       
   254 		}
       
   255 
       
   256         public bool AllowNonRomSymbols
       
   257         {
       
   258             get { return iAllowNonRomSymbols; }
       
   259         }
       
   260 
       
   261 		public int Progress
       
   262 		{
       
   263 			get
       
   264 			{
       
   265 				int prog = 0;
       
   266 				//
       
   267 				if	( iParser != null )
       
   268 				{
       
   269 					prog = iParser.Progress;
       
   270 				}
       
   271 				//
       
   272 				return prog;
       
   273 			}
       
   274 		}
       
   275 
       
   276         public string[] BinaryFileNames
       
   277         {
       
   278             get
       
   279             {
       
   280                 List<string> fileNames = new List<string>( AllSymbols.Count );
       
   281                 //
       
   282                 foreach ( GenericSymbolCollection collection in AllSymbols )
       
   283                 {
       
   284                     fileNames.Add( collection.HostBinaryFileName );
       
   285                 }
       
   286                 //
       
   287                 return fileNames.ToArray();
       
   288             }
       
   289         }
       
   290 
       
   291 		public SymbolsForBinaryCollection AllSymbols
       
   292 		{
       
   293 			get { return iAllSymbols; }
       
   294 		}
       
   295 		#endregion
       
   296 
       
   297         #region From GenericSymbolEngine
       
   298         public override void Reset()
       
   299 		{
       
   300             iActivatedSymbols.Clear();
       
   301 			iIdleSymbols.Clear();
       
   302 			iAllSymbols.Clear();
       
   303             iSymbolFileName = string.Empty;
       
   304             iCurrentBinary = null;
       
   305             iRange = new AddressRange();
       
   306 		}
       
   307 
       
   308         public override bool IsLoaded( string aFileName )
       
   309         {
       
   310             return ( aFileName.ToLower() == iSymbolFileName.ToLower() );
       
   311         }
       
   312 
       
   313         public override bool IsReady
       
   314         {
       
   315             get
       
   316             {
       
   317                 bool ready = ( SymbolFileName.Length > 0 );
       
   318                 //
       
   319                 if	( ready && iParser != null )
       
   320                 {
       
   321                     ready = iParser.IsReady;
       
   322                 }
       
   323                 //
       
   324                 return ready;
       
   325             }
       
   326         }
       
   327 
       
   328         public override GenericSymbolCollection this[ int aIndex ]
       
   329         {
       
   330             get
       
   331             {
       
   332                 return iActivatedSymbols[ aIndex ];
       
   333             }
       
   334         }
       
   335 
       
   336         public override void SaveTaggedCollections( string aFileName )
       
   337         {
       
   338             // We override this so that we search through 'iAllSymbols' rather
       
   339             // than just the activated symbols (which would be the case if we
       
   340             // used the base class version of this method).
       
   341             using ( StreamWriter writer = new StreamWriter( aFileName, false ) )
       
   342             {
       
   343                 foreach ( GenericSymbolCollection collection in iAllSymbols )
       
   344                 {
       
   345                     if ( collection.Tagged )
       
   346                     {
       
   347                         System.Diagnostics.Debug.WriteLine( "STORING: " + collection.HostBinaryFileName );
       
   348                         collection.WriteToStream( writer );
       
   349                     }
       
   350                 }
       
   351             }
       
   352         }
       
   353 
       
   354         public override AddressRange Range
       
   355         {
       
   356             get
       
   357             {
       
   358                 return iRange;
       
   359             }
       
   360         }
       
   361 
       
   362         internal override void UnloadUntagged()
       
   363         {
       
   364 
       
   365         }
       
   366         #endregion
       
   367 
       
   368         #region From IGenericSymbolCollectionStatisticsInterface
       
   369         public override int NumberOfCollections
       
   370         {
       
   371             get { return iActivatedSymbols.Count; }
       
   372         }
       
   373         #endregion
       
   374 
       
   375 		#region AsyncReaderBase observer
       
   376 		private void ParserEventHandler( SymbianUtils.AsyncReaderBase.TEvent aEvent, SymbianUtils.AsyncReaderBase aObject )
       
   377 		{
       
   378 			if	( Observer != null )
       
   379 			{
       
   380 				Observer( aEvent, aObject );
       
   381 			}
       
   382 
       
   383             if  ( aEvent == AsyncReaderBase.TEvent.EReadingComplete )
       
   384             {
       
   385                 iActivatedSymbols.Sort();
       
   386                 iParser = null;
       
   387             }
       
   388 		}
       
   389 		#endregion
       
   390 
       
   391         #region Parser observer - for normal parsing
       
   392         private bool Parser_CollectionCompleted( SymbolsForBinary aCollection )
       
   393         {
       
   394             // Check whether the collection contains any item. If it doesn't, ditch it.
       
   395             // Remove empty collections or sort completed ones.
       
   396             bool takeCollection = false;
       
   397             int count = aCollection.Count;
       
   398             if ( count > 0 )
       
   399             {
       
   400                 // Check whether the collection contains at least 2 symbols, and if not
       
   401                 // does the one and only symbol just have a length of zero?
       
   402                 if ( count == 1 )
       
   403                 {
       
   404                     GenericSymbol symbol = aCollection.FirstSymbol;
       
   405                     takeCollection = ( symbol.Size > 0 ) || symbol.IsUnknownSymbol;
       
   406                 }
       
   407                 else
       
   408                 {
       
   409                     takeCollection = true;
       
   410                 }
       
   411             }
       
   412 
       
   413             // If its okay to take the collection, let's sort it and activate if necessary.
       
   414             if ( takeCollection )
       
   415             {
       
   416 #if INSPECT_SYMBOL_DATA
       
   417                 using ( StreamWriter writer = new StreamWriter( @"C:\Temp\OldSymbols\" + Path.GetFileName( aCollection.HostBinaryFileName ) + ".symbol" ) )
       
   418                 {
       
   419                     aCollection.WriteToStream( writer );
       
   420                 }
       
   421 #endif
       
   422                 // All the symbol collections - whether they are loaded or idle.
       
   423                 iAllSymbols.Add( aCollection );
       
   424 
       
   425                 // Then put the collection in the correct container depending on
       
   426                 // activation type.
       
   427                 if ( iActivationType == TActivationType.EImmediate )
       
   428                 {
       
   429                     aCollection.Sort();
       
   430                     iActivatedSymbols.Add( aCollection );
       
   431                     //
       
   432                     iRange.UpdateMin( aCollection.AddressRangeStart );
       
   433                     iRange.UpdateMax( aCollection.AddressRangeEnd );
       
   434                 }
       
   435                 else if ( iActivationType == TActivationType.EOnDemand )
       
   436                 {
       
   437                     ThreadPool.QueueUserWorkItem( new WaitCallback( SortCollection ), aCollection );
       
   438                     iIdleSymbols.Add( aCollection );
       
   439                 }
       
   440             }
       
   441             else
       
   442             {
       
   443                 //System.Diagnostics.Debug.WriteLine( "Discarded Symbol Collection: " + aCollection.TargetBinary );
       
   444                 //System.Diagnostics.Debug.WriteLine( " " );
       
   445             }
       
   446 
       
   447             iCurrentBinary = null;
       
   448             return SymbolFileParser.KCollectionCompletedAndContinueParsing;
       
   449         }
       
   450 
       
   451         private void Parser_SymbolCreated( SymbolSymbol aSymbol )
       
   452         {
       
   453             // 1) We accept symbols with an address of zero, providing that their size is greater
       
   454             //    than zero.
       
   455             //
       
   456             // 2) We accept symbols with an address greater than zero, irrespective of their size.
       
   457 			if	( ( aSymbol.Address >= 0 || aSymbol.Size > 0 ) || // 1
       
   458                   ( aSymbol.Address == 0 && aSymbol.Size > 0 )    // 2
       
   459                 )
       
   460 			{
       
   461                 iCurrentBinary.Add( this, aSymbol, AllowNonRomSymbols );
       
   462 			}
       
   463             else
       
   464             {
       
   465                 System.Diagnostics.Debug.WriteLine( "  Discarded symbol: " + aSymbol );
       
   466             }
       
   467         }
       
   468         #endregion
       
   469 
       
   470         #region Parser observer - for peeking at a symbol file's first collection
       
   471         private bool Parser_CollectionCompletedSingleOnly( SymbolLib.Sources.Symbol.File.SymbolsForBinary aCollection )
       
   472         {
       
   473             // Call our standard function to handle the collection
       
   474             Parser_CollectionCompleted( aCollection );
       
   475 
       
   476             // Indicate no more parsing required
       
   477             bool ret = SymbolFileParser.KCollectionCompletedAndContinueParsing;
       
   478             if ( aCollection.Count > 0 && iAllSymbols.Count > 0 )
       
   479             {
       
   480                 ret = SymbolFileParser.KCollectionCompletedAndAbortParsing;
       
   481             }
       
   482             //
       
   483             return ret;
       
   484         }
       
   485         #endregion
       
   486 
       
   487         #region SymbolCollectionCreator interface
       
   488         public SymbolsForBinary CreateCollection( string aHostFileName )
       
   489         {
       
   490             iCurrentBinary = new SymbolsForBinary( aHostFileName );
       
   491             iCurrentBinary.SourceFile = SymbolFileName;
       
   492             return iCurrentBinary;
       
   493         }
       
   494         #endregion
       
   495 
       
   496         #region SymbolEntryCreator interface
       
   497         public SymbolSymbol CreateSymbol()
       
   498         {
       
   499             return SymbolSymbol.New( iCurrentBinary );
       
   500         }
       
   501         #endregion
       
   502 
       
   503         #region Internal methods
       
   504         private void CalculateRange()
       
   505         {
       
   506             iRange.Reset();
       
   507             //
       
   508             foreach( SymbolsForBinary file in iActivatedSymbols )
       
   509             {
       
   510                 iRange.UpdateMin( file.AddressRangeStart );
       
   511                 iRange.UpdateMax( file.AddressRangeEnd );
       
   512             }
       
   513         }
       
   514 
       
   515         private void SortCollection( object aCollection )
       
   516         {
       
   517             SymbolsForBinary symbols = aCollection as SymbolsForBinary;
       
   518             if ( symbols != null )
       
   519             {
       
   520                 symbols.Sort();
       
   521             }
       
   522         }
       
   523         #endregion
       
   524 
       
   525         #region Internal constants
       
   526         private const string KSymbolFileExtensionPrimary = ".symbol";
       
   527         #endregion
       
   528 
       
   529         #region Data members
       
   530         private readonly TActivationType iActivationType;
       
   531         private readonly bool iAllowNonRomSymbols;
       
   532 		private string iSymbolFileName = string.Empty;
       
   533         private SymbolsForBinary iCurrentBinary = null;
       
   534         private SymbolFileParser iParser = null;
       
   535         private AddressRange iRange = new AddressRange();
       
   536 		private SymbolsForBinaryCollection iAllSymbols = new SymbolsForBinaryCollection();
       
   537 		private SymbolsForBinaryCollection iIdleSymbols = new SymbolsForBinaryCollection();
       
   538         private SymbolsForBinaryCollection iActivatedSymbols = new SymbolsForBinaryCollection();
       
   539         #endregion
       
   540     }
       
   541 }