Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling convention for dynamically created function in (Visual) C++

I use the following types to create a new function at runtime:

typedef int (*pfunc)(int);

union funcptr {
  pfunc x;
  byte* y;
};

This enables me to write instructions in y and afterwards call the function like this:

byte* p = (byte*)VirtualAllocEx(GetCurrentProcess(), 0, 1<<16, MEM_COMMIT, PAGE_EXECUTE_READWRITE );

// Write some instructions to p

funcptr func;
func.y = p;

int ret = func.x(arg1); // Call the generated function

It is crucial to know how C++ prepare arguments (call convention) and therefore I have looked up the project properties (Visual C++) and I can see it uses __cdecl. It should put arguments on the stack according to: http://msdn.microsoft.com/en-us/library/aa271989(v=vs.60).aspx and http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl but when I look at the assembly generated, the argument is moved to the EAX register.

I want to be absolutely certain how the arguments is prepared. So have I overlooked something about cdecl or is Visual C++ optimizing the call, and if so, how do I ensure it doesn't happen?

Best regards, Lasse Espeholt

like image 895
Lasse Espeholt Avatar asked Nov 26 '11 16:11

Lasse Espeholt


People also ask

What is the __vectorcall calling convention in C++?

/Gv specifies the __vectorcall calling convention for all functions except C++ member functions, functions named main, functions with a vararg variable argument list, or functions that are marked with a conflicting __cdecl, __stdcall, or __fastcall attribute.

What is the __stdcall calling convention in C++?

/Gz specifies the __stdcall calling convention for all functions except C++ member functions, functions named main, and functions that are marked __cdecl, __fastcall, or __vectorcall. All __stdcall functions must have prototypes.

How to use C calling convention callback functions in an unmanaged DLL?

Provides an easy way to use C calling convention callback functions in C# and VB Function in an unmanaged DLL that accepts function pointer as parameter. The type of the function pointer respects the C calling convention (is declared with __cdecl ). You need to import that function in your C# or VB program and to pass a delegate to it.

What is the default calling convention for C++ functions?

/Gd, the default setting, specifies the __cdecl calling convention for all functions except C++ member functions and functions that are marked __stdcall, __fastcall, or __vectorcall.


2 Answers

The EAX register is used for the return value of the function. You state in the comments that you are compiling using /Gd and so the function will use __cdecl. All the same it would make sense in my view to mark the declaration of your function type pfunc with an explicit __cdecl so that there can be no scope for confusion and mis-match.

Of course, there's nothing to stop you using one of the other calling conventions supported by your compiler. The most important point is that whatever calling convention you settle on, you should explicitly specify the calling convention for the function pointer since the compiler is only responsible for one half of the interface.

like image 89
David Heffernan Avatar answered Sep 20 '22 04:09

David Heffernan


At least on Linux, you probably want to use libffi (foreign function interface), and it has even been ported to other systems (including Windows).

And if you want to do machine code generation at runtime, consider using GNU lightning, DotGnu's libjit, LLVM. LuaJit's dynasm etc You could also generate C code into foo.c, get it compiled by forking a gcc -fPIC -shared foo.c -o foo.so command, and dlopen("./foo.so", RTLD_GLOBAL) (and Windows have equivalent ability)

like image 45
Basile Starynkevitch Avatar answered Sep 22 '22 04:09

Basile Starynkevitch