Open main menu

CDOT Wiki β

Changes

Syscalls

2,139 bytes added, 08:17, 10 September 2019
no edit summary
[[Category:Assembly Language]]
The system call (''syscall'') mechanism is used by applications to access kernel services. The userland (application/non-kernel) program loads certain registers designating the system service (syscall) desired and the arguments to that syscall, then invokes a software [[Computer_Architecture#Interrupts_and_Exceptions|interrupt]] or exception request which transfers control to the operating system kernel. Note that switching to kernel mode requires a change of [[Computer_Architecture#Execution_State,_Priviledge_State,_Rings,_or_Privilege_Level|processor mode]] (sometimes call the privilege level or exception level), because the kernel has access to instructions, memory structures, memory areas, and devices which userland programs can't access. The syscall numbers may vary between architectures, and the registers as well as the method used to invoke syscalls are architecture-specific. The processor modes and activity involved in a userland-to-kernel switch also vary by architecture.
High-level languages will wrap the syscall interface in basic wrappers or more advanced mechanisms. For example, in C, the ''write'' syscall can be accessed through the generic <code>syscall</code> wrapper, the <code>write()</code> wrapper, or through more complex functions such as <code>printf()</code>. [[Assembly Language|Assembly language]] programs will often access syscalls directly.
== Syscall Mechanism ==
Every platform has a different syscall mechanism. Each mechanism is documented in the ABI standards for that platform, and a summary of various platforms is contained in the manpage for syscall(2) (run the command <code>man 2 syscall</code> to see this). To invoke a syscallin your own code, load the syscall number and arguments into the appropriate registers, and then invoke the platformarchitecture-specific syscall mechanism., using the details below:
=== x86 32-bit ===
* The syscall number is placed in eax.
* Arguments Integer and pointer arguments are placed in edi, esi, edx, ecx with spill over to the stack(refer to ABI documentation).
* Return value is in eax.
* The syscall is invoked with <code>int 0x80</code>
* The syscall number is placed in rax.
* Arguments Integer and pointer arguments are placed in rdi, rsi, rdx, rcx, r8d, r9d with spill over to the stack(refer to ABI documentation).
* Return value is in rax.
* The syscall is invoked with <code>syscall</code>
* The syscall number is placed in r8.
* Arguments Integer and pointer arguments are placed in r0-r7with spill over to the stack (refer to Procedure Call and ABI documentation).
* Return value is in r0.
* The syscall is invoked with <code>svc 0</code>
== Syscall informationnames, numbers, and arguments == === Syscall names === A list of syscalls can be found in the manpage for <code>syscalls(2)</code> (note: this is different from the manpage for <code>syscall(2)</code> which is a generic syscall wrapper). View this with the command <code>man 2 syscalls</code> Documentation for the C wrappers for most syscalls can be found in the manpage for that wrapper, usually in section 2 of the manual (e.g., <code>write(2)</code>, which is accessed using the command <code>man 2 write</code>).
=== Syscall numbers ===
#define __NR_write 1
 
You can use the <code>ausyscall</code> utility, which part of the Linux ''audit'' package, to determine the number for a given syscall on the particular platform:
 
$ ausyscall x86_64 write
write 1
pwrite 18
writev 20
pwritev 296
process_vm_writev 311
$ ausyscall aarch64 write
write 64
writev 66
pwrite 68
pwritev 70
process_vm_writev 271
 
Note that the syscall table is searched by name, and in the examples above the text "write" matches five different syscalls. The architecture defaults to the current platform if not specified.
=== Syscall arguments and return values ===
extern ssize_t write (int __fd, const void *__buf, size_t __n) __wur;
So this This documents that the ''write'' syscall takes three arguments: the file descriptor, a pointer to the message buffer, and the message size, and returns the number of bytes written or -1 if there was an error. === Documentation === A list of syscalls can be found in the manpage for <code>syscalls(2)</code> (note: this is different from the manpage for <code>syscall(2)</code> which is a generic syscall wrapper). Documentation for the C wrappers for most syscalls can be found in the manpage for that wrapper, usually in section 2 of the manual (e.g., <code>write(2)</code>, which is accessed using the command <code>man 2 write</code>).
== Using the syscall number macro definitions in asm code ==
The syscall macros can be used in an assembly program if that program is processed by the C preprocessor (cpp). The extension <code>.S</code> (uppercase instead of lowercase) is used to designate an assembler source file that must be processed by cpp.
Using either of these approaches, you can use the <code>__NR_''xxxx''</code> macros in your assembler code:
#include <asm/unistd.h>
...
mov $__NR_write,%rax