我的Mac上的以下内容成功:
int main() {
int* addr = (int*) mmap(0, 100, 1 | 2, 2 | 4096, -1, 0);
*addr = 25;
return 0;
}
但是,当我尝试使用分段错误写入*addr
时,下面的代码是相同的但是失败了:
int main() {
int* addr = (int*) syscall(SYS_mmap, 0, 100, 1 | 2, 2 | 4096, -1, 0);
*addr = 25;
return 0;
}
即。 syscall
成功地返回了一个内存地址,但是当我尝试写入它时,它失败了。
我这样编译:
g++ ./c++/mmap.cc -o ./mmap && ./mmap
如果我使用dtruss
运行两个版本:
g++ ./c++/mmap.cc -o ./mmap && sudo dtruss ./mmap
然后两个版本都成功了,我看到两个版本的mmap
调用相同:
mmap(0x0, 0x64, 0x3, 0x1002, 0xFFFFFFFF, 0x0) = 0xXXXXXXX 0
为什么syscall
版本会给我分段错误,我缺少什么?
P.S。如果我在Linux上做类似的事情就可以了。
因此,据我所知,Mac上的mmap
功能无法执行syscall(SYS_mmap, ...
。那它做什么用的?任何人都可以给我一些链接,我可以看到实施。
编辑:
看起来Mac上的syscall
仅返回前4个字节。是否有64位syscall
版本?
拆卸:
mmap
版本:
_main:
0000000100000cf0 pushq %rbp
0000000100000cf1 movq %rsp, %rbp
0000000100000cf4 subq $0x30, %rsp
0000000100000cf8 xorl %eax, %eax
0000000100000cfa movl %eax, %ecx
0000000100000cfc movl $0x64, %eax
0000000100000d01 movl %eax, %esi
0000000100000d03 movl $0x3, %edx
0000000100000d08 movl $0x1002, %eax
0000000100000d0d movl $0xffffffff, %r8d
0000000100000d13 movl $0x0, -0x14(%rbp)
0000000100000d1a movq %rcx, %rdi
0000000100000d1d movq %rcx, -0x28(%rbp)
0000000100000d21 movl %eax, %ecx
0000000100000d23 movq -0x28(%rbp), %r9
0000000100000d27 callq 0x100000ed6 ## symbol stub for: _mmap
0000000100000d2c movq 0x2cd(%rip), %rdi ## literal pool symbol address: __ZNSt3__14coutE
0000000100000d33 movq %rax, -0x20(%rbp)
0000000100000d37 movq -0x20(%rbp), %rax
0000000100000d3b movq %rax, %rsi
syscall
版本:
_main:
0000000100000cf0 pushq %rbp
0000000100000cf1 movq %rsp, %rbp
0000000100000cf4 subq $0x30, %rsp
0000000100000cf8 movl $0xc5, %edi
0000000100000cfd xorl %esi, %esi
0000000100000cff movl $0x64, %edx
0000000100000d04 movl $0x3, %ecx
0000000100000d09 movl $0x1002, %r8d
0000000100000d0f movl $0xffffffff, %r9d
0000000100000d15 movl $0x0, -0x14(%rbp)
0000000100000d1c movl $0x0, (%rsp)
0000000100000d23 movb $0x0, %al
0000000100000d25 callq 0x100000ed6 ## symbol stub for: _syscall
0000000100000d2a movq 0x2cf(%rip), %rdi ## literal pool symbol address: __ZNSt3__14coutE
0000000100000d31 movslq %eax, %r10
0000000100000d34 movq %r10, -0x20(%rbp)
0000000100000d38 movq -0x20(%rbp), %r10
0000000100000d3c movq %r10, %rsi
答案 0 :(得分:5)
显然Mac没有64位syscall
功能,这里有一个简单的实现:
#include <sys/types.h>
#define CARRY_FLAG_BIT 1
inline int64_t syscall6(int64_t num, int64_t arg1, int64_t arg2, int64_t arg3, int64_t arg4, int64_t arg5, int64_t arg6) {
int64_t result;
int64_t flags;
__asm__ __volatile__ (
"movq %6, %%r10;\n"
"movq %7, %%r8;\n"
"movq %8, %%r9;\n"
"syscall;\n"
"movq %%r11, %1;\n"
: "=a" (result), "=r" (flags)
: "a" (num), "D" (arg1), "S" (arg2), "d" (arg3), "r" (arg4), "r" (arg5), "r" (arg6)
: "%r10", "%r8", "%r9", "%rcx", "%r11"
);
return (flags & CARRY_FLAG_BIT) ? -result : result;
}
您可以通过0x2000000
移动系统调用号码在Mac上使用它:
int* addr = (int*) syscall6(0x2000000 + SYS_mmap, 0, 100, 1 | 2, 2 | 4096, -1, 0);
您可以找到更多here。