{**************************************************************************************************} { } { Project JEDI Code Library (JCL) } { } { The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); } { you may not use this file except in compliance with the License. You may obtain a copy of the } { License at http://www.mozilla.org/MPL/ } { } { Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF } { ANY KIND, either express or implied. See the License for the specific language governing rights } { and limitations under the License. } { } { The Original Code is JclCIL.pas. } { } { The Initial Developer of the Original Code is Flier Lu (). } { Portions created by Flier Lu are Copyright (C) Flier Lu. All Rights Reserved. } { } { Contributors: } { Flier Lu (flier) } { Robert Marquardt (marquardt) } { Robert Rossmair (rrossmair) } { Olivier Sannier (obones) } { Petr Vones (pvones) } { } {**************************************************************************************************} { } { Microsoft .Net CIL Instruction Set information support routines and classes. } { } {**************************************************************************************************} { } { Last modified: $Date:: 2009-09-12 22:52:07 +0200 (sam., 12 sept. 2009) $ } { Revision: $Rev:: 3007 $ } { Author: $Author:: outchy $ } { } {**************************************************************************************************} unit JclCIL; interface {$I jcl.inc} uses {$IFDEF UNITVERSIONING} JclUnitVersioning, {$ENDIF UNITVERSIONING} {$IFDEF MSWINDOWS} Windows, {$ENDIF MSWINDOWS} Classes, SysUtils, {$IFDEF HAS_UNIT_CONTNRS} Contnrs, {$ENDIF HAS_UNIT_CONTNRS} JclBase, JclSysUtils, JclMetadata; type TJclOpCode = (opNop, opBreak, opLdArg_0, opLdArg_1, opLdArg_2, opLdArg_3, opLdLoc_0, opLdLoc_1, opLdLoc_2, opLdLoc_3, opStLoc_0, opStLoc_1, opStLoc_2, opStLoc_3, opldArg_s, opLdArga_s, opStArg_s, opLdLoc_s, opLdLoca_s, opStLoc_s, opLdNull, opLdc_I4_M1, opLdc_I4_0, opLdc_I4_1, opLdc_I4_2, opLdc_I4_3, opLdc_I4_4, opLdc_I4_5, opLdc_I4_6, opLdc_I4_7, opLdc_I4_8, opLdc_I4_s, opLdc_i4, opLdc_i8, opLdc_r4, opLdc_r8, opUnused49, opDup, opPop, opJmp, opCall, opCalli, opRet, opBr_s, opBrFalse_s, opBrTrue_s, opBeq_s, opBge_s, opBgt_s, opBle_s, opBlt_s, opBne_un_s, opBge_un_s, opBgt_un_s, opBle_un_s, opBlt_un_s, opBr, opBrFalse, opBrTrue, opBeq, opBge, opBgt, opBle, opBlt, opBne_un, opBge_un, opBgt_un, opBle_un, opBlt_un, opSwitch, opLdInd_i1, opLdInd_i2, opLdInd_u1, opLdInd_u2, opLdInd_i4, opLdInd_u4, opLdInd_i8, opLdInd_i, opLdInd_r4, opLdInd_r8, opLdInd_ref, opStInd_ref, opStInd_i1, opStInd_i2, opStInd_i4, opStInd_i8, opStInd_r4, opStInd_r8, opAdd, opSub, opMul, opDiv, opDiv_un, opRem, opRem_un, opAnd, opOr, opXor, opShl, opShr, opShr_un, opNeg, opNot, opConv_i1, opConv_i2, opConv_i4, opConv_i8, opConv_r4, opConv_r8, opConv_u4, opConv_u8, opCallVirt, opCpObj, opLdObj, opLdStr, opNewObj, opCastClass, opIsInst, opConv_r_un, opUnused58, opUnused1, opUnbox, opThrow, opLdFld, opLdFlda, opStFld, opLdsFld, opLdsFlda, opStsFld, opStObj, opConv_ovf_i1_un, opConv_ovf_i2_un, opConv_ovf_i4_un, opConv_ovf_i8_un, opConv_ovf_u1_un, opConv_ovf_u2_un, opConv_ovf_u4_un, opConv_ovf_u8_un, opConv_ovf_i_un, opConv_ovf_u_un, opBox, opNewArr, opLdLen, opLdElema, opLdElem_i1, opLdElem_u1, opLdElem_i2, opLdElem_u2, opLdElem_i4, opLdElem_u4, opLdElem_i8, opLdElem_i, opLdElem_r4, opLdElem_r8, opLdElem_ref, opStElem_i, opStElem_i1, opStElem_i2, opStElem_i4, opStElem_i8, opStElem_r4, opStElem_r8, opStElem_ref, opUnused2, opUnused3, opUnused4, opUnused5, opUnused6, opUnused7, opUnused8, opUnused9, opUnused10, opUnused11, opUnused12, opUnused13, opUnused14, opUnused15, opUnused16, opUnused17, opConv_ovf_i1, opConv_ovf_u1, opConv_ovf_i2, opConv_ovf_u2, opConv_ovf_i4, opConv_ovf_u4, opConv_ovf_i8, opConv_ovf_u8, opUnused50, opUnused18, opUnused19, opUnused20, opUnused21, opUnused22, opUnused23, opRefAnyVal, opCkFinite, opUnused24, opUnused25, opMkRefAny, opUnused59, opUnused60, opUnused61, opUnused62, opUnused63, opUnused64, opUnused65, opUnused66, opUnused67, opLdToken, opConv_u2, opConv_u1, opConv_i, opConv_ovf_i, opConv_ovf_u, opAdd_ovf, opAdd_ovf_un, opMul_ovf, opMul_ovf_un, opSub_ovf, opSub_ovf_un, opEndFinally, opLeave, opLeave_s, opStInd_i, opConv_u, opUnused26, opUnused27, opUnused28, opUnused29, opUnused30, opUnused31, opUnused32, opUnused33, opUnused34, opUnused35, opUnused36, opUnused37, opUnused38, opUnused39, opUnused40, opUnused41, opUnused42, opUnused43, opUnused44, opUnused45, opUnused46, opUnused47, opUnused48, opPrefix7, opPrefix6, opPrefix5, opPrefix4, opPrefix3, opPrefix2, opPrefix1, opPrefixRef, opArgLlist, opCeq, opCgt, opCgt_un, opClt, opClt_un, opLdFtn, opLdVirtFtn, optUnused56, opLdArg, opLdArga, opStArg, opLdLoc, opLdLoca, opStLoc, opLocalLoc, opUnused57, opEndFilter, opUnaligned, opVolatile, opTail, opInitObj, opUnused68, opCpBlk, opInitBlk, opUnused69, opRethrow, opUnused51, opSizeOf, opRefAnyType, opUnused52, opUnused53, opUnused54, opUnused55, opUnused70); TJclInstructionDumpILOption = (doLineNo, doRawBytes, doIL, doTokenValue, doComment); TJclInstructionDumpILOptions = set of TJclInstructionDumpILOption; TJclInstructionParamType = (ptVoid, ptI1, ptI2, ptI4, ptI8, ptU1, ptU2, ptU4, ptU8, ptR4, ptR8, ptToken, ptSOff, ptLOff, ptArray); const InstructionDumpILAllOption = [doLineNo, doRawBytes, doIL, doTokenValue, doComment]; type TJclClrILGenerator = class; TJclInstruction = class(TObject) private FOpCode: TJclOpCode; FOffset: DWORD; FParam: Variant; FOwner: TJclClrILGenerator; function GetWideOpCode: Boolean; function GetRealOpCode: Byte; function GetName: string; function GetFullName: string; function GetDescription: string; function GetParamType: TJclInstructionParamType; function FormatLabel(Offset: Integer): string; protected function GetSize: DWORD; virtual; function DumpILOption(Option: TJclInstructionDumpILOption): string; virtual; public constructor Create(AOwner: TJclClrILGenerator; AOpCode: TJclOpCode); procedure Load(Stream: TStream); virtual; procedure Save(Stream: TStream); virtual; function DumpIL(Options: TJclInstructionDumpILOptions = [doIL]): string; property Owner: TJclClrILGenerator read FOwner; property OpCode: TJclOpCode read FOpCode; property WideOpCode: Boolean read GetWideOpCode; property RealOpCode: Byte read GetRealOpCode; property Param: Variant read FParam write FParam; property ParamType: TJclInstructionParamType read GetParamType; property Name: string read GetName; property FullName: string read GetFullName; property Description: string read GetDescription; property Size: DWORD read GetSize; property Offset: DWORD read FOffset; end; TJclUnaryInstruction = class(TJclInstruction); TJclBinaryInstruction = class(TJclInstruction); TJclClrILGenerator = class(TObject) private FMethod: TJclClrMethodBody; FInstructions: TObjectList; function GetInstructionCount: Integer; function GetInstruction(const Idx: Integer): TJclInstruction; public constructor Create(AMethod: TJclClrMethodBody = nil); destructor Destroy; override; function DumpIL(Options: TJclInstructionDumpILOptions): string; property Method: TJclClrMethodBody read FMethod; property Instructions[const Idx: Integer]: TJclInstruction read GetInstruction; property InstructionCount: Integer read GetInstructionCount; end; EJclCliInstructionError = class(EJclError); EJclCliInstructionStreamInvalid = class(EJclCliInstructionError); {$IFDEF UNITVERSIONING} const UnitVersioning: TUnitVersionInfo = ( RCSfile: '$URL: https://jcl.svn.sourceforge.net/svnroot/jcl/tags/JCL-2.1-Build3536/jcl/source/windows/JclCIL.pas $'; Revision: '$Revision: 3007 $'; Date: '$Date: 2009-09-12 22:52:07 +0200 (sam., 12 sept. 2009) $'; LogPath: 'JCL\source\windows'; Extra: ''; Data: nil ); {$ENDIF UNITVERSIONING} implementation uses {$IFDEF HAS_UNIT_VARIANTS} Variants, {$ENDIF HAS_UNIT_VARIANTS} JclCLR, JclPeImage, JclStrings, JclResources; type TJclOpCodeInfoType = (itName, itFullName, itDescription); const STP1 = $FE; OpCodeInfos: array [TJclOpCode, TJclOpCodeInfoType] of PResStringRec = ( (@RsCILNamenop, @RsCILCmdnop, @RsCILDescrnop), (@RsCILNamebreak, @RsCILCmdbreak, @RsCILDescrbreak), (@RsCILNameldarg0, @RsCILCmdldarg0, @RsCILDescrldarg0), (@RsCILNameldarg1, @RsCILCmdldarg1, @RsCILDescrldarg1), (@RsCILNameldarg2, @RsCILCmdldarg2, @RsCILDescrldarg2), (@RsCILNameldarg3, @RsCILCmdldarg3, @RsCILDescrldarg3), (@RsCILNameldloc0, @RsCILCmdldloc0, @RsCILDescrldloc0), (@RsCILNameldloc1, @RsCILCmdldloc1, @RsCILDescrldloc1), (@RsCILNameldloc2, @RsCILCmdldloc2, @RsCILDescrldloc2), (@RsCILNameldloc3, @RsCILCmdldloc3, @RsCILDescrldloc3), (@RsCILNamestloc0, @RsCILCmdstloc0, @RsCILDescrstloc0), (@RsCILNamestloc1, @RsCILCmdstloc1, @RsCILDescrstloc1), (@RsCILNamestloc2, @RsCILCmdstloc2, @RsCILDescrstloc2), (@RsCILNamestloc3, @RsCILCmdstloc3, @RsCILDescrstloc3), (@RsCILNameldargs, @RsCILCmdldargs, @RsCILDescrldargs), (@RsCILNameldargas, @RsCILCmdldargas, @RsCILDescrldargas), (@RsCILNamestargs, @RsCILCmdstargs, @RsCILDescrstargs), (@RsCILNameldlocs, @RsCILCmdldlocs, @RsCILDescrldlocs), (@RsCILNameldlocas, @RsCILCmdldlocas, @RsCILDescrldlocas), (@RsCILNamestlocs, @RsCILCmdstlocs, @RsCILDescrstlocs), (@RsCILNameldnull, @RsCILCmdldnull, @RsCILDescrldnull), (@RsCILNameldci4m1, @RsCILCmdldci4m1, @RsCILDescrldci4m1), (@RsCILNameldci40, @RsCILCmdldci40, @RsCILDescrldci40), (@RsCILNameldci41, @RsCILCmdldci41, @RsCILDescrldci41), (@RsCILNameldci42, @RsCILCmdldci42, @RsCILDescrldci42), (@RsCILNameldci43, @RsCILCmdldci43, @RsCILDescrldci43), (@RsCILNameldci44, @RsCILCmdldci44, @RsCILDescrldci44), (@RsCILNameldci45, @RsCILCmdldci45, @RsCILDescrldci45), (@RsCILNameldci46, @RsCILCmdldci46, @RsCILDescrldci46), (@RsCILNameldci47, @RsCILCmdldci47, @RsCILDescrldci47), (@RsCILNameldci48, @RsCILCmdldci48, @RsCILDescrldci48), (@RsCILNameldci4s, @RsCILCmdldci4s, @RsCILDescrldci4s), (@RsCILNameldci4, @RsCILCmdldci4, @RsCILDescrldci4), (@RsCILNameldci8, @RsCILCmdldci8, @RsCILDescrldci8), (@RsCILNameldcr4, @RsCILCmdldcr4, @RsCILDescrldcr4), (@RsCILNameldcr8, @RsCILCmdldcr8, @RsCILDescrldcr8), (@RsCILNameunused1, @RsCILCmdunused1, @RsCILDescrunused1), (@RsCILNamedup, @RsCILCmddup, @RsCILDescrdup), (@RsCILNamepop, @RsCILCmdpop, @RsCILDescrpop), (@RsCILNamejmp, @RsCILCmdjmp, @RsCILDescrjmp), (@RsCILNamecall, @RsCILCmdcall, @RsCILDescrcall), (@RsCILNamecalli, @RsCILCmdcalli, @RsCILDescrcalli), (@RsCILNameret, @RsCILCmdret, @RsCILDescrret), (@RsCILNamebrs, @RsCILCmdbrs, @RsCILDescrbrs), (@RsCILNamebrfalses, @RsCILCmdbrfalses, @RsCILDescrbrfalses), (@RsCILNamebrtrues, @RsCILCmdbrtrues, @RsCILDescrbrtrues), (@RsCILNamebeqs, @RsCILCmdbeqs, @RsCILDescrbeqs), (@RsCILNamebges, @RsCILCmdbges, @RsCILDescrbges), (@RsCILNamebgts, @RsCILCmdbgts, @RsCILDescrbgts), (@RsCILNamebles, @RsCILCmdbles, @RsCILDescrbles), (@RsCILNameblts, @RsCILCmdblts, @RsCILDescrblts), (@RsCILNamebneuns, @RsCILCmdbneuns, @RsCILDescrbneuns), (@RsCILNamebgeuns, @RsCILCmdbgeuns, @RsCILDescrbgeuns), (@RsCILNamebgtuns, @RsCILCmdbgtuns, @RsCILDescrbgtuns), (@RsCILNamebleuns, @RsCILCmdbleuns, @RsCILDescrbleuns), (@RsCILNamebltuns, @RsCILCmdbltuns, @RsCILDescrbltuns), (@RsCILNamebr, @RsCILCmdbr, @RsCILDescrbr), (@RsCILNamebrfalse, @RsCILCmdbrfalse, @RsCILDescrbrfalse), (@RsCILNamebrtrue, @RsCILCmdbrtrue, @RsCILDescrbrtrue), (@RsCILNamebeq, @RsCILCmdbeq, @RsCILDescrbeq), (@RsCILNamebge, @RsCILCmdbge, @RsCILDescrbge), (@RsCILNamebgt, @RsCILCmdbgt, @RsCILDescrbgt), (@RsCILNameble, @RsCILCmdble, @RsCILDescrble), (@RsCILNameblt, @RsCILCmdblt, @RsCILDescrblt), (@RsCILNamebneun, @RsCILCmdbneun, @RsCILDescrbneun), (@RsCILNamebgeun, @RsCILCmdbgeun, @RsCILDescrbgeun), (@RsCILNamebgtun, @RsCILCmdbgtun, @RsCILDescrbgtun), (@RsCILNamebleun, @RsCILCmdbleun, @RsCILDescrbleun), (@RsCILNamebltun, @RsCILCmdbltun, @RsCILDescrbltun), (@RsCILNameswitch, @RsCILCmdswitch, @RsCILDescrswitch), (@RsCILNameldindi1, @RsCILCmdldindi1, @RsCILDescrldindi1), (@RsCILNameldindu1, @RsCILCmdldindu1, @RsCILDescrldindu1), (@RsCILNameldindi2, @RsCILCmdldindi2, @RsCILDescrldindi2), (@RsCILNameldindu2, @RsCILCmdldindu2, @RsCILDescrldindu2), (@RsCILNameldindi4, @RsCILCmdldindi4, @RsCILDescrldindi4), (@RsCILNameldindu4, @RsCILCmdldindu4, @RsCILDescrldindu4), (@RsCILNameldindi8, @RsCILCmdldindi8, @RsCILDescrldindi8), (@RsCILNameldindi, @RsCILCmdldindi, @RsCILDescrldindi), (@RsCILNameldindr4, @RsCILCmdldindr4, @RsCILDescrldindr4), (@RsCILNameldindr8, @RsCILCmdldindr8, @RsCILDescrldindr8), (@RsCILNameldindref, @RsCILCmdldindref, @RsCILDescrldindref), (@RsCILNamestindref, @RsCILCmdstindref, @RsCILDescrstindref), (@RsCILNamestindi1, @RsCILCmdstindi1, @RsCILDescrstindi1), (@RsCILNamestindi2, @RsCILCmdstindi2, @RsCILDescrstindi2), (@RsCILNamestindi4, @RsCILCmdstindi4, @RsCILDescrstindi4), (@RsCILNamestindi8, @RsCILCmdstindi8, @RsCILDescrstindi8), (@RsCILNamestindr4, @RsCILCmdstindr4, @RsCILDescrstindr4), (@RsCILNamestindr8, @RsCILCmdstindr8, @RsCILDescrstindr8), (@RsCILNameadd, @RsCILCmdadd, @RsCILDescradd), (@RsCILNamesub, @RsCILCmdsub, @RsCILDescrsub), (@RsCILNamemul, @RsCILCmdmul, @RsCILDescrmul), (@RsCILNamediv, @RsCILCmddiv, @RsCILDescrdiv), (@RsCILNamedivun, @RsCILCmddivun, @RsCILDescrdivun), (@RsCILNamerem, @RsCILCmdrem, @RsCILDescrrem), (@RsCILNameremun, @RsCILCmdremun, @RsCILDescrremun), (@RsCILNameand, @RsCILCmdand, @RsCILDescrand), (@RsCILNameor, @RsCILCmdor, @RsCILDescror), (@RsCILNamexor, @RsCILCmdxor, @RsCILDescrxor), (@RsCILNameshl, @RsCILCmdshl, @RsCILDescrshl), (@RsCILNameshr, @RsCILCmdshr, @RsCILDescrshr), (@RsCILNameshrun, @RsCILCmdshrun, @RsCILDescrshrun), (@RsCILNameneg, @RsCILCmdneg, @RsCILDescrneg), (@RsCILNamenot, @RsCILCmdnot, @RsCILDescrnot), (@RsCILNameconvi1, @RsCILCmdconvi1, @RsCILDescrconvi1), (@RsCILNameconvi2, @RsCILCmdconvi2, @RsCILDescrconvi2), (@RsCILNameconvi4, @RsCILCmdconvi4, @RsCILDescrconvi4), (@RsCILNameconvi8, @RsCILCmdconvi8, @RsCILDescrconvi8), (@RsCILNameconvr4, @RsCILCmdconvr4, @RsCILDescrconvr4), (@RsCILNameconvr8, @RsCILCmdconvr8, @RsCILDescrconvr8), (@RsCILNameconvu4, @RsCILCmdconvu4, @RsCILDescrconvu4), (@RsCILNameconvu8, @RsCILCmdconvu8, @RsCILDescrconvu8), (@RsCILNamecallvirt, @RsCILCmdcallvirt, @RsCILDescrcallvirt), (@RsCILNamecpobj, @RsCILCmdcpobj, @RsCILDescrcpobj), (@RsCILNameldobj, @RsCILCmdldobj, @RsCILDescrldobj), (@RsCILNameldstr, @RsCILCmdldstr, @RsCILDescrldstr), (@RsCILNamenewobj, @RsCILCmdnewobj, @RsCILDescrnewobj), (@RsCILNamecastclass, @RsCILCmdcastclass, @RsCILDescrcastclass), (@RsCILNameisinst, @RsCILCmdisinst, @RsCILDescrisinst), (@RsCILNameconvrun, @RsCILCmdconvrun, @RsCILDescrconvrun), (@RsCILNameunused2, @RsCILCmdunused2, @RsCILDescrunused2), (@RsCILNameunused3, @RsCILCmdunused3, @RsCILDescrunused3), (@RsCILNameunbox, @RsCILCmdunbox, @RsCILDescrunbox), (@RsCILNamethrow, @RsCILCmdthrow, @RsCILDescrthrow), (@RsCILNameldfld, @RsCILCmdldfld, @RsCILDescrldfld), (@RsCILNameldflda, @RsCILCmdldflda, @RsCILDescrldflda), (@RsCILNamestfld, @RsCILCmdstfld, @RsCILDescrstfld), (@RsCILNameldsfld, @RsCILCmdldsfld, @RsCILDescrldsfld), (@RsCILNameldsflda, @RsCILCmdldsflda, @RsCILDescrldsflda), (@RsCILNamestsfld, @RsCILCmdstsfld, @RsCILDescrstsfld), (@RsCILNamestobj, @RsCILCmdstobj, @RsCILDescrstobj), (@RsCILNameconvovfi1un, @RsCILCmdconvovfi1un, @RsCILDescrconvovfi1un), (@RsCILNameconvovfi2un, @RsCILCmdconvovfi2un, @RsCILDescrconvovfi2un), (@RsCILNameconvovfi4un, @RsCILCmdconvovfi4un, @RsCILDescrconvovfi4un), (@RsCILNameconvovfi8un, @RsCILCmdconvovfi8un, @RsCILDescrconvovfi8un), (@RsCILNameconvovfu1un, @RsCILCmdconvovfu1un, @RsCILDescrconvovfu1un), (@RsCILNameconvovfu2un, @RsCILCmdconvovfu2un, @RsCILDescrconvovfu2un), (@RsCILNameconvovfu4un, @RsCILCmdconvovfu4un, @RsCILDescrconvovfu4un), (@RsCILNameconvovfu8un, @RsCILCmdconvovfu8un, @RsCILDescrconvovfu8un), (@RsCILNameconvovfiun, @RsCILCmdconvovfiun, @RsCILDescrconvovfiun), (@RsCILNameconvovfuun, @RsCILCmdconvovfuun, @RsCILDescrconvovfuun), (@RsCILNamebox, @RsCILCmdbox, @RsCILDescrbox), (@RsCILNamenewarr, @RsCILCmdnewarr, @RsCILDescrnewarr), (@RsCILNameldlen, @RsCILCmdldlen, @RsCILDescrldlen), (@RsCILNameldelema, @RsCILCmdldelema, @RsCILDescrldelema), (@RsCILNameldelemi1, @RsCILCmdldelemi1, @RsCILDescrldelemi1), (@RsCILNameldelemu1, @RsCILCmdldelemu1, @RsCILDescrldelemu1), (@RsCILNameldelemi2, @RsCILCmdldelemi2, @RsCILDescrldelemi2), (@RsCILNameldelemu2, @RsCILCmdldelemu2, @RsCILDescrldelemu2), (@RsCILNameldelemi4, @RsCILCmdldelemi4, @RsCILDescrldelemi4), (@RsCILNameldelemu4, @RsCILCmdldelemu4, @RsCILDescrldelemu4), (@RsCILNameldelemi8, @RsCILCmdldelemi8, @RsCILDescrldelemi8), (@RsCILNameldelemi, @RsCILCmdldelemi, @RsCILDescrldelemi), (@RsCILNameldelemr4, @RsCILCmdldelemr4, @RsCILDescrldelemr4), (@RsCILNameldelemr8, @RsCILCmdldelemr8, @RsCILDescrldelemr8), (@RsCILNameldelemref, @RsCILCmdldelemref, @RsCILDescrldelemref), (@RsCILNamestelemi, @RsCILCmdstelemi, @RsCILDescrstelemi), (@RsCILNamestelemi1, @RsCILCmdstelemi1, @RsCILDescrstelemi1), (@RsCILNamestelemi2, @RsCILCmdstelemi2, @RsCILDescrstelemi2), (@RsCILNamestelemi4, @RsCILCmdstelemi4, @RsCILDescrstelemi4), (@RsCILNamestelemi8, @RsCILCmdstelemi8, @RsCILDescrstelemi8), (@RsCILNamestelemr4, @RsCILCmdstelemr4, @RsCILDescrstelemr4), (@RsCILNamestelemr8, @RsCILCmdstelemr8, @RsCILDescrstelemr8), (@RsCILNamestelemref, @RsCILCmdstelemref, @RsCILDescrstelemref), (@RsCILNameunused4, @RsCILCmdunused4, @RsCILDescrunused4), (@RsCILNameunused5, @RsCILCmdunused5, @RsCILDescrunused5), (@RsCILNameunused6, @RsCILCmdunused6, @RsCILDescrunused6), (@RsCILNameunused7, @RsCILCmdunused7, @RsCILDescrunused7), (@RsCILNameunused8, @RsCILCmdunused8, @RsCILDescrunused8), (@RsCILNameunused9, @RsCILCmdunused9, @RsCILDescrunused9), (@RsCILNameunused10, @RsCILCmdunused10, @RsCILDescrunused10), (@RsCILNameunused11, @RsCILCmdunused11, @RsCILDescrunused11), (@RsCILNameunused12, @RsCILCmdunused12, @RsCILDescrunused12), (@RsCILNameunused13, @RsCILCmdunused13, @RsCILDescrunused13), (@RsCILNameunused14, @RsCILCmdunused14, @RsCILDescrunused14), (@RsCILNameunused15, @RsCILCmdunused15, @RsCILDescrunused15), (@RsCILNameunused16, @RsCILCmdunused16, @RsCILDescrunused16), (@RsCILNameunused17, @RsCILCmdunused17, @RsCILDescrunused17), (@RsCILNameunused18, @RsCILCmdunused18, @RsCILDescrunused18), (@RsCILNameunused19, @RsCILCmdunused19, @RsCILDescrunused19), (@RsCILNameconvovfi1, @RsCILCmdconvovfi1, @RsCILDescrconvovfi1), (@RsCILNameconvovfu1, @RsCILCmdconvovfu1, @RsCILDescrconvovfu1), (@RsCILNameconvovfi2, @RsCILCmdconvovfi2, @RsCILDescrconvovfi2), (@RsCILNameconvovfu2, @RsCILCmdconvovfu2, @RsCILDescrconvovfu2), (@RsCILNameconvovfi4, @RsCILCmdconvovfi4, @RsCILDescrconvovfi4), (@RsCILNameconvovfu4, @RsCILCmdconvovfu4, @RsCILDescrconvovfu4), (@RsCILNameconvovfi8, @RsCILCmdconvovfi8, @RsCILDescrconvovfi8), (@RsCILNameconvovfu8, @RsCILCmdconvovfu8, @RsCILDescrconvovfu8), (@RsCILNameunused20, @RsCILCmdunused20, @RsCILDescrunused20), (@RsCILNameunused21, @RsCILCmdunused21, @RsCILDescrunused21), (@RsCILNameunused22, @RsCILCmdunused22, @RsCILDescrunused22), (@RsCILNameunused23, @RsCILCmdunused23, @RsCILDescrunused23), (@RsCILNameunused24, @RsCILCmdunused24, @RsCILDescrunused24), (@RsCILNameunused25, @RsCILCmdunused25, @RsCILDescrunused25), (@RsCILNameunused26, @RsCILCmdunused26, @RsCILDescrunused26), (@RsCILNamerefanyval, @RsCILCmdrefanyval, @RsCILDescrrefanyval), (@RsCILNameckfinite, @RsCILCmdckfinite, @RsCILDescrckfinite), (@RsCILNameunused27, @RsCILCmdunused27, @RsCILDescrunused27), (@RsCILNameunused28, @RsCILCmdunused28, @RsCILDescrunused28), (@RsCILNamemkrefany, @RsCILCmdmkrefany, @RsCILDescrmkrefany), (@RsCILNameunused29, @RsCILCmdunused29, @RsCILDescrunused29), (@RsCILNameunused30, @RsCILCmdunused30, @RsCILDescrunused30), (@RsCILNameunused31, @RsCILCmdunused31, @RsCILDescrunused31), (@RsCILNameunused32, @RsCILCmdunused32, @RsCILDescrunused32), (@RsCILNameunused33, @RsCILCmdunused33, @RsCILDescrunused33), (@RsCILNameunused34, @RsCILCmdunused34, @RsCILDescrunused34), (@RsCILNameunused35, @RsCILCmdunused35, @RsCILDescrunused35), (@RsCILNameunused36, @RsCILCmdunused36, @RsCILDescrunused36), (@RsCILNameunused37, @RsCILCmdunused37, @RsCILDescrunused37), (@RsCILNameldtoken, @RsCILCmdldtoken, @RsCILDescrldtoken), (@RsCILNameconvu2, @RsCILCmdconvu2, @RsCILDescrconvu2), (@RsCILNameconvu1, @RsCILCmdconvu1, @RsCILDescrconvu1), (@RsCILNameconvi, @RsCILCmdconvi, @RsCILDescrconvi), (@RsCILNameconvovfi, @RsCILCmdconvovfi, @RsCILDescrconvovfi), (@RsCILNameconvovfu, @RsCILCmdconvovfu, @RsCILDescrconvovfu), (@RsCILNameaddovf, @RsCILCmdaddovf, @RsCILDescraddovf), (@RsCILNameaddovfun, @RsCILCmdaddovfun, @RsCILDescraddovfun), (@RsCILNamemulovf, @RsCILCmdmulovf, @RsCILDescrmulovf), (@RsCILNamemulovfun, @RsCILCmdmulovfun, @RsCILDescrmulovfun), (@RsCILNamesubovf, @RsCILCmdsubovf, @RsCILDescrsubovf), (@RsCILNamesubovfun, @RsCILCmdsubovfun, @RsCILDescrsubovfun), (@RsCILNameendfinally, @RsCILCmdendfinally, @RsCILDescrendfinally), (@RsCILNameleave, @RsCILCmdleave, @RsCILDescrleave), (@RsCILNameleaves, @RsCILCmdleaves, @RsCILDescrleaves), (@RsCILNamestindi, @RsCILCmdstindi, @RsCILDescrstindi), (@RsCILNameconvu, @RsCILCmdconvu, @RsCILDescrconvu), (@RsCILNameunused38, @RsCILCmdunused38, @RsCILDescrunused38), (@RsCILNameunused39, @RsCILCmdunused39, @RsCILDescrunused39), (@RsCILNameunused40, @RsCILCmdunused40, @RsCILDescrunused40), (@RsCILNameunused41, @RsCILCmdunused41, @RsCILDescrunused41), (@RsCILNameunused42, @RsCILCmdunused42, @RsCILDescrunused42), (@RsCILNameunused43, @RsCILCmdunused43, @RsCILDescrunused43), (@RsCILNameunused44, @RsCILCmdunused44, @RsCILDescrunused44), (@RsCILNameunused45, @RsCILCmdunused45, @RsCILDescrunused45), (@RsCILNameunused46, @RsCILCmdunused46, @RsCILDescrunused46), (@RsCILNameunused47, @RsCILCmdunused47, @RsCILDescrunused47), (@RsCILNameunused48, @RsCILCmdunused48, @RsCILDescrunused48), (@RsCILNameunused49, @RsCILCmdunused49, @RsCILDescrunused49), (@RsCILNameunused50, @RsCILCmdunused50, @RsCILDescrunused50), (@RsCILNameunused51, @RsCILCmdunused51, @RsCILDescrunused51), (@RsCILNameunused52, @RsCILCmdunused52, @RsCILDescrunused52), (@RsCILNameunused53, @RsCILCmdunused53, @RsCILDescrunused53), (@RsCILNameunused54, @RsCILCmdunused54, @RsCILDescrunused54), (@RsCILNameunused55, @RsCILCmdunused55, @RsCILDescrunused55), (@RsCILNameunused56, @RsCILCmdunused56, @RsCILDescrunused56), (@RsCILNameunused57, @RsCILCmdunused57, @RsCILDescrunused57), (@RsCILNameunused58, @RsCILCmdunused58, @RsCILDescrunused58), (@RsCILNameunused59, @RsCILCmdunused59, @RsCILDescrunused59), (@RsCILNameunused60, @RsCILCmdunused60, @RsCILDescrunused60), (@RsCILNameprefix7, @RsCILCmdprefix7, @RsCILDescrprefix7), (@RsCILNameprefix6, @RsCILCmdprefix6, @RsCILDescrprefix6), (@RsCILNameprefix5, @RsCILCmdprefix5, @RsCILDescrprefix5), (@RsCILNameprefix4, @RsCILCmdprefix4, @RsCILDescrprefix4), (@RsCILNameprefix3, @RsCILCmdprefix3, @RsCILDescrprefix3), (@RsCILNameprefix2, @RsCILCmdprefix2, @RsCILDescrprefix2), (@RsCILNameprefix1, @RsCILCmdprefix1, @RsCILDescrprefix1), (@RsCILNameprefixref, @RsCILCmdprefixref, @RsCILDescrprefixref), (@RsCILNamearglist, @RsCILCmdarglist, @RsCILDescrarglist), (@RsCILNameceq, @RsCILCmdceq, @RsCILDescrceq), (@RsCILNamecgt, @RsCILCmdcgt, @RsCILDescrcgt), (@RsCILNamecgtun, @RsCILCmdcgtun, @RsCILDescrcgtun), (@RsCILNameclt, @RsCILCmdclt, @RsCILDescrclt), (@RsCILNamecltun, @RsCILCmdcltun, @RsCILDescrcltun), (@RsCILNameldftn, @RsCILCmdldftn, @RsCILDescrldftn), (@RsCILNameldvirtftn, @RsCILCmdldvirtftn, @RsCILDescrldvirtftn), (@RsCILNameunused61, @RsCILCmdunused61, @RsCILDescrunused61), (@RsCILNameldarg, @RsCILCmdldarg, @RsCILDescrldarg), (@RsCILNameldarga, @RsCILCmdldarga, @RsCILDescrldarga), (@RsCILNamestarg, @RsCILCmdstarg, @RsCILDescrstarg), (@RsCILNameldloc, @RsCILCmdldloc, @RsCILDescrldloc), (@RsCILNameldloca, @RsCILCmdldloca, @RsCILDescrldloca), (@RsCILNamestloc, @RsCILCmdstloc, @RsCILDescrstloc), (@RsCILNamelocalloc, @RsCILCmdlocalloc, @RsCILDescrlocalloc), (@RsCILNameunused62, @RsCILCmdunused62, @RsCILDescrunused62), (@RsCILNameendfilter, @RsCILCmdendfilter, @RsCILDescrendfilter), (@RsCILNameunaligned, @RsCILCmdunaligned, @RsCILDescrunaligned), (@RsCILNamevolatile, @RsCILCmdvolatile, @RsCILDescrvolatile), (@RsCILNametail, @RsCILCmdtail, @RsCILDescrtail), (@RsCILNameinitobj, @RsCILCmdinitobj, @RsCILDescrinitobj), (@RsCILNameunused63, @RsCILCmdunused63, @RsCILDescrunused63), (@RsCILNamecpblk, @RsCILCmdcpblk, @RsCILDescrcpblk), (@RsCILNameinitblk, @RsCILCmdinitblk, @RsCILDescrinitblk), (@RsCILNameunused64, @RsCILCmdunused64, @RsCILDescrunused64), (@RsCILNamerethrow, @RsCILCmdrethrow, @RsCILDescrrethrow), (@RsCILNameunused65, @RsCILCmdunused65, @RsCILDescrunused65), (@RsCILNamesizeof, @RsCILCmdsizeof, @RsCILDescrsizeof), (@RsCILNamerefanytype, @RsCILCmdrefanytype, @RsCILDescrrefanytype), (@RsCILNameunused66, @RsCILCmdunused66, @RsCILDescrunused66), (@RsCILNameunused67, @RsCILCmdunused67, @RsCILDescrunused67), (@RsCILNameunused68, @RsCILCmdunused68, @RsCILDescrunused68), (@RsCILNameunused69, @RsCILCmdunused69, @RsCILDescrunused69), (@RsCILNameunused70, @RsCILCmdunused70, @RsCILDescrunused70) ); OpCodeParamTypes: array [TJclOpCode] of TJclInstructionParamType = (ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {00} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptU1, ptU1, {08} ptU1, ptU1, ptU1, ptU1, ptVoid, ptVoid, ptVoid, ptVoid, {10} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptI1, {18} ptI4, ptI8, ptR4, ptR8, ptVoid, ptVoid, ptVoid, ptToken, {20} ptToken, ptVoid, ptVoid, ptSOff, ptSOff, ptSOff, ptSOff, ptSOff, {28} ptSOff, ptSOff, ptSOff, ptSOff, ptSOff, ptSOff, ptSOff, ptSOff, {30} ptLOff, ptLOff, ptLOff, ptLOff, ptLOff, ptLOff, ptLOff, ptLOff, {38} ptLOff, ptLOff, ptLOff, ptLOff, ptLOff, ptVoid, ptVoid, ptVoid, {40} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {48} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {50} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {58} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {60} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptToken, {68} ptToken, ptToken, ptToken, ptToken, ptToken, ptToken, ptVoid, ptVoid, {70} ptVoid, ptToken, ptVoid, ptToken, ptToken, ptToken, ptToken, ptToken, {78} ptToken, ptToken, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {80} ptVoid, ptVoid, ptVoid, ptVoid, ptToken, ptToken, ptVoid, ptToken, {88} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {90} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {98} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {A0} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {A8} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {B0} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {B8} ptVoid, ptVoid, ptToken, ptVoid, ptVoid, ptVoid, ptToken, ptVoid, {C0} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {C8} ptToken, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {D0} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptI4, ptI1, ptVoid, {D8} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {E0} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {E8} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {F0} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, {F8} ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptVoid, ptToken, ptToken, {00} ptVoid, ptU2, ptU2, ptU2, ptU2, ptU2, ptU2, ptVoid, {08} ptVoid, ptVoid, ptI1, ptVoid, ptVoid, ptToken, ptVoid, ptVoid, {10} ptVoid, ptVoid, ptVoid, ptVoid, ptToken, ptVoid, ptVoid, ptVoid, {18} ptVoid, ptVoid, ptVoid); {20} //=== { TJclClrILGenerator } ================================================ constructor TJclClrILGenerator.Create(AMethod: TJclClrMethodBody = nil); var OpCode: Byte; Stream: TMemoryStream; Instruction: TJclInstruction; begin inherited Create; FMethod := AMethod; FInstructions := TObjectList.Create; if Assigned(AMethod) then begin Stream := TMemoryStream.Create; try Stream.Write(Method.Code^, Method.Size); Stream.Seek(0, soFromBeginning); while Stream.Position < Stream.Size do begin OpCode := PByte(PAnsiChar(Stream.Memory) + Stream.Position)^; if OpCode = STP1 then begin OpCode := PByte(PAnsiChar(Stream.Memory) + Stream.Position + 1)^; Instruction := TJclInstruction.Create(Self, TJclOpCode(MaxByte + 1 + OpCode)); end else Instruction := TJclInstruction.Create(Self, TJclOpCode(OpCode)); if Assigned(Instruction) then begin FInstructions.Add(Instruction); Instruction.Load(Stream); end; end; finally FreeAndNil(Stream); end; end; end; destructor TJclClrILGenerator.Destroy; begin FreeAndNil(FInstructions); inherited Destroy; end; function TJclClrILGenerator.DumpIL(Options: TJclInstructionDumpILOptions): string; var I, J, Indent: Integer; function FlagsToName(Flags: TJclClrExceptionClauseFlags): string; begin if cfFinally in Flags then Result := 'finally' else if cfFilter in Flags then Result := 'filter' else if cfFault in Flags then Result := 'fault' else Result := 'catch'; end; function IndentStr: string; begin Result := StrRepeat(' ', Indent); end; begin Indent := 0; with TStringList.Create do try for I := 0 to InstructionCount-1 do begin for J := 0 to Method.ExceptionHandlerCount-1 do with Method.ExceptionHandlers[J] do begin if Instructions[I].Offset = TryBlock.Offset then begin Add(IndentStr + '.try'); Add(IndentStr + '{'); Inc(Indent); end; if Instructions[I].Offset = (TryBlock.Offset + TryBlock.Length) then begin Dec(Indent); Add(IndentStr + '} // end .try'); end; if Instructions[I].Offset = HandlerBlock.Offset then begin Add(IndentStr + FlagsToName(Flags)); Add(IndentStr + '{'); Inc(Indent); end; if Instructions[I].Offset = (HandlerBlock.Offset + HandlerBlock.Length) then begin Dec(Indent); Add(IndentStr + '} // end ' + FlagsToName(Flags)); end; end; Add(IndentStr + Instructions[I].DumpIL(Options)); end; Result := Text; finally Free; end; end; function TJclClrILGenerator.GetInstructionCount: Integer; begin Result := FInstructions.Count; end; function TJclClrILGenerator.GetInstruction(const Idx: Integer): TJclInstruction; begin Result := TJclInstruction(FInstructions[Idx]); end; //=== { TJclInstruction } ==================================================== constructor TJclInstruction.Create(AOwner :TJclClrILGenerator; AOpCode: TJclOpCode); begin inherited Create; FOwner := AOwner; FOpCode := AOpCode; end; function TJclInstruction.GetWideOpCode: Boolean; begin Result := Integer(OpCode) > MaxByte; end; function TJclInstruction.GetRealOpCode: Byte; begin if WideOpCode then Result := Integer(OpCode) mod (MaxByte + 1) else Result := Integer(OpCode); end; function TJclInstruction.GetParamType: TJclInstructionParamType; begin Result := OpCodeParamTypes[OpCode]; end; function TJclInstruction.GetName: string; begin Result := LoadResString(OpCodeInfos[OpCode, itName]); end; function TJclInstruction.GetFullName: string; begin Result := LoadResString(OpCodeInfos[OpCode, itFullName]); end; function TJclInstruction.GetDescription: string; begin Result := LoadResString(OpCodeInfos[OpCode, itDescription]) end; function TJclInstruction.GetSize: DWORD; const OpCodeSize: array [Boolean] of DWORD = (1, 2); begin case ParamType of ptSOff, ptI1, ptU1: Result := SizeOf(Byte); ptI2, ptU2: Result := SizeOf(Word); ptLOff, ptI4, ptToken, ptU4, ptR4: Result := SizeOf(DWORD); ptI8, ptU8, ptR8: Result := SizeOf(Int64); ptArray: Result := (VarArrayHighBound(FParam, 1) - VarArrayLowBound(FParam, 1) + 1 + 1) * SizeOf(Integer); else Result := 0; end; Inc(Result, OpCodeSize[OpCode in [opNop..opPrefixRef]]); end; procedure TJclInstruction.Load(Stream: TStream); var Code: Byte; I, ArraySize: DWORD; { TODO : I, ArraySize = DWORD create a serious problem } Value: Integer; begin FOffset := Stream.Position; try Code := 0; Stream.Read(Code, SizeOf(Code)); if WideOpCode then begin if Code <> STP1 then raise EJclCliInstructionStreamInvalid.CreateRes(@RsInstructionStreamInvalid); Stream.Read(Code, SizeOf(Code)); end; if Code <> RealOpCode then raise EJclCliInstructionStreamInvalid.CreateRes(@RsInstructionStreamInvalid); with TVarData(FParam) do case ParamType of ptU1: begin Stream.Read(VByte, SizeOf(Byte)); VType := varByte; end; ptI2: begin Stream.Read(VSmallInt, SizeOf(SmallInt)); VType := varSmallInt; end; ptLOff, ptI4: begin Stream.Read(VInteger, SizeOf(Integer)); VType := varInteger; end; ptR4: begin Stream.Read(VSingle, SizeOf(Single)); VType := varSingle; end; ptR8: begin Stream.Read(VDouble, SizeOf(Double)); VType := varDouble; end; ptArray: begin ArraySize := 0; Stream.Read(ArraySize, SizeOf(ArraySize)); FParam := VarArrayCreate([0, ArraySize-1], varInteger); for I := 0 to ArraySize-1 do { TODO : ArraySize = 0 and we have a nearly endless loop } begin Value := 0; Stream.Read(Value, SizeOf(Value)); FParam[I] := Value; end; end; ptSOff, ptI1: begin Stream.Read(VShortInt, SizeOf(ShortInt)); VType := varShortInt; end; ptU2: begin Stream.Read(VWord, SizeOf(Word)); VType := varWord; end; ptToken, ptU4: begin Stream.Read(VLongWord, SizeOf(LongWord)); VType := varLongWord; end; ptI8, ptU8: begin Stream.Read(VInt64, SizeOf(Int64)); VType := varInt64; end; end; except Stream.Position := FOffset; raise; end; end; procedure TJclInstruction.Save(Stream: TStream); var Code: Byte; ArraySize: DWORD; I, Value: Integer; begin if WideOpCode then begin Code := STP1; Stream.Write(Code, SizeOf(Code)); end; Code := RealOpCode;; Stream.Write(Code, SizeOf(Code)); case ParamType of ptU1: Stream.Write(TVarData(FParam).VByte, SizeOf(Byte)); ptI2: Stream.Write(TVarData(FParam).VSmallInt, SizeOf(SmallInt)); ptLOff, ptI4: Stream.Write(TVarData(FParam).VInteger, SizeOf(Integer)); ptR4: Stream.Write(TVarData(FParam).VSingle, SizeOf(Single)); ptR8: Stream.Write(TVarData(FParam).VDouble, SizeOf(Double)); ptSOff, ptI1: Stream.Write(TVarData(FParam).VShortInt, SizeOf(ShortInt)); ptU2: Stream.Write(TVarData(FParam).VWord, SizeOf(Word)); ptToken, ptU4: Stream.Write(TVarData(FParam).VLongWord, SizeOf(LongWord)); ptI8, ptU8: Stream.Write(TVarData(FParam).VInt64, SizeOf(Int64)); ptArray: begin ArraySize := VarArrayHighBound(FParam, 1) - VarArrayLowBound(FParam, 1) + 1; Stream.Write(ArraySize, SizeOf(ArraySize)); { TODO : VarArrayHighBound to VarArrayLowBound very likely wrong } for I := VarArrayHighBound(FParam, 1) to VarArrayLowBound(FParam, 1) do begin Value := VarArrayGet(FParam, [I]); Stream.Write(Value, SizeOf(Value)); end; end; end; end; function TJclInstruction.DumpIL(Options: TJclInstructionDumpILOptions): string; var Opt: TJclInstructionDumpILOption; begin if doLineNo in Options then Result := DumpILOption(doLineNo) + ': '; if doRawBytes in Options then Result := Result + Format(' /* %.24s */ ', [DumpILOption(doRawBytes)]); for Opt := doIL to doTokenValue do Result := Result + DumpILOption(Opt) + ' '; if (doComment in Options) and ((FullName <> '') or (Description <> '')) then Result := Result + ' // ' + DumpILOption(doComment); end; function TJclInstruction.FormatLabel(Offset: Integer): string; begin Result := 'IL_' + IntToHex(Offset, 4); end; function TJclInstruction.DumpILOption(Option: TJclInstructionDumpILOption): string; function TokenToString(Token: DWORD): string; begin Result := '(' + IntToHex(Token shr 24, 2) + ')' + IntToHex(Token mod (1 shl 24), 6); end; var I: Integer; Row: TJclClrTableRow; CodeStr, ParamStr: string; begin case Option of doLineNo: Result := 'IL_' + IntToHex(Offset, 4); doRawBytes: begin if WideOpCode then CodeStr := IntToHex(STP1, 2); CodeStr := CodeStr + IntToHex(RealOpCode, 2); CodeStr := CodeStr + StrRepeat(' ', 4 - Length(CodeStr)); case ParamType of ptSOff, ptI1, ptU1: ParamStr := IntToHex(TVarData(FParam).VByte, 2); ptArray: ParamStr := 'Array'; ptI2, ptU2: ParamStr := IntToHex(TVarData(FParam).VWord, 4); ptLOff, ptI4, ptU4, ptR4: ParamStr := IntToHex(TVarData(FParam).VLongWord, 8); ptI8, ptU8, ptR8: ParamStr := IntToHex(TVarData(FParam).VInt64, 16); ptToken: ParamStr := TokenToString(TVarData(FParam).VLongWord); else ParamStr := ''; end; ParamStr := ParamStr + StrRepeat(' ', 10 - Length(ParamStr)); Result := CodeStr + ' | ' + ParamStr; end; doIL: begin case ParamType of ptVoid: ; // do nothing ptLOff: Result := FormatLabel(Integer(Offset) + + Integer(Size) + TVarData(Param).VInteger - 1); ptToken: begin if Byte(TJclPeMetadata.TokenTable(TVarData(Param).VLongWord)) = $70 then Result := '"' + Owner.Method.Method.Table.Stream.Metadata.UserStringAt(TJclPeMetadata.TokenIndex(TVarData(Param).VLongWord)) + '"' else begin Row := Owner.Method.Method.Table.Stream.Metadata.Tokens[TVarData(Param).VLongWord]; if Assigned(Row) then begin if Row is TJclClrTableTypeDefRow then Result := TJclClrTableTypeDefRow(Row).FullName else if Row is TJclClrTableTypeRefRow then with TJclClrTableTypeRefRow(Row) do Result := FullName else if Row is TJclClrTableMethodDefRow then with TJclClrTableMethodDefRow(Row) do Result := ParentToken.FullName + '.' + Name else if Row is TJclClrTableMemberRefRow then with TJclClrTableMemberRefRow(Row) do Result := FullName else if Row is TJclClrTableFieldDefRow then with TJclClrTableFieldDefRow(Row) do Result := ParentToken.FullName + '.' + Name else Result := Row.DumpIL; end else Result := ''; end; Result := Result + ' /* ' + IntToHex(TVarData(FParam).VLongWord, 8) + ' */'; end; ptSOff: Result := FormatLabel(Integer(Offset + Size) + TVarData(Param).VShortInt - 1); ptArray: begin for I := VarArrayHighBound(FParam, 1) to VarArrayLowBound(FParam, 1) do begin Result := Result + FormatLabel(Offset + Size + VarArrayGet(FParam, [I])); if I <> VarArrayLowBound(FParam, 1) then Result := Result + ', '; end; Result := ' (' + Result + ')'; end; else Result := VarToStr(Param); end; Result := GetName + StrRepeat(' ', 10 - Length(GetName)) + ' ' + Result; Result := Result + StrRepeat(' ', 20 - Length(Result)); end; doTokenValue: Result := ''; // do nothing doComment: if FullName = '' then Result := Description else if Description = '' then Result := FullName else Result := FullName + ' - ' + Description; end; end; {$IFDEF UNITVERSIONING} initialization RegisterUnitVersion(HInstance, UnitVersioning); finalization UnregisterUnitVersion(HInstance); {$ENDIF UNITVERSIONING} end.