123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <windows.h>
typedef struct {
void *data;
size_t pos, sz;
} args;
args a_new(size_t sz);
void a_destroy(args *a);
void a_push(args *a, void *arg);
void a_print(args a);
int __fastcall a_exec(args a, FARPROC fun);
args a_new(size_t sz) {
args a = (args) {
.pos = 0,
.sz = (sz+3) & ~3, // align to 4 bytes
};
if (!(a.data = calloc(a.sz, 1))) {
perror("calloc");
exit(errno);
}
return a;
}
void a_destroy(args *a) {
memset(a->data, -1, a->sz);
free(a->data);
memset(a, 0, sizeof(args));
}
void a_push(args *a, void *arg) {
if (a->pos == a->sz) {
a->sz *= 2;
void *old = a->data;
if (!(a->data = realloc(a->data, a->sz))) {
a_destroy(old);
perror("realloc");
exit(errno);
}
memset(a->data + a->sz/2, 0, a->sz/2);
}
memcpy(a->data + a->pos, arg, 4);
a->pos += 4;
}
void a_print(args a) {
for (unsigned int i = 0; i < a.sz; i+=4) {
if (i == 0 || i == a.pos) puts("################################");
int val = *(int*)(a.data + i);
printf("%.2d %.8x\n", i, val);
}
}
int __fastcall a_exec(args a, FARPROC fun) {
int res;
__asm__ __volatile__ (
"movl %1, %%esi # source = a->data \n\t"
"subl %2, %%esp # make space on stack \n\t"
"movl %%esp, %%edi # dest = stack \n\t"
"shrl $2, %2 # dword == 4 bytes \n\t"
"rep movsd # copy args onto stack \n\t"
"call *%3 # call fun (stdcall) \n\t"
"movl %%eax, %0 # preserve result \n\t"
: "=r" (res)
: "r" (a.data),
"c" (a.pos),
"r" (fun)
: "%esi", "%edi", "%eax"
);
return res;
}
int main(int c, char *v[static 3]) {
void *dll = LoadLibrary(v[1]); if (!dll) return -1;
FARPROC fun = GetProcAddress(dll, v[2]); if (!fun) return -2;
args a = a_new(64);
for (int i=3; i<c; i++) {
if (*v[i] == '.') {
v[i]++;
a_push(&a, &v[i]);
}
else {
char *ep;
errno = 0;
long n = strtol(v[i], &ep, 0); if (errno | *ep) return -3;
a_push(&a, &n);
}
}
if (**v < 'a') a_print(a);
int ret = a_exec(a, fun);
a_destroy(&a);
return ret;
}