【发布时间】:2018-06-06 05:01:51
【问题描述】:
我的 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 版本给我分段错误,我错过了什么?
附:如果我在 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
【问题讨论】:
-
@t0mm13b 这是一个纯编程问题,以一个非常典型/正确的 SO 问题
Why does the syscall version give me segmentation fault, what am I missing?结尾。只有第二个问题是要求链接,这只能证明 Vad 愿意自己排序;很好! -
@t0mm13b Mac 上的 SYS_mmap 评估为 197,如果您看到 197 系统调用也在您的链接中,它确实是 mmap
-
也许在mac上阅读
man syscall。 -
@usr2564301 -
syscall的返回类型是int。 -
在 Linux 上
syscall是 64 位的。 FreeBSD 人如何执行 64 位系统调用?
标签: c++ c system-calls