0

I have an array with 32bit values (nativeParameters with length nativeParameterCount) and a pointer to the function (void* to a cdecl function, here method->nativeFunction) thats supposed to be called. Now I'm trying to do this:

// Push parameters for call
if (nativeParameterCount != 0) {
    uint32_t count = 0;
pushParameter:
    uint32_t value = nativeParameters[nativeParameterCount - count - 1];
            asm("push %0" : : "r"(value));
    if (++count < nativeParameterCount) goto pushParameter;
}

// Call method
asm("call *%0" : : "r"(method->nativeFunction));

// Return value
uint32_t eax;
uint32_t edx;
asm("push %eax");
asm("push %edx");
asm("pop %0" : "=r"(edx));
asm("pop %0" : "=r"(eax));
uint64_t returnValue = eax;

// If the typesize of the methods return type is >4 bytes, or with EDX
Type returnType = method->returnType.type;
if (TYPE_SIZES[returnType] > 4) {
    returnValue |= (((uint64_t) edx) << 32);
}

// Clean stack
asm("add %%esp, %0" : : "r"(parameterByteSize));

Is this approach suitable to perform a native call (assuming that all target functions accept only 32bit values as parameters)? Can I be sure that it doesn't destroy the stack or mess with registers, or somehow else influence the normal flow? Also, are there other ways of doing this?

Seki
  • 11,135
  • 7
  • 46
  • 70
maxdev
  • 2,491
  • 1
  • 25
  • 50
  • 1
    What's `nativeParameterCount`? What's `nativeParameters`? Why are you `goto`ing instead of using a `for` loop? – The Paramagnetic Croissant Apr 20 '14 at 15:34
  • 1
    Let's step back for a minute: what do you really want to accomplish with this? Do you want to call a function whose function pointer you have? – DarkDust Apr 20 '14 at 15:35
  • @user3477950 i edited the question. `for` or `goto` doesn't really matter here. @DarkDust it's part of a Java virtual machine and it's supposed to call native functions. – maxdev Apr 20 '14 at 15:36
  • 1
    This is totally unsafe. For example, pushing to the stack without the compiler knowing can mess up any local variable references. You should not be using inline asm for this, write a separate asm module where you are in control. – Jester Apr 20 '14 at 15:36
  • 2
    @maxdev Sounds like you want to use assembly to write this code. (Or if you really want to write it in C, then write it ***in C,*** and not in half-C-half-assembly.) – The Paramagnetic Croissant Apr 20 '14 at 15:37
  • But it's C. So why not do `returnValue = method->nativeFunction(nativeParameters);` ? What's the type of `nativeFunction`? – DarkDust Apr 20 '14 at 15:37
  • I can not write it in C, because `nativeFunction` is a `void*` and can point to any kind of function. So I guess I'll have to go the ugly asm way :P – maxdev Apr 20 '14 at 15:39
  • 1
    Also, depending on the architecture/platform the arguments may be passed in registers instead of being pushed on the stack (for example, on [x86-64](http://en.wikipedia.org/wiki/X86_calling_conventions)). – DarkDust Apr 20 '14 at 15:42
  • I should have stated that all functions are `cdecl` functions to. – maxdev Apr 20 '14 at 15:43
  • This is a rinse-repeat of an "old problem" - see http://stackoverflow.com/questions/16142284/convert-inline-assembly-code-to-c (and the linked questions/answers). – FrankH. Apr 29 '14 at 14:31

1 Answers1

2

Instead of doing this manually yourself, you might want to use the dyncall libary which does all this handling for you.

DarkDust
  • 90,870
  • 19
  • 190
  • 224