syscall指令64位传参_Mac OS X下64位汇编与Linux下64位汇编的一些不同

本文对比了Mac OS X和Linux 64位汇编在系统调用号、符号名称、PIE、绝对地址赋值、C库包装以及错误码返回位置上的区别。在Mac OS X中,系统调用号需要加上特定偏移,符号名称需加下划线,PIE导致绝对地址使用受限,且系统调用错误码直接通过rax返回。而在Linux下,这些规则有所不同。
摘要由CSDN通过智能技术生成
32c935c9a8597cf189828697f0103885.png

首先系统调用号大大的不同

mac64和linux32的系统调用号也不同(虽然局部可能有相同)

mac64的系统调用号在:

/usr/include/sys/syscall.h

可以查到,但是调用的时候其值要加上0x2000000,可以写一个宏处理:

%define mk64 0x2000000+

使用方式如下:

mov rax,mk64 1 ;exit NOmov rdi,0 ;error_codesyscall

符号名称不同

如果在mac64下汇编要与C库相链接,所有extern符号名前要加下划线,包括入口点main:

extern _strerrorextern _printfglobal _main_main:

而linux64下汇编和C库链接的时候必须去掉符号前的下划线。

PIE

mac里的PIE(参考:http://blog.csdn.net/mydo/article/details/44906109),在直接使用绝对地址时会发出警告,如想去除警告,必须使用相对地址:

;mov rbx,addr;上一条指令要换成下一条lea rbx,[rel addr]mov rsi,[rbx]

绝对地址赋值

mac64下不允许将值赋到32位的绝对地址里去,比如以下指令出错:

mov [addr],rax

需要强制声明为64位地址或者改用相对地址:

mov [qword addr],rax ;okmov [rel addr],rax ;ok too

但linux64下无此限制。

C库包装

mac64和linux64对系统调用的C库包装有所不同,尤其是处理系统调用返回值的时候;比如mmap调用,linux64 C库貌似不检查参数,而是依据syscall自身检查;

而mac64在调用前会检查参数,如果参数有误,根本不会进行系统调用,直接设置errno,然后返回。

再拿mmap来说,如果在mmap C库函数上设断点,那么在经过N次的fast_syscall_stub之后:

-> 0x7fff8c4fc3b5 : callq 0x7fff8c4fd9e0 ; _dyld_fast_stub_entry(void*, long)

才会进入断点,所以要在fast_syscall_stub上设置条件断点,忽略前面N次的捕获(我测试的程序时或略前面28次),然后会进入kernel动态库中的mmap函数:

libsystem_kernel.dylib`mmap:-> 0x7fff8ad05a96 : pushq %rbp 0x7fff8ad05a97 : movq %rsp, %rbp 0x7fff8ad05a9a : pushq %r15 0x7fff8ad05a9c : pushq %r14 0x7fff8ad05a9e : pushq %r12 0x7fff8ad05aa0 : pushq %rbx 0x7fff8ad05aa1 : movl %r8d, %r15d 0x7fff8ad05aa4 : movq %rsi, %r14

其对传入mmap的参数进行了检查,如果发现参数错误,不会调用真正的__mmap函数,而是设置错误码,然后根据不同的错误类型跳至对应的C库错误处理函数:

0x7fff8ad05b11 : movl $0x16, %edi 0x7fff8ad05b16 : callq 0x7fff8ad03c53 ; cerror_nocancel

下面是cerror_nocancel函数的反汇编:

libsystem_kernel.dylib`cerror_nocancel:-> 0x7fff8ad03c53 : movl %edi, -0x14a629d9(%rip) ; errno 0x7fff8ad03c59 : movq %gs:0x8, %rax 0x7fff8ad03c62 : testq %rax, %rax 0x7fff8ad03c65 : je 0x7fff8ad03c69 ;  0x7fff8ad03c67 : movl %edi, (%rax) 0x7fff8ad03c69 : movq $-0x1, %rax 0x7fff8ad03c70 : movq $-0x1, %rdx 0x7fff8ad03c77 : retq

错误码的返回位置

而且最为关键的一点是,貌似mac64直接将系统调用错误码通过rax返回,而不像linux64那样返回的是错误码的补码。

所以博文linux64汇编调用mmap的例子(博文链接:http://blog.csdn.net/mydo/article/details/45007989)里,syscall返回后的代码必须改写为如下代码:

 ;syscall for mmap syscall cmp rax,0xfff ja next push rax mov [rel errno],rax pop rax or rax,-1

暂时只想到这么多不同点,大家可以继续搭楼 ;)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值