Okay, now the program decompiles properly (the IL changes the way I
want it to), but it still doesn't run correctly. I'm receiving an
InvalidProgramException at runtime as soon as the JIT compiler hits
one of the modified instructions. "JIT Compiler encountered an
internal limitation." Could this have more to do with how I'm
importing the type? Here's my method for that:
private static void SwapTypes(string type)
{
string search = "Namespace." + type;
TypeReference replace =
Module.Import(Type.GetType(search + "New"));
Console.WriteLine("Swapping {0} out for {1}", search,
replace.Name);
SwapTypes(search, replace);
}
Thanks,
Paul Buonopane
On Thu, May 26, 2011 at 9:38 AM, Paul <[email protected]> wrote:
> A tad messy, but I think I finally have it working:
> private static void SwapTypes(string search, TypeReference
> replace)
> {
> foreach (TypeDefinition t in Module.Types)
> {
> foreach (FieldDefinition f in t.Fields)
> {
> if (f.FieldType.FullName == search)
> {
> f.FieldType = replace;
> }
> }
> foreach (MethodDefinition m in t.Methods)
> {
> if (m.ReturnType.ReturnType.FullName
> == search)
> {
> m.ReturnType.ReturnType =
> replace;
> }
> foreach (ParameterDefinition p in
> m.Parameters)
> {
> if (p.ParameterType.FullName
> == search)
> {
> p.ParameterType =
> replace;
> }
> }
> if (m.HasBody)
> {
> foreach (VariableDefinition v
> in m.Body.Variables)
> {
> if
> (v.VariableType.FullName == search)
> {
> v.VariableType
> = replace;
> }
> }
> for (int i = 0; i <
> m.Body.Instructions.Count; i++)
> {
> if
> (m.Body.Instructions[i].Operand is TypeReference &&
> ((TypeReference)m.Body.Instructions[i].Operand).FullName == search)
> {
>
> m.Body.CilWorker.Replace(m.Body.Instructions[i],
> m.Body.CilWorker.Create(m.Body.Instructions[i].OpCode, replace));
> }
> else if
> (m.Body.Instructions[i].Operand is MethodReference &&
> ((MethodReference)m.Body.Instructions[i].Operand).DeclaringType.FullName
> == search)
> {
>
> m.Body.CilWorker.Replace(m.Body.Instructions[i],
> m.Body.CilWorker.Create(m.Body.Instructions[i].OpCode,
> Module.Import(GetMethod(replace.Resolve(),
> ((MethodReference)m.Body.Instructions[i].Operand).Name))));
> }
> else if
> (m.Body.Instructions[i].Operand is FieldReference &&
> ((FieldReference)m.Body.Instructions[i].Operand).DeclaringType.FullName
> == search)
> {
>
> m.Body.CilWorker.Replace(m.Body.Instructions[i],
> m.Body.CilWorker.Create(m.Body.Instructions[i].OpCode,
> Module.Import(GetField(replace.Resolve(),
> ((FieldReference)m.Body.Instructions[i].Operand).Name))));
> }
> }
> }
> }
> }
> }
> Thanks,
> Paul Buonopane
>
>
>
> On Thu, May 26, 2011 at 8:50 AM, Gábor Kozár <[email protected]> wrote:
>> No wonder, you have ignored references to the members of your types.
>> Also, use peverify (it's in Microsoft SDKs - the full path on my machine:
>> C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin) to find out exactly
>> what's wrong with your application.
>> 2011/5/26 Paul <[email protected]>
>>>
>>> Here's what I came up with, but it results in an invalid program:
>>>
>>> private static void SwapTypes(TypeReference search,
>>> TypeReference replace)
>>> {
>>> foreach (TypeDefinition t in Module.Types)
>>> {
>>> foreach (FieldDefinition f in t.Fields)
>>> {
>>> if (f.FieldType == search)
>>> {
>>> f.FieldType = replace;
>>> }
>>> }
>>> foreach (MethodDefinition m in t.Methods)
>>> {
>>> if (m.ReturnType.ReturnType ==
>>> search)
>>> {
>>> m.ReturnType.ReturnType =
>>> replace;
>>> }
>>> foreach (ParameterDefinition p in
>>> m.Parameters)
>>> {
>>> if (p.ParameterType ==
>>> search)
>>> {
>>> p.ParameterType =
>>> replace;
>>> }
>>> }
>>> if (m.HasBody)
>>> {
>>> foreach (VariableDefinition
>>> v in m.Body.Variables)
>>> {
>>> if (v.VariableType
>>> == search)
>>> {
>>>
>>> v.VariableType = replace;
>>> }
>>> }
>>> foreach (Instruction i in
>>> m.Body.Instructions)
>>> {
>>> if (i.Operand is
>>> TypeReference && (TypeReference)i.Operand == search)
>>> {
>>> i.Operand =
>>> replace;
>>> }
>>> }
>>> }
>>> }
>>> }
>>> }
>>>
>>>
>>> Thanks,
>>> Paul Buonopane
>>>
>>>
>>>
>>> On Thu, May 26, 2011 at 5:21 AM, Gábor Kozár <[email protected]> wrote:
>>> > It most certainly is possible, but it'll be not too easy to code.
>>> > Basically
>>> > what you need to do is find all references to Lightning1 or its members
>>> > in
>>> > the assembly you're processing, and replace them with the appropriate
>>> > reference to Lightning2, or its members.
>>> > Go through all types in the assembly, and check their base type, and the
>>> > generic arguments of the base type. Then go through all the methods in
>>> > the
>>> > type (including the property get_* and set_* methods - maybe even the
>>> > event
>>> > add_* and remove_* methods), fix their parameter and local variable
>>> > types,
>>> > then iterate through the instructions to find all references to
>>> > Lightning1
>>> > or its member.
>>> > I believe the easiest way to achieve this would be to check the Operand
>>> > of
>>> > each instruction, and see if it's a TypeReference. If it is, check if it
>>> > is
>>> > Lightning1, and also check its generic arguments. If it's not a
>>> > TypeReference, see if it's a MemberReference whose DeclaringType is
>>> > Lightning1, or has Lightning1 as a generic argument.
>>> > If Lightning1 is an attribute type, make sure to also check the
>>> > CustomAttributes of all eligible members. I think that'll cover
>>> > everything.
>>> > I'm afraid I don't know any easier way to achieve this. Good luck!
>>> > 2011/5/26 Paul Buonopane <[email protected]>
>>> >>
>>> >> Is it possible to inject a type in another's place? For example, if I
>>> >> have Lighting1 and Lighting2, the two being almost identical, could I
>>> >> inject
>>> >> Lighting2 in place of Lighting1? If so, what would it entail? --
>>> >> --
>>> >> mono-cecil
>>> >
>>> > --
>>> > --
>>> > mono-cecil
>>>
>>> --
>>> --
>>> mono-cecil
>>
>> --
>> --
>> mono-cecil
>
--
--
mono-cecil