crashanalysercmd/Libraries/Engine/CrashDebuggerLib/Structures/NThread/NThread.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 CrashDebuggerLib.Structures.KernelObjects;
       
    22 using CrashDebuggerLib.Structures.Common;
       
    23 using CrashDebuggerLib.Structures.Thread;
       
    24 using CrashDebuggerLib.Structures.Register;
       
    25 using CrashDebuggerLib.Structures.UserContextTable;
       
    26 using CrashDebuggerLib.Attributes;
       
    27 using SymbianStructuresLib.Debug.Symbols;
       
    28 using SymbianStructuresLib.Arm.Registers;
       
    29 using SymbianUtils.DataBuffer;
       
    30 
       
    31 namespace CrashDebuggerLib.Structures.NThread
       
    32 {
       
    33     public class NThread : CrashDebuggerAware
       
    34     {
       
    35         #region Enumerations
       
    36         [System.ComponentModel.TypeConverter( typeof( SymbianParserLib.TypeConverters.SymbianEnumConverter ) )]
       
    37         public enum TNThreadState
       
    38         {
       
    39             EUnknown = -1, // Catch all
       
    40             EReady = 0,
       
    41             ESuspended,
       
    42             EWaitFastSemaphore,
       
    43             ESleep,
       
    44             EBlocked,
       
    45             EDead,
       
    46             EWaitDfc
       
    47         }
       
    48 
       
    49         public enum TWaitType
       
    50         {
       
    51             EWaitTypeNotWaiting = 0,
       
    52             EWaitTypeUserWaitForRequest,
       
    53             EWaitTypeUserWaitForAnyRequest
       
    54         }
       
    55         #endregion
       
    56 
       
    57         #region Constructors
       
    58         public NThread( CrashDebuggerInfo aCrashDebugger, DThread aParentThread )
       
    59             : base( aCrashDebugger )
       
    60         {
       
    61             iParentThread = aParentThread;
       
    62             iRegisters = new RegisterCollection( aCrashDebugger, RegisterCollection.TType.ETypeGeneral, aParentThread.OwningProcess );
       
    63         }
       
    64         #endregion
       
    65 
       
    66         #region API
       
    67         public static TNThreadState NStateFromString( string aState )
       
    68         {
       
    69             NThread.TNThreadState ret = NThread.TNThreadState.EUnknown;
       
    70             //
       
    71             switch ( aState.ToUpper() )
       
    72             {
       
    73                 case "READY":
       
    74                     ret = NThread.TNThreadState.EReady;
       
    75                     break;
       
    76                 case "SUSPENDED":
       
    77                     ret = NThread.TNThreadState.ESuspended;
       
    78                     break;
       
    79                 case "WAITFSEM":
       
    80                     ret = NThread.TNThreadState.EWaitFastSemaphore;
       
    81                     break;
       
    82                 case "SLEEP":
       
    83                     ret = NThread.TNThreadState.ESleep;
       
    84                     break;
       
    85                 case "BLOCKED":
       
    86                     ret = NThread.TNThreadState.EBlocked;
       
    87                     break;
       
    88                 case "DEAD":
       
    89                     ret = NThread.TNThreadState.EDead;
       
    90                     break;
       
    91                 case "WAITDFC":
       
    92                     ret = NThread.TNThreadState.EWaitDfc;
       
    93                     break;
       
    94                 default:
       
    95                 case "??":
       
    96                     ret = NThread.TNThreadState.EUnknown;
       
    97                     break;
       
    98             }
       
    99             //
       
   100             return ret;
       
   101         }
       
   102 
       
   103         public RegisterCollection GetRegisters( RegisterCollection.TType aType )
       
   104         {
       
   105             RegisterCollection ret = null;
       
   106 
       
   107             // Are we the currently executing thread?
       
   108             bool isCurrent = iParentThread.IsCurrent;
       
   109             
       
   110             // If we're dealing with the current thread, and we need to supply
       
   111             // user-land registers, then we'll try to work with the user context
       
   112             // tables so long as we are executing in supervisor mode.
       
   113             if ( aType == RegisterCollection.TType.ETypeUser )
       
   114             {
       
   115                 ret = GetUserContextRegisters();
       
   116             }
       
   117             else
       
   118             {
       
   119                 // Trying to get non-user registers
       
   120                 Cpu.CpuInfo cpuInfo = CrashDebugger.InfoCpu;
       
   121                 //
       
   122                 if ( isCurrent )
       
   123                 {
       
   124                     // Just go entirely with current CPU registers
       
   125                     ret = cpuInfo.GetRegisters();
       
   126                 }
       
   127                 else
       
   128                 {
       
   129                     // Best we can do :(
       
   130                     ret = new RegisterCollection( Registers, aType, iParentThread.OwningProcess );
       
   131 
       
   132                     if ( aType == RegisterCollection.TType.ETypeSupervisor )
       
   133                     {
       
   134                         // We know R13_SP because we explicitly are given it
       
   135                         ret[ TArmRegisterType.EArmReg_SP ].Value = SavedSP;
       
   136 
       
   137                         // TODO: We also need to get CPSR from somewhere. We just make it
       
   138                         // up at the moment, which is really bad...
       
   139                         ret[ TArmRegisterType.EArmReg_CPSR ].Value = ret[ TArmRegisterType.EArmReg_SPSR ];
       
   140                     }
       
   141                 }
       
   142             }
       
   143             //
       
   144             return ret;
       
   145         }
       
   146         #endregion
       
   147 
       
   148         #region Properties
       
   149         [PropCat("State")]
       
   150         public TNThreadState NState
       
   151         {
       
   152             get { return iNState; }
       
   153             set { iNState = value; }
       
   154         }
       
   155 
       
   156         [PropCat( "Summary", PropCat.TFormatType.EFormatAsHex )]
       
   157         public uint Address
       
   158         {
       
   159             get { return iAddress; }
       
   160             set { iAddress = value; }
       
   161         }
       
   162 
       
   163         public uint RequestSemaphoreAddress
       
   164         {
       
   165             get
       
   166             {
       
   167                 uint ret = Address;
       
   168                 ret += (uint) CrashDebuggerLib.Platform.NKernOffsets.KOffsetOf_iRequestSemaphore_In_NThread;
       
   169                 return ret;
       
   170             }
       
   171         }
       
   172 
       
   173         public uint WaitObj
       
   174         {
       
   175             get { return iWaitObj; }
       
   176             set { iWaitObj = value; }
       
   177         }
       
   178 
       
   179         [PropCat( "Summary" )]
       
   180         public int Priority
       
   181         {
       
   182             get { return iPriority; }
       
   183             set { iPriority = value; }
       
   184         }
       
   185 
       
   186         [PropCat( "State", PropCat.TFormatType.EFormatAsHex )]
       
   187         public uint Attributes
       
   188         {
       
   189             get { return iAttributes; }
       
   190             set { iAttributes = value; }
       
   191         }
       
   192 
       
   193         [PropCat( "Summary", "Address space" )]
       
   194         public uint AddressSpace
       
   195         {
       
   196             get { return iAddressSpace; }
       
   197             set { iAddressSpace = value; }
       
   198         }
       
   199 
       
   200         [PropCat( "Summary", "Supervisor stack pointer", PropCat.TFormatType.EFormatAsHex )]
       
   201         public uint SavedSP
       
   202         {
       
   203             get { return iSavedSP; }
       
   204             set { iSavedSP = value; }
       
   205         }
       
   206 
       
   207         [PropCat( "Misc", "Return Value" )]
       
   208         public int ReturnValue
       
   209         {
       
   210             get { return iReturnValue; }
       
   211             set { iReturnValue = value; }
       
   212         }
       
   213 
       
   214         [PropCat( "Summary", "Is user thread", PropCat.TFormatType.EFormatAsYesNo )]
       
   215         public bool IsUserThread
       
   216         {
       
   217             get { return iParentThread.IsUserThread; }
       
   218         }
       
   219 
       
   220         [PropCat( "State", "Is the current thread", PropCat.TFormatType.EFormatAsYesNo )]
       
   221         public bool IsCurrent
       
   222         {
       
   223             get { return iParentThread.IsCurrent; }
       
   224         }
       
   225 
       
   226         public bool HaveUserContext
       
   227         {
       
   228             get
       
   229             {
       
   230                 bool haveUserContext = true;
       
   231                 //
       
   232                 switch ( UserContextType )
       
   233                 {
       
   234                 case TUserContextType.EContextNone:
       
   235                 case TUserContextType.EContextUndefined:
       
   236                 case TUserContextType.EContextKernel:
       
   237                     haveUserContext = false;
       
   238                     break;
       
   239                 default:
       
   240                     break;
       
   241                 }
       
   242                 //
       
   243                 return haveUserContext;
       
   244             }
       
   245         }
       
   246 
       
   247         [PropCat( "State", "User context type" )]
       
   248         public TUserContextType UserContextType
       
   249         {
       
   250             get { return iUserContextType; }
       
   251             set { iUserContextType = value; }
       
   252         }
       
   253 
       
   254         [PropCat( "Linked List Info", PropCat.TFormatType.EFormatRecurseInto )]
       
   255         public LinkedListInfo LinkedListInfo
       
   256         {
       
   257             get { return iLinkedListInfo; }
       
   258         }
       
   259 
       
   260         [PropCat( "Mutex Info", PropCat.TFormatType.EFormatRecurseInto )]
       
   261         public NThreadMutexInfo MutexInfo
       
   262         {
       
   263             get { return iMutexInfo; }
       
   264         }
       
   265 
       
   266         [PropCat( "Timing Info", PropCat.TFormatType.EFormatRecurseInto )]
       
   267         public NThreadTimeInfo TimeInfo
       
   268         {
       
   269             get { return iTimeInfo; }
       
   270             set { iTimeInfo = value; }
       
   271         }
       
   272 
       
   273         [PropCat( "Count Info", PropCat.TFormatType.EFormatRecurseInto )]
       
   274         public NThreadCountInfo CountInfo
       
   275         {
       
   276             get { return iCountInfo; }
       
   277             set { iCountInfo = value; }
       
   278         }
       
   279 
       
   280         public NThreadExtraContextInfo ExtraContextInfo
       
   281         {
       
   282             get { return iExtraContextInfo; }
       
   283             set { iExtraContextInfo = value; }
       
   284         }
       
   285 
       
   286         public RegisterCollection Registers
       
   287         {
       
   288             get { return iRegisters; }
       
   289         }
       
   290 
       
   291         public TWaitType WaitType
       
   292         {
       
   293             get
       
   294             {
       
   295                 TWaitType ret = TWaitType.EWaitTypeNotWaiting;
       
   296                 //
       
   297                 RegisterEntry linkReg = Registers[ "R14_USR" ];
       
   298                 Symbol symbol = linkReg.Symbol;
       
   299                 if ( symbol != null )
       
   300                 {
       
   301                     if ( symbol.Name.Contains( "User::WaitForAnyRequest" ) )
       
   302                     {
       
   303                         ret = TWaitType.EWaitTypeUserWaitForAnyRequest;
       
   304                     }
       
   305                     else if ( symbol.Name.Contains( "User::WaitForRequest(TRequestStatus&)" ) )
       
   306                     {
       
   307                         ret = TWaitType.EWaitTypeUserWaitForRequest;
       
   308                     }
       
   309                 }
       
   310                 //
       
   311                 return ret;
       
   312             }
       
   313         }
       
   314         #endregion
       
   315 
       
   316         #region Internal methods
       
   317         // <summary>
       
   318         // This property returns the return address of the instruction
       
   319         // to resume executing when this thread finishes executing within
       
   320         // the context of an exception handler (typically SVC)
       
   321         // </summary>
       
   322         internal uint UserReturnAddress
       
   323         {
       
   324             get
       
   325             {
       
   326                 uint retAddr = 0;
       
   327                 //
       
   328                 switch ( UserContextType )
       
   329                 {
       
   330                 case TUserContextType.EContextNone:
       
   331                 case TUserContextType.EContextUndefined:
       
   332                 case TUserContextType.EContextKernel:
       
   333                     throw new NotSupportedException();
       
   334                 default:
       
   335                     {
       
   336                         Thread.ThreadStackData superStackData = iParentThread.StackInfoSupervisor.Data;
       
   337                         SymbianUtils.DataBuffer.Entry.DataBufferUint uintEntry = superStackData.LastRawDataEntry;
       
   338                         retAddr = uintEntry.Uint;
       
   339                     }
       
   340                     break;
       
   341                 }
       
   342                 //
       
   343                 return retAddr;
       
   344             }
       
   345         }
       
   346 
       
   347         private RegisterCollection GetUserContextRegisters()
       
   348         {
       
   349             bool isCurrent = IsCurrent;
       
   350             RegisterCollection ret = new RegisterCollection( Registers, RegisterCollection.TType.ETypeUser, iParentThread.OwningProcess );
       
   351 
       
   352             // User-land CPSR is stored in SPSR_SVC
       
   353             RegisterEntry spsr = Registers[ TArmRegisterType.EArmReg_SPSR ];
       
   354             ret[ TArmRegisterType.EArmReg_CPSR ].Value = spsr.Value;
       
   355 
       
   356             // Get the context table that we'll need to work out the reg positions
       
   357             UserContextTable.UserContextTable table = CrashDebugger.UserContextTableManager[ UserContextType ];
       
   358 
       
   359             // Get SP and stack data for supervisor thread
       
   360             uint sp = SavedSP;
       
   361             ThreadStackData spData = iParentThread.StackInfoSupervisor.Data;
       
   362             if ( spData.Info.Data.Size > 0 )
       
   363             {
       
   364                 // This is the user side address that will be branched back to once we exit SVC mode...
       
   365                 uint retAddr = UserReturnAddress;
       
   366                 ret[ TArmRegisterType.EArmReg_PC ].Value = retAddr;
       
   367  
       
   368                 // Now try to get the register values off of the supervisor stack
       
   369                 DataBuffer superStackData = spData.Data;
       
   370                 foreach ( ArmRegister reg in ret )
       
   371                 {
       
   372                     if ( UserContextTable.UserContextTable.IsSupported( reg.RegType ) )
       
   373                     {
       
   374                         UserContextTableEntry uctEntry = table[ reg.RegType ];
       
   375                         if ( uctEntry.IsAvailable( isCurrent ) )
       
   376                         {
       
   377                             ArmRegister savedSp = new ArmRegister( TArmRegisterType.EArmReg_SP, sp );
       
   378                             uint newValue = uctEntry.Process( savedSp, superStackData );
       
   379                             reg.Value = newValue;
       
   380                         }
       
   381                     }
       
   382                 }
       
   383             }
       
   384 
       
   385             // Getting context of current thread? Some values can be fetched directly
       
   386             // from the registers if they are not available from the stack.
       
   387             if ( isCurrent && table[ TArmRegisterType.EArmReg_SP ].Type == UserContextTableEntry.TType.EOffsetFromSp )
       
   388             {
       
   389                 RegisterCollection userRegs = CrashDebugger.InfoCpu[ RegisterCollection.TType.ETypeUser ];
       
   390                 //
       
   391                 ret[ TArmRegisterType.EArmReg_SP ].Value = userRegs[ TArmRegisterType.EArmReg_SP ];
       
   392                 ret[ TArmRegisterType.EArmReg_LR ].Value = userRegs[ TArmRegisterType.EArmReg_LR ];
       
   393             }
       
   394 
       
   395             return ret;
       
   396         }
       
   397         #endregion
       
   398 
       
   399         #region Internal constants
       
   400         #endregion
       
   401 
       
   402         #region Clipboard Support
       
   403         public string ToClipboard()
       
   404         {
       
   405             StringBuilder ret = new StringBuilder();
       
   406             //
       
   407             ret.AppendFormat( "NThread Address: 0x{0:x8}, NState: {1}" + System.Environment.NewLine, Address, NState );
       
   408             //
       
   409             return ret.ToString();
       
   410         }
       
   411         #endregion
       
   412 
       
   413         #region From System.Object
       
   414         public override string ToString()
       
   415         {
       
   416             return base.ToString();
       
   417         }
       
   418         #endregion
       
   419 
       
   420         #region Data members
       
   421         private readonly RegisterCollection iRegisters;
       
   422         private readonly DThread iParentThread;
       
   423 
       
   424         private uint iWaitObj = 0;// object on which this thread is waiting
       
   425         private uint iAddress = 0;
       
   426         private int iPriority = 0;
       
   427         private uint iAttributes = 0;
       
   428         private uint iAddressSpace = 0;
       
   429         private uint iSavedSP = 0;
       
   430         private int iReturnValue = 0;
       
   431         
       
   432         private TNThreadState iNState = TNThreadState.EDead;
       
   433         private TUserContextType iUserContextType = TUserContextType.EContextNone;
       
   434 
       
   435         private NThreadMutexInfo iMutexInfo = new NThreadMutexInfo();
       
   436         private NThreadCountInfo iCountInfo = new NThreadCountInfo();
       
   437         private LinkedListInfo iLinkedListInfo = new LinkedListInfo();
       
   438         private NThreadTimeInfo iTimeInfo = new NThreadTimeInfo();
       
   439         private NThreadExtraContextInfo iExtraContextInfo = new NThreadExtraContextInfo();
       
   440         #endregion
       
   441     }
       
   442 }