'Dynamic' function calls

B

BartC

glen herrmannsfeldt said:
(snip on calling functions with an unknown, at compile time, number
of arguments, possibly of unknown type.)

Even worse, if that register is on the x87 stack. You can't just ignore
it, as sometime later, likely at an unexpected time and place, a
floating point stack overflow will be detected.

Fortunately, I will know, at the time of the call, what the result type is.
So a float value can be 'popped' from the FPU stack, even if the function is
being called (from the target language) as a procedure with the return value
unused. (Although of course the language could get the return type wrong,
but that will be a user bug, and could happen also when declared in C.)

Slightly more tricky, are pointers to such functions, which may need the
return type and call-type contained within them to avoid problems (since
there is no static typing).
I do remember random number generators for OS/360 Fortran that would
return either a floating point value between 0 and 1, or a 32 bit
integer, depending on declaring the function INTEGER or REAL.

The (assembler) function returned values in both general and floaing
point registers, and the compiler used the appropriate one.

Many 32 bit compilers will pass an additional argument to store the
result in if the result type is more than 32 bits. (Such as a struct.)
That might not be true for 64 bit compilers.

That sounds unlikely for values such 64-bit versions of int types. It will
probably just use adjacent registers. Not sure about 64-bit structs though..
 
B

BartC

BartC said:
That's a good point. On my machine, calls to normal C functions have the
stack adjusted by the caller. So the extra params are popped.

But with C calls to Win32 functions, for example, this is handled by the
callee, which will only pop what are expected.

Looking at the output of gcc under Windows, this seems to do the opposite of
what I expected:

Calls to normal C functions, have the stack adjusted by the callee.

Calls to Windows functions (__stdcall) have the stack adjusted by the
caller. Yet I can call the same functions from other languages, and I don't
need to do this!

Furthermore, when obtaining the address of a __stdcall function dynamically
(GetProcAddress), it seems to work just as well whether I declare the
function pointer as __stdcall or not. All very strange. Anyway it works at
the minute (based on my extensive tests of calling one function..).

(Example:)

#include <windows.h>

int main (void) {
int fnaddr;

fnaddr=(int)GetProcAddress(LoadLibrary("user32"),"MessageBoxA");
if (fnaddr==0) exit(0);

((int __stdcall (*)(int,char*,char*,int))fnaddr) (0,"With
__stdcall","one",0);
((int (*)(int,char*,char*,int))fnaddr) (0,"Without __stdcall","two",0);

}
 
J

James Kuyper

Theoretically, the number of possible return types is infinite, but
in practical cases not quite. (Mostly due to an unknown number of
levels of indirection, which can easily be handled as (void *)).

Bart's original message said:
"The function return type can be similarly limited to 4 possibilities:
none, 32-bit, 64-bit, and 64-bit floating point".

That's far less than infinite, and none of those types is a pointer
type, so levels of indirection don't come into play.
 
P

Philip Lantz

BartC said:
Looking at the output of gcc under Windows, this seems to do the opposite of
what I expected:

Calls to normal C functions, have the stack adjusted by the callee.

Calls to Windows functions (__stdcall) have the stack adjusted by the
caller. Yet I can call the same functions from other languages, and I don't
need to do this!

Furthermore, when obtaining the address of a __stdcall function dynamically
(GetProcAddress), it seems to work just as well whether I declare the
function pointer as __stdcall or not. All very strange. Anyway it works at
the minute (based on my extensive tests of calling one function..).

(Example:)

#include <windows.h>

int main (void) {
int fnaddr;

fnaddr=(int)GetProcAddress(LoadLibrary("user32"),"MessageBoxA");
if (fnaddr==0) exit(0);

((int __stdcall (*)(int,char*,char*,int))fnaddr) (0,"With
__stdcall","one",0);
((int (*)(int,char*,char*,int))fnaddr) (0,"Without __stdcall","two",0);

}

I would bet that the second of these two calls is messing up the stack,
but since it is followed by
mov esp, ebp
pop ebp
ret
you don't observe a problem.

I suspect that if you try making the incorrect call in a more complex
program, you will discover that it doesn't work right after all.
 
B

BartC

Philip Lantz said:
BartC wrote:

I would bet that the second of these two calls is messing up the stack,
but since it is followed by
mov esp, ebp
pop ebp
ret
you don't observe a problem.

I suspect that if you try making the incorrect call in a more complex
program, you will discover that it doesn't work right after all.

The mystery seems deeper than that. I've been making calls to Win32
functions, via my own language and compiler, for years. This language needs
to use add esp,N after every call to a C library function, but doesn't need
it after a __stdcall (eg. Win32) call.

This language also doesn't use mov esp,ebp at the of a function, but add
esp,N (N being the number of bytes in the stack frame), so would be
sensitive to rogue values of stack pointer. And also, for last few months
the language has depended on the same gcc linker (and presumably the same C
library) as has built the above example!
 
S

SG

Am 21.12.2012 23:13, schrieb BartC:
I have a requirement to call a function where:

o The function address is not known until runtime
o Neither are the number and type of the parameters
o Neither is the type of the function result
o (And neither is the calling convention, but it will likely be one of two)

Maybe libffi is what you are looking for.

Cheers!
SG
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,077
Messages
2,570,567
Members
47,204
Latest member
abhinav72673

Latest Threads

Top