Posted by: Zeeshan Amjad | July 17, 2009

Dynamic Code Generation


Dynamic Code generation (DCG) or Run Time Code Generation (RTCG) generates code during the running. The performance of a program can be significantly improved with the help of Dynamic Compilation because it can access runtime information which is not available at compile time and can do low level optimization which is not possible at compile time and eliminate memory load. It also improves the reliability of the System. Dynamic compilation is currently using in several fields such as Debugger, Operating System, Simulation, and Software libraries etc.

The change of code during the running of application has been part of incremental linker and debugger for a long time such as Peter B. Kessler used this technique to implement fast break point. In his work Kessler replace the instruction of the program at the break point address during run time with new patch of assembled code at required location.

Libraries such as Microsoft’s ATL also use this technique with the name of “Window Thunk”. In ATL Window Thunk is used to call appropriate window procedure when multiple windows are made using ATL Windowing classes. ATL simply insert the machine code at separate memory location during the run time and jump the control at that point dynamically.

There is one structure defined in ATL to store the machine instruction. Because machine instruction can be one byte long and the very next byte may be used for next instruction, therefore this structure doesn’t use byte alignment. Here is a pseudo implementation of it.

  1: #pragma pack(push,1)
  2: // structure to store the machine code
  3: struct Thunk
  4: {
  5:     BYTE    m_jmp;          // op code of jmp instruction
  6:     DWORD   m_relproc;      // relative jmp
  7: };
  8: #pragma pack(pop)


Then it directly store the byte code of jump instruction n the this structure and call the Windows API to flush the instruction cache. Here is pseudo implementation of it.

  1:     Thunk    m_thunk;
  3:     void Init(pFUN pFun, void* pThis)
  4:     {
  5:         // op code of jump instruction
  6:         m_thunk.m_jmp = 0xe9;
  7:         // address of the appripriate function
  8:         m_thunk.m_relproc = (int)pFun - ((int)this+sizeof(Thunk));
 10:         FlushInstructionCache(GetCurrentProcess(), 
 11:                                 &m_thunk, sizeof(m_thunk));
 12:     }


The actual structure defined to store the machine instruction is little bit different. Here is the actual structure for it.

  1: #pragma pack(push,1)
  2: struct _WndProcThunk
  3: {
  4:     DWORD   m_mov;    // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd)
  5:     DWORD   m_this;
  6:     BYTE    m_jmp;    // jmp WndProc
  7:     DWORD   m_relproc;    // relative jmp
  8: };
  9: #pragma pack(pop)

And here is the actual code to store the direct machine code into this structure.

  1: void Init(WNDPROC proc, void* pThis)
  2: {
  3:     thunk.m_mov = 0x042444C7;  //C7 44 24 04
  4:     thunk.m_this = (DWORD)pThis;
  5:     thunk.m_jmp = 0xe9;
  6:     thunk.m_relproc = (int)proc - ((int)this+sizeof(_WndProcThunk));
  8:     FlushInstructionCache(GetCurrentProcess(), &thunk, sizeof(thunk));
  9: }

Microsoft further expended this concept in .Net. In fact in .Net this feature is available at different abstraction level. At very low level one can emit the meta-data or IL. There is a name spaces in .Net to perform this name System.Reflection.Emit. There is a class named OpCode to emit the IL Op Code (Operation Code).

At higher level there is one more class in the same named called MethodBuilder to create methods (functions) at runtime. Microsoft also gives CodeDOM (Code Document Object Model) to generate the code at runtime. Namespace System.CodeDom.Compiler provides classes and interfaces to generate source code at runtime. Even at further higher level if one wants to generate the code in high level language not at OpCode level, then there are different CodeDOMProvider classes for it such as CSharpeCodeProvider, JScriptCodeProvider, VBCodeProvider and CppCodeProvider.

Here is one simple example to dynamically generate one message in C# using the opcodes and execute it. This method seems quite long and labor work. First create assembly dynamically then crate module. In next step create type and finally crate method. After we are done with it then emit the opcode using the Emit class and finally invoke the dynamically generated method. We can even save this, but for simplicity we restricted ourselves with execution only. Here is the simple code to demonstrate this.

  1: using System;
  2: using System.Reflection;
  3: using System.Reflection.Emit;
  5: public class EmitTest
  6: {
  7:     public static void Main()
  8:     {
  9:         AppDomain appDomain = AppDomain.CurrentDomain;
 10:         AssemblyName assemblyName = new AssemblyName();
 11:         assemblyName.Name = "MyAssembly";
 13:         AssemblyBuilder assemblyBuilder =
 14:             appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
 16:         ModuleBuilder moduleBuilder =
 17:             assemblyBuilder.DefineDynamicModule("assemblyModule");
 19:         TypeBuilder typeBuilder =
 20:             moduleBuilder.DefineType("MyType");
 22:         MethodBuilder methodBuilder =
 23:             typeBuilder.DefineMethod("MyDynamicMethod", 
 24:             MethodAttributes.Static | MethodAttributes.Public);
 26:         ILGenerator ilg = methodBuilder.GetILGenerator();
 28:         ilg.Emit(OpCodes.Ldstr, "Hello World from Dynamic Method");
 29:         ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }));
 30:         ilg.Emit(OpCodes.Ret);
 32:         Type type = typeBuilder.CreateType();
 33:         type.InvokeMember("MyDynamicMethod", BindingFlags.InvokeMethod, null, null, null);
 34:     }
 35: }

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: