crashanalysercmd/Libraries/Engine/CrashItemLib/Crash/Processes/CIProcess.cs
changeset 0 818e61de6cd1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crashanalysercmd/Libraries/Engine/CrashItemLib/Crash/Processes/CIProcess.cs	Thu Feb 11 15:50:58 2010 +0200
@@ -0,0 +1,416 @@
+/*
+* 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.Text;
+using System.IO;
+using System.Collections.Generic;
+using SymbianUtils;
+using SymbianUtils.Range;
+using SymbianStructuresLib.Uids;
+using SymbianStructuresLib.CodeSegments;
+using SymbianStructuresLib.Debug.Common.FileName;
+using SymbianStructuresLib.Debug.Symbols;
+using SymbianDebugLib.Engine;
+using SymbianDebugLib.PluginAPI.Types;
+using SymbianDebugLib.PluginAPI.Types.Symbol;
+using CrashItemLib.Crash;
+using CrashItemLib.Crash.Base;
+using CrashItemLib.Crash.Base.DataBinding;
+using CrashItemLib.Crash.Threads;
+using CrashItemLib.Crash.CodeSegs;
+using CrashItemLib.Crash.Container;
+using CrashItemLib.Crash.Symbols;
+using CrashItemLib.Crash.Summarisable;
+
+namespace CrashItemLib.Crash.Processes
+{
+    #region Attributes
+    [CIDBAttributeColumn( "Name", 0 )]
+    [CIDBAttributeColumn( "Value", 1, true )]
+    #endregion
+    public class CIProcess : CIElement, ICISymbolManager
+	{
+		#region Constructors
+        public CIProcess( CIContainer aContainer )
+            : base( aContainer )
+		{
+            base.AddChild( new CISymbolDictionary( aContainer ) );
+		}
+		#endregion
+
+        #region API
+        public CIThread CreateThread()
+        {
+            CIThread ret = new CIThread( this );
+            base.AddChild( ret );
+            return ret;
+        }
+
+        public CICodeSeg CreateCodeSeg( string aName, uint aBase, uint aLimit )
+        {
+            CICodeSeg ret = CreateCodeSeg( aName, aBase, aLimit, true );
+            return ret;
+        }
+        #endregion
+
+        #region Properties
+        [CIDBAttributeCell( "UIDs", 5 )]
+        public UidType Uids
+        {
+            get { return iUids; }
+        }
+
+        [CIDBAttributeCell( "Generation", 3 )]
+        public int Generation
+        {
+            get { return iGeneration; }
+            set { iGeneration = value; }
+        }
+
+        [CIDBAttributeCell( "Priority", 4, 0 )]
+        public int Priority
+        {
+            get { return iPriority; }
+            set { iPriority = value; }
+        }
+
+        [CIDBAttributeCell( "SID", 2, "x8", 0u )]
+        public uint SID
+        {
+            get
+            {
+                uint ret = iSID;
+                //
+                if ( ret == 0 && iUids.MostSignificant != 0 )
+                {
+                    ret = iUids.MostSignificant;
+                }
+                //
+                return ret; 
+            }
+            set 
+            { 
+                iSID = value;
+
+                // Keep UID3 in line with SID
+                if ( Uids[ 2 ] != value )
+                {
+                    Uids[ 2 ] = value;
+                }
+            }
+        }
+
+        [CIDBAttributeCell( "Name", 1 )]
+        public override string Name
+        {
+            get { return iName; }
+            set 
+            { 
+                iName = value; 
+
+                // Make sure it ends in .exe
+                if ( !iName.ToLower().EndsWith( KProcessExtension ) )
+                {
+                    iName += KProcessExtension;
+                }
+            }
+        }
+
+        public CICodeSegList CodeSegments
+        {
+            get
+            {
+                CIElementList<CICodeSeg> codeSegs = base.ChildrenByType<CICodeSeg>();
+
+                // Sort them
+                Comparison<CICodeSeg> comparer = delegate( CICodeSeg aLeft, CICodeSeg aRight )
+                {
+                    return string.Compare( aLeft.Name, aRight.Name, true );
+                };
+                codeSegs.Sort( comparer );
+
+                CICodeSegList ret = new CICodeSegList( this, codeSegs );
+                return ret; 
+            }
+        }
+
+        public CIThread[] Threads
+        {
+            get
+            {
+                CIElementList<CIThread> list = base.ChildrenByType<CIThread>();
+                CIThread[] ret = list.ToArray();
+                return ret;
+            }
+        }
+
+        public CIThread[] ThreadsWhichExitedAbnormally
+        {
+            get
+            {
+                // We use an anonymous delegate (predicate in this case) to search through
+                // all the direct children of this object that have crashed.
+                CIElementList<CIThread> threads = base.ChildrenByType<CIThread>( 
+                    delegate(CIThread aThread )
+                    {
+                        return aThread.IsAbnormalTermination;
+                    }
+                );
+                return threads.ToArray();
+            }
+        }
+
+        public CIThread PrimaryThread
+        {
+            get
+            {
+                CIThread ret = null;
+                //
+                CIElementList<CIThread> threads = this.ChildrenByType<CIThread>();
+                if ( threads.Count == 1 )
+                {
+                    ret = threads[ 0 ];
+                }
+                else
+                {
+                    // Assumption: The main thread (at least in symbian OS) is the thread which has
+                    // the closest id to that of the process itself.
+                    CIElementId minDelta = int.MaxValue;
+                    foreach ( CIThread thread in this.GetEnumeratorThreads() )
+                    {
+                        CIElementId delta = thread.Id - this.Id;
+                        //
+                        if ( delta < minDelta )
+                        {
+                            ret = thread;
+                        }
+                        if ( delta == 1 )
+                        {
+                            // Optimisation
+                            break;
+                        }
+                    }
+                }
+                //
+                return ret;
+            }
+        }
+
+        public CIThread FirstCrashedThread
+        {
+            get
+            {
+                CIThread  ret = null;
+
+                // Try the primary thread first
+                CIThread primary = PrimaryThread;
+                if ( primary != null && primary.IsAbnormalTermination )
+                {
+                    ret = primary;
+                }
+                else
+                {
+                    // The primary summary is the first summary we can locate
+                    // that relates to a crash.
+                    foreach ( CIThread thread in this.GetEnumeratorThreads() )
+                    {
+                        bool isCrash = thread.IsAbnormalTermination;
+                        if ( isCrash )
+                        {
+                            // Try to find corresponding summarisable entry
+                            ret = thread;
+                            break;
+                        }
+                    }
+                }
+                //
+                return ret;
+            }
+        }
+
+        public CISymbolDictionary Symbols
+        {
+            get { return base.ChildByType( typeof( CISymbolDictionary ) ) as CISymbolDictionary; }
+        }
+
+        public bool IsAbnormalTermination
+        {
+            get
+            {
+                bool ret = false;
+                //
+                foreach ( CIThread thread in this.GetEnumeratorThreads() )
+                {
+                    if ( thread.IsAbnormalTermination )
+                    {
+                        ret = true;
+                        break;
+                    }
+                }
+                //
+                return ret;
+            }
+        }
+        #endregion
+
+        #region Enumerators
+        public IEnumerable<CIThread> GetEnumeratorThreads()
+        {
+            return Threads;
+        }
+
+        public IEnumerable<CICodeSeg> GetEnumeratorCodeSegs()
+        {
+            return CodeSegments;
+        }
+        #endregion
+
+        #region Internal constants
+        private const string KProcessExtension = ".exe";
+        private const string KUnknownProcessName = "UnknownProcess.exe";
+        private const int KBaseOperationMultiplier = 5;
+        #endregion
+
+        #region Internal methods
+        private CICodeSeg CreateCodeSeg( string aName, uint aBase, uint aLimit, bool aExplict )
+        {
+            CICodeSeg ret = new CICodeSeg( this );
+            ret.Name = aName;
+            ret.Base = aBase;
+            ret.Limit = aLimit;
+            ret.IsExplicit = aExplict;
+
+            // Primary store is the child nodes
+            base.AddChild( ret );
+
+            base.Trace( "[CIProcess] CreateCodeSeg() - this: {0}, ret: {1}", this, ret );
+            return ret;
+        }
+
+        private void EnsureCodeSegmentExistsForSymbol( CIElementFinalizationParameters aParams, CISymbol aSymbol )
+        {
+            if ( !aSymbol.IsNull )
+            {
+                Symbol symbol = aSymbol;
+                SymbolCollection collection = symbol.Collection;
+                //
+                string binaryInDevice = PlatformFileNameConstants.Device.KPathWildcardSysBin;
+                binaryInDevice += Path.GetFileName( collection.FileName.EitherFullNameButDevicePreferred );
+                //
+                CICodeSegList codeSegs = CodeSegments;
+                bool alreadyExists = codeSegs.Contains( binaryInDevice );
+                if ( !alreadyExists )
+                {
+                    // Assume no match found - create implicit/speculative code segment
+                    AddressRange newCodeSegRange = collection.SubsumedPrimaryRange;
+                    CICodeSeg newCodeSeg = CreateCodeSeg( binaryInDevice, newCodeSegRange.Min, newCodeSegRange.Max, false );
+
+                    base.Trace( "[CIProcess] EnsureCodeSegmentExistsForSymbol() - creating implicitly identified code seg: " + newCodeSeg.ToString() + " for symbol: " + aSymbol.ToString() );
+
+                    // Resolve it
+                    newCodeSeg.Resolve( aParams.DebugEngineView );
+                }
+            }
+        }
+
+        private void DiscardImplicitCodeSegments()
+        {
+            // Go through each child and see if it's a code seg. If it is, and if 
+            // it is implicit, throw it away
+            int childCount = base.Count;
+            for( int i=childCount-1; i>=0; i-- )
+            {
+                CIElement element = base[ i ];
+                if ( element is CICodeSeg )
+                {
+                    CICodeSeg cs = (CICodeSeg) element;
+                    //
+                    if ( !cs.IsExplicit )
+                    {
+                        base.Trace( string.Format( "[CIProcess] DiscardImplicitCodeSegments() - dicarded: {0}", cs ) );
+                        base.RemoveChild( cs );
+                    }
+                }
+            }
+        }
+
+        private void CreateImplicitCodeSegments( CIElementFinalizationParameters aParams )
+        {
+            CIElementList<CISymbol> children = base.ChildrenByType<CISymbol>( TChildSearchType.EEntireHierarchy );
+            base.Trace( string.Format( "[CIProcess] CreateImplicitCodeSegments() - children count: {1}, {0}", this, children.Count ) );
+            //
+            foreach ( CISymbol symbol in children )
+            {
+                EnsureCodeSegmentExistsForSymbol( aParams, symbol );
+            }
+        }
+        #endregion
+
+        #region From CIElement
+        internal override void DoFinalize( CIElementFinalizationParameters aParams, Queue<CIElement> aCallBackLast, bool aForceFinalize )
+        {
+            base.Trace( string.Format( "[CIProcess] DoFinalize() - START - {0}", this ) );
+
+            // The process' children need to use a process-relative debug engine view in order that they
+            // can correctly resolve any RAM-loaded code.
+            // Therefore, rather than use the so-called "global" debug engine view (which only has
+            // XIP visibility) we create a process-specific set of finalization parameters (for use with 
+            // the process' children) which contain a process-relative view of the world.
+            using ( CIElementFinalizationParameters processRelativeParameters = new CIElementFinalizationParameters( aParams.Engine, this.Name, this.CodeSegments ) )
+            {
+                // Discard any implicit code segments. These are created automagically when an XIP symbol
+                // is found. We'll re-create them anyway in a moment after the symbols have been updated.
+                base.Trace( string.Format( "[CIProcess] DoFinalize() - discarding implicit XIP CodeSegs... - {0}", this ) );
+                DiscardImplicitCodeSegments();
+                base.Trace( string.Format( "[CIProcess] DoFinalize() - discarded implicit XIP CodeSegs - {0}", this ) );
+
+                // Tell our children
+                base.DoFinalize( processRelativeParameters, aCallBackLast, aForceFinalize );
+
+                // Finally, re-create implicit XIP codesegments
+                base.Trace( string.Format( "[CIProcess] DoFinalize() - creating implicit XIP CodeSegs... - {0}", this ) );
+                CreateImplicitCodeSegments( aParams );
+                base.Trace( string.Format( "[CIProcess] DoFinalize() - created implicit XIP CodeSegs - {0}", this ) );
+            }
+            //
+            base.Trace( string.Format( "[CIProcess] DoFinalize() - END - {0}", this ) );
+        }
+        #endregion
+
+        #region From System.Object
+        public override string ToString()
+        {
+            return Name;
+        }
+        #endregion
+
+        #region From ICISymbolManager
+        public CISymbolDictionary SymbolDictionary
+        {
+            get { return this.Symbols; }
+        }
+        #endregion
+
+        #region Data members
+        private uint iSID = 0;
+        private int iPriority = 0;
+        private int iGeneration = 1;
+        private UidType iUids = new UidType();
+        private string iName = KUnknownProcessName;
+        #endregion
+    }
+}