crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianStructuresLib/Debug/Symbols/Symbols/SymbolCollection.cs
changeset 0 818e61de6cd1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianStructuresLib/Debug/Symbols/Symbols/SymbolCollection.cs	Thu Feb 11 15:50:58 2010 +0200
@@ -0,0 +1,980 @@
+/*
+* 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.Collections.Generic;
+using System.Threading;
+using SymbianUtils;
+using SymbianUtils.Range;
+using SymbianStructuresLib.CodeSegments;
+using SymbianStructuresLib.Debug.Symbols.Interfaces;
+using SymbianStructuresLib.Debug.Common.Id;
+using SymbianStructuresLib.Debug.Common.Interfaces;
+using SymbianStructuresLib.Debug.Common.FileName;
+
+namespace SymbianStructuresLib.Debug.Symbols
+{
+    public class SymbolCollection : DisposableObject, IEnumerable<Symbol>, IComparable<SymbolCollection>, IComparer<Symbol>, IFormattable
+    {
+        #region Static constructors
+        public static SymbolCollection New( IPlatformIdAllocator aIdAllocator, string aFileNameInHost, string aFileNameInDevice )
+        {
+            SymbolCollection ret = new SymbolCollection( aIdAllocator, aFileNameInHost, aFileNameInDevice );
+            return ret;
+        }
+
+        public static SymbolCollection NewCopy( IPlatformIdAllocator aIdAllocator, SymbolCollection aCollection )
+        {
+            SymbolCollection ret = new SymbolCollection( aIdAllocator, aCollection );
+            return ret;
+        }
+
+        public static SymbolCollection NewByHostFileName( IPlatformIdAllocator aIdAllocator, string aFileName )
+        {
+            SymbolCollection ret = new SymbolCollection( aIdAllocator, aFileName );
+            return ret;
+        }
+        #endregion
+
+        #region Delegates & events
+        public delegate void RelocationStatusChangeHandler( SymbolCollection aCollection );
+        public event RelocationStatusChangeHandler RelocationStatusChanged;
+        #endregion
+
+        #region Constructors
+        private SymbolCollection( IPlatformIdAllocator aIdAllocator, string aFileNameInHost )
+		{
+            iOriginalCollection = null;
+            iId = aIdAllocator.AllocateId();
+            iIdAllocator = aIdAllocator;
+            iFileName = PlatformFileName.NewByHostName( aFileNameInHost );
+            DefaultSymbolAdd();
+		}
+
+        private SymbolCollection( IPlatformIdAllocator aIdAllocator, string aFileNameInHost, string aFileNameInDevice )
+            : this( aIdAllocator, aFileNameInHost )
+        {
+            iFileName.FileNameInDevice = aFileNameInDevice;
+        }
+
+        private SymbolCollection( IPlatformIdAllocator aIdAllocator, SymbolCollection aCopy )
+        {
+            iId = aIdAllocator.AllocateId();
+            iIdAllocator = aIdAllocator;
+            iTag = aCopy.iTag;
+            iOriginalCollection = aCopy;
+            iFlags = aCopy.iFlags;
+            iTagged = aCopy.iTagged;
+            iBaseAddress = aCopy.iBaseAddress;
+            iCodeSegmentResolver = aCopy.iCodeSegmentResolver;
+            iRelocationHandler = aCopy.iRelocationHandler;
+            iFileName = PlatformFileName.New( aCopy.FileName );
+            iCodeSegmentResolver = aCopy.IfaceCodeSegmentResolver;
+            iRelocationHandler = aCopy.IfaceRelocationHandler;
+
+            // Deep copy symbols
+            foreach ( Symbol symbol in aCopy )
+            {
+                Symbol clone = Symbol.NewClone( this, symbol );
+                iSymbols.Add( clone );
+            }
+
+            // Recalculate addresses
+            RecalculationAddressRange();
+        }
+		#endregion
+
+        #region API
+        public void Serialize( StreamWriter aWriter )
+        {
+            StringBuilder temp = new StringBuilder();
+            //
+            lock ( iFileName )
+            {
+                temp.AppendLine( string.Empty );
+                temp.AppendLine( "From    " + iFileName.FileNameInHost );
+                temp.AppendLine( string.Empty );
+            }
+            //
+            lock ( iSymbols )
+            {
+                foreach ( Symbol symbol in iSymbols )
+                {
+                    temp.AppendLine( symbol.ToString( "stream", null ) );
+                }
+            }
+
+            aWriter.Write( temp.ToString() );
+        }
+
+        public void Add( Symbol aSymbol )
+        {
+            if ( aSymbol.IsDefault )
+            {
+                throw new ArgumentException( "Cannot add default symbol" );
+            }
+            //
+            lock ( iSymbols )
+            {
+                int count = iSymbols.Count;
+                if ( count == 1 )
+                {
+                    // Possibly...
+                    DefaultSymbolRemove();
+                }
+
+                // Because count might have changed if we removed default
+                // symbol.
+                count = iSymbols.Count;
+                if ( count >= 1 )
+                {
+                    Symbol last = iSymbols[ count - 1 ];
+                    if ( aSymbol.Address < last.Address )
+                    {
+                        // We appear to be adding a symbol with an earlier address,
+                        // which implies we need to sort the collection.
+                        lock( iFlagLock )
+                        {
+                            iFlags |= TFlags.EFlagsRequiresSorting;
+                        }
+                    }
+                }
+                
+                // Now add it
+                iSymbols.Add( aSymbol );
+                //
+                if ( !InTransaction )
+                {
+                    RecalculationAddressRange();
+                }
+            }
+        }
+
+        public void AddRange( IEnumerable<Symbol> aSymbols )
+        {
+            TransactionBegin();
+            //
+            try
+            {
+                foreach ( Symbol symbol in aSymbols )
+                {
+                    Add( symbol );
+                }
+            }
+            finally
+            {
+                TransactionEnd();
+            }
+        }
+
+        public void Clear()
+        {
+            lock ( iSymbols )
+            {
+                iSymbols.Clear();
+                
+                // We are definitely empty so force the default symbol to be
+                // added irrespective of flags
+                DefaultSymbolAdd( true );
+            }
+        }
+
+        public void Remove( Symbol aSymbol )
+        {
+            if ( aSymbol.IsDefault )
+            {
+                throw new ArgumentException( "Cannot remove default symbol" );
+            }
+            //
+            lock ( iSymbols )
+            {
+                iSymbols.Remove( aSymbol );
+                if ( iSymbols.Count == 0 )
+                {
+                    // We are definitely empty so force the default symbol to be
+                    // added irrespective of flags
+                    DefaultSymbolAdd( true );
+                    System.Diagnostics.Debug.Assert( IsEmptyApartFromDefaultSymbol );
+                }
+            }
+        }
+
+        public void RemoveAt( int aIndex )
+        {
+            lock ( iSymbols )
+            {
+                Symbol symbol = iSymbols[ aIndex ];
+                if ( symbol.IsDefault )
+                {
+                    throw new ArgumentException( "Cannot remove default symbol" );
+                }
+                //
+                iSymbols.RemoveAt( aIndex );
+                if ( iSymbols.Count == 0 )
+                {
+                    // We are definitely empty so force the default symbol to be
+                    // added irrespective of flags
+                    DefaultSymbolAdd( true );
+                    System.Diagnostics.Debug.Assert( IsEmptyApartFromDefaultSymbol );
+                }
+            }
+        }
+ 
+        public bool Contains( uint aAddress )
+        {
+            if ( iAddresses == null )
+            {
+                iAddresses = new AddressRangeCollection( (IEnumerable<AddressRange>) this );
+                RecalculationAddressRange();
+            }
+            //
+            bool found = iAddresses.Contains( aAddress );
+            return found;
+        }
+
+        public bool IsMatchingCodeSegment( CodeSegDefinition aCodeSegment )
+        {
+            bool ret = false;
+            //
+            if ( iCodeSegmentResolver != null )
+            {
+                ret = iCodeSegmentResolver.IsMatchingCodeSegment( this, aCodeSegment );
+            }
+            else
+            {
+                PlatformFileName codeSegName = PlatformFileName.NewByDeviceName( aCodeSegment.FileName );
+                ret = FileName.Equals( codeSegName );
+            }
+            //
+            return ret;
+        }
+
+        public void Sort()
+        {
+            if ( ( iFlags & TFlags.EFlagsRequiresSorting ) == TFlags.EFlagsRequiresSorting )
+            {
+                iSymbols.Sort( this );
+                RecalculationAddressRange();
+            }
+        }
+
+        public void SortAsync()
+        {
+            if ( ( iFlags & TFlags.EFlagsRequiresSorting ) == TFlags.EFlagsRequiresSorting )
+            {
+                ThreadPool.QueueUserWorkItem( new WaitCallback( InitiateAsyncSort ) );
+            }
+        }
+
+        public void Relocate( uint aTo )
+        {
+            uint old = iBaseAddress;
+            iBaseAddress = aTo;
+            //
+            if ( iRelocationHandler != null )
+            {
+                iRelocationHandler.PrepareForRelocation( this, old, BaseAddress );
+            }
+            //
+            RecalculationAddressRange();
+        }
+
+        public void TransactionBegin()
+        {
+            lock ( iFlagLock )
+            {
+                iFlags |= TFlags.EFlagsInTransaction;
+            }
+        }
+
+        public void TransactionEnd()
+        {
+            lock ( iFlagLock )
+            {
+                iFlags &= ~TFlags.EFlagsInTransaction;
+            }
+
+            RecalculationAddressRange();
+        }
+
+        public void Clone( IEnumerable<Symbol> aSymbols )
+        {
+            // Deep copy symbols
+            Clear();
+            try
+            {
+                TransactionBegin();
+                foreach ( Symbol symbol in aSymbols )
+                {
+                    // Make sure we don't try to add the default symbol. The symbol collection
+                    // manages this automatically.
+                    if ( symbol.IsDefault )
+                    {
+                    }
+                    else
+                    {
+                        Symbol clone = Symbol.NewClone( this, symbol );
+                        Add( clone );
+                    }
+                }
+            }
+            finally
+            {
+                TransactionEnd();
+            }
+        }
+        #endregion
+
+		#region Properties
+		public int Count
+		{
+            get
+            {
+                lock ( iSymbols )
+                {
+                    return iSymbols.Count;
+                }
+            }
+		}
+
+		public Symbol this[ int aIndex ]
+		{
+            get
+            {
+                lock ( iSymbols )
+                {
+                    return iSymbols[ aIndex ];
+                }
+            }
+        }
+
+        public Symbol this[ uint aAddress ]
+        {
+            get
+            {
+                // For debugging
+                int x = 0;
+                if ( x > 0 )
+                {
+                    string dump = Dump( aAddress );
+                    System.Diagnostics.Debug.WriteLine( dump );
+                }
+                //
+                Symbol ret = null;
+                Symbol temp = Symbol.NewTemp( this, aAddress );
+                //
+                lock ( iSymbols )
+                {
+                    AddressFindingComparer comparer = new AddressFindingComparer();
+                    int pos = iSymbols.BinarySearch( temp, comparer );
+                    int count = iSymbols.Count;
+                    //
+                    if ( pos >= 0 && pos < count )
+                    {
+                        ret = iSymbols[ pos ];
+                        System.Diagnostics.Debug.Assert( ret.AddressRange.Contains( aAddress ) );
+                    }
+                }
+                //
+                return ret;
+            }
+        }
+
+        public Symbol FirstSymbol
+		{
+			get
+			{
+				Symbol ret = null;
+                lock ( iSymbols )
+                {
+                    if ( Count > 0 )
+                    {
+                        ret = this[ 0 ];
+                    }
+                }
+				return ret;
+			}
+		}
+
+		public Symbol LastSymbol
+		{
+			get
+			{
+				Symbol ret = null;
+                lock ( iSymbols )
+                {
+                    if ( Count > 0 )
+                    {
+                        ret = this[ Count - 1 ];
+                    }
+                }
+				return ret;
+			}
+		}
+
+        public bool Tagged
+        {
+            get { return iTagged; }
+            set
+            {
+                // The 'tagged' property is one of the few that we must (and can safely)
+                // cascade to the original underlying collection. 
+                //
+                // We do this, because when working with ROFS/relocated symbols, we generally
+                // clone and fixup, rather than fixup the original. This permits us to use
+                // a symbol collection at multiple base addresses (i.e. use the same symbols within
+                // different process-relative views of the "world").
+                //
+                // If we don't cascade the tagged attribute to the original (i.e. primary) symbol
+                // collection, then when the client application wants to serialized tagged collections
+                // the ROFS collections will potentially be missing (if they have been unloaded).
+                if ( iOriginalCollection != null )
+                {
+                    iOriginalCollection.Tagged = value;
+                    iTagged = value;
+                }
+                else if ( iTagged != value )
+                {
+                    iTagged = value;
+                    if ( iTagged )
+                    {
+                        System.Diagnostics.Debug.WriteLine( string.Format( "[S] TAGGING: 0x{0:x8}, {1}", this.BaseAddress, iFileName ) );
+                    }
+                }
+            }
+        }
+
+        public bool InTransaction
+        {
+            get { return ( iFlags & TFlags.EFlagsInTransaction ) == TFlags.EFlagsInTransaction; }
+        }
+
+        public bool IsRelocatable
+        {
+            get { return ( iFlags & TFlags.EFlagsIsRelocatable ) == TFlags.EFlagsIsRelocatable; }
+            set
+            {
+                lock ( iFlagLock )
+                {
+                    bool wasSet = ( iFlags & TFlags.EFlagsIsRelocatable ) == TFlags.EFlagsIsRelocatable;
+                    if ( wasSet != value )
+                    {
+                        if ( value )
+                        {
+                            iFlags |= TFlags.EFlagsIsRelocatable;
+                        }
+                        else
+                        {
+                            iFlags &= ~TFlags.EFlagsIsRelocatable;
+                        }
+
+                        // Report event if needed
+                        if ( RelocationStatusChanged != null )
+                        {
+                            RelocationStatusChanged( this );
+                        }
+                    }
+                }
+            }
+        }
+
+        public bool IsFixed
+        {
+            get { return !IsRelocatable; }
+            set
+            {
+                IsRelocatable = !value;
+            }
+        }
+
+        public bool IsEmptyApartFromDefaultSymbol
+        {
+            get
+            { 
+                bool ret = ( iFlags & TFlags.EFlagsIsEmptyApartFromDefaultSymbol ) == TFlags.EFlagsIsEmptyApartFromDefaultSymbol;
+                return ret;
+            }
+            private set
+            {
+                lock ( iFlagLock )
+                {
+                    if ( value )
+                    {
+                        iFlags |= TFlags.EFlagsIsEmptyApartFromDefaultSymbol;
+                    }
+                    else
+                    {
+                        iFlags &= ~TFlags.EFlagsIsEmptyApartFromDefaultSymbol;
+                    }
+                }
+            }
+        }
+
+        public object Tag
+        {
+            get { return iTag; }
+            set
+            {
+                iTag = value;
+            }
+        }
+
+        public uint BaseAddress
+        {
+            get
+            {
+                uint ret = iBaseAddress;
+                return ret;
+            }
+        }
+
+        public PlatformId Id
+        {
+            get { return iId; }
+        }
+
+        public PlatformFileName FileName
+		{
+			get { return iFileName; }
+		}
+
+        public SymbolCollectionList ParentList
+        {
+            get { return iParentList; }
+            internal set { iParentList = value; }
+        }
+
+        public AddressRange SubsumedPrimaryRange
+        {
+            get
+            {
+                AddressRange ret = new AddressRange( this.BaseAddress, this.BaseAddress );
+                //
+                if ( iAddresses != null )
+                {
+                    int count = iAddresses.Count;
+                    for( int i=0; i<count; i++ )
+                    {
+                        AddressRange segment = iAddresses[ i ];
+                        
+                        // Ranges should be reliably sorted/calculated so that we
+                        // shouldn't end up going backwards beyond the base address
+                        // of the code segment
+                        System.Diagnostics.Debug.Assert( segment.Min >= ret.Min );
+
+                        // If the segmented address range doesn't sit within the existing
+                        // range we are building, then we may need to extend our return
+                        // value.
+                        if ( !ret.Contains( segment ) )
+                        {
+                            uint diff = segment.Min - ret.Max;
+                            if ( diff <= KMaximumNonConsecutiveAddressRangeDifferenceToSubsume )
+                            {
+                                ret.UpdateMax( segment.Max );
+                            }
+                        }
+                    }
+                }
+                //
+                return ret;
+            }
+        }
+
+        public object SyncRoot
+        {
+            get
+            {
+                return iSymbols;
+            }
+        }
+		#endregion
+
+        #region Properties - interfaces
+        public ISymbolCodeSegmentResolver IfaceCodeSegmentResolver
+        {
+            get { return iCodeSegmentResolver; }
+            set { iCodeSegmentResolver = value; }
+        }
+
+        public ISymbolCollectionRelocationHandler IfaceRelocationHandler
+        {
+            get { return iRelocationHandler; }
+            set { iRelocationHandler = value; }
+        }
+        #endregion
+
+        #region From IComparable<SymbolCollection>
+        public int CompareTo( SymbolCollection aCollection )
+		{
+            int ret = ( aCollection.FileName == this.FileName ) ? 0 : -1;
+			//
+            if ( ret == 0 )
+            {
+                if ( BaseAddress == aCollection.BaseAddress )
+                {
+                    ret = 0;
+                }
+                else if ( BaseAddress > aCollection.BaseAddress )
+                {
+                    ret = 1;
+                }
+                else
+                {
+                    ret = -1;
+                }
+            }
+			//
+			return ret;
+		}
+		#endregion
+
+        #region From IComparer<Symbol>
+        public int Compare( Symbol aLeft, Symbol aRight )
+        {
+            System.Diagnostics.Debug.Assert( aLeft.EndAddress >= aLeft.Address );
+            System.Diagnostics.Debug.Assert( aRight.EndAddress >= aRight.Address );
+            //
+            int ret = -1;
+            //
+            if ( aLeft.Address == aRight.Address && aLeft.EndAddress == aRight.EndAddress )
+            {
+                ret = 0;
+            }
+            else if ( aLeft.EndAddress == aRight.Address )
+            {
+                System.Diagnostics.Debug.Assert( aLeft.Address < aRight.Address );
+                System.Diagnostics.Debug.Assert( aRight.EndAddress >= aLeft.EndAddress );
+                //
+                ret = -1;
+            }
+            else if ( aLeft.Address == aRight.EndAddress )
+            {
+                System.Diagnostics.Debug.Assert( aRight.Address < aLeft.Address );
+                System.Diagnostics.Debug.Assert( aLeft.EndAddress >= aRight.EndAddress );
+                //
+                ret = 1;
+            }
+            else if ( aLeft.Address > aRight.EndAddress )
+            {
+                System.Diagnostics.Debug.Assert( aLeft.EndAddress > aRight.EndAddress );
+                System.Diagnostics.Debug.Assert( aLeft.EndAddress > aRight.Address );
+                ret = 1;
+            }
+            else if ( aLeft.EndAddress < aRight.Address )
+            {
+                System.Diagnostics.Debug.Assert( aLeft.Address < aRight.EndAddress );
+                System.Diagnostics.Debug.Assert( aRight.EndAddress > aLeft.EndAddress );
+                ret = -1;
+            }
+            //
+            return ret;
+        }
+        #endregion
+
+        #region From IEnumerable<Symbol>
+        IEnumerator<Symbol> IEnumerable<Symbol>.GetEnumerator()
+        {
+            foreach ( Symbol entry in iSymbols )
+            {
+                yield return entry;
+            }
+        }
+
+        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+        {
+            foreach ( Symbol entry in iSymbols )
+            {
+                yield return entry;
+            }
+        }
+        #endregion
+
+        #region From IFormattable
+        public string ToString( string aFormat, IFormatProvider aFormatProvider )
+        {
+            string ret = string.Empty;
+            //
+            if ( aFormat == null )
+            {
+                ret = iFileName.ToString();
+            }
+            else if ( aFormat.ToUpper() == "FULL" )
+            {
+                ret = Dump();
+            }
+            else
+            {
+                throw new FormatException( string.Format( "Invalid format string: '{0}'.", aFormat ) );
+            }
+            //
+            return ret;
+        }
+        #endregion
+
+        #region From System.Object
+        public override string ToString()
+        {
+            return iFileName.ToString();
+        }
+
+        public override bool Equals( object aObject )
+        {
+            if ( aObject != null && aObject is SymbolCollection )
+            {
+                SymbolCollection col = (SymbolCollection) aObject;
+                bool ret = ( col.FileName == this.FileName );
+                return ret;
+            }
+            //
+            return base.Equals( aObject );
+        }
+
+        public override int GetHashCode()
+        {
+            return iFileName.GetHashCode();
+        }
+        #endregion
+
+        #region Internal enumerations
+        [Flags]
+        private enum TFlags : byte
+        {
+            EFlagsNone = 0,
+            EFlagsInTransaction = 1,
+            EFlagsIsRelocatable = 2,
+            EFlagsIsEmptyApartFromDefaultSymbol = 4,
+            EFlagsRequiresSorting = 8,
+        };
+        #endregion
+
+        #region Internal constants
+        private const uint KMaximumNonConsecutiveAddressRangeDifferenceToSubsume = 512;
+        #endregion
+
+        #region Internal methods
+        private string Dump()
+        {
+            string ret = Dump( uint.MaxValue );
+            return ret;
+        }
+
+        private string Dump( uint aAddress )
+        {
+#if SYMCOL_INVARIANT_CHECK
+            DebugCheckInvariant();
+#endif
+            //
+            StringBuilder ret = new StringBuilder();
+            //
+            int i = 0;
+            string line = string.Empty;
+            //
+            lock ( iSymbols )
+            {
+                foreach ( Symbol entry in iSymbols )
+                {
+                    if ( aAddress != uint.MaxValue && entry.Contains( aAddress ) )
+                    {
+                        line = i.ToString( "d8" ) + " * [" + entry.Address.ToString( "x8" ) + "-" + entry.EndAddress.ToString( "x8" ) + "] " + entry.Name;
+                    }
+                    else
+                    {
+                        line = i.ToString( "d8" ) + "   [" + entry.Address.ToString( "x8" ) + "-" + entry.EndAddress.ToString( "x8" ) + "] " + entry.Name;
+                    }
+                    //
+                    ret.AppendLine( line );
+                    i++;
+                }
+            }
+            //
+            return ret.ToString();
+        }
+
+        private void DefaultSymbolAdd()
+        {
+            DefaultSymbolAdd( false );
+        }
+
+        private void DefaultSymbolAdd( bool aForce )
+        {
+#if SYMCOL_INVARIANT_CHECK
+            DebugCheckInvariant();
+#endif
+            //
+            if ( !IsEmptyApartFromDefaultSymbol || aForce )
+            {
+                lock ( iSymbols )
+                {
+                    System.Diagnostics.Debug.Assert( Count == 0 );
+                    Symbol def = Symbol.NewDefault( this );
+                    iSymbols.Add( def );
+                    IsEmptyApartFromDefaultSymbol = true;
+                }
+            }
+        }
+
+        private void DefaultSymbolRemove()
+        {
+#if SYMCOL_INVARIANT_CHECK
+            DebugCheckInvariant();
+#endif
+            //
+            if ( IsEmptyApartFromDefaultSymbol )
+            {
+                lock ( iSymbols )
+                {
+                    int count = iSymbols.Count;
+                    //
+                    if ( IsEmptyApartFromDefaultSymbol )
+                    {
+                        System.Diagnostics.Debug.Assert( count == 1 && this.FirstSymbol.IsDefault );
+                        iSymbols.RemoveAt( 0 );
+                        IsEmptyApartFromDefaultSymbol = false;
+                    }
+#if SYMCOL_INVARIANT_CHECK
+                else if ( count > 0 )
+                {
+                    System.Diagnostics.Debug.Assert( this.FirstSymbol.IsDefault == false );
+                }
+#endif
+                }
+            }
+        }
+
+        private void InitiateAsyncSort( object aNotUsed )
+        {
+            Sort();
+        }
+
+#if SYMCOL_INVARIANT_CHECK
+        private void DebugCheckInvariant()
+        {
+            lock ( iSymbols )
+            {
+                int count = Count;
+                if ( count > 0 )
+                {
+                    Symbol first = this.FirstSymbol;
+                    if ( first.IsDefault )
+                    {
+                        System.Diagnostics.Debug.Assert( IsEmptyApartFromDefaultSymbol );
+                        System.Diagnostics.Debug.Assert( count == 1 );
+                    }
+                }
+            }
+        }
+#endif
+
+        private void RecalculationAddressRange()
+        {
+#if SYMCOL_INVARIANT_CHECK
+            DebugCheckInvariant();
+#endif
+            //
+            if ( !InTransaction )
+            {
+                AddressRangeCollection range = new AddressRangeCollection();
+                lock ( iSymbols )
+                {
+                    foreach ( Symbol entry in iSymbols )
+                    {
+                        range.Add( entry.AddressRange );
+                    }
+                }
+                //
+                iAddresses = range;
+            }
+        }
+        #endregion
+
+        #region Internal properties
+        internal IPlatformIdAllocator IdAllocator
+        {
+            get { return iIdAllocator; }
+        }
+
+        internal AddressRangeCollection AddressRangeCollection
+        {
+            get { return iAddresses; }
+        }
+        #endregion
+
+        #region Internal classes
+        internal class AddressFindingComparer : IComparer<Symbol>
+        {
+            public int Compare( Symbol aLeft, Symbol aRight )
+            {
+                int ret = -1;
+                //
+                AddressRange lr = aLeft.AddressRange;
+                AddressRange rr = aRight.AddressRange;
+                //
+                if ( lr.Contains( rr ) || rr.Contains( lr ) )
+                {
+                    ret = 0;
+                }
+                else
+                {
+                    ret = lr.CompareTo( rr );
+                }
+                //
+                return ret;
+            }
+        }
+        #endregion
+
+        #region From DisposableObject
+        protected override void CleanupManagedResources()
+        {
+            try
+            {
+                base.CleanupManagedResources();
+            }
+            finally
+            {
+                iTag = null;
+                if ( iAddresses != null )
+                {
+                    iAddresses.Clear();
+                }
+                iSymbols.Clear();
+                iParentList = null;
+                iCodeSegmentResolver = null;
+                iRelocationHandler = null;
+            }
+        }
+        #endregion
+
+        #region Data members
+        private readonly PlatformId iId;
+        private readonly IPlatformIdAllocator iIdAllocator;
+        private readonly PlatformFileName iFileName;
+        private readonly SymbolCollection iOriginalCollection = null;
+        private object iTag = null;
+        private object iFlagLock = new object();
+        private bool iTagged = false;
+        private TFlags iFlags = TFlags.EFlagsNone;
+        private uint iBaseAddress = 0;
+        private AddressRangeCollection iAddresses = null;
+        private List<Symbol> iSymbols = new List<Symbol>();
+        private SymbolCollectionList iParentList = null;
+        private ISymbolCodeSegmentResolver iCodeSegmentResolver = null;
+        private ISymbolCollectionRelocationHandler iRelocationHandler = null;
+		#endregion
+    }
+}