crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbolLib/Generic/Symbol/GenericSymbol.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.Collections;
using System.Text;
using System.Text.RegularExpressions;
using SymbianUtils.Range;
using SymbianUtils;

namespace SymbolLib.Generics
{
    #region Exception
	public class GenericSymbolicCreationException : Exception
	{
	}
    #endregion

	public abstract class GenericSymbol
	{
		#region Enumerations
		public enum TAddressType
		{
            // Do not change the order - these are priority based with
            // the most important symbol type appearing with a larger
            // value
			EAddressTypeUnknown = -1,
            EAddressTypeReadOnlySymbol = 0,
			EAddressTypeKernelGlobalVariable,
            EAddressTypeSubObject,
            EAddressTypeLabel,
			EAddressTypeRAMSymbol,
            EAddressTypeROMSymbol,
		}

        public enum TSourceType
        {
            ESourceTypeFileSymbol = 0,
            ESourceTypeFileMap
        }

        public enum TInstructionSet
        {
            EInstructionSetARM = 0,
            EInstructionSetTHUMB
        }
		#endregion

        #region Public constants
        public const int KNullEntryAddress = 0;
        public const string KNonMatchingObjectName = "Unknown Object";
        public const string KNonMatchingSymbolName = "Unknown Symbol";
        #endregion

        #region Constructors
        protected GenericSymbol( GenericSymbolCollection aCollection )
		{
            iCollection = aCollection;
		}
		#endregion

		#region Abstract API
        public abstract TSourceType SourceType { get; }

		public abstract bool Parse( string aLine );
		#endregion

		#region Framework API
		public virtual bool FallsWithinDomain(long aAddress)
		{
			return (aAddress >= Address && aAddress <= EndAddress);
		}

		public virtual bool IsSubObject
		{
			get
			{
				bool ret = ( AddressType == TAddressType.EAddressTypeSubObject );
				return ret;
			}
		}

		public virtual bool IsLabel
		{
			get
			{
				bool ret = ( AddressType == TAddressType.EAddressTypeLabel );
				return ret;
			}
		}

		public virtual bool IsSymbol
		{
			get
			{
				bool ret = ( Collection.BaseAddress == 0 || AddressType == TAddressType.EAddressTypeRAMSymbol || AddressType == TAddressType.EAddressTypeROMSymbol );
				return ret;
			}
		}

		public virtual MemoryModel.TMemoryModelType MemoryModelType // Guess
		{
			get
			{
				return iStaticMemoryModelType;
			}
		}

		public virtual TAddressType AddressType
		{
			get
			{
				TAddressType ret = TAddressType.EAddressTypeUnknown;

				if	( Address >= 0xF8000000 && Address < 0xFFEFFFFF )
				{
					// ROM Symbol, Moving Memory Model
					ret = TAddressType.EAddressTypeROMSymbol;
				}
				else if ( Address >= 0xF4000000 && Address < 0xF7FFFFFF )
				{
					// RAM Symbol, Moving Memory Model
					ret = TAddressType.EAddressTypeRAMSymbol;
				}
				else if ( Address >= 0x64000000 && Address < 0x64FFFFFF )
				{
					// Kernel global, Moving Memory Model
					ret = TAddressType.EAddressTypeKernelGlobalVariable;
				}
				else if ( Address >= 0xc8000000 && Address < 0xC8FFFFFF)
				{
					// Kernel global, Multiple Memory Model
					ret = TAddressType.EAddressTypeKernelGlobalVariable;
				}
				else if ( Address >= 0x80000000 && Address < 0x8FFFFFFF )
				{
					// ROM Symbol, Multiple Memory Model
					ret = TAddressType.EAddressTypeROMSymbol;
				}
				else if ( Address >= 0x3C000000 && Address < 0x3DFFFFFF )
				{
					// RAM Symbol, Moving Memory Model [1gb]
					ret = TAddressType.EAddressTypeRAMSymbol;
				}
				else if ( Address >= 0x70000000 && Address < 0x7FFFFFFF )
				{
					// RAM Symbol, Moving Memory Model [2gb]
					ret = TAddressType.EAddressTypeRAMSymbol;
				}
                else if ( Address < 0x10000000 )
                {
                    // A non-fixed up ROFS symbol entry
                    ret = TAddressType.EAddressTypeRAMSymbol;
                }
				
				// These can over-ride the previous items...
				if	( iSymbol.IndexOf("Image$$ER_RO$$") >= 0 )
				{
					ret = TAddressType.EAddressTypeReadOnlySymbol;
				}
				else if ( iSymbol.IndexOf("__sub_object(") > 0 )
				{
					ret = TAddressType.EAddressTypeSubObject;
				}
				else if ( ret != TAddressType.EAddressTypeKernelGlobalVariable )
				{
                    bool containsBrackets = iSymbol.Contains( "(" ) && iSymbol.Contains( ")" );
                    if ( !containsBrackets )
                    {
                        ret = TAddressType.EAddressTypeLabel;
                    }
				}

				return ret;
			}
		}
		#endregion

        #region API
        public static string UnknownOffset()
        {
            string text = "[+ ??????]";
            return text;
        }

        public uint Offset( uint aInstructionAddress )
        {
            uint baseAddressOffset = aInstructionAddress - System.Convert.ToUInt32( Address );
            return baseAddressOffset;
        }

        public string OffsetAsString( uint aInstructionAddress )
        {
            uint baseAddressOffset = Offset( aInstructionAddress );
            string text = "[+ 0x" + baseAddressOffset.ToString( "x4" ) + "]";
            return text;
        }
        #endregion

