Reputation: 2357
I am working on a dynamic language written in go. I am using C to allow this language to access syscalls (for linux at least). C's any
type is a void*
, so I thought that I can pass them into a syscall. I tested using some code which looks like:
#include <stdio.h>
#include <unistd.h>
static inline long int vpsyscall(void* a0, void* a1, void* a2, void* a3) {
return syscall(*((int*)a0), a1, a2, a3);
}
int main() {
int a_ = 1;
void* a = &a_;
int b_ = 1;
void* b = &b_;
char* c_ = "hello\n";
void* c = &c_;
int d_ = 6;
void* d = &d_;
long int ret = tusksyscall(a, b, c, d);
printf("%ld\n", ret);
}
I expect that this code should output
hello
0
to the console.
Instead, I get
-1
which (at least to my knowledge) means error.
Strangely, when I pass 1 argument (the ax), it works
int _ax = 39;
void* ax = &_ax;
long int ret = vpsyscall(ax, 0, 0, 0);
printf("%ld\n", ret);
It gives me the desired output (in this case, just the pid). So, whats going on here, and how can I pass void pointers to a syscall (if there is any way)?
Upvotes: 1
Views: 630
Reputation: 57922
The Linux system call interface only takes values which are either pointers, or integers that are the same size as a pointer and can be safely cast to them. But you are not passing such objects, you are passing pointers to them. So for instance, instead of asking the OS to write to file descriptor 1, you're asking it to write to file descriptor 0x7fffdeadbeef
or whatever the address of the local variable b_
happens to be. Clearly this will not succeed.
You need to cast instead of taking the address with the &
operator.
You also might as well make the first argument of type int
since you know that's what it will always be.
Try
static inline long int vpsyscall(int a0, void* a1, void* a2, void* a3) {
return syscall(a0, a1, a2, a3);
}
int main() {
vpsyscall(1, (void *)1, "hello", (void *)6);
}
I think you're misled by thinking of void *
as an "any" type. It can be a pointer to any object, but it's not interchangeable with that object. To get the object back, you have to cast your pointer to the type of the object and dereference it. That's what you did with the first argument to your vpsyscall
, which is why it worked, even though it was unnecessarily complicated.
Upvotes: 2