Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling C++ member function with reference argument from asm

Tags:

c++

x86

assembly

I want to call C++ member function through asm blocks. The compiler is MSVC++ (VS2008) and portability is not a concern. I have to built a remoting/RMI type mechanism for an embedded system. The client sends object name, method name, arguments(serialized) and i need to invoke the method to an appropriate object. The type information I can get from PDB file. I need to write a generic Invoke function. I am stuck at how to invoke a member function which takes an object as argument. Specifially. I am unable to get a pointer to copy ctor. Any idea.

PS: The code below compiles and run correctly for C::funcRef

#include <stdio.h>
struct Point
{
   int x;
   int y;
   Point() 
   { 
       x = 10; 
       y =10;
   }
   Point(const Point& p)
   {
       x = p.x;
       y = p.y;
   }
   virtual ~Point() 
   {
   }
};

class C
{
 public:
     void funcRef(Point& p) 
     { 
         printf("C::funcRef\n x= %d, y =%d\n", p.x, p.y);
     }
     void funcObj(Point p) 
     { 
         printf("C::funcObj\nx = %d y = %d\n", p.x, p.y); 

      }

};




void main()
{
   C* c = new C;
   Point p;



   //c->funcRef(p);
   // this works
   __asm
   {

      lea eax, p;
      push eax; 
      mov ecx, c;
      call [C::funcRef];

   }

  // c->funcObj(p); 
   __asm 
   {
       sub esp, 12; // make room for sizeof(Point)
       mov ecx, esp; 
       lea eax, p;
       push eax;
       // how to call copy ctor here
       mov ecx, c;
       call [C::funcObj];

   }

}
like image 861
Charvak Avatar asked Nov 03 '22 06:11

Charvak


1 Answers

Since the copy constructor is non-virtual, you'll just have to look it up by name and call it. Find out how your compiler mangles copy constructors, and how to resolve symbols by name (you might be interested in GetProcAddress).

Here is a linux example, but note it uses different calling convention to visual studio:

#include <stdio.h>
#include <dlfcn.h>

struct Point
{
   int x;
   int y;
   Point()
   {
       printf("Default constructing point @%p\n", this);
       x = 10;
       y = 10;
   }
   Point(const Point& p) __attribute__((used, visibility("default")))
   {
       printf("Copy constructing point @%p from point @%p\n", this, &p);
       x = p.x;
       y = p.y;
   }
   virtual ~Point()
   {
       printf("Point @%p destroyed\n", this);
   }
};

class C
{
 public:
     void funcRef(Point& p)
     {
         printf("C::funcRef\n x= %d, y =%d\n", p.x, p.y);
     }
     void funcObj(Point p)
     {
         printf("C::funcObj p = %p, x = %d, y = %d\n", &p, p.x, p.y);

      }

};

typedef void (C::*FRef)(Point&);
typedef void (C::*FObj)(Point);

int main()
{
   C* c = new C;
   Point p;

   FRef _fref =  &C::funcRef;
   FObj _fobj =  &C::funcObj;

//   c->funcObj(p);
   void* self = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
   printf("Module handle for self is %p\n", self);
   // mangled name of Point::Point(const Point&)
   void* constructor = dlsym(self, "_ZN5PointC1ERKS_");
   printf("Constructor address is %p\n", constructor);
   void* dummy;
   __asm__ __volatile__ (
      "sub esp, 32\n\t"
      "mov [esp+4], %[p] # argument to copy constructor\n\t"
      "lea eax, [esp+20]\n\t"
      "mov [esp], eax # this pointer\n\t"
      "call %[constructor] # construct instance at [esp+20]\n\t"
      "lea eax, [esp+20]\n\t"
      "mov [esp+4], eax # argument to function\n\t"
      "mov [esp], %[c] # this pointer\n\t"
      "call %[fobj]\n\t"
      "lea eax, [esp+20]\n\t"
      "mov [esp], eax # this pointer\n\t"
      "mov eax, [eax] # vtable\n\t"
      "call [eax] # destructor\n\t"
      "add esp, 32 # free rest of stack\n\t"
      : "=a" (dummy), "=c" (dummy)
      : [p] "a" (&p), [c] "S" (&c), [fobj] "D" ((void*)_fobj), [constructor] "c" (constructor)
      : "edx");
   return 0;
}

Test run:

Default constructing point @0xffc145e4
Module handle for self is 0xf77fb900
Constructor address is 0x8048c02
Copy constructing point @0xffc145b4 from point @0xffc145e4
C::funcObj p = 0xffc145b4, x = 10, y = 10
Point @0xffc145b4 destroyed
Point @0xffc145e4 destroyed
like image 123
Jester Avatar answered Nov 09 '22 05:11

Jester