crashanalysercmd/Libraries/Engine/CrashItemLib/Crash/Processes/CIProcess.cs
changeset 0 818e61de6cd1
equal deleted inserted replaced
-1:000000000000 0:818e61de6cd1
       
     1 /*
       
     2 * Copyright (c) 2009 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 using System;
       
    18 using System.Text;
       
    19 using System.IO;
       
    20 using System.Collections.Generic;
       
    21 using SymbianUtils;
       
    22 using SymbianUtils.Range;
       
    23 using SymbianStructuresLib.Uids;
       
    24 using SymbianStructuresLib.CodeSegments;
       
    25 using SymbianStructuresLib.Debug.Common.FileName;
       
    26 using SymbianStructuresLib.Debug.Symbols;
       
    27 using SymbianDebugLib.Engine;
       
    28 using SymbianDebugLib.PluginAPI.Types;
       
    29 using SymbianDebugLib.PluginAPI.Types.Symbol;
       
    30 using CrashItemLib.Crash;
       
    31 using CrashItemLib.Crash.Base;
       
    32 using CrashItemLib.Crash.Base.DataBinding;
       
    33 using CrashItemLib.Crash.Threads;
       
    34 using CrashItemLib.Crash.CodeSegs;
       
    35 using CrashItemLib.Crash.Container;
       
    36 using CrashItemLib.Crash.Symbols;
       
    37 using CrashItemLib.Crash.Summarisable;
       
    38 
       
    39 namespace CrashItemLib.Crash.Processes
       
    40 {
       
    41     #region Attributes
       
    42     [CIDBAttributeColumn( "Name", 0 )]
       
    43     [CIDBAttributeColumn( "Value", 1, true )]
       
    44     #endregion
       
    45     public class CIProcess : CIElement, ICISymbolManager
       
    46 	{
       
    47 		#region Constructors
       
    48         public CIProcess( CIContainer aContainer )
       
    49             : base( aContainer )
       
    50 		{
       
    51             base.AddChild( new CISymbolDictionary( aContainer ) );
       
    52 		}
       
    53 		#endregion
       
    54 
       
    55         #region API
       
    56         public CIThread CreateThread()
       
    57         {
       
    58             CIThread ret = new CIThread( this );
       
    59             base.AddChild( ret );
       
    60             return ret;
       
    61         }
       
    62 
       
    63         public CICodeSeg CreateCodeSeg( string aName, uint aBase, uint aLimit )
       
    64         {
       
    65             CICodeSeg ret = CreateCodeSeg( aName, aBase, aLimit, true );
       
    66             return ret;
       
    67         }
       
    68         #endregion
       
    69 
       
    70         #region Properties
       
    71         [CIDBAttributeCell( "UIDs", 5 )]
       
    72         public UidType Uids
       
    73         {
       
    74             get { return iUids; }
       
    75         }
       
    76 
       
    77         [CIDBAttributeCell( "Generation", 3 )]
       
    78         public int Generation
       
    79         {
       
    80             get { return iGeneration; }
       
    81             set { iGeneration = value; }
       
    82         }
       
    83 
       
    84         [CIDBAttributeCell( "Priority", 4, 0 )]
       
    85         public int Priority
       
    86         {
       
    87             get { return iPriority; }
       
    88             set { iPriority = value; }
       
    89         }
       
    90 
       
    91         [CIDBAttributeCell( "SID", 2, "x8", 0u )]
       
    92         public uint SID
       
    93         {
       
    94             get
       
    95             {
       
    96                 uint ret = iSID;
       
    97                 //
       
    98                 if ( ret == 0 && iUids.MostSignificant != 0 )
       
    99                 {
       
   100                     ret = iUids.MostSignificant;
       
   101                 }
       
   102                 //
       
   103                 return ret; 
       
   104             }
       
   105             set 
       
   106             { 
       
   107                 iSID = value;
       
   108 
       
   109                 // Keep UID3 in line with SID
       
   110                 if ( Uids[ 2 ] != value )
       
   111                 {
       
   112                     Uids[ 2 ] = value;
       
   113                 }
       
   114             }
       
   115         }
       
   116 
       
   117         [CIDBAttributeCell( "Name", 1 )]
       
   118         public override string Name
       
   119         {
       
   120             get { return iName; }
       
   121             set 
       
   122             { 
       
   123                 iName = value; 
       
   124 
       
   125                 // Make sure it ends in .exe
       
   126                 if ( !iName.ToLower().EndsWith( KProcessExtension ) )
       
   127                 {
       
   128                     iName += KProcessExtension;
       
   129                 }
       
   130             }
       
   131         }
       
   132 
       
   133         public CICodeSegList CodeSegments
       
   134         {
       
   135             get
       
   136             {
       
   137                 CIElementList<CICodeSeg> codeSegs = base.ChildrenByType<CICodeSeg>();
       
   138 
       
   139                 // Sort them
       
   140                 Comparison<CICodeSeg> comparer = delegate( CICodeSeg aLeft, CICodeSeg aRight )
       
   141                 {
       
   142                     return string.Compare( aLeft.Name, aRight.Name, true );
       
   143                 };
       
   144                 codeSegs.Sort( comparer );
       
   145 
       
   146                 CICodeSegList ret = new CICodeSegList( this, codeSegs );
       
   147                 return ret; 
       
   148             }
       
   149         }
       
   150 
       
   151         public CIThread[] Threads
       
   152         {
       
   153             get
       
   154             {
       
   155                 CIElementList<CIThread> list = base.ChildrenByType<CIThread>();
       
   156                 CIThread[] ret = list.ToArray();
       
   157                 return ret;
       
   158             }
       
   159         }
       
   160 
       
   161         public CIThread[] ThreadsWhichExitedAbnormally
       
   162         {
       
   163             get
       
   164             {
       
   165                 // We use an anonymous delegate (predicate in this case) to search through
       
   166                 // all the direct children of this object that have crashed.
       
   167                 CIElementList<CIThread> threads = base.ChildrenByType<CIThread>( 
       
   168                     delegate(CIThread aThread )
       
   169                     {
       
   170                         return aThread.IsAbnormalTermination;
       
   171                     }
       
   172                 );
       
   173                 return threads.ToArray();
       
   174             }
       
   175         }
       
   176 
       
   177         public CIThread PrimaryThread
       
   178         {
       
   179             get
       
   180             {
       
   181                 CIThread ret = null;
       
   182                 //
       
   183                 CIElementList<CIThread> threads = this.ChildrenByType<CIThread>();
       
   184                 if ( threads.Count == 1 )
       
   185                 {
       
   186                     ret = threads[ 0 ];
       
   187                 }
       
   188                 else
       
   189                 {
       
   190                     // Assumption: The main thread (at least in symbian OS) is the thread which has
       
   191                     // the closest id to that of the process itself.
       
   192                     CIElementId minDelta = int.MaxValue;
       
   193                     foreach ( CIThread thread in this.GetEnumeratorThreads() )
       
   194                     {
       
   195                         CIElementId delta = thread.Id - this.Id;
       
   196                         //
       
   197                         if ( delta < minDelta )
       
   198                         {
       
   199                             ret = thread;
       
   200                         }
       
   201                         if ( delta == 1 )
       
   202                         {
       
   203                             // Optimisation
       
   204                             break;
       
   205                         }
       
   206                     }
       
   207                 }
       
   208                 //
       
   209                 return ret;
       
   210             }
       
   211         }
       
   212 
       
   213         public CIThread FirstCrashedThread
       
   214         {
       
   215             get
       
   216             {
       
   217                 CIThread  ret = null;
       
   218 
       
   219                 // Try the primary thread first
       
   220                 CIThread primary = PrimaryThread;
       
   221                 if ( primary != null && primary.IsAbnormalTermination )
       
   222                 {
       
   223                     ret = primary;
       
   224                 }
       
   225                 else
       
   226                 {
       
   227                     // The primary summary is the first summary we can locate
       
   228                     // that relates to a crash.
       
   229                     foreach ( CIThread thread in this.GetEnumeratorThreads() )
       
   230                     {
       
   231                         bool isCrash = thread.IsAbnormalTermination;
       
   232                         if ( isCrash )
       
   233                         {
       
   234                             // Try to find corresponding summarisable entry
       
   235                             ret = thread;
       
   236                             break;
       
   237                         }
       
   238                     }
       
   239                 }
       
   240                 //
       
   241                 return ret;
       
   242             }
       
   243         }
       
   244 
       
   245         public CISymbolDictionary Symbols
       
   246         {
       
   247             get { return base.ChildByType( typeof( CISymbolDictionary ) ) as CISymbolDictionary; }
       
   248         }
       
   249 
       
   250         public bool IsAbnormalTermination
       
   251         {
       
   252             get
       
   253             {
       
   254                 bool ret = false;
       
   255                 //
       
   256                 foreach ( CIThread thread in this.GetEnumeratorThreads() )
       
   257                 {
       
   258                     if ( thread.IsAbnormalTermination )
       
   259                     {
       
   260                         ret = true;
       
   261                         break;
       
   262                     }
       
   263                 }
       
   264                 //
       
   265                 return ret;
       
   266             }
       
   267         }
       
   268         #endregion
       
   269 
       
   270         #region Enumerators
       
   271         public IEnumerable<CIThread> GetEnumeratorThreads()
       
   272         {
       
   273             return Threads;
       
   274         }
       
   275 
       
   276         public IEnumerable<CICodeSeg> GetEnumeratorCodeSegs()
       
   277         {
       
   278             return CodeSegments;
       
   279         }
       
   280         #endregion
       
   281 
       
   282         #region Internal constants
       
   283         private const string KProcessExtension = ".exe";
       
   284         private const string KUnknownProcessName = "UnknownProcess.exe";
       
   285         private const int KBaseOperationMultiplier = 5;
       
   286         #endregion
       
   287 
       
   288         #region Internal methods
       
   289         private CICodeSeg CreateCodeSeg( string aName, uint aBase, uint aLimit, bool aExplict )
       
   290         {
       
   291             CICodeSeg ret = new CICodeSeg( this );
       
   292             ret.Name = aName;
       
   293             ret.Base = aBase;
       
   294             ret.Limit = aLimit;
       
   295             ret.IsExplicit = aExplict;
       
   296 
       
   297             // Primary store is the child nodes
       
   298             base.AddChild( ret );
       
   299 
       
   300             base.Trace( "[CIProcess] CreateCodeSeg() - this: {0}, ret: {1}", this, ret );
       
   301             return ret;
       
   302         }
       
   303 
       
   304         private void EnsureCodeSegmentExistsForSymbol( CIElementFinalizationParameters aParams, CISymbol aSymbol )
       
   305         {
       
   306             if ( !aSymbol.IsNull )
       
   307             {
       
   308                 Symbol symbol = aSymbol;
       
   309                 SymbolCollection collection = symbol.Collection;
       
   310                 //
       
   311                 string binaryInDevice = PlatformFileNameConstants.Device.KPathWildcardSysBin;
       
   312                 binaryInDevice += Path.GetFileName( collection.FileName.EitherFullNameButDevicePreferred );
       
   313                 //
       
   314                 CICodeSegList codeSegs = CodeSegments;
       
   315                 bool alreadyExists = codeSegs.Contains( binaryInDevice );
       
   316                 if ( !alreadyExists )
       
   317                 {
       
   318                     // Assume no match found - create implicit/speculative code segment
       
   319                     AddressRange newCodeSegRange = collection.SubsumedPrimaryRange;
       
   320                     CICodeSeg newCodeSeg = CreateCodeSeg( binaryInDevice, newCodeSegRange.Min, newCodeSegRange.Max, false );
       
   321 
       
   322                     base.Trace( "[CIProcess] EnsureCodeSegmentExistsForSymbol() - creating implicitly identified code seg: " + newCodeSeg.ToString() + " for symbol: " + aSymbol.ToString() );
       
   323 
       
   324                     // Resolve it
       
   325                     newCodeSeg.Resolve( aParams.DebugEngineView );
       
   326                 }
       
   327             }
       
   328         }
       
   329 
       
   330         private void DiscardImplicitCodeSegments()
       
   331         {
       
   332             // Go through each child and see if it's a code seg. If it is, and if 
       
   333             // it is implicit, throw it away
       
   334             int childCount = base.Count;
       
   335             for( int i=childCount-1; i>=0; i-- )
       
   336             {
       
   337                 CIElement element = base[ i ];
       
   338                 if ( element is CICodeSeg )
       
   339                 {
       
   340                     CICodeSeg cs = (CICodeSeg) element;
       
   341                     //
       
   342                     if ( !cs.IsExplicit )
       
   343                     {
       
   344                         base.Trace( string.Format( "[CIProcess] DiscardImplicitCodeSegments() - dicarded: {0}", cs ) );
       
   345                         base.RemoveChild( cs );
       
   346                     }
       
   347                 }
       
   348             }
       
   349         }
       
   350 
       
   351         private void CreateImplicitCodeSegments( CIElementFinalizationParameters aParams )
       
   352         {
       
   353             CIElementList<CISymbol> children = base.ChildrenByType<CISymbol>( TChildSearchType.EEntireHierarchy );
       
   354             base.Trace( string.Format( "[CIProcess] CreateImplicitCodeSegments() - children count: {1}, {0}", this, children.Count ) );
       
   355             //
       
   356             foreach ( CISymbol symbol in children )
       
   357             {
       
   358                 EnsureCodeSegmentExistsForSymbol( aParams, symbol );
       
   359             }
       
   360         }
       
   361         #endregion
       
   362 
       
   363         #region From CIElement
       
   364         internal override void DoFinalize( CIElementFinalizationParameters aParams, Queue<CIElement> aCallBackLast, bool aForceFinalize )
       
   365         {
       
   366             base.Trace( string.Format( "[CIProcess] DoFinalize() - START - {0}", this ) );
       
   367 
       
   368             // The process' children need to use a process-relative debug engine view in order that they
       
   369             // can correctly resolve any RAM-loaded code.
       
   370             // Therefore, rather than use the so-called "global" debug engine view (which only has
       
   371             // XIP visibility) we create a process-specific set of finalization parameters (for use with 
       
   372             // the process' children) which contain a process-relative view of the world.
       
   373             using ( CIElementFinalizationParameters processRelativeParameters = new CIElementFinalizationParameters( aParams.Engine, this.Name, this.CodeSegments ) )
       
   374             {
       
   375                 // Discard any implicit code segments. These are created automagically when an XIP symbol
       
   376                 // is found. We'll re-create them anyway in a moment after the symbols have been updated.
       
   377                 base.Trace( string.Format( "[CIProcess] DoFinalize() - discarding implicit XIP CodeSegs... - {0}", this ) );
       
   378                 DiscardImplicitCodeSegments();
       
   379                 base.Trace( string.Format( "[CIProcess] DoFinalize() - discarded implicit XIP CodeSegs - {0}", this ) );
       
   380 
       
   381                 // Tell our children
       
   382                 base.DoFinalize( processRelativeParameters, aCallBackLast, aForceFinalize );
       
   383 
       
   384                 // Finally, re-create implicit XIP codesegments
       
   385                 base.Trace( string.Format( "[CIProcess] DoFinalize() - creating implicit XIP CodeSegs... - {0}", this ) );
       
   386                 CreateImplicitCodeSegments( aParams );
       
   387                 base.Trace( string.Format( "[CIProcess] DoFinalize() - created implicit XIP CodeSegs - {0}", this ) );
       
   388             }
       
   389             //
       
   390             base.Trace( string.Format( "[CIProcess] DoFinalize() - END - {0}", this ) );
       
   391         }
       
   392         #endregion
       
   393 
       
   394         #region From System.Object
       
   395         public override string ToString()
       
   396         {
       
   397             return Name;
       
   398         }
       
   399         #endregion
       
   400 
       
   401         #region From ICISymbolManager
       
   402         public CISymbolDictionary SymbolDictionary
       
   403         {
       
   404             get { return this.Symbols; }
       
   405         }
       
   406         #endregion
       
   407 
       
   408         #region Data members
       
   409         private uint iSID = 0;
       
   410         private int iPriority = 0;
       
   411         private int iGeneration = 1;
       
   412         private UidType iUids = new UidType();
       
   413         private string iName = KUnknownProcessName;
       
   414         #endregion
       
   415     }
       
   416 }