0

I learn that system call number is passed as the immediate operand of "svc (or swi)" instruction on ARM OABI (Old Application Binary Interface). The immediate operand is "0x900000+(Number of system call)" For example, the EXIT system call is issued as follows.

svc    #0x900001    @ sys_exit

I become curious about the implementation of syscall() function because sycall() gets the system call number as its argument. I guess the binary code of syscall() cannot create easily, if the argument value is created dynamically. However, the binary code of syscall() of glibc is simple. It sets the number of system call to "register r0" and the arguements to "register r1-r6". After then, execute "svc #0x900071".

The test environment is Debian lenny ARM OABI, Linux 2.6.26, gcc 4.2, glibc 2.7.18. The binary code of syscall() is as follows.

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>

The syscall is called as follows. This is sample of "syscall(SYS_getuid)".

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

What is "svc #0x900071"? It works as super system call.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Kuniyasu Suzaki
  • 157
  • 2
  • 9
  • although the architecture has room for and allows for an immediate encoding in the instruction, but there are arm vs thumb encodings, and now it becomes a system problem, do you do the system design allowing for either mode to make the call or only one, it is more work to try to figure out the mode and decode, so using registers which you are probably using anyway and essentially ignoring the immediate in the instruction, is a sane design. but all of this is part of the system design so look up the call rules for the operating system you are using. just google it. – old_timer Jan 10 '18 at 13:11

2 Answers2

2

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

There are some work to do before/after you do a real system call, eg: register saving/restoring.

So, syscall() is a helper to do that.

   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.

And have a look at here:

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

and here:

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

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

Well, 0x900000 + 113 == 0x900071.

So, syscall() calls a real system call :)

shawn
  • 4,305
  • 1
  • 17
  • 25
2

Thank you, Shawn!

I checked the "/usr/include/asm/unistd.h" file and find the following sentence.

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

I also check the same file on ARM Debian EABI (i.e., ARMEL) and find the same sentence. However, the man page of "syscalls" has no system call of "syscall". I know the explanation of man is not trustful.

So, I check the binary code of syscall() on EABI Linux. It is following.

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>

It is interesting because the EABI glibc does not use the syscall(113). The syscall is called as follows. This is sample of "syscall(SYS_getuid)".

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

The syscall number is passed by the register "r0" to < syscall >, and it is moved it to register "r7" in the < syscall >, which follows the rule of EABI defined "man syscall".

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

Yes, syscall() on OABI also follows the rule using the special system call "__NR_syscall".

So, is "__NR_syscall" is special system call for OABI?

However, EABI Linux keeps the "__NR_syscall". Is it for compatibility? I know EABI Linux kernel can run the OABI binary.

Kuniyasu Suzaki
  • 157
  • 2
  • 9
  • Yes, `swi 0x900000 + syscall_number` is for OABI (Old, Legacy). `r7=syscall_number; swi 0x0` is for EABI. The support of OABI must be turned on in kernel, otherwise only EABI code can run. – shawn Jan 11 '18 at 04:23
  • make menuconfig: `[*] Use the ARM EABI to compile the kernel`, `[ ] Allow old ABI binaries to run with this kernel (EXPERIMENTAL)` – shawn Jan 11 '18 at 04:27
  • Thank you, Shawn! I understand the situation. The treatment of OABI on EABI Linux is funny. – Kuniyasu Suzaki Jan 11 '18 at 05:34
  • Do anybody know the "Only One System Call Linux" ? I think OABI makes possible this funny Linux distribution. It may be (un)secure? :-) – Kuniyasu Suzaki Jan 11 '18 at 05:46