1,885
edits
Changes
Syscalls
,Created page with 'Category:Assembly Language The System call (''syscall'') mechanism is the mechanism used by an application to access kernel services. High-level languages will wrap the sysca…'
[[Category:Assembly Language]]
The System call (''syscall'') mechanism is the mechanism used by an application to access kernel services. 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 <code>write()</code> wrapper, or through more complex functions such as <code>printf()</code>.
== Syscall Mechanism ==
To invoke a syscall, load syscall number and arguments into the appropriate registers, and then invoke the platform-specific syscall mechanism.
=== x86 32-bit ===
* The syscall number is placed in eax.
* Arguments are placed in edi, esi, edx, ecx with spill over to the stack.
* Return value is in eax.
* The syscall is invoked with <code>int 0x80</code>
=== x86 64-bit ===
* The syscall number is placed in rax.
* Arguments are placed in rdi, rsi, rdx, rcx, r8d, r9d with spill over to the stack.
* Return value is in rax.
* The syscall is invoked with <code>syscall</code>
=== aarch64 ===
* The syscall number is placed in r8.
* Arguments are placed in r0-r7.
* Return value is in r0.
* The syscall is invoked with <code>svc 0</code>
== Syscall information, numbers, and arguments ==
=== Syscall numbers ===
Syscall numbers are defined in <nowiki><asm/unistd.h></nowiki> (<code>/usr/include/asm/unistd.h</code>). If you examine this file, you'll find that it includes different files depending on the platform, because the syscall numbers are platform-specific (on newer platforms, there has been an attempt to use consistent syscall numbers). In this included file, you will find macros for each syscall named <code>__NR_''syscall''</code> which identifies the number for each syscall. For example, aarch64 includes the file <code>/usr/include/asm-generic/unistd.h</code>, which lists this macro for the ''write'' syscall:
#define __NR_write 64
But on x86_64 the macro definition is taken from <code>/usr/include/asm/unistd_64.h</code>:
#define __NR_write 1
=== Syscall arguments and return values ===
The details of each syscall's arguments and return value are listed in <nowiki><unistd.h></nowiki> (<code>/usr/include/unistd.h</code>) in a combination of comments and C extern declarations.For example, for the '''write''' syscall:
/* Write N bytes of BUF to FD. Return the number written, or -1.
This function is a cancellation point and therefore not marked with
__THROW. */
extern ssize_t write (int __fd, const void *__buf, size_t __n) __wur;
So 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 macro definitions in asm code ==
The syscall macros can be used in a C program if that program is processed by the C preprocessor (cpp). The extension <code>,S</code> is used to designate an assembler source file that must be processed by cpp.
There are two ways to do this:
1. Invoke cpp explicitly:
cpp foo.S > foo.s
as foo.s -o foo.o
ld foo.o -o foo
2. Use ''gcc'' to invoke the assembler and linker:
gcc foo.S -o foo
{{Admon/important|Initialization Code and Entry Point|When the assembler is invoked through gcc, C initialization code is inserted into the binary, which increases its size. This initialization will look for the entry point <code>main</code> instead of <code>_start</code>.}}
The System call (''syscall'') mechanism is the mechanism used by an application to access kernel services. 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 <code>write()</code> wrapper, or through more complex functions such as <code>printf()</code>.
== Syscall Mechanism ==
To invoke a syscall, load syscall number and arguments into the appropriate registers, and then invoke the platform-specific syscall mechanism.
=== x86 32-bit ===
* The syscall number is placed in eax.
* Arguments are placed in edi, esi, edx, ecx with spill over to the stack.
* Return value is in eax.
* The syscall is invoked with <code>int 0x80</code>
=== x86 64-bit ===
* The syscall number is placed in rax.
* Arguments are placed in rdi, rsi, rdx, rcx, r8d, r9d with spill over to the stack.
* Return value is in rax.
* The syscall is invoked with <code>syscall</code>
=== aarch64 ===
* The syscall number is placed in r8.
* Arguments are placed in r0-r7.
* Return value is in r0.
* The syscall is invoked with <code>svc 0</code>
== Syscall information, numbers, and arguments ==
=== Syscall numbers ===
Syscall numbers are defined in <nowiki><asm/unistd.h></nowiki> (<code>/usr/include/asm/unistd.h</code>). If you examine this file, you'll find that it includes different files depending on the platform, because the syscall numbers are platform-specific (on newer platforms, there has been an attempt to use consistent syscall numbers). In this included file, you will find macros for each syscall named <code>__NR_''syscall''</code> which identifies the number for each syscall. For example, aarch64 includes the file <code>/usr/include/asm-generic/unistd.h</code>, which lists this macro for the ''write'' syscall:
#define __NR_write 64
But on x86_64 the macro definition is taken from <code>/usr/include/asm/unistd_64.h</code>:
#define __NR_write 1
=== Syscall arguments and return values ===
The details of each syscall's arguments and return value are listed in <nowiki><unistd.h></nowiki> (<code>/usr/include/unistd.h</code>) in a combination of comments and C extern declarations.For example, for the '''write''' syscall:
/* Write N bytes of BUF to FD. Return the number written, or -1.
This function is a cancellation point and therefore not marked with
__THROW. */
extern ssize_t write (int __fd, const void *__buf, size_t __n) __wur;
So 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 macro definitions in asm code ==
The syscall macros can be used in a C program if that program is processed by the C preprocessor (cpp). The extension <code>,S</code> is used to designate an assembler source file that must be processed by cpp.
There are two ways to do this:
1. Invoke cpp explicitly:
cpp foo.S > foo.s
as foo.s -o foo.o
ld foo.o -o foo
2. Use ''gcc'' to invoke the assembler and linker:
gcc foo.S -o foo
{{Admon/important|Initialization Code and Entry Point|When the assembler is invoked through gcc, C initialization code is inserted into the binary, which increases its size. This initialization will look for the entry point <code>main</code> instead of <code>_start</code>.}}