Inside Kenaz Loader
Kenaz Loader perform the task of loading previously compiled Kenaz code and making them available to the C++ code.
Loading
The loading is quite straight forward. When previously saving, we have annotated the code with various information, as shown in the following diagram :


At load-time, those references are tracked and replaced with their real value. References to functions are replaced by functions's address, enum value by their integer value... At the end of this reference replacing process, we have a fully functional opcode flow that can now be called.
From C++ to Kenaz
There are two ways to call Kenaz code from C++ : using the reflection API, or using the "Full Integration" feature of kenaz. The reflection API looks like C# or Java reflection API, and from a technical point of view, there is nothing really interesting, except maybe the code to call function. This is the only part in Kenaz that had to be written in assembly. The code had to mimic a function call with stdcall/thiscall calling convention (thus, we can't use function with variable argument because they use cdecl calling convention). The assembly code pushes arguments on the stack, move the Kenaz "this pointer" to ecx and finally calls the function and returns immediately. By returning immediately, we let the FPU stack and ALU reg in their current state, meaning that the caller will find what it expects where it should be. In the following code, val is the argument list. It was previously built by another function from the kenaz API, the code you see here is a private function)
			
template <typename T> 
T KzMethod::doInvoke(unsigned int *val, int num)
{

   void * func    = this->m_ptr;
   void * thisPtr = this->m_thisPtr;
   _asm 
   {

        mov eax, val;
        mov ecx, num;
	
	//Push argument on stack

    pushLoop:
        cmp ecx, 0;
        je doCall;
	dec ecx;
	push DWORD PTR[eax + 4*ecx];
	jmp pushLoop;
	
	
	
	doCall: 
	mov eax, func;
	mov ecx, thisPtr;
	call eax; 

        //Here, we let register / FPU stack in their current state
    }
}
The reflection api is quite nice, but using it implies an overhead that may not be always acceptable / desirable.

The second way to call Kenaz code from C++ code is to use the full integration feature of Kenaz. By using the apiOutput metadata, we tell the kenaz compiler to generate a C++ stub of the Kenaz  class/interface. For example, the kenaz class :
			
class truc [apiOutput()]
{

   public int a;
   public int c;

   public int bidule()
   {
      return  this.a;
   }
}
will have the following C++ stub
namespace KzAPI
{
   #pragma pack(1)
   class KZtruc
   {
   public:
      virtual int bidule()=0;
      int a;
      int c;
   };
   #pragma pack()  
};
Note that the function was replaced by a pure virtual function. This is absolutely necessary for three reasons :
  1. We don't want user to instanciante kenaz object with the C++ new operator
  2. Without the virtual keyword, the C++ compiler will attempt and fail to perform a static linking
  3. With the virtual keyword, the C++ compiler will expect a V-table to be present and perform call to the function through v-table, and this is a great thing for us (explication comes right now)
To understand the way the integration with C++ code works, we have to take a look at how the C++ compiler (here, visual C++ 7.1) builds its C++ objet. By taking a look at the disassembly from C++ code, I was able to find out the following : In our example, the object in memory should look like :


Another example, lets take the following C++ code :
class a
{
public:
   virtual int func1()=0;
}

class b
{
public:
   virtual int func2()=0;
}


#pragma pack(1)
class myClass : public a, public b
{
public:
   virtual int bidule()=0;
   int a;
   int c;
};
#pragma pack()

The myClass class will have the following memory representation :


Now that we have theses informations, we are able to construct objects the way vc++ does, and that is what the Kenaz loader also does. It generates v-table in the order expected by vs, and places member where vs would place them. That means, using the stub generated by Kenaz, we are able to call Kenaz code directly from C++ code without any overhead. (just an indirect call).
From Kenaz to C++
Calling C++ code from kenaz is easy. In kenaz, this is done the following way :
class myClass
{
   external int func();

   int test()
   {
       return func();
   }
}

Then, the kenaz compiler makes no difference between an external call or a standard kenaz function call. (except for the calling convention, which can be specified using the convention metadata). The question left is "how to make the binding between kenaz code and C++ code". When the CPU will execute the code to call "func", it will first be redirected to a temporary code, and this is this temporary code that will redirect the code flow to the real target, specified by the C++ user (if no target is provided, it resolves by default to a function that throws an exception). To make things a little bit easier to understand :


You see here the indirection. The benefit of this method is that we are able to modify the target at run time without having to modify existing kenaz code, just by modifying the temporary code. The temporary code performs a jmp instead of a call to leave the stack intact (call push EIP on the stack).



top of page