Linux x64 calling convention

yamnikov-oleg / calling_conventions.md

Source: man syscall

Architecture calling conventions

Every architecture has its own way of invoking and passing arguments to the kernel. The details for various architectures are listed in the two tables below.

The first table lists the instruction used to transition to kernel mode, (which might not be the fastest or best way to transition to the kernel, so you might have to refer to vdso(7) ), the register used to indicate the system call number, and the register used to return the system call result.

arch/ABI instruction syscall # retval Notes
arm/OABI swi NR a1 NR is syscall #
arm/EABI swi 0x0 r7 r0
arm64 svc #0 x8 x0
blackfin excpt 0x0 P0 R0
i386 int $0x80 eax eax
ia64 break 0x100000 r15 r8 See below
mips syscall v0 v0 See below
parisc ble 0x100(%sr2, %r0) r20 r28
s390 svc 0 r1 r2 See below
s390x svc 0 r1 r2 See below
sparc/32 t 0x10 g1 o0
sparc/64 t 0x6d g1 o0
x86_64 syscall rax rax See below
x32 syscall rax rax See below

For s390 and s390x, NR (the system call number) may be passed directly with «svc NR» if it is less than 256.

The x32 ABI uses the same instruction as the x86_64 ABI and is used on the same processors. To differentiate between them, the bit mask __X32_SYSCALL_BIT is bitwise-ORed into the system call number for system calls under the x32 ABI.

On a few architectures, a register is used to indicate simple boolean failure of the system call: ia64 uses r10 for this purpose, and mips uses a3.

The second table shows the registers used to pass the system call arguments.

arch/ABI arg1 arg2 arg3 arg4 arg5 arg6 arg7 Notes
arm/OABI a1 a2 a3 a4 v1 v2 v3
arm/EABI r0 r1 r2 r3 r4 r5 r6
arm64 x0 x1 x2 x3 x4 x5
blackfin R0 R1 R2 R3 R4 R5
i386 ebx ecx edx esi edi ebp
ia64 out0 out1 out2 out3 out4 out5
mips/o32 a0 a1 a2 a3 See below
mips/n32,64 a0 a1 a2 a3 a4 a5
parisc r26 r25 r24 r23 r22 r21
s390 r2 r3 r4 r5 r6 r7
s390x r2 r3 r4 r5 r6 r7
sparc/32 o0 o1 o2 o3 o4 o5
sparc/64 o0 o1 o2 o3 o4 o5
x86_64 rdi rsi rdx r10 r8 r9
x32 rdi rsi rdx r10 r8 r9

The mips/o32 system call convention passes arguments 5 through 8 on the user stack.

Note that these tables don’t cover the entire calling convention — some architectures may indiscriminately clobber other registers not listed here.

Review: cb4c4e8 on 2 Dec 2015.

32-bit system call numbers and entry vectors

Источник

What are the calling conventions for UNIX & Linux system calls (and user-space functions) on i386 and x86-64

Following links explain x86-32 system call conventions for both UNIX (BSD flavor) & Linux:

But what are the x86-64 system call conventions on both UNIX & Linux?

4 Answers 4

I verified these using GNU Assembler (gas) on Linux.

Kernel Interface

x86-32 aka i386 Linux System Call convention:

In x86-32 parameters for Linux system call are passed using registers. %eax for syscall_number. %ebx, %ecx, %edx, %esi, %edi, %ebp are used for passing 6 parameters to system calls.

The return value is in %eax . All other registers (including EFLAGS) are preserved across the int $0x80 .

I took following snippet from the Linux Assembly Tutorial but I’m doubtful about this. If any one can show an example, it would be great.

If there are more than six arguments, %ebx must contain the memory location where the list of arguments is stored — but don’t worry about this because it’s unlikely that you’ll use a syscall with more than six arguments.

For an example and a little more reading, refer to http://www.int80h.org/bsdasm/#alternate-calling-convention. Another example of a Hello World for i386 Linux using int 0x80 : Hello, world in assembly language with Linux system calls?

There is a faster way to make 32-bit system calls: using sysenter . The kernel maps a page of memory into every process (the vDSO), with the user-space side of the sysenter dance, which has to cooperate with the kernel for it to be able to find the return address. Arg to register mapping is the same as for int $0x80 . You should normally call into the vDSO instead of using sysenter directly. (See The Definitive Guide to Linux System Calls for info on linking and calling into the vDSO, and for more info on sysenter , and everything else to do with system calls.)

x86-32 [Free|Open|Net|DragonFly]BSD UNIX System Call convention:

Parameters are passed on the stack. Push the parameters (last parameter pushed first) on to the stack. Then push an additional 32-bit of dummy data (Its not actually dummy data. refer to following link for more info) and then give a system call instruction int $0x80

x86-64 Linux System Call convention:

(Note: x86-64 Mac OS X is similar but different from Linux. TODO: check what *BSD does)

Refer to section: «A.2 AMD64 Linux Kernel Conventions» of System V Application Binary Interface AMD64 Architecture Processor Supplement. The latest versions of the i386 and x86-64 System V psABIs can be found linked from this page in the ABI maintainer’s repo. (See also the x86 tag wiki for up-to-date ABI links and lots of other good stuff about x86 asm.)