        #region Properties
        public TInstructionSet InstructionSet
        {
            get
            {
                TInstructionSet ret = TInstructionSet.EInstructionSetARM;
                //
                if ( ( iFlags & TFlags.EFlagsIsThumb ) == TFlags.EFlagsIsThumb )
                {
                    ret = TInstructionSet.EInstructionSetTHUMB;
                }
                //
                return ret;
            }
        }

        public long BaseAddress
        {
            get { return iCollection.BaseAddress; }
        }

		public long Address
		{
			get
            {
                long address = BaseAddress + iOffsetAddress;
                return address;
            }
		}

		public long EndAddress
		{
			get
            {
                long ret = BaseAddress + iOffsetEndAddress;
                return ret;
            }
		}

		public long Size
		{
			get { return iSize; }
			set
			{
				System.Diagnostics.Debug.Assert( value >= 0 );
				iSize = value;
                
                // We need to update the end address
                if ( iSize > 0 )
                {
                    long address = OffsetAddress;
                    OffsetEndAddress = address + iSize - 1;
                }
                else
                {
                    OffsetEndAddress = OffsetAddress;
                }

                System.Diagnostics.Debug.Assert( iOffsetEndAddress >= OffsetAddress );
			}
		}

        public AddressRange AddressRange
        {
            get { return new AddressRange( Address, EndAddress ); }
        }

		public string Symbol
		{
			get { return iSymbol; }
			set
			{
				iSymbol = value;
                if ( StartsWithAny( KVTableOrTypeInfoPrefixes, value ) )
                {
                    iFlags |= TFlags.EFlagsVTable;
                }
			}
		}

		public string SymbolNameWithoutVTablePrefix
		{
			get
            {
                StringBuilder ret = new StringBuilder( Symbol );
                //
                ret = ret.Replace( "vtable for ", string.Empty );
                ret = ret.Replace( "typeinfo for ", string.Empty );
                ret = ret.Replace( "typeinfo name for ", string.Empty );
                //
                return ret.ToString();
            }
		}

		public string Object
		{
			get { return iObject; }
			set { iObject = value; }
		}

		public string ObjectWithoutSection
		{
			get
			{
				string ret = string.Empty;
                //
                if  ( Object != null )
                {
                    ret = Object;
                    //
                    int bracketPos = ret.IndexOf( "(" );
                    if	( bracketPos > 0 )
                    {
                        ret = ret.Substring( 0, bracketPos ).Trim();
                    }
                }

                // Casing looks odd and it can also confuse
                // hash table look ups in dependent code.
                //ret = SymbianUtils.Strings.StringCaser.PrettyCase( ret );
				return ret;
			}
		}

        public GenericSymbolCollection Collection
        {
            get { return iCollection; }
        }
  
        public bool IsUnknownSymbol
        {
            get
            {
                bool ret = Symbol.StartsWith( KNonMatchingSymbolName ) &&
                           ( OffsetAddress == GenericSymbol.KNullEntryAddress );
                return ret;
            }
        }

        public bool IsVTable
        {
            get
            {
                bool ret = ( iFlags & TFlags.EFlagsVTable ) == TFlags.EFlagsVTable;
                return ret;
            }
        }
        #endregion
        
        #region Internal enumerations
        [Flags]
        private enum TFlags : byte
        {
            EFlagsNone = 0,
            EFlagsVTable = 1,
            EFlagsIsThumb = 2,
        };
        #endregion

        #region Internal properties
        internal long OffsetAddress
        {
            get { return iOffsetAddress; }
            set
            {
                long remainder = value & 0x1;
                if ( remainder != 0 )
                {
                    iFlags |= TFlags.EFlagsIsThumb;
                }
                else
                {
                    iFlags &= ~TFlags.EFlagsIsThumb;
                }

                iOffsetAddress = value & 0xFFFFFFFE;

                // If we've not yet decided upon the type of memory model,
                // now is the time to work it out.
                if  ( iOffsetAddress > 0 && iStaticMemoryModelType == MemoryModel.TMemoryModelType.EMemoryModelUnknown )
                {
                    long address = Address;
                    iStaticMemoryModelType = MemoryModel.TypeByAddress( address );
                }
            }
        }

        private long OffsetEndAddress
        {
            set { iOffsetEndAddress = value; }
        }
        #endregion

		#region Internal constants
		protected const int KBaseHex = 16;
        private static readonly string[] KVTableOrTypeInfoPrefixes = new string[] { "vtable for ", "typeinfo for ", "typeinfo name for " };
		#endregion

		#region From System.Object
		public override string ToString()
		{
            string ret = string.Format( "{0:x8}    {1:x4}    {2} [{3}]", Address, Size, Symbol, Object );
			return ret;
		}
        
        public string ToStringForStream()
        {
            StringBuilder ret = new StringBuilder();
            //
            ret.Append( Address.ToString( "x8" ) );
            ret.Append( "    " );
            ret.Append( Size.ToString( "x4" ) );
            ret.Append( "    " );
            ret.Append( Symbol.PadRight( 40, ' ' ) );
            ret.Append( " " );
            ret.Append( Object );
            //
            return ret.ToString();
        }

        public static bool StartsWithAny( string[] aPrefixes, string aText )
        {
            bool ret = false;
            //
            foreach ( string p in aPrefixes )
            {
                if ( aText.StartsWith( p ) )
                {
                    ret = true;
                    break;
                }
            }
            //
            return ret;
        }
	    #endregion

		#region Data members
		protected long iSize;
		#endregion

		#region Internal data members
		private long iOffsetAddress;
		private long iOffsetEndAddress;
        private string iSymbol = string.Empty;
		private string iObject = string.Empty;
        private TFlags iFlags = TFlags.EFlagsNone;
        private readonly GenericSymbolCollection iCollection;
        private static MemoryModel.TMemoryModelType iStaticMemoryModelType = MemoryModel.TMemoryModelType.EMemoryModelUnknown;
		#endregion
	}
}