在ARM-OABI上实现syscall()。什么是“svc#0x900071”?

时间:2018-01-10 08:46:22

标签: linux arm system-calls abi

我知道系统调用号作为ARM OABI(旧应用程序二进制接口)上的“svc(或swi)”指令的立即操作数传递。立即操作数为“0x900000 +(系统调用次数)”例如,EXIT系统调用按如下方式发出。

svc    #0x900001    @ sys_exit

我对syscall()函数的实现感到好奇,因为sycall()获取系统调用号作为其参数。我想如果参数值是动态创建的,那么syscall()的二进制代码就不能轻易创建。 但是,glibc的syscall()的二进制代码很简单。它将系统调用次数设置为“寄存器r0”,并将参数设置为“寄存器r1-r6”。之后,执行“svc#0x900071”。

测试环境是Debian lenny ARM OABI,Linux 2.6.26,gcc 4.2,glibc 2.7.18。 syscall()的二进制代码如下。

00012560 <syscall>:
   12560:       e1a0c00d        mov     ip, sp
   12564:       e92d0070        push    {r4, r5, r6}
   12568:       e89c0070        ldm     ip, {r4, r5, r6}
   1256c:       ef900071        svc     0x00900071
   12570:       e8bd0070        pop     {r4, r5, r6}
   12574:       e3700a01        cmn     r0, #4096       ; 0x1000
   12578:       31a0f00e        movcc   pc, lr
   1257c:       ea000547        b       13aa0 <__syscall_error>

系统调用的调用方式如下。这是“syscall(SYS_getuid)”的示例。

8270:       e3a00609        mov     r0, #9437184    ; 0x900000
8274:       e2800018        add     r0, r0, #24     ; 0x18
8278:       eb0028b8        bl      12560 <syscall>

什么是“svc#0x900071”?它可以作为超级系统调用。

2 个答案:

答案 0 :(得分:1)

http://man7.org/linux/man-pages/man2/syscall.2.html

在进行真正的系统调用之前/之后还有一些工作要做,例如:注册保存/恢复。

所以,syscall()是帮助你做到这一点。

   syscall() is a small library function that invokes the system call
   whose assembly language interface has the specified number with the
   specified arguments.  Employing syscall() is useful, for example,
   when invoking a system call that has no wrapper function in the C
   library.

   syscall() saves CPU registers before making the system call, restores
   the registers upon return from the system call, and stores any error
   code returned by the system call in errno(3) if an error occurs.

看看这里:

https://w3challs.com/syscalls/?arch=arm_strong

在这里:

https://chromium.googlesource.com/native_client/nacl-newlib/+/master/libgloss/arm/linux-syscall.h

# define SYS_BASE 0x900000
#define SYS_syscall                (SYS_BASE+113)

好吧,0x900000 + 113 == 0x900071。

因此,syscall()调用真正的系统调用:)

答案 1 :(得分:0)

谢谢你,肖恩!

我检查了&#34; /usr/include/asm/unistd.h"提交并找到以下句子。

#define __NR_syscall                    (__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */

我还检查了ARM Debian EABI(即ARMEL)上的相同文件并找到了相同的句子。然而,&#34;系统调用&#34;的手册页没有系统调用&#34;系统调用&#34;。我知道对人的解释是不可靠的。

所以,我在EABI Linux上检查了syscall()的二进制代码。它正在跟随。

00014670 <syscall>:
14670:       e1a0c00d        mov     ip, sp
14674:       e92d00f0        push    {r4, r5, r6, r7}
14678:       e1a07000        mov     r7, r0
1467c:       e1a00001        mov     r0, r1
14680:       e1a01002        mov     r1, r2
14684:       e1a02003        mov     r2, r3
14688:       e89c0078        ldm     ip, {r3, r4, r5, r6}
1468c:       ef000000        svc     0x00000000
14690:       e8bd00f0        pop     {r4, r5, r6, r7}
14694:       e3700a01        cmn     r0, #4096       ; 0x1000
14698:       312fff1e        bxcc    lr
1469c:       ea00061b        b       15f10 <__syscall_error>

有趣的是因为 EABI glibc不使用系统调用(113)。系统调用的调用方式如下。这是&#34;系统调用(SYS_getuid)&#34;。

的示例
826c:       e3a00014        mov     r0, #20
8270:       eb0030fe        bl      14670 <syscall>

系统调用号由寄存器&#34; r0&#34;传递。到&lt;系统调用&gt;,然后将其移动到注册&#34; r7&#34;在&lt;系统调用&gt;,遵循EABI定义的规则&#34; man syscall&#34;。

   arch/ABI   instruction          syscall #   retval Notes
   -------------------------------------------------------------------
   arm/OABI   swi NR               -           a1     NR is syscall #
   arm/EABI   swi 0x0              r7          r0

是的,OABI上的syscall()也遵循使用特殊系统调用&#34; __ NR_syscall&#34;的规则。

所以,是&#34; __ NR_syscall&#34;是OABI的特殊系统调用吗?

然而,EABI Linux保留了&#34; __ NR_syscall&#34;。是兼容性吗?我知道EABI Linux内核可以运行OABI二进制文件。