crashanalysercmd/Libraries/Engine/CrashItemLib/Crash/CodeSegs/CICodeSeg.cs
author Matti Laitinen <matti.t.laitinen@nokia.com>
Thu, 11 Feb 2010 15:50:58 +0200
changeset 0 818e61de6cd1
permissions -rw-r--r--
Add initial version of Crash Analyser cmdline under EPL

/*
* 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.Collections.Generic;
using SymbianDebugLib.Engine;
using SymbianDebugLib.PluginAPI.Types;
using SymbianDebugLib.PluginAPI.Types.Symbol;
using SymbianStructuresLib.Uids;
using SymbianUtils.DataBuffer;
using SymbianStructuresLib.CodeSegments;
using SymbianStructuresLib.Debug.Symbols;
using SymbianUtils;
using SymbianUtils.Range;
using CrashItemLib.Crash;
using CrashItemLib.Crash.Base;
using CrashItemLib.Crash.Messages;
using CrashItemLib.Crash.Processes;
using CrashItemLib.Crash.Symbols;

namespace CrashItemLib.Crash.CodeSegs
{
    public class CICodeSeg : CIElement
    {
        #region Constructors
        public CICodeSeg( CIProcess aProcess )
            : this( aProcess, new CodeSegDefinition() )
		{
		}
        
        public CICodeSeg( CIProcess aProcess, CodeSegDefinition aCodeSegDef )
            : base( aProcess.Container )
        {
            iOwningProcess = aProcess;
            iCodeSegDef = aCodeSegDef;
        }
        #endregion

        #region API
        public bool Contains( uint aAddress )
        {
            bool ret = Range.Contains( aAddress );
            return ret;
        }

        internal void Resolve( DbgEngineView aDebugEngineView )
        {
            base.Trace( "[CICodeSeg] Resolve() - START - this: {0}", this );
            ResetState();

            // Check whether we have a symbol already loaded for the code segment's base address
            uint baseAddress = this.Base;
            //
            SymbolCollection col = null;
            Symbol symbol = aDebugEngineView.Symbols.Lookup( baseAddress, out col );
            base.Trace( "[CICodeSeg] Resolve() - symbol: {0}, symbolCollection: {1}", symbol, col );
            //
            if ( symbol != null )
            {
                // This must be valid if we found a symbol
                System.Diagnostics.Debug.Assert( col != null );
            }
            else
            {
                // Symbol engine is not aware of the code segment's base address, but we can check by name
                // as well...
                col = aDebugEngineView.Symbols[ iCodeSegDef ];
            }

            // Update state
            IsResolved = ( col != null );
            AssociatedSymbolCollection = col;

            base.Trace( "[CICodeSeg] Resolve() - END - this: {0}, resolved: {1}, iCodeSegDef.FileName: {2}", this, this.IsResolved, iCodeSegDef.FileName );
        }
        #endregion

        #region Properties
        public override string Name
        {
            get { return iCodeSegDef.FileName; }
            set 
            {
                iCodeSegDef.FileName = value;
            }
        }

        public uint Base
        {
            get { return iCodeSegDef.Base; }
            set { iCodeSegDef.Base = value; }
        }

        public uint Limit
        {
            get { return iCodeSegDef.Limit; }
            set
            {
                iCodeSegDef.Limit = value; 
            }
        }

        public uint Size
        {
            get 
            { 
                // The address range contains all-inclusive values.
                //
                // E.g. a range of 0x00 -> 0x10 would include the values...:
                //
                //   0x00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C, 0D, 0E, 0F, 0x10
                //
                // ...and therefore AddressRange.Size would return 17.
                //
                // Symbian OS treats the range as non-inclusive, so the value is one too large.
                // Hence we subtract one
                uint ret = iCodeSegDef.Size - 1;
                return ret;
            }
        }

        public uint Checksum
        {
            get { return iCodeSegDef.Checksum; }
            set { iCodeSegDef.Checksum = value; }
        }

        public bool IsResolved
        {
            get { return iIsResolved; }
            private set
            { 
                iIsResolved = value;
                base.Trace( "[CICodeSeg] Resolve() - this: {0}, resolved: {1}", this, iIsResolved );
            }
        }

        public bool IsMismatched
        {
            get { return MismatchAddress != KNoSymbolicMismatchAddress; }
        }

        public bool IsSpeculative
        {
            get { return !IsExplicit; }
        }

        public bool IsExplicit
        {
            get { return iIsExplicit; }
            internal set { iIsExplicit = value; }
        }

        public uint MismatchAddress
        {
            get { return iMismatchAddress; }
            private set { iMismatchAddress = value; }
        }

        public AddressRange Range
        {
            get
            {
                // We do this so that calling Range.ToString() won't include a file name!
                AddressRange ret = new AddressRange( iCodeSegDef );
                return ret;
            }
        }

        public CIProcess OwningProcess
        {
            get 
            {
                System.Diagnostics.Debug.Assert( iOwningProcess != null );
                return iOwningProcess; 
            }
        }

        public SymbolCollection AssociatedSymbolCollection
        {
            get { return iAssociatedSymbolCollection; }
            private set
            {
                iAssociatedSymbolCollection = value;
                if ( iAssociatedSymbolCollection != null )
                {
                    bool misMatch = ( iAssociatedSymbolCollection.BaseAddress != this.Base );
                    if ( misMatch )
                    {
                        MismatchAddress = iAssociatedSymbolCollection.BaseAddress;
                    }
                }
            }
        }
        #endregion

        #region Operators
        public static implicit operator CodeSegDefinition( CICodeSeg aCodeSeg )
        {
            return aCodeSeg.iCodeSegDef;
        }
        #endregion

        #region Internal constants
        private const uint KNoSymbolicMismatchAddress = 0;
        #endregion

        #region Internal methods
        private void ResetState()
        {
            IsResolved = false;
            MismatchAddress = 0;
        }

        private Symbol BaseAddressSymbolAndCollection( DbgViewSymbol aSymbolView, out SymbolCollection aCollection )
        {
            Symbol ret = aSymbolView.Lookup( this.Base, out aCollection );
            return ret;
        }
        #endregion

        #region From CIElement
        internal override void OnFinalize( CIElementFinalizationParameters aParams )
        {
            try
            {
                base.OnFinalize( aParams );
            }
            finally
            {
                Resolve( aParams.DebugEngineView );
            }
        }
        #endregion
        
        #region From System.Object
        public override string ToString()
        {
            StringBuilder ret = new StringBuilder();
            ret.AppendFormat( "{0:x8}-{1:x8} {2}", this.Base, this.Limit, this.Name );
            return ret.ToString();
        }
        #endregion

        #region Data members
        private readonly CIProcess iOwningProcess;
        private bool iIsResolved = false;
        private bool iIsExplicit = false;
        private uint iMismatchAddress = KNoSymbolicMismatchAddress;
        private CodeSegDefinition iCodeSegDef = new CodeSegDefinition();
        private SymbolCollection iAssociatedSymbolCollection = null;
        #endregion
    }
}