diff -r 000000000000 -r 818e61de6cd1 crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianStructuresLib/Debug/Symbols/Symbols/Symbol.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianStructuresLib/Debug/Symbols/Symbols/Symbol.cs Thu Feb 11 15:50:58 2010 +0200 @@ -0,0 +1,605 @@ +#define TRACE_INTERNING +/* +* 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 System.ComponentModel; +using SymbianUtils.Range; +using SymbianUtils.Strings; +using SymbianStructuresLib.Arm; +using SymbianStructuresLib.MemoryModel; +using SymbianStructuresLib.Debug.Symbols.Constants; +using SymbianStructuresLib.Debug.Common.Id; + +namespace SymbianStructuresLib.Debug.Symbols +{ + public class Symbol : IFormattable + { + #region Static constructors + public static Symbol New( SymbolCollection aCollection ) + { + return new Symbol( aCollection ); + } + + public static Symbol NewDefault() + { + Symbol ret = new Symbol( null ); + // + ret.IsDefault = true; + ret.Size = 0; + ret.OffsetAddress = SymbolConstants.KNullEntryAddress; + ret.Object = SymbolConstants.KNonMatchingObjectName; + ret.iName = InternedName.NewExplicit( SymbolConstants.KNonMatchingInternedName ); + // + return ret; + } + + internal static Symbol NewDefault( SymbolCollection aCollection ) + { + Symbol ret = new Symbol( aCollection ); + // + ret.IsDefault = true; + ret.Size = 0; + ret.OffsetAddress = SymbolConstants.KNullEntryAddress; + ret.Object = SymbolConstants.KNonMatchingObjectName; + ret.iName = InternedName.NewExplicit( SymbolConstants.KNonMatchingInternedName ); + // + return ret; + } + + internal static Symbol NewTemp( SymbolCollection aCollection, uint aAddress ) + { + Symbol ret = new Symbol( aCollection ); + // + ret.Size = 0; + ret.OffsetAddress = aAddress - aCollection.BaseAddress; + ret.iName = InternedName.NewExplicit( "TempInternal" ); + ret.Object = "TempInternal"; + // + return ret; + } + + internal static Symbol NewClone( SymbolCollection aCollection, Symbol aSymbol ) + { + return new Symbol( aCollection, aSymbol ); + } + #endregion + + #region Constructors + private Symbol( SymbolCollection aCollection ) + { + iCollection = aCollection; + // + if ( aCollection != null ) + { + iId = aCollection.IdAllocator.AllocateId().Value; + } + } + + private Symbol( SymbolCollection aCollection, Symbol aSymbol ) + : this( aCollection ) + { + iSize = aSymbol.iSize; + iOffsetAddress = aSymbol.iOffsetAddress; + iName = aSymbol.iName; + iObject = aSymbol.iObject; + iFlags = aSymbol.iFlags; + iId = aCollection.IdAllocator.AllocateId().Value; + } + #endregion + + #region API + public bool Contains( uint aAddress ) + { + bool ret = ( aAddress >= Address && aAddress <= EndAddress ); + return ret; + } + + public uint Offset( uint aInstructionAddress ) + { + uint offset = aInstructionAddress - Address; + return offset; + } + #endregion + + #region Properties + public uint Address + { + get + { + uint address = BaseAddress + OffsetAddress; + return address; + } + } + + public uint EndAddress + { + get + { + uint address = Address; + uint size = Size; + // + if ( size > 0 ) + { + address += ( size - 1 ); + } + // + return address; + } + } + + public uint Size + { + get { return iSize; } + set + { + iSize = value; + System.Diagnostics.Debug.Assert( OffsetEndAddress >= OffsetAddress ); + } + } + + public AddressRange AddressRange + { + get { return new AddressRange( Address, EndAddress ); } + } + + public string Name + { + get + { + string ret = string.Empty; + // + if ( iName != null ) + { + ret = iName.ToString(); + } + // + return ret; + } + set + { + iName = InternedName.New( value ); + + // Remove all property flags + iFlags &= ~TFlags.EFlagsIsFunction; + iFlags &= ~TFlags.EFlagsIsVTable; + iFlags &= ~TFlags.EFlagsIsReadonly; + iFlags &= ~TFlags.EFlagsIsSubObject; + + if ( InternedName.IsVTable( value ) ) + { + iFlags |= TFlags.EFlagsIsVTable; + } + else if ( InternedName.IsReadOnly( value ) ) + { + iFlags |= TFlags.EFlagsIsReadonly; + } + else if ( InternedName.IsSubObject( value ) ) + { + iFlags |= TFlags.EFlagsIsSubObject; + } + else if ( InternedName.IsFunction( value ) ) + { + iFlags |= TFlags.EFlagsIsFunction; + } + } + } + + public string NameWithoutVTablePrefix + { + get + { + StringBuilder ret = new StringBuilder( Name ); + // + 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 + { + string ret = string.Empty; + // + if ( iObject != null ) + { + ret = iObject; + } + // + return ret; + } + set + { + iObject = string.Intern( 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(); + } + } + // + return ret; + } + } + + public SymbolCollection Collection + { + // NB: can be null + get { return iCollection; } + } + + public TArmInstructionSet InstructionSet + { + get + { + TArmInstructionSet ret = TArmInstructionSet.EARM; + uint remainder = iOffsetAddress & 0x1; + if ( remainder != 0 ) + { + ret = TArmInstructionSet.ETHUMB; + } + return ret; + } + } + + public PlatformId Id + { + get { return new PlatformId( iId ); } + } + + [Browsable( false )] + [EditorBrowsable( EditorBrowsableState.Never )] + public uint OffsetAddress + { + get + { + // Don't include the top bit in any returned address + uint ret = iOffsetAddress & 0xFFFFFFFE; + return ret; + } + set + { + iOffsetAddress = value; + } + } + + [Browsable( false )] + [EditorBrowsable( EditorBrowsableState.Never )] + private uint OffsetEndAddress + { + get + { + uint ret = iOffsetAddress + iSize; + if ( InstructionSet == TArmInstructionSet.ETHUMB && iSize > 0 ) + { + // For thumb, the end address is one too big, due to the MSB. + --ret; + } + return ret; + } + } + #endregion + + #region Type query + public bool IsFunction + { + get + { + bool ret = ( iFlags & TFlags.EFlagsIsFunction ) != 0; + return ret; + } + } + + public bool IsVTable + { + get + { + bool ret = ( iFlags & TFlags.EFlagsIsVTable ) == TFlags.EFlagsIsVTable; + return ret; + } + } + + public bool IsDefault + { + get + { + bool ret = ( iFlags & TFlags.EFlagsIsDefault ) == TFlags.EFlagsIsDefault; + return ret; + } + set + { + if ( value ) + { + iFlags |= TFlags.EFlagsIsDefault; + } + else + { + iFlags &= ~TFlags.EFlagsIsDefault; + } + } + } + + public bool IsFromRAMLoadedCode + { + get + { + uint address = this.Address; + TMemoryModelRegion region = MMUtilities.RegionByAddress( address ); + bool ret = ( region == TMemoryModelRegion.EMemoryModelRegionRAMLoadedCode ); + return ret; + } + } + + public TSymbolType Type + { + get + { + TSymbolType ret = TSymbolType.EUnknown; + + // First check against forced flags + if ( ( iFlags & TFlags.EFlagsIsForcedSection ) == TFlags.EFlagsIsForcedSection ) + { + ret = TSymbolType.ESection; + } + else if ( ( iFlags & TFlags.EFlagsIsForcedCode ) == TFlags.EFlagsIsForcedCode ) + { + ret = TSymbolType.ECode; + } + else if ( ( iFlags & TFlags.EFlagsIsForcedData ) == TFlags.EFlagsIsForcedData ) + { + ret = TSymbolType.EData; + } + else if ( ( iFlags & TFlags.EFlagsIsForcedNumber ) == TFlags.EFlagsIsForcedNumber ) + { + ret = TSymbolType.ENumber; + } + + // If still unknown, work it out... + if ( ret == TSymbolType.EUnknown ) + { + // First entries override type + if ( ( iFlags & TFlags.EFlagsIsReadonly ) != 0 ) + { + ret = TSymbolType.EReadOnlySymbol; + } + else if ( ( iFlags & TFlags.EFlagsIsSubObject ) != 0 ) + { + ret = TSymbolType.ESubObject; + } + else if ( Address >= 0xF8000000 && Address < 0xFFEFFFFF ) + { + // ROM Symbol, Moving Memory Model + ret = TSymbolType.EROMSymbol; + } + else if ( Address >= 0xF4000000 && Address < 0xF7FFFFFF ) + { + // RAM Symbol, Moving Memory Model + ret = TSymbolType.ERAMSymbol; + } + else if ( Address >= 0x64000000 && Address < 0x64FFFFFF ) + { + // Kernel global, Moving Memory Model + ret = TSymbolType.EKernelGlobalVariable; + } + else if ( Address >= 0xc8000000 && Address < 0xC8FFFFFF ) + { + // Kernel global, Multiple Memory Model + ret = TSymbolType.EKernelGlobalVariable; + } + else if ( Address >= 0x80000000 && Address < 0x8FFFFFFF ) + { + // ROM Symbol, Multiple Memory Model + ret = TSymbolType.EROMSymbol; + } + else if ( Address >= 0x3C000000 && Address < 0x3DFFFFFF ) + { + // RAM Symbol, Moving Memory Model [1gb] + ret = TSymbolType.ERAMSymbol; + } + else if ( Address >= 0x70000000 && Address < 0x7FFFFFFF ) + { + // RAM Symbol, Moving Memory Model [2gb] + ret = TSymbolType.ERAMSymbol; + } + else if ( Address < 0x10000000 ) + { + // A non-fixed up ROFS symbol entry + ret = TSymbolType.ERAMSymbol; + } + else if ( ret != TSymbolType.EKernelGlobalVariable ) + { + bool isFunction = IsFunction; + if ( isFunction == false ) + { + ret = TSymbolType.ELabel; + } + } + } + // + return ret; + } + set + { + iFlags &= ~TFlags.EFlagsIsForcedCode; + iFlags &= ~TFlags.EFlagsIsForcedData; + iFlags &= ~TFlags.EFlagsIsForcedNumber; + iFlags &= ~TFlags.EFlagsIsForcedSection; + // + switch ( value ) + { + case TSymbolType.ESection: + iFlags |= TFlags.EFlagsIsForcedSection; + break; + case TSymbolType.ECode: + iFlags |= TFlags.EFlagsIsForcedCode; + break; + case TSymbolType.EData: + iFlags |= TFlags.EFlagsIsForcedData; + break; + case TSymbolType.ENumber: + iFlags |= TFlags.EFlagsIsForcedNumber; + break; + default: + throw new ArgumentException( "Specified type cannot be programatically set" ); + } + } + } + + public TSymbolSource Source + { + get + { + TSymbolSource ret = TSymbolSource.ESourceWasUnknown; + // + if ( ( iFlags & TFlags.EFlagsIsFromMapFile ) == TFlags.EFlagsIsFromMapFile ) + { + ret = TSymbolSource.ESourceWasMapFile; + } + else if ( ( iFlags & TFlags.EFlagsIsFromSymbolFile ) == TFlags.EFlagsIsFromSymbolFile ) + { + ret = TSymbolSource.ESourceWasSymbolFile; + } + // + return ret; + } + set + { + iFlags &= ~TFlags.EFlagsIsFromMapFile; + iFlags &= ~TFlags.EFlagsIsFromSymbolFile; + // + switch ( value ) + { + case TSymbolSource.ESourceWasMapFile: + iFlags |= TFlags.EFlagsIsFromMapFile; + break; + case TSymbolSource.ESourceWasSymbolFile: + iFlags |= TFlags.EFlagsIsFromSymbolFile; + break; + default: + case TSymbolSource.ESourceWasUnknown: + break; + } + } + } + #endregion + + #region Internal enumerations + [Flags] + private enum TFlags : ushort + { + EFlagsNone = 0, + EFlagsIsDefault = 1, + EFlagsIsVTable = 2, + EFlagsIsFunction = 4, + EFlagsIsReadonly = 8, + EFlagsIsSubObject = 16, + EFlagsIsForcedCode = 32, + EFlagsIsForcedData = 64, + EFlagsIsForcedNumber = 128, + EFlagsIsForcedSection = 256, + EFlagsIsFromMapFile = 512, + EFlagsIsFromSymbolFile = 1024 + }; + #endregion + + #region Internal methods + private uint BaseAddress + { + get + { + if ( iCollection != null ) + { + return iCollection.BaseAddress; + } + // + return 0; + } + } + #endregion + + #region From System.Object + public override string ToString() + { + string ret = ToString( null, null ); + return ret; + } + + public string ToStringOffset( uint aFrom ) + { + uint baseAddressOffset = Offset( aFrom ); + string text = "[+ 0x" + baseAddressOffset.ToString( "x4" ) + "]"; + return text; + } + #endregion + + #region IFormattable Members + public string ToString( string aFormat, IFormatProvider aFormatProvider ) + { + string ret = string.Empty; + // + if ( string.IsNullOrEmpty( aFormat ) ) + { + ret = string.Format( "{0:x8} {1:x4} {2} [{3}]", Address, Size, Name, Object ); + } + else + { + string format = aFormat.Trim().ToUpper(); + // + if ( format == "STREAM" ) + { + ret = string.Format( "{0:x8} {1:x4} {2} [{3}]", Address, Size, Name.PadRight( 40, ' ' ), Object ); + } + else + { + throw new FormatException( String.Format( "Invalid format string: '{0}'.", aFormat ) ); + } + } + // + return ret; + } + #endregion + + #region Data members + private readonly SymbolCollection iCollection; + private readonly uint iId; // This saves 8 bytes per instance over using PlatformId directly + private uint iSize; + private uint iOffsetAddress; + private string iObject = null; + private InternedName iName = null; + private TFlags iFlags = TFlags.EFlagsNone; + #endregion + } +} \ No newline at end of file