diff -r 000000000000 -r 818e61de6cd1 crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbolLib/Generic/Symbol/GenericSymbol.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbolLib/Generic/Symbol/GenericSymbol.cs Thu Feb 11 15:50:58 2010 +0200 @@ -0,0 +1,464 @@ +/* +* 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 + } +}