我一直在尝试使用 mmap 分配内存,但是到目前为止,我还不知道如何正确地进行分配。在下面可以看到我编写的一个函数,它从C调用。它产生的结果始终是197
,与系统调用号相同。
C声明:
extern "C" void * ll_alloc ();
程序集定义:
_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
我直接从C调用了mmap,一切正常,调用了我所做的:
void * mem = mmap(NULL, 4096, PROT_WRITE | PROT_READ, MAP_ANON | MAP_SHARED, -1, 0);
答案 0 :(得分:1)
mov rcx, 0x1000 | 0x0001
是不对的:syscall
instruction本身会破坏RCX(带有保存的RIP)。
在x86-64 Linux上,syscall的调用约定将R10用作第4个arg,而不是按函数调用约定arg顺序使用RCX。 (What are the calling conventions for UNIX & Linux system calls on i386 and x86-64)
我认为OS X做同样的事情(所以mov r10d, 0x1000 | 0x1
),但是内核实际上无法读取syscall
之前的用户空间RCX中的内容,所以绝对不是那个寄存器。另请参阅对64-bit syscall documentation for MacOS assembly
此外,x86-64 MacOS使用的呼叫号码与x86-64 Linux不同。尽管根据https://sigsegv.pl/osx-bsd-syscalls/ 197是正确的,但这似乎与x86-64有关。 (并且197不是Linux系统调用号)
我以为我记得需要设置更高位的实际EAX值,例如0x2000xyz
;也许那是您需要添加的东西。 更新:是的,macOS 64-bit System Call Table说明将0x2000000
添加到电话号码中是正确的。
单步进入对C库mmap
的调用,以在syscall
指令从已知良好的库实现中运行时查看寄存器值。
还可以在您的手写asm程序上使用dtruss
(MacOS)或strace
来查看内核认为它实际上在做什么。