Reputation: 491
I've been trying to allocate memory with mmap, but so far I do not know how to do it properly. Below you can see a function I have written, it is called from C. The result it produces is always 197
, which is the same as syscall number.
C declaration:
extern "C" void * ll_alloc ();
Assembly definition:
_ll_alloc:
sub rsp, 8
mov r9, 0
mov rdi, 0
mov rax, 197
mov rsi, 4096
mov r8, -1
mov rdx, 0x02 | 0x01
mov rcx, 0x1000 | 0x0001
syscall
add rsp, 8
ret
I called mmap directly from C and everything works as expected, call I made:
void * mem = mmap(NULL, 4096, PROT_WRITE | PROT_READ, MAP_ANON | MAP_SHARED, -1, 0);
Upvotes: 1
Views: 564
Reputation: 363942
mov rcx, 0x1000 | 0x0001
can't be right: the syscall
instruction itself destroys RCX (with the saved RIP).
On x86-64 Linux the calling convention for syscalls uses R10 for the 4th arg, in place of RCX in the function-calling convention arg order. (What are the calling conventions for UNIX & Linux system calls on i386 and x86-64)
I think OS X does the same thing (so mov r10d, 0x1000 | 0x1
), but it's literally impossible for the kernel to read what was in user-space RCX before syscall
, so it's definitely not that register. See also comments on 64-bit syscall documentation for MacOS assembly
Also, x86-64 MacOS uses different call numbers than x86-64 Linux. Although 197 is correct according to https://sigsegv.pl/osx-bsd-syscalls/ which does seem to be about x86-64. (And 197 isn't the Linux syscall number)
I thought I remembered the actual EAX value needing a higher bit set, like 0x2000xyz
; maybe that's something you need to add. Update: yes, macOS 64-bit System Call Table explains that adding 0x2000000
to the call number is correct.
Single-step into the call to C library mmap
call to see register values when the syscall
instruction runs from the known-good library implementation.
Also use dtruss
(MacOS) or strace
on your hand-written asm program to see what the kernel thinks it's actually doing.
Upvotes: 1