Appendix F: Linux System Call Tables
This appendix provides system call numbers and argument conventions for the three architectures covered in this book. All values are for the Linux kernel.
Argument conventions:
- x86-64: syscall instruction; number in RAX; args in RDI, RSI, RDX, R10, R8, R9; return in RAX
- ARM64: svc #0 instruction; number in X8; args in X0, X1, X2, X3, X4, X5; return in X0
- RISC-V: ecall instruction; number in a7; args in a0, a1, a2, a3, a4, a5; return in a0
Note: ARM64 and RISC-V Linux use the same syscall numbers (from the generic syscall table in include/uapi/asm-generic/unistd.h). x86-64 uses a separate historical table.
File I/O
| Name |
x86-64 |
ARM64 |
RISC-V |
Key Arguments |
read |
0 |
63 |
63 |
fd, buf, count → bytes read |
write |
1 |
64 |
64 |
fd, buf, count → bytes written |
open |
2 |
56 |
56 |
pathname, flags, mode → fd |
close |
3 |
57 |
57 |
fd → 0 |
stat |
4 |
80 |
80 |
pathname, struct stat * → 0 |
fstat |
5 |
80 |
80 |
fd, struct stat * → 0 |
lstat |
6 |
1039 |
1039 |
pathname, struct stat * (no follow symlink) → 0 |
poll |
7 |
73 |
73 |
fds, nfds, timeout → ready count |
lseek |
8 |
62 |
62 |
fd, offset, whence → new offset |
openat |
257 |
56 |
56 |
dirfd, pathname, flags, mode → fd |
readv |
19 |
65 |
65 |
fd, iov, iovcnt → bytes read |
writev |
20 |
66 |
66 |
fd, iov, iovcnt → bytes written |
pread64 |
17 |
67 |
67 |
fd, buf, count, offset → bytes read |
pwrite64 |
18 |
68 |
68 |
fd, buf, count, offset → bytes written |
readlink |
89 |
78 |
78 |
pathname, buf, bufsiz → len |
truncate |
76 |
45 |
45 |
pathname, length → 0 |
ftruncate |
77 |
46 |
46 |
fd, length → 0 |
getcwd |
79 |
17 |
17 |
buf, size → buf |
chdir |
80 |
49 |
49 |
pathname → 0 |
rename |
82 |
38 |
38 |
oldpath, newpath → 0 |
mkdir |
83 |
34 |
34 |
pathname, mode → 0 |
rmdir |
84 |
35 |
35 |
pathname → 0 |
unlink |
87 |
35 |
35 |
pathname → 0 |
symlink |
88 |
36 |
36 |
target, linkpath → 0 |
chmod |
90 |
52 |
52 |
pathname, mode → 0 |
fchmod |
91 |
52 |
52 |
fd, mode → 0 |
getdents64 |
217 |
61 |
61 |
fd, dirp, count → bytes read |
ioctl |
16 |
29 |
29 |
fd, request, arg → result |
fcntl |
72 |
25 |
25 |
fd, cmd, arg → result |
dup |
32 |
23 |
23 |
oldfd → newfd |
dup2 |
33 |
1041 |
1041 |
oldfd, newfd → newfd |
dup3 |
292 |
24 |
24 |
oldfd, newfd, flags → newfd |
pipe |
22 |
59 |
59 |
pipefd[2] → 0 |
pipe2 |
293 |
59 |
59 |
pipefd[2], flags → 0 |
Memory Management
| Name |
x86-64 |
ARM64 |
RISC-V |
Key Arguments |
mmap |
9 |
222 |
222 |
addr, length, prot, flags, fd, offset → addr |
mprotect |
10 |
226 |
226 |
addr, length, prot → 0 |
munmap |
11 |
215 |
215 |
addr, length → 0 |
brk |
12 |
214 |
214 |
addr → new brk |
mremap |
25 |
216 |
216 |
addr, old_len, new_len, flags, new_addr → addr |
msync |
26 |
227 |
227 |
addr, length, flags → 0 |
madvise |
28 |
233 |
233 |
addr, length, advice → 0 |
mincore |
27 |
232 |
232 |
addr, length, vec → 0 |
mlock |
149 |
228 |
228 |
addr, length → 0 |
munlock |
150 |
229 |
229 |
addr, length → 0 |
mmap Protection Flags (prot argument)
| Flag |
Value |
Meaning |
PROT_NONE |
0 |
No access |
PROT_READ |
1 |
Read permission |
PROT_WRITE |
2 |
Write permission |
PROT_EXEC |
4 |
Execute permission |
mmap Map Flags (flags argument)
| Flag |
Value |
Meaning |
MAP_SHARED |
1 |
Shared mapping |
MAP_PRIVATE |
2 |
Private copy-on-write mapping |
MAP_ANONYMOUS |
32 |
Not backed by a file |
MAP_FIXED |
16 |
Map at exactly addr |
MAP_POPULATE |
32768 |
Pre-fault pages |
Process and Thread Management
| Name |
x86-64 |
ARM64 |
RISC-V |
Key Arguments |
fork |
57 |
1079 |
1079 |
→ pid (0 in child, child pid in parent) |
vfork |
58 |
1071 |
1071 |
→ pid |
clone |
56 |
220 |
220 |
flags, child_stack, ptid, ctid, regs → tid |
execve |
59 |
221 |
221 |
filename, argv, envp → 0 (or error) |
execveat |
322 |
281 |
281 |
dirfd, filename, argv, envp, flags |
exit |
60 |
93 |
93 |
status code (no return) |
exit_group |
231 |
94 |
94 |
status code (exits all threads) |
wait4 |
61 |
1062 |
1062 |
pid, wstatus, options, rusage → pid |
waitid |
247 |
95 |
95 |
idtype, id, infop, options, rusage → 0 |
kill |
62 |
129 |
129 |
pid, sig → 0 |
tkill |
200 |
130 |
130 |
tid, sig → 0 |
getpid |
39 |
172 |
172 |
→ pid |
gettid |
186 |
178 |
178 |
→ tid |
getppid |
110 |
173 |
173 |
→ ppid |
getuid |
102 |
174 |
174 |
→ uid |
getgid |
104 |
176 |
176 |
→ gid |
geteuid |
107 |
175 |
175 |
→ euid |
getegid |
108 |
177 |
177 |
→ egid |
setuid |
105 |
146 |
146 |
uid → 0 |
setgid |
106 |
144 |
144 |
gid → 0 |
sched_yield |
24 |
124 |
124 |
→ 0 |
nanosleep |
35 |
101 |
101 |
req, rem → 0 |
getrusage |
98 |
165 |
165 |
who, usage → 0 |
times |
100 |
153 |
153 |
buf → clock ticks |
prctl |
157 |
167 |
167 |
option, arg2, arg3, arg4, arg5 → result |
arch_prctl |
158 |
— |
— |
code, addr → 0 (x86-64: sets FS/GS base) |
Signals
| Name |
x86-64 |
ARM64 |
RISC-V |
Key Arguments |
rt_sigaction |
13 |
134 |
134 |
sig, act, oact, sigsetsize → 0 |
rt_sigprocmask |
14 |
135 |
135 |
how, set, oldset, sigsetsize → 0 |
rt_sigreturn |
15 |
139 |
139 |
(no args; restores state from sigframe on stack) |
rt_sigsuspend |
130 |
133 |
133 |
mask, sigsetsize → -EINTR |
rt_sigpending |
127 |
136 |
136 |
set, sigsetsize → 0 |
alarm |
37 |
— |
— |
seconds → remaining alarm |
pause |
34 |
— |
— |
(wait for signal) |
signalfd4 |
289 |
74 |
74 |
fd, mask, sizemask, flags → fd |
Common Signal Numbers
| Signal |
Number |
Default Action |
Description |
| SIGHUP |
1 |
Terminate |
Hangup |
| SIGINT |
2 |
Terminate |
Interrupt (Ctrl+C) |
| SIGQUIT |
3 |
Core dump |
Quit |
| SIGILL |
4 |
Core dump |
Illegal instruction |
| SIGTRAP |
5 |
Core dump |
Trace/breakpoint trap |
| SIGABRT |
6 |
Core dump |
Abort signal |
| SIGBUS |
7 |
Core dump |
Bus error (bad memory access) |
| SIGFPE |
8 |
Core dump |
Floating-point exception |
| SIGKILL |
9 |
Terminate |
Kill (cannot be caught) |
| SIGSEGV |
11 |
Core dump |
Segmentation fault |
| SIGPIPE |
13 |
Terminate |
Broken pipe |
| SIGALRM |
14 |
Terminate |
Timer signal |
| SIGTERM |
15 |
Terminate |
Termination signal |
| SIGCHLD |
17 |
Ignore |
Child stopped or terminated |
| SIGCONT |
18 |
Continue |
Continue if stopped |
| SIGSTOP |
19 |
Stop |
Stop (cannot be caught) |
| SIGTSTP |
20 |
Stop |
Stop typed at terminal |
| SIGWINCH |
28 |
Ignore |
Window size changed |
Networking
| Name |
x86-64 |
ARM64 |
RISC-V |
Key Arguments |
socket |
41 |
198 |
198 |
domain, type, protocol → fd |
bind |
49 |
200 |
200 |
sockfd, addr, addrlen → 0 |
listen |
50 |
201 |
201 |
sockfd, backlog → 0 |
accept |
43 |
202 |
202 |
sockfd, addr, addrlen → fd |
accept4 |
288 |
242 |
242 |
sockfd, addr, addrlen, flags → fd |
connect |
42 |
203 |
203 |
sockfd, addr, addrlen → 0 |
recv |
— |
— |
— |
(use recvfrom with NULL addr) |
recvfrom |
45 |
207 |
207 |
sockfd, buf, len, flags, src_addr, addrlen |
send |
— |
— |
— |
(use sendto with NULL addr) |
sendto |
44 |
206 |
206 |
sockfd, buf, len, flags, dest_addr, addrlen |
setsockopt |
54 |
208 |
208 |
sockfd, level, optname, optval, optlen |
getsockopt |
55 |
209 |
209 |
sockfd, level, optname, optval, optlen |
shutdown |
48 |
210 |
210 |
sockfd, how → 0 |
getpeername |
52 |
205 |
205 |
sockfd, addr, addrlen → 0 |
getsockname |
51 |
204 |
204 |
sockfd, addr, addrlen → 0 |
Time
| Name |
x86-64 |
ARM64 |
RISC-V |
Key Arguments |
time |
201 |
1063 |
1063 |
tloc → seconds since epoch |
gettimeofday |
96 |
169 |
169 |
tv, tz → 0 |
clock_gettime |
228 |
113 |
113 |
clkid, tp → 0 |
clock_settime |
227 |
112 |
112 |
clkid, tp → 0 |
clock_getres |
229 |
114 |
114 |
clkid, res → 0 |
clock_nanosleep |
230 |
115 |
115 |
clkid, flags, req, rem → 0 |
timer_create |
222 |
107 |
107 |
clkid, evp, timerid → 0 |
timer_settime |
223 |
110 |
110 |
timerid, flags, new_value, old_value → 0 |
Clock IDs
| ID |
Value |
Description |
CLOCK_REALTIME |
0 |
Wall-clock time |
CLOCK_MONOTONIC |
1 |
Monotonic time since unspecified point |
CLOCK_PROCESS_CPUTIME_ID |
2 |
CPU time of calling process |
CLOCK_THREAD_CPUTIME_ID |
3 |
CPU time of calling thread |
CLOCK_MONOTONIC_RAW |
4 |
Hardware-based monotonic clock |
CLOCK_BOOTTIME |
7 |
Monotonic + suspend time |
Error Return Conventions
On success, most syscalls return 0 (or a positive value such as a file descriptor or byte count).
On error, syscalls return a negative value equal to the negated errno constant. For example:
- -2 = ENOENT (No such file or directory)
- -12 = ENOMEM (Out of memory)
- -22 = EINVAL (Invalid argument)
- -9 = EBADF (Bad file descriptor)
- -11 = EAGAIN / EWOULDBLOCK (Resource temporarily unavailable)
The C library wrapper functions (read(), write(), etc.) detect negative return values, negate them, store the result in errno, and return -1 to the calling C code.
In assembly, after syscall, check if rax is in the range -4095 to -1 to detect an error. The kernel guarantees that successful return values are not in this range (with the exception of mmap, which can return addresses near 0xFFFFFFFFFFFFF000).
Quick Assembly Templates
Hello World (x86-64)
section .data
msg db "Hello, World!", 10
msglen equ $ - msg
section .text
global _start
_start:
mov rax, 1 ; write
mov rdi, 1 ; stdout
lea rsi, [rel msg] ; buffer
mov rdx, msglen ; length
syscall
mov rax, 60 ; exit
xor rdi, rdi ; status 0
syscall
Hello World (ARM64)
.data
msg: .ascii "Hello, World!\n"
msglen = . - msg
.text
.global _start
_start:
mov x8, #64 // write
mov x0, #1 // stdout
adr x1, msg // buffer
mov x2, #msglen // length
svc #0
mov x8, #93 // exit
mov x0, #0 // status 0
svc #0
Hello World (RISC-V)
.data
msg: .ascii "Hello, World!\n"
msglen = . - msg
.text
.global _start
_start:
li a7, 64 # write
li a0, 1 # stdout
la a1, msg # buffer
li a2, msglen # length
ecall
li a7, 93 # exit
li a0, 0 # status 0
ecall