diff -r 000000000000 -r 818e61de6cd1 crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianStructuresLib/Debug/Code/Code/CodeCollection.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianStructuresLib/Debug/Code/Code/CodeCollection.cs Thu Feb 11 15:50:58 2010 +0200 @@ -0,0 +1,453 @@ +/* +* 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.IO; +using System.Text; +using System.Collections.Generic; +using SymbianUtils; +using SymbianUtils.Range; +using SymbianUtils.Streams; +using SymbianStructuresLib.Arm; +using SymbianStructuresLib.Arm.Instructions; +using SymbianStructuresLib.CodeSegments; +using SymbianStructuresLib.Debug.Common.Id; +using SymbianStructuresLib.Debug.Common.FileName; +using SymbianStructuresLib.Debug.Common.Interfaces; +using SymbianStructuresLib.Debug.Code.Interfaces; + +namespace SymbianStructuresLib.Debug.Code +{ + public sealed class CodeCollection : DisposableObject, IComparable, IArmInstructionProvider + { + #region Static constructors + public static CodeCollection New( IPlatformIdAllocator aIdAllocator, string aFileNameInHost, string aFileNameInDevice ) + { + CodeCollection ret = new CodeCollection( aIdAllocator, aFileNameInHost, aFileNameInDevice ); + return ret; + } + + public static CodeCollection NewCopy( IPlatformIdAllocator aIdAllocator, CodeCollection aCollection ) + { + CodeCollection ret = new CodeCollection( aIdAllocator, aCollection ); + return ret; + } + + public static CodeCollection NewByHostFileName( IPlatformIdAllocator aIdAllocator, string aFileName ) + { + CodeCollection ret = new CodeCollection( aIdAllocator, aFileName ); + return ret; + } + #endregion + + #region Delegates & events + public delegate void RelocationStatusChangeHandler( CodeCollection aCollection ); + public event RelocationStatusChangeHandler RelocationStatusChanged; + #endregion + + #region Constructors + private CodeCollection( IPlatformIdAllocator aIdAllocator, string aFileNameInHost ) + { + iId = aIdAllocator.AllocateId(); + iFileName = PlatformFileName.NewByHostName( aFileNameInHost ); + } + + private CodeCollection( IPlatformIdAllocator aIdAllocator, string aFileNameInHost, string aFileNameInDevice ) + : this( aIdAllocator, aFileNameInHost ) + { + iFileName.FileNameInDevice = aFileNameInDevice; + } + + private CodeCollection( IPlatformIdAllocator aIdAllocator, CodeCollection aCopy ) + { + iId = aIdAllocator.AllocateId(); + // + iCode = aCopy.iCode; + iTag = aCopy.iTag; + iFlags = aCopy.iFlags; + iTagged = aCopy.iTagged; + iBaseAddress = aCopy.iBaseAddress; + iCodeSegmentResolver = aCopy.iCodeSegmentResolver; + iRelocationHandler = aCopy.iRelocationHandler; + iFileName = PlatformFileName.New( aCopy.FileName ); + iInstructionConverter = aCopy.IfaceInstructionConverter; + iCodeSegmentResolver = aCopy.IfaceCodeSegmentResolver; + iRelocationHandler = aCopy.IfaceRelocationHandler; + } + #endregion + + #region API + public bool Contains( uint aAddress ) + { + bool ret = IsInstructionAddressValid( aAddress ); + return ret; + } + + public bool IsMatchingCodeSegment( CodeSegDefinition aCodeSegment ) + { + bool ret = false; + // + if ( iCodeSegmentResolver != null ) + { + ret = iCodeSegmentResolver.IsMatchingCodeSegment( this, aCodeSegment ); + } + else + { + PlatformFileName codeSegName = PlatformFileName.NewByDeviceName( aCodeSegment.FileName ); + ret = FileName.Equals( codeSegName ); + } + // + return ret; + } + + public void Relocate( uint aTo ) + { + if ( aTo != iBaseAddress ) + { + uint old = iBaseAddress; + iBaseAddress = aTo; + // + if ( iRelocationHandler != null ) + { + iRelocationHandler.PrepareForRelocation( this, old, BaseAddress ); + } + } + } + #endregion + + #region Properties + public uint Size + { + get + { + uint ret = 0; + if ( iCode != null ) + { + ret = (uint) iCode.Length; + } + return ret; + } + } + + public bool Tagged + { + get { return iTagged; } + set + { + iTagged = value; + } + } + + public bool IsRelocatable + { + get { return ( iFlags & TFlags.EFlagsIsRelocatable ) == TFlags.EFlagsIsRelocatable; } + set + { + lock ( iFlagLock ) + { + bool wasSet = ( iFlags & TFlags.EFlagsIsRelocatable ) == TFlags.EFlagsIsRelocatable; + if ( wasSet != value ) + { + if ( value ) + { + iFlags |= TFlags.EFlagsIsRelocatable; + } + else + { + iFlags &= ~TFlags.EFlagsIsRelocatable; + } + + // Report event if needed + if ( RelocationStatusChanged != null ) + { + RelocationStatusChanged( this ); + } + } + } + } + } + + public bool IsFixed + { + get { return !IsRelocatable; } + set { IsRelocatable = !value; } + } + + public object Tag + { + get { return iTag; } + set + { + iTag = value; + } + } + + public uint BaseAddress + { + get + { + uint ret = iBaseAddress; + return ret; + } + } + + public bool IsCodeAvailable + { + get { return iCode != null; } + } + + public byte[] Code + { + get { return iCode; } + set + { + iCode = value; + } + } + + public PlatformId Id + { + get { return iId; } + } + + public PlatformFileName FileName + { + get { return iFileName; } + } + + public CodeCollectionList ParentList + { + get { return iParentList; } + internal set { iParentList = value; } + } + #endregion + + #region Properties - interfaces + public ICodeCollectionCodeSegmentResolver IfaceCodeSegmentResolver + { + get { return iCodeSegmentResolver; } + set { iCodeSegmentResolver = value; } + } + + public ICodeCollectionRelocationHandler IfaceRelocationHandler + { + get { return iRelocationHandler; } + set { iRelocationHandler = value; } + } + + public ICodeCollectionInstructionConverter IfaceInstructionConverter + { + get { return iInstructionConverter; } + set { iInstructionConverter = value; } + } + #endregion + + #region Internal enumerations + [Flags] + private enum TFlags : byte + { + EFlagsNone = 0, + EFlagsIsRelocatable = 1 + }; + #endregion + + #region Internal constants + #endregion + + #region Internal methods + #endregion + + #region From IArmInstructionProvider + public bool IsInstructionAddressValid( uint aAddress ) + { + bool valid = false; + // + if ( IsCodeAvailable ) + { + AddressRange range = new AddressRange( this.BaseAddress, 0 ); + range.UpdateMax( range.Min + iCode.Length ); + // + valid = range.Contains( aAddress ); + } + // + return valid; + } + + public uint GetDataUInt32( uint aAddress ) + { + uint ret = 0; + IArmInstruction[] inst = null; + // + bool available = GetInstructions( aAddress, TArmInstructionSet.EARM, 1, out inst ); + if ( available && inst.Length >= 1 ) + { + ret = inst[ 0 ].AIRawValue; + } + // + return ret; + } + + public ushort GetDataUInt16( uint aAddress ) + { + ushort ret = 0; + IArmInstruction[] inst = null; + // + bool available = GetInstructions( aAddress, TArmInstructionSet.ETHUMB, 1, out inst ); + if ( available && inst.Length >= 1 ) + { + ret = inst[ 0 ].AIRawValue; + } + // + return ret; + } + + public bool GetInstructions( uint aAddress, TArmInstructionSet aInstructionSet, int aCount, out IArmInstruction[] aInstructions ) + { + bool valid = false; + aInstructions = new IArmInstruction[ 0 ]; + + // We need the code and the instruction converter + if ( IsCodeAvailable && IfaceInstructionConverter != null ) + { + // Check range is valid + AddressRange range = new AddressRange( iBaseAddress, 0 ); + range.UpdateMax( range.Min + iCode.Length ); + uint extent = aAddress + ( (uint) aCount * (uint) aInstructionSet ); + // + valid = range.Contains( aAddress ) && range.Contains( extent ); + if ( valid ) + { + List rawInstructions = new List(); + // + using ( SymbianStreamReaderLE reader = SymbianStreamReaderLE.New( new MemoryStream( iCode ) ) ) + { + uint address = aAddress - iBaseAddress; + reader.Seek( address ); + // + for ( int i = 0; i < aCount; i++ ) + { + uint value = 0; + // + switch ( aInstructionSet ) + { + case TArmInstructionSet.ETHUMB: + value = reader.ReadUInt16(); + break; + case TArmInstructionSet.EARM: + value = reader.ReadUInt32(); + break; + default: + case TArmInstructionSet.EJAZELLE: + throw new NotSupportedException( "Jazelle is not supported" ); + } + // + rawInstructions.Add( value ); + address += (uint) aInstructionSet; + } + } + // + aInstructions = iInstructionConverter.ConvertRawValuesToInstructions( aInstructionSet, rawInstructions.ToArray(), aAddress ); + } + } + + // Return empty array if not valid + return valid; + } + #endregion + + #region From IComparable + public int CompareTo( CodeCollection aCollection ) + { + int ret = ( aCollection.FileName == this.FileName ) ? 0 : -1; + // + if ( ret == 0 ) + { + if ( BaseAddress == aCollection.BaseAddress ) + { + ret = 0; + } + else if ( BaseAddress > aCollection.BaseAddress ) + { + ret = 1; + } + else + { + ret = -1; + } + } + // + return ret; + } + #endregion + + #region From DisposableObject + protected override void CleanupManagedResources() + { + try + { + base.CleanupManagedResources(); + } + finally + { + iTag = null; + iParentList = null; + iInstructionConverter = null; + iCodeSegmentResolver = null; + iRelocationHandler = null; + } + } + #endregion + + #region From System.Object + public override string ToString() + { + return iFileName.ToString(); + } + + public override bool Equals( object aObject ) + { + if ( aObject != null && aObject is CodeCollection ) + { + CodeCollection col = (CodeCollection) aObject; + bool ret = ( col.FileName == this.FileName ); + return ret; + } + // + return base.Equals( aObject ); + } + + public override int GetHashCode() + { + return iFileName.GetHashCode(); + } + #endregion + + #region Data members + private readonly PlatformId iId; + private readonly PlatformFileName iFileName; + private object iTag = null; + private object iFlagLock = new object(); + private byte[] iCode = null; + private uint iBaseAddress = 0; + private bool iTagged = false; + private TFlags iFlags = TFlags.EFlagsNone; + private CodeCollectionList iParentList = null; + private ICodeCollectionCodeSegmentResolver iCodeSegmentResolver = null; + private ICodeCollectionRelocationHandler iRelocationHandler = null; + private ICodeCollectionInstructionConverter iInstructionConverter = null; + #endregion + } +}