crashanalysercmd/Libraries/Engine/CrashDebuggerLib/Structures/Register/RegisterCollection.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 SymbianStructuresLib.Arm.Registers;
       
    22 using SymbianStructuresLib.Debug.Symbols;
       
    23 using SymbianDebugLib.Engine;
       
    24 using SymbianDebugLib.PluginAPI.Types.Symbol;
       
    25 using CrashDebuggerLib.Structures.KernelObjects;
       
    26 using CrashDebuggerLib.Structures.Common;
       
    27 using CrashDebuggerLib.Structures.Process;
       
    28 
       
    29 namespace CrashDebuggerLib.Structures.Register
       
    30 {
       
    31     public class RegisterCollection : CrashDebuggerAware, IEnumerable<RegisterEntry>, IARCBackingStore, IComparer<RegisterEntry>
       
    32     {
       
    33         #region Enumerations
       
    34         public enum TType
       
    35         {
       
    36             // Special cases
       
    37             ETypeGeneral        = -1,       // CPU specific
       
    38             ETypeCommonBank     = 0,        // R00 -> R07 inclusive
       
    39 
       
    40             // Linked into to CPSR values
       
    41             ETypeUser           = 0x10,     // 0b10000
       
    42             ETypeFastInterrupt  = 0x11,     // 0b10001
       
    43             ETypeInterrupt      = 0x12,     // 0b10010
       
    44             ETypeSupervisor     = 0x13,     // 0b10011
       
    45             ETypeAbort          = 0x17,     // 0b10111
       
    46             ETypeUndefined      = 0x1B,     // 0b11011
       
    47 
       
    48             // Not used in Symbian OS
       
    49             ETypeSystem         = 0x1F      // 0b11111
       
    50         }
       
    51         #endregion
       
    52 
       
    53         #region Constructors
       
    54         internal RegisterCollection( CrashDebuggerInfo aCrashDebugger, TType aType )
       
    55             : this( aCrashDebugger, aType, null, null )
       
    56         {
       
    57         }
       
    58 
       
    59         internal RegisterCollection( CrashDebuggerInfo aCrashDebugger, TType aType, DProcess aProcess )
       
    60             : this( aCrashDebugger, aType, aProcess, null )
       
    61         {
       
    62         }
       
    63 
       
    64         internal RegisterCollection( RegisterCollection aCopy, TType aType, DProcess aProcess )
       
    65             : this( aCopy.CrashDebugger, aType, aProcess, null )
       
    66         {
       
    67             foreach ( RegisterEntry entry in aCopy )
       
    68             {
       
    69                 Add( entry.OriginalName, entry.Value );
       
    70             }
       
    71         }
       
    72 
       
    73         internal RegisterCollection( CrashDebuggerInfo aCrashDebugger, TType aType, DProcess aProcess, RegisterCollection aLinkedWith )
       
    74             : base( aCrashDebugger )
       
    75         {
       
    76             iType = aType;
       
    77             iProcess = aProcess;
       
    78 
       
    79             iEntries = new ArmRegisterCollection();
       
    80             iEntries.BackingStore = this as IARCBackingStore;
       
    81 
       
    82             iLinkedWith = aLinkedWith;
       
    83         }
       
    84         #endregion
       
    85 
       
    86         #region API
       
    87         public RegisterEntry Add( string aName, uint aValue )
       
    88         {
       
    89             ArmRegister added = iEntries.Add( aName, aValue );
       
    90             RegisterEntry ret = added as RegisterEntry;
       
    91             return ret;
       
    92         }
       
    93 
       
    94         public void AddMany( params TArmRegisterType[] aTypes )
       
    95         {
       
    96             foreach ( TArmRegisterType reg in aTypes )
       
    97             {
       
    98                 string name = ArmRegister.GetTypeName( reg );
       
    99                 Add( name, 0 );
       
   100             }
       
   101         }
       
   102 
       
   103         public bool Exists( string aName )
       
   104         {
       
   105             // Need this to map the specified name into a common name.
       
   106             // I.e. convert R14_USR to R14
       
   107             RegisterEntry temp = new RegisterEntry( this, aName, 0 );
       
   108 
       
   109             // First try concrete entries
       
   110             bool ret = iEntries.Contains( temp.Name );
       
   111             if ( !ret && iLinkedWith != null )
       
   112             {
       
   113                 // Try linked
       
   114                 ret = iLinkedWith.Exists( temp.Name );
       
   115             }
       
   116 
       
   117             return ret;
       
   118         }
       
   119 
       
   120         public void Clear()
       
   121         {
       
   122             iEntries.Clear();
       
   123         }
       
   124 
       
   125         public static string BankName( TType aType )
       
   126         {
       
   127             string ret = string.Empty;
       
   128             //
       
   129             switch ( aType )
       
   130             {
       
   131             default:
       
   132             case TType.ETypeGeneral:
       
   133             case TType.ETypeCommonBank:
       
   134                 ret = string.Empty;
       
   135                 break;
       
   136             case TType.ETypeAbort:
       
   137                 ret = "ABT";
       
   138                 break;
       
   139             case TType.ETypeFastInterrupt:
       
   140                 ret = "FIQ";
       
   141                 break;
       
   142             case TType.ETypeInterrupt:
       
   143                 ret = "IRQ";
       
   144                 break;
       
   145             case TType.ETypeSupervisor:
       
   146                 ret = "SVC";
       
   147                 break;
       
   148             case TType.ETypeSystem:
       
   149                 ret = "SYS";
       
   150                 break;
       
   151             case TType.ETypeUndefined:
       
   152                 ret = "UND";
       
   153                 break;
       
   154             case TType.ETypeUser:
       
   155                 ret = "USR";
       
   156                 break;
       
   157             }
       
   158             //
       
   159             return ret;
       
   160         }
       
   161         #endregion
       
   162 
       
   163         #region Properties
       
   164         public string Name
       
   165         {
       
   166             get { return iName; }
       
   167             set { iName = value; }
       
   168         }
       
   169 
       
   170         public RegisterEntry this[ string aName ]
       
   171         {
       
   172             get
       
   173             {
       
   174                 RegisterEntry ret = new RegisterEntry( this, aName, 0 );
       
   175                 
       
   176                 // First try concrete entries in this object
       
   177                 if ( iEntries.Contains( ret.Name ) )
       
   178                 {
       
   179                     ret = (RegisterEntry) iEntries[ ret.Name ];
       
   180                 }
       
   181                 else if ( iLinkedWith != null && iLinkedWith.Exists( ret.Name ) )
       
   182                 {
       
   183                     // Try linked entries
       
   184                     ret = iLinkedWith[ ret.Name ];
       
   185                 }
       
   186                 else
       
   187                 {
       
   188                     // Not found
       
   189                     Add( aName, 0 );
       
   190                 }
       
   191                 //
       
   192                 return ret;
       
   193             }
       
   194         }
       
   195 
       
   196         public RegisterEntry this[ TArmRegisterType aType ]
       
   197         {
       
   198             get
       
   199             {
       
   200                 RegisterEntry ret = new RegisterEntry( this, aType );
       
   201                 return this[ ret.Name ];
       
   202             }
       
   203         }
       
   204 
       
   205         public int Count
       
   206         {
       
   207             get
       
   208             {
       
   209                 int ret = iEntries.Count;
       
   210                 //
       
   211                 if ( iLinkedWith != null )
       
   212                 {
       
   213                     ret += iLinkedWith.Count;
       
   214                 }
       
   215                 //
       
   216                 return ret;
       
   217             }
       
   218         }
       
   219         #endregion
       
   220 
       
   221         #region Operators
       
   222         public static implicit operator ArmRegisterCollection( RegisterCollection aSelf )
       
   223         {
       
   224             return aSelf.iEntries;
       
   225         }
       
   226         #endregion
       
   227 
       
   228         #region Internal methods
       
   229         public void Dump()
       
   230         {
       
   231             System.Diagnostics.Debug.WriteLine( "REGISTERS [" + iType + "]" );
       
   232             System.Diagnostics.Debug.WriteLine( string.Empty );
       
   233             //
       
   234             string regs = this.ToString();
       
   235             System.Diagnostics.Debug.WriteLine( regs );
       
   236         }
       
   237 
       
   238         internal Symbol LookUpSymbol( uint aAddress )
       
   239         {
       
   240             Symbol ret = null;
       
   241             //
       
   242             if ( iProcess != null )
       
   243             {
       
   244                 ret = iProcess.LookUpSymbol( aAddress );
       
   245             }
       
   246             else
       
   247             {
       
   248                 ret = base.CrashDebugger.LookUpSymbol( aAddress );
       
   249             }
       
   250             //
       
   251             return ret;
       
   252         }
       
   253         #endregion
       
   254 
       
   255         #region IArmRegisterBackingStore Members
       
   256         void IARCBackingStore.ARCBSClear()
       
   257         {
       
   258             // Nothing to do - our entries are derived from ArmRegister and 
       
   259             // are owned by iEntries.
       
   260         }
       
   261 
       
   262         void IARCBackingStore.ARCBSRemove( ArmRegister aRegister )
       
   263         {
       
   264             // Nothing to do - our entries are derived from ArmRegister and 
       
   265             // are owned by iEntries.
       
   266         }
       
   267 
       
   268         ArmRegister IARCBackingStore.ARCBSCreate( TArmRegisterType aType, string aName, uint aValue )
       
   269         {
       
   270             RegisterEntry entry = null;
       
   271             //            
       
   272             if ( aType == TArmRegisterType.EArmReg_CPSR )
       
   273             {
       
   274                 // CPSR is a bit special...
       
   275                 entry = new RegisterEntryCPSR( this, aValue );
       
   276             }
       
   277             else
       
   278             {
       
   279                 entry = new RegisterEntry( this, aName, aValue );
       
   280                 entry.RegType = aType;
       
   281             }
       
   282             //
       
   283             return entry;
       
   284         }
       
   285         #endregion
       
   286 
       
   287         #region From IComparer<RegisterEntry>
       
   288         public int Compare( RegisterEntry aLeft, RegisterEntry aRight )
       
   289         {
       
   290             int ret = -1;
       
   291 
       
   292             // Try to order the registers so that Rnn register names come first
       
   293             // then CPSR, then the other stuff.
       
   294             TArmRegisterType leftType = aLeft.RegType;
       
   295             TArmRegisterType rightType = aRight.RegType;
       
   296             //
       
   297             if ( leftType != TArmRegisterType.EArmReg_Other && rightType == TArmRegisterType.EArmReg_Other )
       
   298             {
       
   299                 // Left is smaller since it's a standard register
       
   300                 ret = -1;
       
   301             }
       
   302             else if ( leftType == TArmRegisterType.EArmReg_Other && rightType != TArmRegisterType.EArmReg_Other )
       
   303             {
       
   304                 // Right is smaller since it's a standard register
       
   305                 ret = 1;
       
   306             }
       
   307             else if ( leftType == TArmRegisterType.EArmReg_Other && rightType == TArmRegisterType.EArmReg_Other )
       
   308             {
       
   309                 // Must compare names since both are non-standard registers
       
   310                 ret = aLeft.OriginalName.CompareTo( aRight.OriginalName );
       
   311             }
       
   312             else 
       
   313             {
       
   314                 // Registers are not non-standard, compare based upon numerical value
       
   315                 if ( leftType == rightType )
       
   316                 {
       
   317                     ret = 0;
       
   318                 }
       
   319                 else if ( leftType > rightType )
       
   320                 {
       
   321                     ret = 1;
       
   322                 }
       
   323             }
       
   324             //
       
   325             return ret;
       
   326         }
       
   327         #endregion
       
   328 
       
   329         #region From IEnumerable<RegisterEntry>
       
   330         public IEnumerator<RegisterEntry> GetEnumerator()
       
   331         {
       
   332             SortedList<string, RegisterEntry> entries = new SortedList<string, RegisterEntry>();
       
   333 
       
   334             // Get specific entries - we always take all of these
       
   335             foreach ( ArmRegister reg in iEntries )
       
   336             {
       
   337                 entries.Add( reg.Name, (RegisterEntry) reg );
       
   338             }
       
   339 
       
   340             // And also common entries
       
   341             if ( iLinkedWith != null )
       
   342             {
       
   343                 foreach( RegisterEntry reg in iLinkedWith )
       
   344                 {
       
   345                     // Make sure that the concrete entries override
       
   346                     // any common values
       
   347                     if ( entries.ContainsKey( reg.Name ) == false )
       
   348                     {
       
   349                         entries.Add( reg.Name, reg );
       
   350                     }
       
   351                 }
       
   352             }
       
   353 
       
   354             // For some reason, sorted list isn't actually sorting the entries
       
   355             // by key properly. We must do this ourselves... Ugh :(
       
   356             List<RegisterEntry> ret = new List<RegisterEntry>();
       
   357             foreach ( KeyValuePair<string, RegisterEntry> pair in entries )
       
   358             {
       
   359                 ret.Add( pair.Value );
       
   360             }
       
   361             ret.Sort( this );
       
   362 
       
   363             // Now we can iterate...
       
   364             foreach ( RegisterEntry entry in ret )
       
   365             {
       
   366                 yield return entry;
       
   367             }
       
   368         }
       
   369 
       
   370         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
       
   371         {
       
   372             IEnumerator<RegisterEntry> self = (IEnumerator<RegisterEntry>) this;
       
   373             System.Collections.IEnumerator ret = (System.Collections.IEnumerator) self;
       
   374             return ret;
       
   375         }
       
   376         #endregion
       
   377 
       
   378         #region From System.Object
       
   379         public override string ToString()
       
   380         {
       
   381             StringBuilder ret = new StringBuilder();
       
   382             foreach ( RegisterEntry entry in this )
       
   383             {
       
   384                 ret.AppendLine( entry.ToString() );
       
   385             }
       
   386             //
       
   387             string text = ret.ToString();
       
   388             return text;
       
   389         }
       
   390         #endregion
       
   391 
       
   392         #region Data members
       
   393         private readonly TType iType;
       
   394         private readonly DProcess iProcess;
       
   395         private readonly RegisterCollection iLinkedWith;
       
   396         private readonly ArmRegisterCollection iEntries;
       
   397         private string iName = string.Empty;
       
   398         #endregion
       
   399     }
       
   400 }