Here is the snippet from this section:

  1. User-level applications use as integer registers for passing the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9. The kernel interface uses %rdi, %rsi, %rdx, %r10, %r8 and %r9.
  2. A system-call is done via the syscall instruction. This clobbers %rcx and %r11 as well as the %rax return value, but other registers are preserved.
  3. The number of the syscall has to be passed in register %rax.
  4. System-calls are limited to six arguments, no argument is passed directly on the stack.
  5. Returning from the syscall, register %rax contains the result of the system-call. A value in the range between -4095 and -1 indicates an error, it is -errno .
  6. Only values of class INTEGER or class MEMORY are passed to the kernel.

Remember this is from the Linux-specific appendix to the ABI, and even for Linux it’s informative not normative. (But it is in fact accurate.)

This 32-bit int $0x80 ABI is usable in 64-bit code (but highly not recommended). What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code? It still truncates its inputs to 32-bit, so it’s unsuitable for pointers, and it zeros r8-r11.

User Interface: function calling

x86-32 Function Calling convention:

In x86-32 parameters were passed on stack. Last parameter was pushed first on to the stack until all parameters are done and then call instruction was executed. This is used for calling C library (libc) functions on Linux from assembly.

Modern versions of the i386 System V ABI (used on Linux) require 16-byte alignment of %esp before a call , like the x86-64 System V ABI has always required. Callees are allowed to assume that and use SSE 16-byte loads/stores that fault on unaligned. But historically, Linux only required 4-byte stack alignment, so it took extra work to reserve naturally-aligned space even for an 8-byte double or something.

Some other modern 32-bit systems still don’t require more than 4 byte stack alignment.

x86-64 System V user-space Function Calling convention:

x86-64 System V passes args in registers, which is more efficient than i386 System V’s stack args convention. It avoids the latency and extra instructions of storing args to memory (cache) and then loading them back again in the callee. This works well because there are more registers available, and is better for modern high-performance CPUs where latency and out-of-order execution matter. (The i386 ABI is very old).

In this new mechanism: First the parameters are divided into classes. The class of each parameter determines the manner in which it is passed to the called function.

For complete information refer to : «3.2 Function Calling Sequence» of System V Application Binary Interface AMD64 Architecture Processor Supplement which reads, in part:

Once arguments are classified, the registers get assigned (in left-to-right order) for passing as follows:

  1. If the class is MEMORY, pass the argument on the stack.
  2. If the class is INTEGER, the next available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9 is used

So %rdi, %rsi, %rdx, %rcx, %r8 and %r9 are the registers in order used to pass integer/pointer (i.e. INTEGER class) parameters to any libc function from assembly. %rdi is used for the first INTEGER parameter. %rsi for 2nd, %rdx for 3rd and so on. Then call instruction should be given. The stack ( %rsp ) must be 16B-aligned when call executes.

If there are more than 6 INTEGER parameters, the 7th INTEGER parameter and later are passed on the stack. (Caller pops, same as x86-32.)

The first 8 floating point args are passed in %xmm0-7, later on the stack. There are no call-preserved vector registers. (A function with a mix of FP and integer arguments can have more than 8 total register arguments.)

Variadic functions (like printf ) always need %al = the number of FP register args.

There are rules for when to pack structs into registers ( rdx:rax on return) vs. in memory. See the ABI for details, and check compiler output to make sure your code agrees with compilers about how something should be passed/returned.

Note that the Windows x64 function calling convention has multiple significant differences from x86-64 System V, like shadow space that must be reserved by the caller (instead of a red-zone), and call-preserved xmm6-xmm15. And very different rules for which arg goes in which register.

Источник

What are the calling conventions for UNIX & Linux system calls on i386 and x86-64

A system call is the fundamental interface between an application and the Linux kernel. When a Unix/Linux program does a file I/O, network data transfer or invokes some process which directly or indirectly interact with the low level instructions, then system call is involved. Making these calls usually involves using a library called glibc which contains the functions.

Examples

Below is a list of some frequently used system calls and their purpose.

Sr.No System Call Purpose
1 chmod change permissions of a file
2 chdir change working directory
3 fork create a child process
4 unlink delete a name and possibly the file it refers to

A systems programmer writes program that will not directly make the systems call, rather than he will just specify which system call to use. This involves using a calling convention which is dependent or the hardware architecture of the system where the kernel sits. Hence different architectures have different calling conventions.

A calling convention is an implementation-level design for how subroutines receive parameters from their caller and how the results are returned. Differences in various implementations include where parameters, return values, return addresses and scope links are placed (registers, stack or memory etc.), and how the tasks of preparing for a function call and restoring the environment afterward are divided between the caller and the callee.

Calling convention variation

Below is a list of some of the scenarios describing how the Calling convention varies between different architecture

  • Which registers the called function must preserve for the caller.
  • How the task of setting up for and cleaning up after a function call is divided between the caller and the callee.
  • How return value is delivered from the callee back to the caller — on the stack, in a register, or within the heap etc.
  • Where parameters, return values and return addresses are placed
  • The order in which actual arguments for formal parameters are passed.

Comparing x86-32 and x86-64 bit

A single CPU architecture always have more than one possible calling convention but the industry has agreed to some general approach across the architectures form different producers. The 32-bit architecture has 32 registers while x64 extends x86’s 8 general-purpose registers to be 64-bit. Hence there is a difference in the implementation of calling conventions. Below is comparison of major calling conventions between these two architectures.

Источник

Читайте также:  Samsung mobile print windows
Оцените статью