Invalid IL code generated

733 Views Asked by At

I'm trying to merge two methods together (one method from my project, one from a dll) and write them to a dll. The original code looks like this:

 .method public hidebysig static class Storage.DataMap 
    Create() cil managed 
  {
    .maxstack 8

    // [22 7 - 22 70]
    IL_0000: call         unmanaged stdcall native int Storage.DataMapPlugin::DataMap_CreateEmptyDataMap()
    IL_0005: newobj       instance void Storage.DataMap::.ctor(native int)
    IL_000a: ret          

  } // end of method DataMap::Create

I want to add a simple Console.WriteLine to this code, I end up with the following: (From decompiler)

  .method public hidebysig static class Storage.DataMap 
    Create() cil managed 
  {
    .maxstack 8

    // [22 7 - 22 44]
    IL_0000: ldstr        "Hello World"
    IL_0005: call         void [mscorlib]System.Console::WriteLine(string)

    // [23 7 - 23 70]
    IL_000a: call         unmanaged stdcall native int Storage.DataMapPlugin::DataMap_CreateEmptyDataMap()
    IL_000f: newobj       instance void Storage.DataMap::.ctor(native int)
    IL_0014: ret          

  } // end of method DataMap::Create

My decompiler is not able to decompile this (dotPeek) so I am assuming that the IL I generated is invalid. However, I'm not sure what's wrong with my generated IL.

I'm using dnlib with C# to get both the method's IL code, then Concat both blocks of code together (I stripped the nop and ret statements (except for that last one)). To recompile the code I use the ModuleDef#Write(String) function, I've had success with this when writing my own IL statements, but not when merging already existing statements.

(The following IL is all printed from the console, not from decompiler)
Original part 1 IL:

IL_0000: nop
IL_0001: ldstr "Hello World"
IL_0006: call System.Void System.Console::WriteLine(System.String)
IL_000B: nop
IL_000C: ret

Original part 2 IL:

IL_0000: call System.IntPtr Storage.DataMapPlugin::DataMap_CreateEmptyDataMap()
IL_0005: newobj System.Void Storage.DataMap::.ctor(System.IntPtr)
IL_000A: ret

Merged IL:

IL_0001: ldstr "Hello World"
IL_0006: call System.Void System.Console::WriteLine(System.String)
IL_0000: call System.IntPtr Storage.DataMapPlugin::DataMap_CreateEmptyDataMap()
IL_0005: newobj System.Void Storage.DataMap::.ctor(System.IntPtr)
IL_000A: ret
1

There are 1 best solutions below

0
On BEST ANSWER

I fixed my own problem. As multiple individuals correctly pointed out in the comments, the IL is correct. The issue wasn't related to my code or the generated IL, but to the decompiler, dotPeek.

What happend was the following: I generated the DLL for the first time, but the IL was wrong (it had 2 return statements), decompiled it with dotPeek and saw that the IL was malformed. I did this again but with the correct IL (only 1 return statement) and deleted the old DLL, renamed the new DLL to the old, deleted, one. DotPeek however did not like this, it would show me the updated IL, but not the updated code.

After many restarts and removing/re-adding the assembly I found out this was the case. dnSpy seems to work much better than dotPeek so I'll be using that in the future.