--- /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
+ }
+}