crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianStructuresLib/Debug/Symbols/Symbols/SymbolCollection.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.Collections.Generic;
       
    21 using System.Threading;
       
    22 using SymbianUtils;
       
    23 using SymbianUtils.Range;
       
    24 using SymbianStructuresLib.CodeSegments;
       
    25 using SymbianStructuresLib.Debug.Symbols.Interfaces;
       
    26 using SymbianStructuresLib.Debug.Common.Id;
       
    27 using SymbianStructuresLib.Debug.Common.Interfaces;
       
    28 using SymbianStructuresLib.Debug.Common.FileName;
       
    29 
       
    30 namespace SymbianStructuresLib.Debug.Symbols
       
    31 {
       
    32     public class SymbolCollection : DisposableObject, IEnumerable<Symbol>, IComparable<SymbolCollection>, IComparer<Symbol>, IFormattable
       
    33     {
       
    34         #region Static constructors
       
    35         public static SymbolCollection New( IPlatformIdAllocator aIdAllocator, string aFileNameInHost, string aFileNameInDevice )
       
    36         {
       
    37             SymbolCollection ret = new SymbolCollection( aIdAllocator, aFileNameInHost, aFileNameInDevice );
       
    38             return ret;
       
    39         }
       
    40 
       
    41         public static SymbolCollection NewCopy( IPlatformIdAllocator aIdAllocator, SymbolCollection aCollection )
       
    42         {
       
    43             SymbolCollection ret = new SymbolCollection( aIdAllocator, aCollection );
       
    44             return ret;
       
    45         }
       
    46 
       
    47         public static SymbolCollection NewByHostFileName( IPlatformIdAllocator aIdAllocator, string aFileName )
       
    48         {
       
    49             SymbolCollection ret = new SymbolCollection( aIdAllocator, aFileName );
       
    50             return ret;
       
    51         }
       
    52         #endregion
       
    53 
       
    54         #region Delegates & events
       
    55         public delegate void RelocationStatusChangeHandler( SymbolCollection aCollection );
       
    56         public event RelocationStatusChangeHandler RelocationStatusChanged;
       
    57         #endregion
       
    58 
       
    59         #region Constructors
       
    60         private SymbolCollection( IPlatformIdAllocator aIdAllocator, string aFileNameInHost )
       
    61 		{
       
    62             iOriginalCollection = null;
       
    63             iId = aIdAllocator.AllocateId();
       
    64             iIdAllocator = aIdAllocator;
       
    65             iFileName = PlatformFileName.NewByHostName( aFileNameInHost );
       
    66             DefaultSymbolAdd();
       
    67 		}
       
    68 
       
    69         private SymbolCollection( IPlatformIdAllocator aIdAllocator, string aFileNameInHost, string aFileNameInDevice )
       
    70             : this( aIdAllocator, aFileNameInHost )
       
    71         {
       
    72             iFileName.FileNameInDevice = aFileNameInDevice;
       
    73         }
       
    74 
       
    75         private SymbolCollection( IPlatformIdAllocator aIdAllocator, SymbolCollection aCopy )
       
    76         {
       
    77             iId = aIdAllocator.AllocateId();
       
    78             iIdAllocator = aIdAllocator;
       
    79             iTag = aCopy.iTag;
       
    80             iOriginalCollection = aCopy;
       
    81             iFlags = aCopy.iFlags;
       
    82             iTagged = aCopy.iTagged;
       
    83             iBaseAddress = aCopy.iBaseAddress;
       
    84             iCodeSegmentResolver = aCopy.iCodeSegmentResolver;
       
    85             iRelocationHandler = aCopy.iRelocationHandler;
       
    86             iFileName = PlatformFileName.New( aCopy.FileName );
       
    87             iCodeSegmentResolver = aCopy.IfaceCodeSegmentResolver;
       
    88             iRelocationHandler = aCopy.IfaceRelocationHandler;
       
    89 
       
    90             // Deep copy symbols
       
    91             foreach ( Symbol symbol in aCopy )
       
    92             {
       
    93                 Symbol clone = Symbol.NewClone( this, symbol );
       
    94                 iSymbols.Add( clone );
       
    95             }
       
    96 
       
    97             // Recalculate addresses
       
    98             RecalculationAddressRange();
       
    99         }
       
   100 		#endregion
       
   101 
       
   102         #region API
       
   103         public void Serialize( StreamWriter aWriter )
       
   104         {
       
   105             StringBuilder temp = new StringBuilder();
       
   106             //
       
   107             lock ( iFileName )
       
   108             {
       
   109                 temp.AppendLine( string.Empty );
       
   110                 temp.AppendLine( "From    " + iFileName.FileNameInHost );
       
   111                 temp.AppendLine( string.Empty );
       
   112             }
       
   113             //
       
   114             lock ( iSymbols )
       
   115             {
       
   116                 foreach ( Symbol symbol in iSymbols )
       
   117                 {
       
   118                     temp.AppendLine( symbol.ToString( "stream", null ) );
       
   119                 }
       
   120             }
       
   121 
       
   122             aWriter.Write( temp.ToString() );
       
   123         }
       
   124 
       
   125         public void Add( Symbol aSymbol )
       
   126         {
       
   127             if ( aSymbol.IsDefault )
       
   128             {
       
   129                 throw new ArgumentException( "Cannot add default symbol" );
       
   130             }
       
   131             //
       
   132             lock ( iSymbols )
       
   133             {
       
   134                 int count = iSymbols.Count;
       
   135                 if ( count == 1 )
       
   136                 {
       
   137                     // Possibly...
       
   138                     DefaultSymbolRemove();
       
   139                 }
       
   140 
       
   141                 // Because count might have changed if we removed default
       
   142                 // symbol.
       
   143                 count = iSymbols.Count;
       
   144                 if ( count >= 1 )
       
   145                 {
       
   146                     Symbol last = iSymbols[ count - 1 ];
       
   147                     if ( aSymbol.Address < last.Address )
       
   148                     {
       
   149                         // We appear to be adding a symbol with an earlier address,
       
   150                         // which implies we need to sort the collection.
       
   151                         lock( iFlagLock )
       
   152                         {
       
   153                             iFlags |= TFlags.EFlagsRequiresSorting;
       
   154                         }
       
   155                     }
       
   156                 }
       
   157                 
       
   158                 // Now add it
       
   159                 iSymbols.Add( aSymbol );
       
   160                 //
       
   161                 if ( !InTransaction )
       
   162                 {
       
   163                     RecalculationAddressRange();
       
   164                 }
       
   165             }
       
   166         }
       
   167 
       
   168         public void AddRange( IEnumerable<Symbol> aSymbols )
       
   169         {
       
   170             TransactionBegin();
       
   171             //
       
   172             try
       
   173             {
       
   174                 foreach ( Symbol symbol in aSymbols )
       
   175                 {
       
   176                     Add( symbol );
       
   177                 }
       
   178             }
       
   179             finally
       
   180             {
       
   181                 TransactionEnd();
       
   182             }
       
   183         }
       
   184 
       
   185         public void Clear()
       
   186         {
       
   187             lock ( iSymbols )
       
   188             {
       
   189                 iSymbols.Clear();
       
   190                 
       
   191                 // We are definitely empty so force the default symbol to be
       
   192                 // added irrespective of flags
       
   193                 DefaultSymbolAdd( true );
       
   194             }
       
   195         }
       
   196 
       
   197         public void Remove( Symbol aSymbol )
       
   198         {
       
   199             if ( aSymbol.IsDefault )
       
   200             {
       
   201                 throw new ArgumentException( "Cannot remove default symbol" );
       
   202             }
       
   203             //
       
   204             lock ( iSymbols )
       
   205             {
       
   206                 iSymbols.Remove( aSymbol );
       
   207                 if ( iSymbols.Count == 0 )
       
   208                 {
       
   209                     // We are definitely empty so force the default symbol to be
       
   210                     // added irrespective of flags
       
   211                     DefaultSymbolAdd( true );
       
   212                     System.Diagnostics.Debug.Assert( IsEmptyApartFromDefaultSymbol );
       
   213                 }
       
   214             }
       
   215         }
       
   216 
       
   217         public void RemoveAt( int aIndex )
       
   218         {
       
   219             lock ( iSymbols )
       
   220             {
       
   221                 Symbol symbol = iSymbols[ aIndex ];
       
   222                 if ( symbol.IsDefault )
       
   223                 {
       
   224                     throw new ArgumentException( "Cannot remove default symbol" );
       
   225                 }
       
   226                 //
       
   227                 iSymbols.RemoveAt( aIndex );
       
   228                 if ( iSymbols.Count == 0 )
       
   229                 {
       
   230                     // We are definitely empty so force the default symbol to be
       
   231                     // added irrespective of flags
       
   232                     DefaultSymbolAdd( true );
       
   233                     System.Diagnostics.Debug.Assert( IsEmptyApartFromDefaultSymbol );
       
   234                 }
       
   235             }
       
   236         }
       
   237  
       
   238         public bool Contains( uint aAddress )
       
   239         {
       
   240             if ( iAddresses == null )
       
   241             {
       
   242                 iAddresses = new AddressRangeCollection( (IEnumerable<AddressRange>) this );
       
   243                 RecalculationAddressRange();
       
   244             }
       
   245             //
       
   246             bool found = iAddresses.Contains( aAddress );
       
   247             return found;
       
   248         }
       
   249 
       
   250         public bool IsMatchingCodeSegment( CodeSegDefinition aCodeSegment )
       
   251         {
       
   252             bool ret = false;
       
   253             //
       
   254             if ( iCodeSegmentResolver != null )
       
   255             {
       
   256                 ret = iCodeSegmentResolver.IsMatchingCodeSegment( this, aCodeSegment );
       
   257             }
       
   258             else
       
   259             {
       
   260                 PlatformFileName codeSegName = PlatformFileName.NewByDeviceName( aCodeSegment.FileName );
       
   261                 ret = FileName.Equals( codeSegName );
       
   262             }
       
   263             //
       
   264             return ret;
       
   265         }
       
   266 
       
   267         public void Sort()
       
   268         {
       
   269             if ( ( iFlags & TFlags.EFlagsRequiresSorting ) == TFlags.EFlagsRequiresSorting )
       
   270             {
       
   271                 iSymbols.Sort( this );
       
   272                 RecalculationAddressRange();
       
   273             }
       
   274         }
       
   275 
       
   276         public void SortAsync()
       
   277         {
       
   278             if ( ( iFlags & TFlags.EFlagsRequiresSorting ) == TFlags.EFlagsRequiresSorting )
       
   279             {
       
   280                 ThreadPool.QueueUserWorkItem( new WaitCallback( InitiateAsyncSort ) );
       
   281             }
       
   282         }
       
   283 
       
   284         public void Relocate( uint aTo )
       
   285         {
       
   286             uint old = iBaseAddress;
       
   287             iBaseAddress = aTo;
       
   288             //
       
   289             if ( iRelocationHandler != null )
       
   290             {
       
   291                 iRelocationHandler.PrepareForRelocation( this, old, BaseAddress );
       
   292             }
       
   293             //
       
   294             RecalculationAddressRange();
       
   295         }
       
   296 
       
   297         public void TransactionBegin()
       
   298         {
       
   299             lock ( iFlagLock )
       
   300             {
       
   301                 iFlags |= TFlags.EFlagsInTransaction;
       
   302             }
       
   303         }
       
   304 
       
   305         public void TransactionEnd()
       
   306         {
       
   307             lock ( iFlagLock )
       
   308             {
       
   309                 iFlags &= ~TFlags.EFlagsInTransaction;
       
   310             }
       
   311 
       
   312             RecalculationAddressRange();
       
   313         }
       
   314 
       
   315         public void Clone( IEnumerable<Symbol> aSymbols )
       
   316         {
       
   317             // Deep copy symbols
       
   318             Clear();
       
   319             try
       
   320             {
       
   321                 TransactionBegin();
       
   322                 foreach ( Symbol symbol in aSymbols )
       
   323                 {
       
   324                     // Make sure we don't try to add the default symbol. The symbol collection
       
   325                     // manages this automatically.
       
   326                     if ( symbol.IsDefault )
       
   327                     {
       
   328                     }
       
   329                     else
       
   330                     {
       
   331                         Symbol clone = Symbol.NewClone( this, symbol );
       
   332                         Add( clone );
       
   333                     }
       
   334                 }
       
   335             }
       
   336             finally
       
   337             {
       
   338                 TransactionEnd();
       
   339             }
       
   340         }
       
   341         #endregion
       
   342 
       
   343 		#region Properties
       
   344 		public int Count
       
   345 		{
       
   346             get
       
   347             {
       
   348                 lock ( iSymbols )
       
   349                 {
       
   350                     return iSymbols.Count;
       
   351                 }
       
   352             }
       
   353 		}
       
   354 
       
   355 		public Symbol this[ int aIndex ]
       
   356 		{
       
   357             get
       
   358             {
       
   359                 lock ( iSymbols )
       
   360                 {
       
   361                     return iSymbols[ aIndex ];
       
   362                 }
       
   363             }
       
   364         }
       
   365 
       
   366         public Symbol this[ uint aAddress ]
       
   367         {
       
   368             get
       
   369             {
       
   370                 // For debugging
       
   371                 int x = 0;
       
   372                 if ( x > 0 )
       
   373                 {
       
   374                     string dump = Dump( aAddress );
       
   375                     System.Diagnostics.Debug.WriteLine( dump );
       
   376                 }
       
   377                 //
       
   378                 Symbol ret = null;
       
   379                 Symbol temp = Symbol.NewTemp( this, aAddress );
       
   380                 //
       
   381                 lock ( iSymbols )
       
   382                 {
       
   383                     AddressFindingComparer comparer = new AddressFindingComparer();
       
   384                     int pos = iSymbols.BinarySearch( temp, comparer );
       
   385                     int count = iSymbols.Count;
       
   386                     //
       
   387                     if ( pos >= 0 && pos < count )
       
   388                     {
       
   389                         ret = iSymbols[ pos ];
       
   390                         System.Diagnostics.Debug.Assert( ret.AddressRange.Contains( aAddress ) );
       
   391                     }
       
   392                 }
       
   393                 //
       
   394                 return ret;
       
   395             }
       
   396         }
       
   397 
       
   398         public Symbol FirstSymbol
       
   399 		{
       
   400 			get
       
   401 			{
       
   402 				Symbol ret = null;
       
   403                 lock ( iSymbols )
       
   404                 {
       
   405                     if ( Count > 0 )
       
   406                     {
       
   407                         ret = this[ 0 ];
       
   408                     }
       
   409                 }
       
   410 				return ret;
       
   411 			}
       
   412 		}
       
   413 
       
   414 		public Symbol LastSymbol
       
   415 		{
       
   416 			get
       
   417 			{
       
   418 				Symbol ret = null;
       
   419                 lock ( iSymbols )
       
   420                 {
       
   421                     if ( Count > 0 )
       
   422                     {
       
   423                         ret = this[ Count - 1 ];
       
   424                     }
       
   425                 }
       
   426 				return ret;
       
   427 			}
       
   428 		}
       
   429 
       
   430         public bool Tagged
       
   431         {
       
   432             get { return iTagged; }
       
   433             set
       
   434             {
       
   435                 // The 'tagged' property is one of the few that we must (and can safely)
       
   436                 // cascade to the original underlying collection. 
       
   437                 //
       
   438                 // We do this, because when working with ROFS/relocated symbols, we generally
       
   439                 // clone and fixup, rather than fixup the original. This permits us to use
       
   440                 // a symbol collection at multiple base addresses (i.e. use the same symbols within
       
   441                 // different process-relative views of the "world").
       
   442                 //
       
   443                 // If we don't cascade the tagged attribute to the original (i.e. primary) symbol
       
   444                 // collection, then when the client application wants to serialized tagged collections
       
   445                 // the ROFS collections will potentially be missing (if they have been unloaded).
       
   446                 if ( iOriginalCollection != null )
       
   447                 {
       
   448                     iOriginalCollection.Tagged = value;
       
   449                     iTagged = value;
       
   450                 }
       
   451                 else if ( iTagged != value )
       
   452                 {
       
   453                     iTagged = value;
       
   454                     if ( iTagged )
       
   455                     {
       
   456                         System.Diagnostics.Debug.WriteLine( string.Format( "[S] TAGGING: 0x{0:x8}, {1}", this.BaseAddress, iFileName ) );
       
   457                     }
       
   458                 }
       
   459             }
       
   460         }
       
   461 
       
   462         public bool InTransaction
       
   463         {
       
   464             get { return ( iFlags & TFlags.EFlagsInTransaction ) == TFlags.EFlagsInTransaction; }
       
   465         }
       
   466 
       
   467         public bool IsRelocatable
       
   468         {
       
   469             get { return ( iFlags & TFlags.EFlagsIsRelocatable ) == TFlags.EFlagsIsRelocatable; }
       
   470             set
       
   471             {
       
   472                 lock ( iFlagLock )
       
   473                 {
       
   474                     bool wasSet = ( iFlags & TFlags.EFlagsIsRelocatable ) == TFlags.EFlagsIsRelocatable;
       
   475                     if ( wasSet != value )
       
   476                     {
       
   477                         if ( value )
       
   478                         {
       
   479                             iFlags |= TFlags.EFlagsIsRelocatable;
       
   480                         }
       
   481                         else
       
   482                         {
       
   483                             iFlags &= ~TFlags.EFlagsIsRelocatable;
       
   484                         }
       
   485 
       
   486                         // Report event if needed
       
   487                         if ( RelocationStatusChanged != null )
       
   488                         {
       
   489                             RelocationStatusChanged( this );
       
   490                         }
       
   491                     }
       
   492                 }
       
   493             }
       
   494         }
       
   495 
       
   496         public bool IsFixed
       
   497         {
       
   498             get { return !IsRelocatable; }
       
   499             set
       
   500             {
       
   501                 IsRelocatable = !value;
       
   502             }
       
   503         }
       
   504 
       
   505         public bool IsEmptyApartFromDefaultSymbol
       
   506         {
       
   507             get
       
   508             { 
       
   509                 bool ret = ( iFlags & TFlags.EFlagsIsEmptyApartFromDefaultSymbol ) == TFlags.EFlagsIsEmptyApartFromDefaultSymbol;
       
   510                 return ret;
       
   511             }
       
   512             private set
       
   513             {
       
   514                 lock ( iFlagLock )
       
   515                 {
       
   516                     if ( value )
       
   517                     {
       
   518                         iFlags |= TFlags.EFlagsIsEmptyApartFromDefaultSymbol;
       
   519                     }
       
   520                     else
       
   521                     {
       
   522                         iFlags &= ~TFlags.EFlagsIsEmptyApartFromDefaultSymbol;
       
   523                     }
       
   524                 }
       
   525             }
       
   526         }
       
   527 
       
   528         public object Tag
       
   529         {
       
   530             get { return iTag; }
       
   531             set
       
   532             {
       
   533                 iTag = value;
       
   534             }
       
   535         }
       
   536 
       
   537         public uint BaseAddress
       
   538         {
       
   539             get
       
   540             {
       
   541                 uint ret = iBaseAddress;
       
   542                 return ret;
       
   543             }
       
   544         }
       
   545 
       
   546         public PlatformId Id
       
   547         {
       
   548             get { return iId; }
       
   549         }
       
   550 
       
   551         public PlatformFileName FileName
       
   552 		{
       
   553 			get { return iFileName; }
       
   554 		}
       
   555 
       
   556         public SymbolCollectionList ParentList
       
   557         {
       
   558             get { return iParentList; }
       
   559             internal set { iParentList = value; }
       
   560         }
       
   561 
       
   562         public AddressRange SubsumedPrimaryRange
       
   563         {
       
   564             get
       
   565             {
       
   566                 AddressRange ret = new AddressRange( this.BaseAddress, this.BaseAddress );
       
   567                 //
       
   568                 if ( iAddresses != null )
       
   569                 {
       
   570                     int count = iAddresses.Count;
       
   571                     for( int i=0; i<count; i++ )
       
   572                     {
       
   573                         AddressRange segment = iAddresses[ i ];
       
   574                         
       
   575                         // Ranges should be reliably sorted/calculated so that we
       
   576                         // shouldn't end up going backwards beyond the base address
       
   577                         // of the code segment
       
   578                         System.Diagnostics.Debug.Assert( segment.Min >= ret.Min );
       
   579 
       
   580                         // If the segmented address range doesn't sit within the existing
       
   581                         // range we are building, then we may need to extend our return
       
   582                         // value.
       
   583                         if ( !ret.Contains( segment ) )
       
   584                         {
       
   585                             uint diff = segment.Min - ret.Max;
       
   586                             if ( diff <= KMaximumNonConsecutiveAddressRangeDifferenceToSubsume )
       
   587                             {
       
   588                                 ret.UpdateMax( segment.Max );
       
   589                             }
       
   590                         }
       
   591                     }
       
   592                 }
       
   593                 //
       
   594                 return ret;
       
   595             }
       
   596         }
       
   597 
       
   598         public object SyncRoot
       
   599         {
       
   600             get
       
   601             {
       
   602                 return iSymbols;
       
   603             }
       
   604         }
       
   605 		#endregion
       
   606 
       
   607         #region Properties - interfaces
       
   608         public ISymbolCodeSegmentResolver IfaceCodeSegmentResolver
       
   609         {
       
   610             get { return iCodeSegmentResolver; }
       
   611             set { iCodeSegmentResolver = value; }
       
   612         }
       
   613 
       
   614         public ISymbolCollectionRelocationHandler IfaceRelocationHandler
       
   615         {
       
   616             get { return iRelocationHandler; }
       
   617             set { iRelocationHandler = value; }
       
   618         }
       
   619         #endregion
       
   620 
       
   621         #region From IComparable<SymbolCollection>
       
   622         public int CompareTo( SymbolCollection aCollection )
       
   623 		{
       
   624             int ret = ( aCollection.FileName == this.FileName ) ? 0 : -1;
       
   625 			//
       
   626             if ( ret == 0 )
       
   627             {
       
   628                 if ( BaseAddress == aCollection.BaseAddress )
       
   629                 {
       
   630                     ret = 0;
       
   631                 }
       
   632                 else if ( BaseAddress > aCollection.BaseAddress )
       
   633                 {
       
   634                     ret = 1;
       
   635                 }
       
   636                 else
       
   637                 {
       
   638                     ret = -1;
       
   639                 }
       
   640             }
       
   641 			//
       
   642 			return ret;
       
   643 		}
       
   644 		#endregion
       
   645 
       
   646         #region From IComparer<Symbol>
       
   647         public int Compare( Symbol aLeft, Symbol aRight )
       
   648         {
       
   649             System.Diagnostics.Debug.Assert( aLeft.EndAddress >= aLeft.Address );
       
   650             System.Diagnostics.Debug.Assert( aRight.EndAddress >= aRight.Address );
       
   651             //
       
   652             int ret = -1;
       
   653             //
       
   654             if ( aLeft.Address == aRight.Address && aLeft.EndAddress == aRight.EndAddress )
       
   655             {
       
   656                 ret = 0;
       
   657             }
       
   658             else if ( aLeft.EndAddress == aRight.Address )
       
   659             {
       
   660                 System.Diagnostics.Debug.Assert( aLeft.Address < aRight.Address );
       
   661                 System.Diagnostics.Debug.Assert( aRight.EndAddress >= aLeft.EndAddress );
       
   662                 //
       
   663                 ret = -1;
       
   664             }
       
   665             else if ( aLeft.Address == aRight.EndAddress )
       
   666             {
       
   667                 System.Diagnostics.Debug.Assert( aRight.Address < aLeft.Address );
       
   668                 System.Diagnostics.Debug.Assert( aLeft.EndAddress >= aRight.EndAddress );
       
   669                 //
       
   670                 ret = 1;
       
   671             }
       
   672             else if ( aLeft.Address > aRight.EndAddress )
       
   673             {
       
   674                 System.Diagnostics.Debug.Assert( aLeft.EndAddress > aRight.EndAddress );
       
   675                 System.Diagnostics.Debug.Assert( aLeft.EndAddress > aRight.Address );
       
   676                 ret = 1;
       
   677             }
       
   678             else if ( aLeft.EndAddress < aRight.Address )
       
   679             {
       
   680                 System.Diagnostics.Debug.Assert( aLeft.Address < aRight.EndAddress );
       
   681                 System.Diagnostics.Debug.Assert( aRight.EndAddress > aLeft.EndAddress );
       
   682                 ret = -1;
       
   683             }
       
   684             //
       
   685             return ret;
       
   686         }
       
   687         #endregion
       
   688 
       
   689         #region From IEnumerable<Symbol>
       
   690         IEnumerator<Symbol> IEnumerable<Symbol>.GetEnumerator()
       
   691         {
       
   692             foreach ( Symbol entry in iSymbols )
       
   693             {
       
   694                 yield return entry;
       
   695             }
       
   696         }
       
   697 
       
   698         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
       
   699         {
       
   700             foreach ( Symbol entry in iSymbols )
       
   701             {
       
   702                 yield return entry;
       
   703             }
       
   704         }
       
   705         #endregion
       
   706 
       
   707         #region From IFormattable
       
   708         public string ToString( string aFormat, IFormatProvider aFormatProvider )
       
   709         {
       
   710             string ret = string.Empty;
       
   711             //
       
   712             if ( aFormat == null )
       
   713             {
       
   714                 ret = iFileName.ToString();
       
   715             }
       
   716             else if ( aFormat.ToUpper() == "FULL" )
       
   717             {
       
   718                 ret = Dump();
       
   719             }
       
   720             else
       
   721             {
       
   722                 throw new FormatException( string.Format( "Invalid format string: '{0}'.", aFormat ) );
       
   723             }
       
   724             //
       
   725             return ret;
       
   726         }
       
   727         #endregion
       
   728 
       
   729         #region From System.Object
       
   730         public override string ToString()
       
   731         {
       
   732             return iFileName.ToString();
       
   733         }
       
   734 
       
   735         public override bool Equals( object aObject )
       
   736         {
       
   737             if ( aObject != null && aObject is SymbolCollection )
       
   738             {
       
   739                 SymbolCollection col = (SymbolCollection) aObject;
       
   740                 bool ret = ( col.FileName == this.FileName );
       
   741                 return ret;
       
   742             }
       
   743             //
       
   744             return base.Equals( aObject );
       
   745         }
       
   746 
       
   747         public override int GetHashCode()
       
   748         {
       
   749             return iFileName.GetHashCode();
       
   750         }
       
   751         #endregion
       
   752 
       
   753         #region Internal enumerations
       
   754         [Flags]
       
   755         private enum TFlags : byte
       
   756         {
       
   757             EFlagsNone = 0,
       
   758             EFlagsInTransaction = 1,
       
   759             EFlagsIsRelocatable = 2,
       
   760             EFlagsIsEmptyApartFromDefaultSymbol = 4,
       
   761             EFlagsRequiresSorting = 8,
       
   762         };
       
   763         #endregion
       
   764 
       
   765         #region Internal constants
       
   766         private const uint KMaximumNonConsecutiveAddressRangeDifferenceToSubsume = 512;
       
   767         #endregion
       
   768 
       
   769         #region Internal methods
       
   770         private string Dump()
       
   771         {
       
   772             string ret = Dump( uint.MaxValue );
       
   773             return ret;
       
   774         }
       
   775 
       
   776         private string Dump( uint aAddress )
       
   777         {
       
   778 #if SYMCOL_INVARIANT_CHECK
       
   779             DebugCheckInvariant();
       
   780 #endif
       
   781             //
       
   782             StringBuilder ret = new StringBuilder();
       
   783             //
       
   784             int i = 0;
       
   785             string line = string.Empty;
       
   786             //
       
   787             lock ( iSymbols )
       
   788             {
       
   789                 foreach ( Symbol entry in iSymbols )
       
   790                 {
       
   791                     if ( aAddress != uint.MaxValue && entry.Contains( aAddress ) )
       
   792                     {
       
   793                         line = i.ToString( "d8" ) + " * [" + entry.Address.ToString( "x8" ) + "-" + entry.EndAddress.ToString( "x8" ) + "] " + entry.Name;
       
   794                     }
       
   795                     else
       
   796                     {
       
   797                         line = i.ToString( "d8" ) + "   [" + entry.Address.ToString( "x8" ) + "-" + entry.EndAddress.ToString( "x8" ) + "] " + entry.Name;
       
   798                     }
       
   799                     //
       
   800                     ret.AppendLine( line );
       
   801                     i++;
       
   802                 }
       
   803             }
       
   804             //
       
   805             return ret.ToString();
       
   806         }
       
   807 
       
   808         private void DefaultSymbolAdd()
       
   809         {
       
   810             DefaultSymbolAdd( false );
       
   811         }
       
   812 
       
   813         private void DefaultSymbolAdd( bool aForce )
       
   814         {
       
   815 #if SYMCOL_INVARIANT_CHECK
       
   816             DebugCheckInvariant();
       
   817 #endif
       
   818             //
       
   819             if ( !IsEmptyApartFromDefaultSymbol || aForce )
       
   820             {
       
   821                 lock ( iSymbols )
       
   822                 {
       
   823                     System.Diagnostics.Debug.Assert( Count == 0 );
       
   824                     Symbol def = Symbol.NewDefault( this );
       
   825                     iSymbols.Add( def );
       
   826                     IsEmptyApartFromDefaultSymbol = true;
       
   827                 }
       
   828             }
       
   829         }
       
   830 
       
   831         private void DefaultSymbolRemove()
       
   832         {
       
   833 #if SYMCOL_INVARIANT_CHECK
       
   834             DebugCheckInvariant();
       
   835 #endif
       
   836             //
       
   837             if ( IsEmptyApartFromDefaultSymbol )
       
   838             {
       
   839                 lock ( iSymbols )
       
   840                 {
       
   841                     int count = iSymbols.Count;
       
   842                     //
       
   843                     if ( IsEmptyApartFromDefaultSymbol )
       
   844                     {
       
   845                         System.Diagnostics.Debug.Assert( count == 1 && this.FirstSymbol.IsDefault );
       
   846                         iSymbols.RemoveAt( 0 );
       
   847                         IsEmptyApartFromDefaultSymbol = false;
       
   848                     }
       
   849 #if SYMCOL_INVARIANT_CHECK
       
   850                 else if ( count > 0 )
       
   851                 {
       
   852                     System.Diagnostics.Debug.Assert( this.FirstSymbol.IsDefault == false );
       
   853                 }
       
   854 #endif
       
   855                 }
       
   856             }
       
   857         }
       
   858 
       
   859         private void InitiateAsyncSort( object aNotUsed )
       
   860         {
       
   861             Sort();
       
   862         }
       
   863 
       
   864 #if SYMCOL_INVARIANT_CHECK
       
   865         private void DebugCheckInvariant()
       
   866         {
       
   867             lock ( iSymbols )
       
   868             {
       
   869                 int count = Count;
       
   870                 if ( count > 0 )
       
   871                 {
       
   872                     Symbol first = this.FirstSymbol;
       
   873                     if ( first.IsDefault )
       
   874                     {
       
   875                         System.Diagnostics.Debug.Assert( IsEmptyApartFromDefaultSymbol );
       
   876                         System.Diagnostics.Debug.Assert( count == 1 );
       
   877                     }
       
   878                 }
       
   879             }
       
   880         }
       
   881 #endif
       
   882 
       
   883         private void RecalculationAddressRange()
       
   884         {
       
   885 #if SYMCOL_INVARIANT_CHECK
       
   886             DebugCheckInvariant();
       
   887 #endif
       
   888             //
       
   889             if ( !InTransaction )
       
   890             {
       
   891                 AddressRangeCollection range = new AddressRangeCollection();
       
   892                 lock ( iSymbols )
       
   893                 {
       
   894                     foreach ( Symbol entry in iSymbols )
       
   895                     {
       
   896                         range.Add( entry.AddressRange );
       
   897                     }
       
   898                 }
       
   899                 //
       
   900                 iAddresses = range;
       
   901             }
       
   902         }
       
   903         #endregion
       
   904 
       
   905         #region Internal properties
       
   906         internal IPlatformIdAllocator IdAllocator
       
   907         {
       
   908             get { return iIdAllocator; }
       
   909         }
       
   910 
       
   911         internal AddressRangeCollection AddressRangeCollection
       
   912         {
       
   913             get { return iAddresses; }
       
   914         }
       
   915         #endregion
       
   916 
       
   917         #region Internal classes
       
   918         internal class AddressFindingComparer : IComparer<Symbol>
       
   919         {
       
   920             public int Compare( Symbol aLeft, Symbol aRight )
       
   921             {
       
   922                 int ret = -1;
       
   923                 //
       
   924                 AddressRange lr = aLeft.AddressRange;
       
   925                 AddressRange rr = aRight.AddressRange;
       
   926                 //
       
   927                 if ( lr.Contains( rr ) || rr.Contains( lr ) )
       
   928                 {
       
   929                     ret = 0;
       
   930                 }
       
   931                 else
       
   932                 {
       
   933                     ret = lr.CompareTo( rr );
       
   934                 }
       
   935                 //
       
   936                 return ret;
       
   937             }
       
   938         }
       
   939         #endregion
       
   940 
       
   941         #region From DisposableObject
       
   942         protected override void CleanupManagedResources()
       
   943         {
       
   944             try
       
   945             {
       
   946                 base.CleanupManagedResources();
       
   947             }
       
   948             finally
       
   949             {
       
   950                 iTag = null;
       
   951                 if ( iAddresses != null )
       
   952                 {
       
   953                     iAddresses.Clear();
       
   954                 }
       
   955                 iSymbols.Clear();
       
   956                 iParentList = null;
       
   957                 iCodeSegmentResolver = null;
       
   958                 iRelocationHandler = null;
       
   959             }
       
   960         }
       
   961         #endregion
       
   962 
       
   963         #region Data members
       
   964         private readonly PlatformId iId;
       
   965         private readonly IPlatformIdAllocator iIdAllocator;
       
   966         private readonly PlatformFileName iFileName;
       
   967         private readonly SymbolCollection iOriginalCollection = null;
       
   968         private object iTag = null;
       
   969         private object iFlagLock = new object();
       
   970         private bool iTagged = false;
       
   971         private TFlags iFlags = TFlags.EFlagsNone;
       
   972         private uint iBaseAddress = 0;
       
   973         private AddressRangeCollection iAddresses = null;
       
   974         private List<Symbol> iSymbols = new List<Symbol>();
       
   975         private SymbolCollectionList iParentList = null;
       
   976         private ISymbolCodeSegmentResolver iCodeSegmentResolver = null;
       
   977         private ISymbolCollectionRelocationHandler iRelocationHandler = null;
       
   978 		#endregion
       
   979     }
       
   980 }