2011-09-22 10:55:30 +08:00
/ *
2012-01-10 06:02:47 +08:00
Copyright ( C ) 2011 - 2012 de4dot @gmail . com
2011-09-22 10:55:30 +08:00
This file is part of de4dot .
de4dot is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
de4dot is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with de4dot . If not , see < http : //www.gnu.org/licenses/>.
* /
using System ;
using System.Collections.Generic ;
2012-11-01 21:39:39 +08:00
using dot10.DotNet ;
using dot10.DotNet.Emit ;
2011-09-22 10:55:30 +08:00
using de4dot.blocks ;
2011-12-09 16:02:06 +08:00
namespace de4dot.code.deobfuscators {
2012-05-29 17:13:39 +08:00
abstract class ProxyCallFixerBase {
2012-11-01 21:39:39 +08:00
protected ModuleDefMD module ;
protected List < MethodDef > delegateCreatorMethods = new List < MethodDef > ( ) ;
protected Dictionary < TypeDef , bool > delegateTypesDict = new Dictionary < TypeDef , bool > ( ) ;
2012-05-29 17:13:39 +08:00
protected int errors = 0 ;
2011-11-28 18:45:48 +08:00
public int Errors {
get { return errors ; }
}
2011-09-22 10:55:30 +08:00
2011-12-28 20:33:10 +08:00
protected class DelegateInfo {
2012-11-01 21:39:39 +08:00
public IMethod methodRef ; // Method we should call
public FieldDef field ; // Field holding the Delegate instance
2011-10-23 19:43:32 +08:00
public OpCode callOpcode ;
2012-11-01 21:39:39 +08:00
public DelegateInfo ( FieldDef field , IMethod methodRef , OpCode callOpcode ) {
2011-09-22 10:55:30 +08:00
this . field = field ;
this . methodRef = methodRef ;
2011-10-23 19:43:32 +08:00
this . callOpcode = callOpcode ;
2011-09-22 10:55:30 +08:00
}
}
public int RemovedDelegateCreatorCalls { get ; set ; }
2011-10-23 19:43:32 +08:00
2012-11-01 21:39:39 +08:00
public IEnumerable < TypeDef > DelegateTypes {
2011-09-22 10:55:30 +08:00
get { return delegateTypesDict . Keys ; }
}
2011-10-23 19:43:32 +08:00
2012-11-01 21:39:39 +08:00
public IEnumerable < TypeDef > DelegateCreatorTypes {
2011-10-23 19:43:32 +08:00
get {
foreach ( var method in delegateCreatorMethods )
yield return method . DeclaringType ;
}
2011-09-22 10:55:30 +08:00
}
2012-11-01 21:39:39 +08:00
public virtual IEnumerable < Tuple < MethodDef , string > > OtherMethods {
get { return new List < Tuple < MethodDef , string > > ( ) ; }
2012-07-27 14:02:27 +08:00
}
2011-09-22 10:55:30 +08:00
public bool Detected {
2011-10-23 19:43:32 +08:00
get { return delegateCreatorMethods . Count ! = 0 ; }
2011-09-22 10:55:30 +08:00
}
2012-11-01 21:39:39 +08:00
protected ProxyCallFixerBase ( ModuleDefMD module ) {
2011-09-22 10:55:30 +08:00
this . module = module ;
}
2012-11-01 21:39:39 +08:00
protected ProxyCallFixerBase ( ModuleDefMD module , ProxyCallFixerBase oldOne ) {
2012-02-07 11:45:04 +08:00
this . module = module ;
foreach ( var method in oldOne . delegateCreatorMethods )
delegateCreatorMethods . Add ( lookup ( method , "Could not find delegate creator method" ) ) ;
foreach ( var kv in oldOne . delegateTypesDict )
delegateTypesDict [ lookup ( kv . Key , "Could not find delegate type" ) ] = kv . Value ;
}
2012-05-29 17:13:39 +08:00
protected DelegateInfo copy ( DelegateInfo di ) {
2012-02-07 11:45:04 +08:00
var method = lookup ( di . methodRef , "Could not find method ref" ) ;
var field = lookup ( di . field , "Could not find delegate field" ) ;
return new DelegateInfo ( field , method , di . callOpcode ) ;
}
2012-11-01 21:39:39 +08:00
protected T lookup < T > ( T def , string errorMessage ) where T : class , ICodedToken {
2012-02-07 11:45:04 +08:00
return DeobUtils . lookup ( module , def , errorMessage ) ;
}
2012-11-01 21:39:39 +08:00
protected void setDelegateCreatorMethod ( MethodDef delegateCreatorMethod ) {
2011-10-23 19:43:32 +08:00
if ( delegateCreatorMethod = = null )
return ;
delegateCreatorMethods . Add ( delegateCreatorMethod ) ;
}
2012-11-01 21:39:39 +08:00
protected bool isDelegateCreatorMethod ( MethodDef method ) {
2011-10-23 19:43:32 +08:00
foreach ( var m in delegateCreatorMethods ) {
if ( m = = method )
return true ;
}
return false ;
2011-09-22 10:55:30 +08:00
}
2012-11-01 21:39:39 +08:00
protected virtual IEnumerable < TypeDef > getDelegateTypes ( ) {
2012-02-07 09:02:49 +08:00
foreach ( var type in module . Types ) {
if ( type . BaseType = = null | | type . BaseType . FullName ! = "System.MulticastDelegate" )
continue ;
yield return type ;
}
}
2012-05-29 17:13:39 +08:00
protected class BlockInstr {
public Block Block { get ; set ; }
public int Index { get ; set ; }
}
protected class RemoveInfo {
public int Index { get ; set ; }
public DelegateInfo DelegateInfo { get ; set ; }
public bool IsCall {
get { return DelegateInfo ! = null ; }
}
}
protected virtual bool ProxyCallIsObfuscated {
get { return false ; }
}
public void deobfuscate ( Blocks blocks ) {
if ( blocks . Method . DeclaringType ! = null & & delegateTypesDict . ContainsKey ( blocks . Method . DeclaringType ) )
return ;
var allBlocks = blocks . MethodBlocks . getAllBlocks ( ) ;
int loops = ProxyCallIsObfuscated ? 50 : 1 ;
for ( int i = 0 ; i < loops ; i + + ) {
if ( ! deobfuscate ( blocks , allBlocks ) )
break ;
}
deobfuscateEnd ( blocks , allBlocks ) ;
}
protected abstract bool deobfuscate ( Blocks blocks , IList < Block > allBlocks ) ;
protected virtual void deobfuscateEnd ( Blocks blocks , IList < Block > allBlocks ) {
}
protected static void add ( Dictionary < Block , List < RemoveInfo > > removeInfos , Block block , int index , DelegateInfo di ) {
List < RemoveInfo > list ;
if ( ! removeInfos . TryGetValue ( block , out list ) )
removeInfos [ block ] = list = new List < RemoveInfo > ( ) ;
list . Add ( new RemoveInfo {
Index = index ,
DelegateInfo = di ,
} ) ;
}
protected static bool fixProxyCalls ( Dictionary < Block , List < RemoveInfo > > removeInfos ) {
foreach ( var block in removeInfos . Keys ) {
var list = removeInfos [ block ] ;
var removeIndexes = new List < int > ( list . Count ) ;
foreach ( var info in list ) {
if ( info . IsCall ) {
var opcode = info . DelegateInfo . callOpcode ;
var newInstr = Instruction . Create ( opcode , info . DelegateInfo . methodRef ) ;
block . replace ( info . Index , 1 , newInstr ) ;
}
else
removeIndexes . Add ( info . Index ) ;
}
2012-11-18 10:02:12 +08:00
if ( removeIndexes . Count > 0 )
block . remove ( removeIndexes ) ;
2012-05-29 17:13:39 +08:00
}
return removeInfos . Count > 0 ;
}
}
// Fixes proxy calls that call the delegate inline in the code, eg.:
// ldsfld delegate_instance
// ...push args...
// call Invoke
abstract class ProxyCallFixer1 : ProxyCallFixerBase {
FieldDefinitionAndDeclaringTypeDict < DelegateInfo > fieldToDelegateInfo = new FieldDefinitionAndDeclaringTypeDict < DelegateInfo > ( ) ;
2012-11-01 21:39:39 +08:00
protected ProxyCallFixer1 ( ModuleDefMD module )
2012-05-29 17:13:39 +08:00
: base ( module ) {
}
2012-11-01 21:39:39 +08:00
protected ProxyCallFixer1 ( ModuleDefMD module , ProxyCallFixer1 oldOne )
2012-05-29 17:13:39 +08:00
: base ( module , oldOne ) {
foreach ( var key in oldOne . fieldToDelegateInfo . getKeys ( ) )
fieldToDelegateInfo . add ( lookup ( key , "Could not find field" ) , copy ( oldOne . fieldToDelegateInfo . find ( key ) ) ) ;
}
protected void addDelegateInfo ( DelegateInfo di ) {
fieldToDelegateInfo . add ( di . field , di ) ;
}
2012-11-01 21:39:39 +08:00
protected DelegateInfo getDelegateInfo ( IField field ) {
2012-05-29 17:13:39 +08:00
if ( field = = null )
return null ;
return fieldToDelegateInfo . find ( field ) ;
}
2011-09-22 10:55:30 +08:00
public void find ( ) {
2011-10-23 19:43:32 +08:00
if ( delegateCreatorMethods . Count = = 0 )
2011-09-22 10:55:30 +08:00
return ;
2012-11-11 12:31:11 +08:00
Logger . v ( "Finding all proxy delegates" ) ;
2012-07-07 06:58:18 +08:00
foreach ( var tmp in getDelegateTypes ( ) ) {
var type = tmp ;
2012-11-17 06:50:52 +08:00
var cctor = type . FindStaticConstructor ( ) ;
2012-11-06 22:58:55 +08:00
if ( cctor = = null | | ! cctor . HasBody )
2011-09-22 10:55:30 +08:00
continue ;
if ( ! type . HasFields )
continue ;
2012-07-07 06:58:18 +08:00
object context = checkCctor ( ref type , cctor ) ;
2011-10-23 19:43:32 +08:00
if ( context = = null )
2011-09-22 10:55:30 +08:00
continue ;
2012-11-11 12:31:11 +08:00
Logger . v ( "Found proxy delegate: {0} ({1:X8})" , Utils . removeNewlines ( type ) , type . MDToken . ToUInt32 ( ) ) ;
2011-09-22 10:55:30 +08:00
RemovedDelegateCreatorCalls + + ;
2011-10-23 19:43:32 +08:00
2012-11-11 12:31:11 +08:00
Logger . Instance . indent ( ) ;
2011-09-22 10:55:30 +08:00
foreach ( var field in type . Fields ) {
2012-01-04 02:22:45 +08:00
if ( ! field . IsStatic )
2011-09-22 10:55:30 +08:00
continue ;
2012-11-01 21:39:39 +08:00
IMethod calledMethod ;
2011-10-23 19:43:32 +08:00
OpCode callOpcode ;
getCallInfo ( context , field , out calledMethod , out callOpcode ) ;
if ( calledMethod = = null )
2012-01-04 02:22:45 +08:00
continue ;
2011-12-28 20:33:10 +08:00
addDelegateInfo ( new DelegateInfo ( field , calledMethod , callOpcode ) ) ;
2012-11-11 12:31:11 +08:00
Logger . v ( "Field: {0}, Opcode: {1}, Method: {2} ({3:X8})" ,
2012-01-04 02:52:40 +08:00
Utils . removeNewlines ( field . Name ) ,
callOpcode ,
Utils . removeNewlines ( calledMethod ) ,
2012-11-01 21:39:39 +08:00
calledMethod . MDToken . Raw ) ;
2011-09-22 10:55:30 +08:00
}
2012-11-11 12:31:11 +08:00
Logger . Instance . deIndent ( ) ;
2011-09-22 10:55:30 +08:00
delegateTypesDict [ type ] = true ;
}
}
2012-11-01 21:39:39 +08:00
protected abstract object checkCctor ( ref TypeDef type , MethodDef cctor ) ;
protected abstract void getCallInfo ( object context , FieldDef field , out IMethod calledMethod , out OpCode callOpcode ) ;
2011-10-23 19:43:32 +08:00
2012-05-29 17:13:39 +08:00
protected override bool deobfuscate ( Blocks blocks , IList < Block > allBlocks ) {
2011-09-22 10:55:30 +08:00
var removeInfos = new Dictionary < Block , List < RemoveInfo > > ( ) ;
foreach ( var block in allBlocks ) {
var instrs = block . Instructions ;
for ( int i = 0 ; i < instrs . Count ; i + + ) {
2011-10-23 19:43:32 +08:00
var instr = instrs [ i ] ;
2012-05-29 17:13:39 +08:00
if ( instr . OpCode ! = OpCodes . Ldsfld )
continue ;
2012-11-01 21:39:39 +08:00
var di = getDelegateInfo ( instr . Operand as IField ) ;
2012-05-29 17:13:39 +08:00
if ( di = = null )
continue ;
2012-05-30 01:13:43 +08:00
var callInfo = findProxyCall ( di , block , i ) ;
2012-05-29 17:13:39 +08:00
if ( callInfo ! = null ) {
add ( removeInfos , block , i , null ) ;
add ( removeInfos , callInfo . Block , callInfo . Index , di ) ;
2011-09-22 10:55:30 +08:00
}
2012-05-29 17:13:39 +08:00
else {
errors + + ;
2012-11-11 12:31:11 +08:00
Logger . w ( "Could not fix proxy call. Method: {0} ({1:X8}), Proxy type: {2} ({3:X8})" ,
2012-05-29 17:13:39 +08:00
Utils . removeNewlines ( blocks . Method ) ,
2012-11-01 21:39:39 +08:00
blocks . Method . MDToken . ToInt32 ( ) ,
2012-05-29 17:13:39 +08:00
Utils . removeNewlines ( di . field . DeclaringType ) ,
2012-11-01 21:39:39 +08:00
di . field . DeclaringType . MDToken . ToInt32 ( ) ) ;
2011-09-22 10:55:30 +08:00
}
}
}
2012-05-29 17:13:39 +08:00
return fixProxyCalls ( removeInfos ) ;
2011-09-22 10:55:30 +08:00
}
2012-05-30 01:13:43 +08:00
protected virtual BlockInstr findProxyCall ( DelegateInfo di , Block block , int index ) {
return findProxyCall ( di , block , index , new Dictionary < Block , bool > ( ) , 1 ) ;
}
2011-09-22 10:55:30 +08:00
BlockInstr findProxyCall ( DelegateInfo di , Block block , int index , Dictionary < Block , bool > visited , int stack ) {
if ( visited . ContainsKey ( block ) )
return null ;
if ( index < = 0 )
visited [ block ] = true ;
var instrs = block . Instructions ;
for ( int i = index + 1 ; i < instrs . Count ; i + + ) {
if ( stack < = 0 )
return null ;
var instr = instrs [ i ] ;
2012-11-01 21:39:39 +08:00
instr . Instruction . UpdateStack ( ref stack , false ) ;
2011-09-22 10:55:30 +08:00
if ( stack < 0 )
return null ;
2012-02-07 09:02:49 +08:00
if ( instr . OpCode ! = OpCodes . Call & & instr . OpCode ! = OpCodes . Callvirt ) {
if ( stack < = 0 )
return null ;
2011-09-22 10:55:30 +08:00
continue ;
2012-02-07 09:02:49 +08:00
}
2012-11-01 21:39:39 +08:00
var calledMethod = instr . Operand as IMethod ;
2012-02-07 09:02:49 +08:00
if ( calledMethod = = null )
return null ;
if ( stack ! = ( DotNetUtils . hasReturnValue ( calledMethod ) ? 1 : 0 ) )
2011-09-22 10:55:30 +08:00
continue ;
2012-02-07 09:02:49 +08:00
if ( calledMethod . Name ! = "Invoke" )
return null ;
2011-09-22 10:55:30 +08:00
return new BlockInstr {
Block = block ,
Index = i ,
} ;
}
if ( stack < = 0 )
return null ;
foreach ( var target in block . getTargets ( ) ) {
var info = findProxyCall ( di , target , - 1 , visited , stack ) ;
if ( info ! = null )
return info ;
}
return null ;
}
2012-05-29 17:13:39 +08:00
protected override void deobfuscateEnd ( Blocks blocks , IList < Block > allBlocks ) {
fixBrokenCalls ( blocks . Method , allBlocks ) ;
}
2011-09-22 10:55:30 +08:00
// The obfuscator could be buggy and call a proxy delegate without pushing the
// instance field. SA has done it, so let's fix it.
2012-11-01 21:39:39 +08:00
void fixBrokenCalls ( MethodDef obfuscatedMethod , IList < Block > allBlocks ) {
2011-09-22 10:55:30 +08:00
foreach ( var block in allBlocks ) {
var instrs = block . Instructions ;
for ( int i = 0 ; i < instrs . Count ; i + + ) {
var call = instrs [ i ] ;
if ( call . OpCode ! = OpCodes . Call & & call . OpCode ! = OpCodes . Callvirt )
continue ;
2012-11-01 21:39:39 +08:00
var methodRef = call . Operand as IMethod ;
2012-07-22 05:13:34 +08:00
if ( methodRef = = null | | methodRef . Name ! = "Invoke" )
2011-09-22 10:55:30 +08:00
continue ;
2012-11-01 21:39:39 +08:00
MethodDef method = DotNetUtils . getMethod2 ( module , methodRef ) ;
if ( method = = null | | method . DeclaringType = = null )
2011-09-22 10:55:30 +08:00
continue ;
2012-11-01 21:39:39 +08:00
if ( ! delegateTypesDict . ContainsKey ( method . DeclaringType ) )
2011-09-22 10:55:30 +08:00
continue ;
// Oooops!!! The obfuscator is buggy. Well, let's hope it is, or it's my code. ;)
2012-11-11 12:31:11 +08:00
Logger . w ( "Holy obfuscator bugs, Batman! Found a proxy delegate call with no instance push in {0:X8}. Replacing it with a throw..." , obfuscatedMethod . MDToken . ToInt32 ( ) ) ;
2011-09-22 10:55:30 +08:00
block . insert ( i , Instruction . Create ( OpCodes . Ldnull ) ) ;
block . replace ( i + 1 , 1 , Instruction . Create ( OpCodes . Throw ) ) ;
i + + ;
}
}
}
}
2012-05-29 17:13:39 +08:00
// Fixes proxy calls that call a static method which then calls
// Invoke() on a delegate instance, eg.:
// ...push args...
// call static method
abstract class ProxyCallFixer2 : ProxyCallFixerBase {
MethodDefinitionAndDeclaringTypeDict < DelegateInfo > proxyMethodToDelegateInfo = new MethodDefinitionAndDeclaringTypeDict < DelegateInfo > ( ) ;
2012-11-01 21:39:39 +08:00
protected ProxyCallFixer2 ( ModuleDefMD module )
2012-05-29 17:13:39 +08:00
: base ( module ) {
}
2012-11-01 21:39:39 +08:00
protected ProxyCallFixer2 ( ModuleDefMD module , ProxyCallFixer2 oldOne )
2012-05-29 17:13:39 +08:00
: base ( module , oldOne ) {
foreach ( var oldMethod in oldOne . proxyMethodToDelegateInfo . getKeys ( ) ) {
var oldDi = oldOne . proxyMethodToDelegateInfo . find ( oldMethod ) ;
var method = lookup ( oldMethod , "Could not find proxy method" ) ;
proxyMethodToDelegateInfo . add ( method , copy ( oldDi ) ) ;
}
}
public void find ( ) {
if ( delegateCreatorMethods . Count = = 0 )
return ;
2012-11-11 12:31:11 +08:00
Logger . v ( "Finding all proxy delegates" ) ;
2012-07-31 13:13:07 +08:00
find2 ( ) ;
}
protected void find2 ( ) {
2012-05-29 17:13:39 +08:00
foreach ( var type in getDelegateTypes ( ) ) {
2012-11-17 06:50:52 +08:00
var cctor = type . FindStaticConstructor ( ) ;
2012-11-06 22:58:55 +08:00
if ( cctor = = null | | ! cctor . HasBody )
2012-05-29 17:13:39 +08:00
continue ;
if ( ! type . HasFields )
continue ;
object context = checkCctor ( type , cctor ) ;
if ( context = = null )
continue ;
2012-11-11 12:31:11 +08:00
Logger . v ( "Found proxy delegate: {0} ({1:X8})" , Utils . removeNewlines ( type ) , type . MDToken . ToUInt32 ( ) ) ;
2012-05-29 17:13:39 +08:00
RemovedDelegateCreatorCalls + + ;
var fieldToMethod = getFieldToMethodDictionary ( type ) ;
2012-11-11 12:31:11 +08:00
Logger . Instance . indent ( ) ;
2012-05-29 17:13:39 +08:00
foreach ( var field in type . Fields ) {
2012-11-01 21:39:39 +08:00
MethodDef proxyMethod ;
2012-05-29 17:13:39 +08:00
if ( ! fieldToMethod . TryGetValue ( field , out proxyMethod ) )
continue ;
2012-11-01 21:39:39 +08:00
IMethod calledMethod ;
2012-05-29 17:13:39 +08:00
OpCode callOpcode ;
getCallInfo ( context , field , out calledMethod , out callOpcode ) ;
if ( calledMethod = = null )
continue ;
add ( proxyMethod , new DelegateInfo ( field , calledMethod , callOpcode ) ) ;
2012-11-11 12:31:11 +08:00
Logger . v ( "Field: {0}, Opcode: {1}, Method: {2} ({3:X8})" ,
2012-05-29 17:13:39 +08:00
Utils . removeNewlines ( field . Name ) ,
callOpcode ,
Utils . removeNewlines ( calledMethod ) ,
2012-11-01 21:39:39 +08:00
calledMethod . MDToken . ToUInt32 ( ) ) ;
2012-05-29 17:13:39 +08:00
}
2012-11-11 12:31:11 +08:00
Logger . Instance . deIndent ( ) ;
2012-05-29 17:13:39 +08:00
delegateTypesDict [ type ] = true ;
}
}
2012-11-01 21:39:39 +08:00
protected void add ( MethodDef method , DelegateInfo di ) {
2012-05-29 17:13:39 +08:00
proxyMethodToDelegateInfo . add ( method , di ) ;
}
2012-11-01 21:39:39 +08:00
protected abstract object checkCctor ( TypeDef type , MethodDef cctor ) ;
protected abstract void getCallInfo ( object context , FieldDef field , out IMethod calledMethod , out OpCode callOpcode ) ;
2012-05-29 17:13:39 +08:00
2012-11-01 21:39:39 +08:00
Dictionary < FieldDef , MethodDef > getFieldToMethodDictionary ( TypeDef type ) {
var dict = new Dictionary < FieldDef , MethodDef > ( ) ;
2012-07-27 13:57:13 +08:00
foreach ( var method in type . Methods ) {
2012-11-06 22:58:55 +08:00
if ( ! method . IsStatic | | ! method . HasBody | | method . Name = = ".cctor" )
2012-07-27 13:57:13 +08:00
continue ;
2012-11-06 22:58:55 +08:00
var instructions = method . Body . Instructions ;
2012-07-27 13:57:13 +08:00
for ( int i = 0 ; i < instructions . Count ; i + + ) {
var instr = instructions [ i ] ;
if ( instr . OpCode . Code ! = Code . Ldsfld )
continue ;
2012-11-01 21:39:39 +08:00
var field = instr . Operand as FieldDef ;
2012-07-27 13:57:13 +08:00
if ( field = = null )
continue ;
dict [ field ] = method ;
break ;
}
}
return dict ;
}
2012-05-29 17:13:39 +08:00
protected override bool deobfuscate ( Blocks blocks , IList < Block > allBlocks ) {
var removeInfos = new Dictionary < Block , List < RemoveInfo > > ( ) ;
foreach ( var block in allBlocks ) {
var instrs = block . Instructions ;
for ( int i = 0 ; i < instrs . Count ; i + + ) {
var instr = instrs [ i ] ;
if ( instr . OpCode ! = OpCodes . Call )
continue ;
2012-11-01 21:39:39 +08:00
var method = instr . Operand as IMethod ;
2012-05-29 17:13:39 +08:00
if ( method = = null )
continue ;
var di = proxyMethodToDelegateInfo . find ( method ) ;
if ( di = = null )
continue ;
add ( removeInfos , block , i , di ) ;
}
}
return fixProxyCalls ( removeInfos ) ;
}
}
2012-05-30 01:13:43 +08:00
// Fixes proxy calls that call a static method with the instance of
2012-07-07 06:58:18 +08:00
// a delegate as the last arg, which then calls the Invoke method.
2012-05-30 01:13:43 +08:00
// ...push args...
// ldsfld delegate instance
// call static method
abstract class ProxyCallFixer3 : ProxyCallFixer1 {
2012-11-01 21:39:39 +08:00
protected ProxyCallFixer3 ( ModuleDefMD module )
2012-05-30 01:13:43 +08:00
: base ( module ) {
}
2012-11-01 21:39:39 +08:00
protected ProxyCallFixer3 ( ModuleDefMD module , ProxyCallFixer3 oldOne )
2012-05-30 01:13:43 +08:00
: base ( module , oldOne ) {
}
protected override BlockInstr findProxyCall ( DelegateInfo di , Block block , int index ) {
index + + ;
if ( index > = block . Instructions . Count )
return null ;
var calledMethod = getCalledMethod ( block . Instructions [ index ] ) ;
if ( calledMethod = = null )
return null ;
return new BlockInstr {
Block = block ,
Index = index ,
} ;
}
2012-11-01 21:39:39 +08:00
static IMethod getCalledMethod ( Instr instr ) {
2012-05-30 01:13:43 +08:00
if ( instr . OpCode . Code ! = Code . Call )
return null ;
2012-11-01 21:39:39 +08:00
return instr . Operand as IMethod ;
2012-05-30 01:13:43 +08:00
}
}
2011-09-22 10:55:30 +08:00
}