How to execute a 64-bit syscall on Mac in C++.
I need the below to work:
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
int main() {
long* addr = (long*) syscall(SYS_mmap, 0, 100, 1 | 2, 2 | 4096, -1, 0);
}
The problem is that addr below should be 64-bit as it is a pointer, but it truncates the result to 32-bit value.
I compile with:
g++ ./mmap.cc -o ./mmap
P.S. I know there exists mmap function, the above is just an example, I need to get syscall function to work.
P.P.S. The problem is that on 64-bit systems syscall should return 64-bit value, but in Mac unistd.h it is defined as int:
int syscall(int, ...);
Is that a bug? The mmap system call return correctly void*:
void * mmap(void *, size_t, int, int, int, off_t) __DARWIN_ALIAS(mmap);
How is mmap actually implemented?
P.P.P.S.
On Linux it is defined correctly as long:
long syscall(long number, ...);
After some searching I did not find a way to execute 64-bit system calls on Mac.
So, I implemented those myself, you can find the functions here.
Also, if you use those functions don't forget to add 0x2000000 Unix system call class shift to your system call numbers:
int SYS_write = 4;
int STDOUT = 1;
char* str = "Hello world\n";
syscall3(0x2000000 + SYS_write, STDOUT, str, 12);
The syscall function is deprecated on OS X as Ken Thomases pointed out.
For your specific example, you should use mmap instead of syscall. The mmap function is not implemented in terms of the syscall function but in terms of __mmap:
libsystem_kernel.dylib`mmap:
0x7fff643fa69e <+87>: callq 0x7fff643fe998 ; __mmap
which, in turn, does the actual syscall and is probably implemented in assembly:
libsystem_kernel.dylib`__mmap:
0x7fff643fe998 <+0>: movl $0x20000c5, %eax ; imm = 0x20000C5
0x7fff643fe99d <+5>: movq %rcx, %r10
0x7fff643fe9a0 <+8>: syscall
0x7fff643fe9a2 <+10>: jae 0x7fff643fe9ac ; <+20>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With