crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianCodeLib/SourceManagement/Source/CodeSource.cs
changeset 0 818e61de6cd1
equal deleted inserted replaced
-1:000000000000 0:818e61de6cd1
       
     1 /*
       
     2 * Copyright (c) 2004-2008 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 
       
    18 using System;
       
    19 using System.Collections.Generic;
       
    20 using System.Text;
       
    21 using SymbianUtils;
       
    22 using SymbianUtils.Range;
       
    23 using SymbianUtils.Threading;
       
    24 using SymbianStructuresLib.Arm;
       
    25 using SymbianStructuresLib.Arm.Instructions;
       
    26 using SymbianStructuresLib.CodeSegments;
       
    27 using SymbianStructuresLib.Debug.Code;
       
    28 using SymbianStructuresLib.Debug.Code.Interfaces;
       
    29 using SymbianStructuresLib.Debug.Common.FileName;
       
    30 using SymbianCodeLib.SourceManagement.Provisioning;
       
    31 
       
    32 namespace SymbianCodeLib.SourceManagement.Source
       
    33 {
       
    34     public abstract class CodeSource : DisposableObject, IEnumerable<CodeCollection>, ICodeCollectionRelocationHandler, ICodeCollectionInstructionConverter
       
    35     {
       
    36         #region Delegates & events
       
    37         public delegate void EventHandlerFunction( TEvent aEvent, CodeSource aSource, object aData );
       
    38         public event EventHandlerFunction EventHandler;
       
    39         #endregion
       
    40 
       
    41         #region Enumerations
       
    42         public enum TEvent
       
    43         {
       
    44             EReadingStarted = 0,
       
    45             EReadingProgress,
       
    46             EReadingComplete
       
    47         }
       
    48 
       
    49         public enum TTimeToRead
       
    50         {
       
    51             EReadWhenPriming = 0,
       
    52             EReadWhenNeeded // i.e. relocated
       
    53         }
       
    54         #endregion
       
    55 
       
    56         #region Constructors
       
    57         public CodeSource( string aURI, CodeSourceProvider aProvider )
       
    58         {
       
    59             iURI = aURI;
       
    60             iProvider = aProvider;
       
    61         }
       
    62         #endregion
       
    63 
       
    64         #region API
       
    65         public virtual void Read( TSynchronicity aSynchronicity )
       
    66         {
       
    67             bool isReading = this.IsReadInProgress;
       
    68             if ( isReading )
       
    69             {
       
    70                 // Another thread is already reading this source.
       
    71                 // If the caller asked for asynchronous reading, then when the
       
    72                 // other thread completes the read the caller (in this thread) 
       
    73                 // will be notified via the normal event callback framework - in which
       
    74                 // case we need do nothing at all - just let the other thread get on with it.
       
    75                 //
       
    76                 // If, on the other hand, the caller requested a synchronous read, then they
       
    77                 // will expect the code to be ready at the point in time which we return to them.
       
    78                 //
       
    79                 // In this situation, we should block this method until the code becomes ready.
       
    80                 if ( aSynchronicity == TSynchronicity.ESynchronous )
       
    81                 {
       
    82                     while ( this.IsReadInProgress )
       
    83                     {
       
    84                         System.Threading.Thread.Sleep( 0 );
       
    85                     }
       
    86                 }
       
    87             }
       
    88             else
       
    89             {
       
    90                 DoRead( aSynchronicity );
       
    91             }
       
    92         }
       
    93 
       
    94         public virtual void Add( CodeCollection aCollection )
       
    95         {
       
    96             // We can always do this task
       
    97             aCollection.IfaceInstructionConverter = this;
       
    98 
       
    99             // We want to be told if the collection changes it's relocation state.
       
   100             aCollection.RelocationStatusChanged += new CodeCollection.RelocationStatusChangeHandler( Collection_RelocationStatusChanged );
       
   101 
       
   102             lock ( iCollectionsAll )
       
   103             {
       
   104                 iCollectionsAll.Add( aCollection );
       
   105             }
       
   106 
       
   107             CategoriseCollection( aCollection );
       
   108         }
       
   109 
       
   110         public virtual void Remove( CodeCollection aCollection )
       
   111         {
       
   112             aCollection.RelocationStatusChanged -= new CodeCollection.RelocationStatusChangeHandler( Collection_RelocationStatusChanged );
       
   113             //
       
   114             lock ( iCollectionsAll )
       
   115             {
       
   116                 iCollectionsAll.Remove( aCollection );
       
   117             }
       
   118             lock ( iAlwaysActivatedCollections )
       
   119             {
       
   120                 iAlwaysActivatedCollections.Remove( aCollection );
       
   121             }
       
   122         }
       
   123 
       
   124         public virtual bool Contains( uint aAddress )
       
   125         {
       
   126             return iAlwaysActivatedCollections.Contains( aAddress );
       
   127         }
       
   128 
       
   129         public virtual bool ProvideInstructions( uint aAddress, TArmInstructionSet aInstructionSet, int aCount, out IArmInstruction[] aInstructions )
       
   130         {
       
   131             lock ( iAlwaysActivatedCollections )
       
   132             {
       
   133                 bool ret = iAlwaysActivatedCollections.GetInstructions( aAddress, aInstructionSet, aCount, out aInstructions );
       
   134                 return ret;
       
   135             }
       
   136         }
       
   137 
       
   138         protected abstract void DoRead( TSynchronicity aSynchronicity );
       
   139 
       
   140         protected virtual void OnAddedToCollection( CodeSourceCollection aCollection )
       
   141         {
       
   142             ++iReferenceCount;
       
   143         }
       
   144 
       
   145         protected virtual void OnRemovedFromCollection( CodeSourceCollection aCollection )
       
   146         {
       
   147             if ( --iReferenceCount <= 0 )
       
   148             {
       
   149                 this.Dispose();
       
   150             }
       
   151         }
       
   152 
       
   153         protected virtual void OnPrepareForRelocation( CodeCollection aCollection, uint aOldBase, uint aNewBase )
       
   154         {
       
   155             // If we read our data during priming, then we don't need to do anything... otherwise, we should
       
   156             // read the data now.
       
   157             //
       
   158             // However, don't initiate a read if we already have obtained code for the specified collection
       
   159             // (this can be the case if we are relocating a cloned code collection which has already been activated
       
   160             // itself in the past).
       
   161             if ( aCollection.IsCodeAvailable == false )
       
   162             {
       
   163                 System.Diagnostics.Debug.Assert( this.IsReady == false );
       
   164                 //
       
   165                 if ( TimeToRead == TTimeToRead.EReadWhenNeeded )
       
   166                 {
       
   167                     this.Read( TSynchronicity.ESynchronous );
       
   168                 }
       
   169             }
       
   170         }
       
   171 
       
   172         protected virtual void OnReadComplete()
       
   173         {
       
   174         }
       
   175         #endregion
       
   176 
       
   177         #region API - framework
       
   178         public void ReportEvent( TEvent aEvent )
       
   179         {
       
   180             ReportEvent( aEvent, null );
       
   181         }
       
   182 
       
   183         public void ReportEvent( TEvent aEvent, object aData )
       
   184         {
       
   185             PreProcessEvent( aEvent );
       
   186 
       
   187             // Cascade
       
   188             if ( EventHandler != null )
       
   189             {
       
   190                 EventHandler( aEvent, this, aData );
       
   191             }
       
   192         }
       
   193         #endregion
       
   194 
       
   195         #region Properties
       
   196         public int Count
       
   197         {
       
   198             get { return iCollectionsAll.Count; }
       
   199         }
       
   200 
       
   201         public string URI
       
   202         {
       
   203             get
       
   204             {
       
   205                 lock ( iURI )
       
   206                 {
       
   207                     return iURI;
       
   208                 }
       
   209             }
       
   210             set
       
   211             {
       
   212                 lock ( iURI )
       
   213                 {
       
   214                     iURI = value;
       
   215                 }
       
   216             }
       
   217 
       
   218         }
       
   219 
       
   220         public string FileName
       
   221         {
       
   222             get { return iProvider.GetFileName( this ); }
       
   223         }
       
   224 
       
   225         public TTimeToRead TimeToRead
       
   226         {
       
   227             get { return iTimeToRead; }
       
   228             set
       
   229             {
       
   230                 iTimeToRead = value;
       
   231             }
       
   232         }
       
   233 
       
   234         public CodeSourceProvider Provider
       
   235         {
       
   236             get
       
   237             {
       
   238                 lock ( iProvider )
       
   239                 {
       
   240                     return iProvider;
       
   241                 }
       
   242             }
       
   243         }
       
   244 
       
   245         public CodeCollection this[ int aIndex ]
       
   246         {
       
   247             get { return iCollectionsAll[ aIndex ]; }
       
   248         }
       
   249 
       
   250         public virtual CodeCollection this[ CodeSegDefinition aCodeSegment ]
       
   251         {
       
   252             get
       
   253             {
       
   254                 CodeCollection ret = iCollectionsAll[ aCodeSegment ];
       
   255                 return ret;
       
   256             }
       
   257         }
       
   258 
       
   259         public virtual CodeCollection this[ PlatformFileName aFileName ]
       
   260         {
       
   261             get
       
   262             {
       
   263                 lock ( iCollectionsAll )
       
   264                 {
       
   265                     CodeCollection ret = iCollectionsAll[ aFileName ];
       
   266                     return ret;
       
   267                 }
       
   268             }
       
   269         }
       
   270 
       
   271         public bool IsReady
       
   272         {
       
   273             get
       
   274             {
       
   275                 lock ( iFlagsSyncRoot )
       
   276                 {
       
   277                     bool ret = ( iFlags & TFlags.EFlagsIsReady ) != 0;
       
   278                     return ret;
       
   279                 }
       
   280             }
       
   281             set
       
   282             {
       
   283                 lock ( iFlagsSyncRoot )
       
   284                 {
       
   285                     if ( value )
       
   286                     {
       
   287                         iFlags |= TFlags.EFlagsIsReady;
       
   288                     }
       
   289                     else
       
   290                     {
       
   291                         iFlags &= ~TFlags.EFlagsIsReady;
       
   292                     }
       
   293                 }
       
   294             }
       
   295         }
       
   296 
       
   297         public bool IsReadInProgress
       
   298         {
       
   299             get
       
   300             {
       
   301                 lock ( iFlagsSyncRoot )
       
   302                 {
       
   303                     bool ret = ( iFlags & TFlags.EFlagsIsReadInProgress ) != 0;
       
   304                     return ret;
       
   305                 }
       
   306             }
       
   307             set
       
   308             {
       
   309                 lock ( iFlagsSyncRoot )
       
   310                 {
       
   311                     if ( value )
       
   312                     {
       
   313                         iFlags |= TFlags.EFlagsIsReadInProgress;
       
   314                     }
       
   315                     else
       
   316                     {
       
   317                         iFlags &= ~TFlags.EFlagsIsReadInProgress;
       
   318                     }
       
   319                 }
       
   320             }
       
   321         }
       
   322         #endregion
       
   323 
       
   324         #region Event handlers
       
   325         private void Collection_RelocationStatusChanged( CodeCollection aCollection )
       
   326         {
       
   327             CategoriseCollection( aCollection );
       
   328         }
       
   329         #endregion
       
   330 
       
   331         #region Internal methods
       
   332         internal int CountActivated
       
   333         {
       
   334             get { return iAlwaysActivatedCollections.Count; }
       
   335         }
       
   336 
       
   337         internal void AddedToCollection( CodeSourceCollection aCollection )
       
   338         {
       
   339             OnAddedToCollection( aCollection );
       
   340         }
       
   341 
       
   342         internal void RemovedFromCollection( CodeSourceCollection aCollection )
       
   343         {
       
   344             OnRemovedFromCollection( aCollection );
       
   345         }
       
   346 
       
   347         private void CategoriseCollection( CodeCollection aCollection )
       
   348         {
       
   349             // Reset state
       
   350             lock ( iAlwaysActivatedCollections )
       
   351             {
       
   352                 iAlwaysActivatedCollections.Remove( aCollection );
       
   353                 aCollection.IfaceRelocationHandler = null;
       
   354             }
       
   355 
       
   356             // Collections which do not move from their pre-determined base address
       
   357             // are transparently "activated" which means that they will be queried
       
   358             // automatically during symbolic look up.
       
   359             if ( aCollection.IsFixed )
       
   360             {
       
   361                 lock ( iAlwaysActivatedCollections )
       
   362                 {
       
   363                     iAlwaysActivatedCollections.Add( aCollection );
       
   364                 }
       
   365             }
       
   366             else
       
   367             {
       
   368                 // Otherwise, we must wait until the client relocates the code
       
   369                 // and then we will be called back. During the callback processing
       
   370                 // we'll load the code (if needed) and fixup the base address.
       
   371                 aCollection.IfaceRelocationHandler = this;
       
   372             }
       
   373         }
       
   374 
       
   375         private void PreProcessEvent( TEvent aEvent )
       
   376         {
       
   377             switch ( aEvent )
       
   378             {
       
   379             case TEvent.EReadingStarted:
       
   380                 IsReady = false;
       
   381                 IsReadInProgress = true;
       
   382                 break;
       
   383             case TEvent.EReadingComplete:
       
   384                 IsReady = true;
       
   385                 IsReadInProgress = false;
       
   386                 OnReadComplete();
       
   387                 break;
       
   388             }
       
   389         }
       
   390         #endregion
       
   391 
       
   392         #region Internal enumerations
       
   393         [Flags]
       
   394         private enum TFlags
       
   395         {
       
   396             EFlagsNone = 0,
       
   397             EFlagsIsReady = 1,
       
   398             EFlagsIsReadInProgress = 2
       
   399         }
       
   400         #endregion
       
   401 
       
   402         #region From ICodeCollectionRelocationHandler
       
   403         public void PrepareForRelocation( CodeCollection aCollection, uint aOldBase, uint aNewBase )
       
   404         {
       
   405             OnPrepareForRelocation( aCollection, aOldBase, aNewBase );
       
   406         }
       
   407         #endregion
       
   408 
       
   409         #region From ICodeCollectionInstructionConverter
       
   410         public IArmInstruction[] ConvertRawValuesToInstructions( TArmInstructionSet aInstructionSet, uint[] aRawValues, uint aStartingAddress )
       
   411         {
       
   412             IArmInstruction[] ret = iProvider.ConvertToInstructions( aInstructionSet, aRawValues, aStartingAddress );
       
   413             return ret;
       
   414         }
       
   415         #endregion
       
   416 
       
   417         #region From IEnumerable<CodeCollection>
       
   418         public IEnumerator<CodeCollection> GetEnumerator()
       
   419         {
       
   420             foreach ( CodeCollection col in iCollectionsAll )
       
   421             {
       
   422                 yield return col;
       
   423             }
       
   424         }
       
   425 
       
   426         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
       
   427         {
       
   428             foreach ( CodeCollection col in iCollectionsAll )
       
   429             {
       
   430                 yield return col;
       
   431             }
       
   432         }
       
   433         #endregion
       
   434 
       
   435         #region From DisposableObject
       
   436         protected override void CleanupManagedResources()
       
   437         {
       
   438             try
       
   439             {
       
   440                 base.CleanupManagedResources();
       
   441             }
       
   442             finally
       
   443             {
       
   444                 int count = iCollectionsAll.Count;
       
   445                 for ( int i = count - 1; i >= 0; i-- )
       
   446                 {
       
   447                     CodeCollection col = iCollectionsAll[ i ];
       
   448                     Remove( col );
       
   449                     col.Dispose();
       
   450                 }
       
   451 
       
   452                 // These should both be empty in any case
       
   453                 iCollectionsAll.Clear();
       
   454                 iAlwaysActivatedCollections.Clear();
       
   455             }
       
   456         }
       
   457         #endregion
       
   458 
       
   459         #region From System.Object
       
   460         public override string ToString()
       
   461         {
       
   462             return URI;
       
   463         }
       
   464 
       
   465         public override int GetHashCode()
       
   466         {
       
   467             return URI.GetHashCode();
       
   468         }
       
   469 
       
   470         public override bool Equals( object aObject )
       
   471         {
       
   472             if ( aObject is CodeSource )
       
   473             {
       
   474                 CodeSource other = (CodeSource) aObject;
       
   475                 bool ret = ( string.Compare( other.URI, this.URI, StringComparison.CurrentCultureIgnoreCase ) == 0 );
       
   476                 return ret;
       
   477             }
       
   478             //
       
   479             return base.Equals( aObject );
       
   480         }
       
   481         #endregion
       
   482 
       
   483         #region Data members
       
   484         private readonly CodeSourceProvider iProvider;
       
   485         private string iURI = string.Empty;
       
   486         private int iReferenceCount = 0;
       
   487         private TTimeToRead iTimeToRead = TTimeToRead.EReadWhenPriming;
       
   488         private CodeCollectionList iCollectionsAll = new CodeCollectionList();
       
   489         private CodeCollectionList iAlwaysActivatedCollections = new CodeCollectionList();
       
   490         private object iFlagsSyncRoot = new object();
       
   491         private TFlags iFlags = TFlags.EFlagsNone;
       
   492         #endregion
       
   493     }
       
   494 }