Understanding cil & dynamic assemblies

1,313 views
1,240 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,313
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Understanding cil & dynamic assemblies

  1. 1. Understanding CIL & Dynamic Assemblies<br />Paul Fryer<br />June 2011<br />
  2. 2. Why learn CIL?<br />Understand how various .net languages map to CIL tokens.<br />Disassemble, edit CIL, and recompile.<br />Build dynamic assemblies using System.Refelection.Emit.<br />Leveraging CTS features that aren’t available in higher level languages (C# can’t define global level members for example).<br />
  3. 3. Token Sets<br />CIL Directives<br />.namespace, .class, .method, .assembly<br />CIL Attributes<br />public, extends, implements<br />CIL Operation Codes (opcodes)<br />ldstr, box, unbox, throw, sizeof<br />
  4. 4. Opcode/Mnemonic Distinction<br />Mnemonic symbols (add, sub) are used rather than binary opcodes (0X85, 0X59).<br />Decompilers like ildasm.exe map the opcodes to their mnemonic representations.<br />
  5. 5. CIL is Stack Based<br />When looking at CIL code you’ll notice things like stloc.0 – the zero represents index 0 on the stack.<br />
  6. 6. Look at Compiled Assemblies<br />Use ildsam.exe to disassemble assembly.<br /><Microsoft SDKs>Windowsv7.0Abin<br />Commercial tools exist too:<br />Reflector http://reflector.red-gate.com<br />
  7. 7. Write IL Code with an IDE<br />MonoDevelop<br />http://monodevelop.com<br />
  8. 8. Write “Hello World”<br /> .method public hidebysig static void Main(string[] args) cil managed<br /> {<br /> .entrypoint<br /> .maxstack 1<br />ldstr "Hello World!"<br /> call void [mscorlib]System.Console::WriteLine(string)<br /> ret<br /> }<br />
  9. 9. Stack Multiple Variables<br /> .method public hidebysig static void Main(string[] args) cil managed<br /> {<br /> .entrypoint<br /> .maxstack 3<br /> .locals init ([0] string myStr, [1] int32 myInt, [2] object myObj)<br />ldstr "CIL code is Fun!"<br /> stloc.0<br /> ldc.i4 33<br /> stloc.1<br />newobj instance void [mscorlib]System.Object::.ctor()<br /> stloc.2<br /> ret<br /> }<br />
  10. 10. For Loop<br /> .method public hidebysig static void Main(string[] args) cil managed<br /> {<br /> .entrypoint<br /> .maxstack 2<br /> .locals init ([0] int32 i)<br /> IL_0: ldc.i4.0<br /> IL_1: stloc.0<br /> IL_2: br.s IL_8<br /> IL_4: ldloc.0<br /> IL_5: ldc.i4.1<br /> IL_6: add<br /> IL_7: stloc.0<br /> IL_8: ldloc.0<br /> IL_9: ldc.i4.s 10<br />IL_b: blt.s IL_4<br /> ret<br /> }<br />
  11. 11. Generate Dynamic Assemblies<br />We’ll use the System.Reflection.Emitnamespace to output dynamic code into our current AppDomain.<br />
  12. 12. public static void CreateMyAsm(AppDomaincurAppDomain)<br /> {<br /> // Build the assembly name.<br />var name = new AssemblyName("MyAssembly") {Version = new Version("1.0.0.0")};<br /> // Create a new assembly in the current app domain.<br />var assembly = curAppDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Save);<br /> // Because this is a single file assembly, the module name is the same as assembly.<br />var module = assembly.DefineDynamicModule("MyAssembly", "MyAssembly.dll");<br /> // Define the public class named "HelloWorld".<br />varhelloWorldClass = module.DefineType("MyAssembly.HelloWorld", TypeAttributes.Public);<br /> // Define the string variable named "theMessage".<br />varmsgField = helloWorldClass.DefineField("theMessage", Type.GetType("System.String"), FieldAttributes.Private);<br /> // Create the custom constructor.<br />varconstructorArgs = new[] {typeof (string)};<br />var constructor = helloWorldClass.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, constructorArgs);<br />varconstructorIL = constructor.GetILGenerator();<br />constructorIL.Emit(OpCodes.Ldarg_0);<br />varobjectClass = typeof (object);<br />varsuperConstructor = objectClass.GetConstructor(new Type[0]);<br />constructorIL.Emit(OpCodes.Call, superConstructor);<br />constructorIL.Emit(OpCodes.Ldarg_0);<br />constructorIL.Emit(OpCodes.Ldarg_1);<br />constructorIL.Emit(OpCodes.Stfld, msgField);<br />constructorIL.Emit(OpCodes.Ret);<br /> // Create the default constructor.<br />helloWorldClass.DefineDefaultConstructor(MethodAttributes.Public);<br /> // create the GetMsg() method.<br />vargetMsgMethod = helloWorldClass.DefineMethod("GetMsg", MethodAttributes.Public, typeof (string), null);<br />varmethodIL = getMsgMethod.GetILGenerator();<br />methodIL.Emit(OpCodes.Ldarg_0);<br />methodIL.Emit(OpCodes.Ldfld, msgField);<br />methodIL.Emit(OpCodes.Ret);<br /> // create the hellow world method<br />varsayHiMethod = helloWorldClass.DefineMethod("SayHello", MethodAttributes.Public, null, null);<br />methodIL = sayHiMethod.GetILGenerator();<br />methodIL.EmitWriteLine("Hello from the HelloWorld class!");<br />methodIL.Emit(OpCodes.Ret);<br /> // Bake the HelloWorld class<br />helloWorldClass.CreateType();<br /> // (optionally) save assembly to file<br />assembly.Save("MyAssembly.dll");<br /> }<br />

×