crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianETMLib/Common/State/Implementations/ETMDecodeStatePHeader.cs
changeset 0 818e61de6cd1
equal deleted inserted replaced
-1:000000000000 0:818e61de6cd1
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 using System;
       
    19 using System.Collections.Generic;
       
    20 using System.Text;
       
    21 using SymbianUtils.BasicTypes;
       
    22 using SymbianStructuresLib.Arm;
       
    23 using SymbianStructuresLib.Arm.Exceptions;
       
    24 using SymbianETMLib.Common.Types;
       
    25 using SymbianETMLib.Common.Packets;
       
    26 using SymbianETMLib.Common.Utilities;
       
    27 using SymbianETMLib.Common.Exception;
       
    28 
       
    29 namespace SymbianETMLib.Common.State
       
    30 {
       
    31     public class ETMDecodeStatePHeader : ETMDecodeState
       
    32     {
       
    33         #region Constructors
       
    34         public ETMDecodeStatePHeader( ETMStateData aManager )
       
    35             : base( aManager )
       
    36         {
       
    37         }
       
    38 
       
    39         static ETMDecodeStatePHeader()
       
    40         {
       
    41             // ARM branch instructions
       
    42             iBranchMask_ARM_BOrBL = new SymMask( "#### 101 # ######## ######## ########" );
       
    43             iBranchMask_ARM_BLX_BranchToThumb = new SymMask( "1111 101 # ######## ######## ########" );
       
    44 
       
    45             // THUMB branch instructions
       
    46             iBranchMask_THUMB_B1 = new SymMask( "1101 #### ########" );
       
    47             iBranchMask_THUMB_B2 = new SymMask( "11100  ###########" );
       
    48             iBranchMask_THUMB_BLX_Part1 = new SymMask( "11110  ###########" ); // Multi-instruction branch
       
    49             iBranchMask_THUMB_BLX_Part2 = new SymMask( "111#1  ###########" ); // Multi-instruction branch
       
    50         }
       
    51         #endregion
       
    52 
       
    53         #region API
       
    54         public override ETMDecodeState HandleByte( SymByte aByte )
       
    55         {
       
    56             ETMDecodeState nextState = new ETMDecodeStateSynchronized( base.StateData );
       
    57             //
       
    58             ETMPcktBase packet = Packets.Factory.ETMPacketFactory.Create( aByte );
       
    59             if ( packet is ETMPcktPHeaderFormat1 )
       
    60             {
       
    61                 ETMPcktPHeaderFormat1 pHeader1 = (ETMPcktPHeaderFormat1) packet;
       
    62                 ProcessFormat1Conditions( pHeader1 );
       
    63             }
       
    64             else if ( packet is ETMPcktPHeaderFormat2 )
       
    65             {
       
    66                 ETMPcktPHeaderFormat2 pHeader2 = (ETMPcktPHeaderFormat2) packet;
       
    67                 ProcessFormat2Conditions( pHeader2 );
       
    68             }
       
    69             else
       
    70             {
       
    71                 throw new ETMException( "ERROR: P-HEADER is not supported" );
       
    72             }
       
    73             //
       
    74             return nextState;
       
    75         }
       
    76         #endregion
       
    77 
       
    78         #region Properties
       
    79         #endregion
       
    80 
       
    81         #region Internal enumerations
       
    82         private enum TMultiPartThumbBranch
       
    83         {
       
    84             ETHUMBBL = 0x3,
       
    85             ETHUMBBLX = 0x1,
       
    86         }
       
    87         #endregion
       
    88 
       
    89         #region Internal methods
       
    90         private void ProcessFormat1Conditions( ETMPcktPHeaderFormat1 aHeader )
       
    91         {
       
    92             string pass = aHeader.ConditionCountPassed > 0 ? string.Format( "{0} x PASS", aHeader.ConditionCountPassed ) : string.Empty;
       
    93             string fail = aHeader.ConditionCountFailed > 0 ? string.Format( ", {0} x FAIL", aHeader.ConditionCountFailed ) : string.Empty;
       
    94             base.Trace( "{0} - {1} {2}", base.MakeTracePacketPrefix( "P-HEADER(1)" ), pass, fail );
       
    95 
       
    96             // Get the total number of instructions processed
       
    97             int totalExecutedInstructionCount = aHeader.ConditionCountPassed + aHeader.ConditionCountFailed;
       
    98 
       
    99             // Trace passed instructions
       
   100             for ( int i = 0; i < aHeader.ConditionCountPassed; i++ )
       
   101             {
       
   102                 uint address = base.StateData.CurrentAddress;
       
   103                 ETMInstruction instruction = base.StateData.FetchInstruction( address );
       
   104                 //
       
   105                 TraceAtom( ETMPcktPHeaderBase.TAtomType.EAtomE_Passed, instruction );
       
   106                 
       
   107                 // We will now check the current instruction to see if it's a branch.
       
   108                 // If it is, then we don't need to increment the instruction address, because
       
   109                 // the explicit branch will set a new PC location.
       
   110                 //
       
   111                 // Note that in the case of a thumb BLX, i.e. two 16-bit instructions which
       
   112                 // interpreted together form a +/-4mb branch address, we also need
       
   113                 // to ensure that the 
       
   114                 bool branched = CheckForBranch( instruction );
       
   115                 if ( !branched )
       
   116                 {
       
   117                     base.StateData.IncrementPC();
       
   118                 }
       
   119             }
       
   120 
       
   121             // Trace and failed instructions
       
   122             if ( aHeader.ConditionCountFailed > 0 )
       
   123             {
       
   124                 uint address = base.StateData.CurrentAddress;
       
   125                 ETMInstruction instruction = base.StateData.FetchInstruction( address );
       
   126                 //
       
   127                 TraceAtom( ETMPcktPHeaderBase.TAtomType.EAtomN_Failed, instruction );
       
   128                 base.StateData.IncrementPC();
       
   129             }
       
   130 
       
   131             // Spacer - to make the verbose output easier to read...
       
   132             base.Trace( string.Empty );
       
   133         }
       
   134 
       
   135         private void ProcessFormat2Conditions( ETMPcktPHeaderFormat2 aHeader )
       
   136         {
       
   137             string atom1TypeName = TraceAtomTypeName( aHeader.Atom1Type );
       
   138             string atom2TypeName = TraceAtomTypeName( aHeader.Atom2Type );
       
   139             base.Trace( "{0} - 1 x {1}, 1 x {2}", base.MakeTracePacketPrefix( "P-HEADER(2)" ), atom1TypeName, atom2TypeName );
       
   140 
       
   141             // First instruction
       
   142             {
       
   143                 uint address1 = base.StateData.CurrentAddress;
       
   144                 ETMInstruction inst1 = base.StateData.FetchInstruction( address1 );
       
   145                 TraceAtom( aHeader.Atom1Type, inst1 );
       
   146                 if ( aHeader.Atom1Type == ETMPcktPHeaderBase.TAtomType.EAtomE_Passed )
       
   147                 {
       
   148                     bool branched = CheckForBranch( inst1 );
       
   149                     if ( !branched )
       
   150                     {
       
   151                         base.StateData.IncrementPC();
       
   152                     }
       
   153                 }
       
   154                 else
       
   155                 {
       
   156                     base.StateData.IncrementPC();
       
   157                 }
       
   158             }
       
   159 
       
   160             // Second instruction
       
   161             {
       
   162                 uint address2 = base.StateData.CurrentAddress;
       
   163                 ETMInstruction inst2 = base.StateData.FetchInstruction( address2 );
       
   164                 TraceAtom( aHeader.Atom2Type, inst2 );
       
   165                 if ( aHeader.Atom2Type == ETMPcktPHeaderBase.TAtomType.EAtomE_Passed )
       
   166                 {
       
   167                     bool branched = CheckForBranch( inst2 );
       
   168                     if ( !branched )
       
   169                     {
       
   170                         base.StateData.IncrementPC();
       
   171                     }
       
   172                 }
       
   173                 else
       
   174                 {
       
   175                     base.StateData.IncrementPC();
       
   176                 }
       
   177             }
       
   178 
       
   179             // Spacer - to make the verbose output easier to read...
       
   180             base.Trace( string.Empty );
       
   181         }
       
   182 
       
   183         private bool HandleTHUMBMultiInstructionBranch( uint aInstruction1, uint aInstruction2 )
       
   184         {
       
   185             bool branched = false;
       
   186 
       
   187             // THUMB multi branch with link exchange instruction - consumes 32 bits
       
   188             // of the instruction pipeline, i.e. instructions @ aIndex and aIndex+1 both
       
   189             // consumed.
       
   190             //
       
   191             // Check the signature is correct:
       
   192             //
       
   193             // NB: 
       
   194             //   The first Thumb instruction has H == 10 and supplies the high part of the 
       
   195             //   branch offset. This instruction sets up for the subroutine call and is 
       
   196             //   shared between the BL and BLX forms.
       
   197             //
       
   198             //   The second Thumb instruction has H == 11 (for BL) or H == 01 (for BLX). It 
       
   199             //   supplies the low part of the branch offset and causes the subroutine call 
       
   200             //   to take place.
       
   201             //
       
   202             //  15   14   13   12 11   10                        0
       
   203             // ----------------------------------------------------  
       
   204             //  1    1    1      H     <---     offset_11      -->
       
   205             //
       
   206             // mask1  =      11 00000000000
       
   207             // value1 =      10 00000000000
       
   208             //           111 11 10111010101
       
   209             // mask2  =       1 00000000000
       
   210             // value2 =       1 00000000000
       
   211             //           111 10 11111111111
       
   212             bool inst1Valid = ( ( aInstruction1 & 0x1800 ) == 0x1000 );
       
   213             bool inst2Valid = ( ( aInstruction2 & 0x0800 ) == 0x0800 );
       
   214 
       
   215             if ( inst1Valid && inst2Valid )
       
   216             {
       
   217                 TArmInstructionSet newInstructionSet = TArmInstructionSet.ETHUMB;
       
   218                 TMultiPartThumbBranch branchType = TMultiPartThumbBranch.ETHUMBBL;
       
   219                 if ( ( aInstruction2 & 0x1800 ) == 0x0800 )
       
   220                 {
       
   221                     branchType = TMultiPartThumbBranch.ETHUMBBLX;
       
   222                     newInstructionSet = TArmInstructionSet.EARM;
       
   223                 }
       
   224 
       
   225                 // We subtract two, because we're already handling the second instruction
       
   226                 // and the address is relative to the first.
       
   227                 uint address = base.StateData.CurrentAddress - 2;
       
   228 
       
   229                 // 111 10 00000000100
       
   230                 //    100000000000000
       
   231                 // 
       
   232                 int instImmediate1 = SignExtend11BitTo32BitTHUMB( aInstruction1 & 0x7FF, 12 );
       
   233                 address = (uint) ( address + instImmediate1 );
       
   234                 address += 4;
       
   235 
       
   236                 // 111 01 11101011010
       
   237                 //        11111111111 (0x7FF)
       
   238                 //        11101011010 = 0x75A * 2 = EB4
       
   239                 //
       
   240                 // 111 01 11011100010
       
   241                 //        11011100010 = 0X6E2 * 2 = DC4
       
   242                 // 
       
   243                 // 
       
   244 
       
   245                 // Second instruction
       
   246                 uint instImmediate2 = ( aInstruction2 & 0x7FF ) * 2;
       
   247                 address += instImmediate2;
       
   248 
       
   249                 // For BLX, the resulting address is forced to be word-aligned by 
       
   250                 // clearing bit[1].
       
   251                 if ( branchType == TMultiPartThumbBranch.ETHUMBBLX )
       
   252                 {
       
   253                     address = address & 0xFFFFFFFD;
       
   254                 }
       
   255 
       
   256                 base.StateData.SetPC( address, newInstructionSet );
       
   257                 branched = true;
       
   258             }
       
   259             else
       
   260             {
       
   261                 // Oops. We ran out of instructions. This shouldn't ever happen
       
   262                 // assuming that the P-HEADER's are synched properly.
       
   263                 throw new ETMException( "ERROR - synchronisation lost with P-HEADERS - 2nd THUMB BLX instruction missing" );
       
   264             }
       
   265 
       
   266             return branched;
       
   267         }
       
   268 
       
   269         private bool CheckForBranch( ETMInstruction aInstruction )
       
   270         {
       
   271             bool branched = false;
       
   272             TArmInstructionSet originalInstructionSet = base.StateData.CurrentInstructionSet;
       
   273             SymAddress originalAddress = new SymAddress( base.StateData.CurrentAddress.Address );
       
   274             //
       
   275             if ( base.StateData.LastBranch.IsKnown )
       
   276             {
       
   277                 uint address = base.StateData.CurrentAddress;
       
   278                 TArmInstructionSet instructionSet = base.StateData.CurrentInstructionSet;
       
   279                 //
       
   280                 if ( instructionSet == TArmInstructionSet.EARM )
       
   281                 {
       
   282                     if ( iBranchMask_ARM_BOrBL.IsMatch( aInstruction ) )
       
   283                     {
       
   284                         // 1110 101 0 111111111111111111111101
       
   285                         int offset = SignExtend24BitTo32BitARM( aInstruction & 0x00FFFFFF );
       
   286                         base.StateData.SetPC( (uint) ( address + offset ) );
       
   287                         branched = true;
       
   288                     }
       
   289                     else if ( iBranchMask_ARM_BLX_BranchToThumb.IsMatch( aInstruction ) )
       
   290                     {
       
   291                         // TODO: verify this - no data to test at the moment
       
   292                         int offset = SignExtend24BitTo32BitARM( aInstruction & 0x00FFFFFF );
       
   293                         base.StateData.SetPC( (uint) ( address + offset ), TArmInstructionSet.ETHUMB );
       
   294                         branched = true;
       
   295                     }
       
   296                 }
       
   297                 else if ( instructionSet == TArmInstructionSet.ETHUMB )
       
   298                 {
       
   299                     if ( iBranchMask_THUMB_B1.IsMatch( aInstruction ) )
       
   300                     {
       
   301                         //  15 14 13 12   11 -> 8    7    ->      0
       
   302                         // -----------------------------------------
       
   303                         //   1  1  0  1     cond     signed_immed_8
       
   304                         int offset = SignExtend8BitTo32BitTHUMB( aInstruction & 0xFF );
       
   305                         base.StateData.SetPC( (uint) ( address + offset ) );
       
   306                         branched = true;
       
   307                     }
       
   308                     else if ( iBranchMask_THUMB_B2.IsMatch( aInstruction ) )
       
   309                     {
       
   310                         //  15 14 13 12 11   10        ->         0
       
   311                         // -----------------------------------------
       
   312                         //   1  1  0  1  1       signed_immed_11
       
   313                         int offset = SignExtend11BitTo32BitTHUMB( aInstruction & 0x7FF );
       
   314                         base.StateData.SetPC( (uint) ( address + offset ) );
       
   315                         branched = true;
       
   316                     }
       
   317                     else
       
   318                     {
       
   319                         ETMInstruction inst1 = base.StateData.LastInstruction;
       
   320                         bool inst1Match = iBranchMask_THUMB_BLX_Part1.IsMatch( inst1.AIRawValue );
       
   321                         ETMInstruction inst2 = aInstruction;
       
   322                         bool inst2Match = iBranchMask_THUMB_BLX_Part2.IsMatch( inst2.AIRawValue );
       
   323                         //
       
   324                         if ( inst1Match && inst2Match )
       
   325                         {
       
   326                             branched = HandleTHUMBMultiInstructionBranch( inst1.AIRawValue, inst2.AIRawValue );
       
   327                             System.Diagnostics.Debug.Assert( branched == true );
       
   328                         }
       
   329                     }
       
   330                 }
       
   331                 else
       
   332                 {
       
   333                     throw new NotSupportedException();
       
   334                 }
       
   335             }
       
   336             if ( branched )
       
   337             {
       
   338                 base.StateData.IncrementProcessedInstructionCounter();
       
   339                 TraceDirectBranch( originalAddress, originalInstructionSet, base.StateData.CurrentAddress, base.StateData.CurrentInstructionSet );
       
   340             }
       
   341 
       
   342             // Always cache the last processed instruction
       
   343             base.StateData.LastInstruction = aInstruction;
       
   344             return branched;
       
   345         }
       
   346 
       
   347         private void TraceDirectBranch( SymAddress aOriginalAddress, TArmInstructionSet aOriginalISet, SymAddress aNewAddress, TArmInstructionSet aNewISet )
       
   348         {
       
   349             StringBuilder lines = new StringBuilder();
       
   350             lines.AppendLine( "   BRANCH-D" );
       
   351             //
       
   352             if ( base.StateData.LastBranch.IsKnown )
       
   353             {
       
   354                 lines.AppendLine( string.Format( "       from: {0} 0x{1:x8} {2}", ETMDecodeState.MakeInstructionSetPrefix( aOriginalISet ), aOriginalAddress, StateData.Engine.LookUpSymbol( aOriginalAddress ) ) );
       
   355                 lines.AppendLine( string.Format( "         to: {0} 0x{1:x8} {2}", ETMDecodeState.MakeInstructionSetPrefix( aNewISet ), aNewAddress, StateData.Engine.LookUpSymbol( aNewAddress ) ) );
       
   356             }
       
   357             else
       
   358             {
       
   359             }
       
   360             //
       
   361             base.Trace( lines.ToString() );
       
   362         }
       
   363 
       
   364         #region Utilities
       
   365         private static string TraceAtomTypeName( ETMPcktPHeaderBase.TAtomType aType )
       
   366         {
       
   367             switch ( aType )
       
   368             {
       
   369             default:
       
   370             case ETMPcktPHeaderBase.TAtomType.EAtomNotApplicable:
       
   371                 return "        ";
       
   372             case ETMPcktPHeaderBase.TAtomType.EAtomE_Passed:
       
   373                 return "  PASS  ";
       
   374             case ETMPcktPHeaderBase.TAtomType.EAtomN_Failed:
       
   375                 return "* FAIL *";
       
   376             case ETMPcktPHeaderBase.TAtomType.EAtomW_CycleBoundary:
       
   377                 return " CYBNDR ";
       
   378             }
       
   379         }
       
   380 
       
   381         private void TraceAtom( ETMPcktPHeaderBase.TAtomType aType, ETMInstruction aInstruction )
       
   382         {
       
   383             string atomTypeName = TraceAtomTypeName( aType );
       
   384             //
       
   385             StringBuilder text = new StringBuilder();
       
   386             text.AppendFormat( "{0}   0x{1}:    {2}         {3}",
       
   387                 base.StateData.NumberOfProcessedInstructions.ToString().PadLeft( 6, ' ' ),
       
   388                 base.StateData.CurrentAddress.AddressHex,
       
   389                 base.StateData.CurrentAddress.AddressBinary,
       
   390                 atomTypeName
       
   391                 );
       
   392             //
       
   393             if ( base.StateData.LastBranch.IsKnown )
       
   394             {
       
   395                 string disasm = aInstruction.ToString();
       
   396                 text.Append( "    " + disasm );
       
   397             }
       
   398             //
       
   399             base.Trace( text.ToString() );
       
   400         }
       
   401 
       
   402         private static int SignExtend24BitTo32BitARM( uint aImmediate )
       
   403         {
       
   404             int offset;
       
   405             //
       
   406             unchecked
       
   407             {
       
   408                 if ( ( aImmediate & 0x00800000 ) == 0x00800000 )
       
   409                 {
       
   410                     offset = (int) ( 0xff000000 | aImmediate );
       
   411                 }
       
   412                 else
       
   413                 {
       
   414                     offset = (int) aImmediate;
       
   415                 }
       
   416             }
       
   417             //
       
   418             offset <<= 2;
       
   419             offset += 8; // pipeline
       
   420             return offset;
       
   421         }
       
   422 
       
   423         private static int SignExtend11BitTo32BitTHUMB( uint aImmediate )
       
   424         {
       
   425             int offset = SignExtend11BitTo32BitTHUMB( aImmediate, 1 );
       
   426             offset += 4; // pipeline
       
   427             return offset;
       
   428         }
       
   429 
       
   430         private static int SignExtend11BitTo32BitTHUMB( uint aImmediate, int aLeftShiftCount )
       
   431         {
       
   432             int offset;
       
   433             //
       
   434             unchecked
       
   435             {
       
   436                 //  10  9  8  7  6  5  4  3  2  1  0
       
   437                 // ----------------------------------
       
   438                 //   1  0  0  0  0  0  0  0  0  0  0
       
   439                 if ( ( aImmediate & 0x00000400 ) == 0x00000400 )
       
   440                 {
       
   441                     // 11111111111111111111100000000000
       
   442                     //                      10000000000
       
   443                     offset = (int) ( 0xFFFFF800 | aImmediate );
       
   444                 }
       
   445                 else
       
   446                 {
       
   447                     offset = (int) aImmediate;
       
   448                 }
       
   449             }
       
   450             //
       
   451             offset <<= aLeftShiftCount;
       
   452             return offset;
       
   453         }
       
   454 
       
   455         private static int SignExtend8BitTo32BitTHUMB( uint aImmediate )
       
   456         {
       
   457             int offset; 
       
   458             //
       
   459             unchecked
       
   460             {
       
   461                 //  7  6  5  4  3  2  1  0
       
   462                 // ------------------------
       
   463                 //  1  0  0  0  0  0  0  0
       
   464                 if ( ( aImmediate & 0x00000080 ) == 0x00000080 )
       
   465                 {
       
   466                     // 11111111111111111111111100000000
       
   467                     //                         10000000
       
   468                     offset = (int) ( 0xFFFFFF00 | aImmediate );
       
   469                 }
       
   470                 else
       
   471                 {
       
   472                     offset = (int) aImmediate;
       
   473                 }
       
   474             }
       
   475             //
       
   476             offset <<= 1;
       
   477             offset += 4; // pipeline
       
   478             return offset;
       
   479         }
       
   480         #endregion
       
   481 
       
   482         #endregion
       
   483 
       
   484         #region From System.Object
       
   485         #endregion
       
   486 
       
   487         #region Data members
       
   488         private static readonly SymMask iBranchMask_ARM_BOrBL;
       
   489         private static readonly SymMask iBranchMask_ARM_BLX_BranchToThumb;
       
   490         private static readonly SymMask iBranchMask_THUMB_B1;
       
   491         private static readonly SymMask iBranchMask_THUMB_B2;
       
   492         private static readonly SymMask iBranchMask_THUMB_BLX_Part1;
       
   493         private static readonly SymMask iBranchMask_THUMB_BLX_Part2;
       
   494         #endregion
       
   495     }
       
   496 }