1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
3 * Copyright (C) 2017-2018 Willy Tarreau <w@1wt.eu>
7 * This file is designed to be used as a libc alternative for minimal programs
8 * with very limited requirements. It consists of a small number of syscall and
9 * type definitions, and the minimal startup code needed to call main().
10 * All syscalls are declared as static functions so that they can be optimized
11 * away by the compiler when not used.
13 * Syscalls are split into 3 levels:
14 * - The lower level is the arch-specific syscall() definition, consisting in
15 * assembly code in compound expressions. These are called my_syscall0() to
16 * my_syscall6() depending on the number of arguments. The MIPS
17 * implementation is limited to 5 arguments. All input arguments are cast
18 * to a long stored in a register. These expressions always return the
19 * syscall's return value as a signed long value which is often either a
20 * pointer or the negated errno value.
22 * - The second level is mostly architecture-independent. It is made of
23 * static functions called sys_<name>() which rely on my_syscallN()
24 * depending on the syscall definition. These functions are responsible
25 * for exposing the appropriate types for the syscall arguments (int,
26 * pointers, etc) and for setting the appropriate return type (often int).
27 * A few of them are architecture-specific because the syscalls are not all
28 * mapped exactly the same among architectures. For example, some archs do
29 * not implement select() and need pselect6() instead, so the sys_select()
30 * function will have to abstract this.
32 * - The third level is the libc call definition. It exposes the lower raw
33 * sys_<name>() calls in a way that looks like what a libc usually does,
34 * takes care of specific input values, and of setting errno upon error.
35 * There can be minor variations compared to standard libc calls. For
36 * example the open() call always takes 3 args here.
38 * The errno variable is declared static and unused. This way it can be
39 * optimized away if not used. However this means that a program made of
40 * multiple C files may observe different errno values (one per C file). For
41 * the type of programs this project targets it usually is not a problem. The
42 * resulting program may even be reduced by defining the NOLIBC_IGNORE_ERRNO
43 * macro, in which case the errno value will never be assigned.
45 * Some stdint-like integer types are defined. These are valid on all currently
46 * supported architectures, because signs are enforced, ints are assumed to be
47 * 32 bits, longs the size of a pointer and long long 64 bits. If more
48 * architectures have to be supported, this may need to be adapted.
50 * Some macro definitions like the O_* values passed to open(), and some
51 * structures like the sys_stat struct depend on the architecture.
53 * The definitions start with the architecture-specific parts, which are picked
54 * based on what the compiler knows about the target architecture, and are
55 * completed with the generic code. Since it is the compiler which sets the
56 * target architecture, cross-compiling normally works out of the box without
57 * having to specify anything.
59 * Finally some very common libc-level functions are provided. It is the case
60 * for a few functions usually found in string.h, ctype.h, or stdlib.h. Nothing
61 * is currently provided regarding stdio emulation.
63 * The macro NOLIBC is always defined, so that it is possible for a program to
64 * check this macro to know if it is being built against and decide to disable
65 * some features or simply not to include some standard libc files.
67 * Ideally this file should be split in multiple files for easier long term
68 * maintenance, but provided as a single file as it is now, it's quite
69 * convenient to use. Maybe some variations involving a set of includes at the
72 * A simple static executable may be built this way :
73 * $ gcc -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \
74 * -static -include nolibc.h -lgcc -o hello hello.c
76 * A very useful calling convention table may be found here :
77 * http://man7.org/linux/man-pages/man2/syscall.2.html
79 * This doc is quite convenient though not necessarily up to date :
80 * https://w3challs.com/syscalls/
84 /* Some archs (at least aarch64) don't expose the regular syscalls anymore by
85 * default, either because they have an "_at" replacement, or because there are
86 * more modern alternatives. For now we'd rather still use them.
88 #define __ARCH_WANT_SYSCALL_NO_AT
89 #define __ARCH_WANT_SYSCALL_NO_FLAGS
90 #define __ARCH_WANT_SYSCALL_DEPRECATED
92 #include <asm/unistd.h>
93 #include <asm/ioctls.h>
94 #include <asm/errno.h>
96 #include <linux/loop.h>
100 /* this way it will be removed if unused */
103 #ifndef NOLIBC_IGNORE_ERRNO
104 #define SET_ERRNO(v) do { errno = (v); } while (0)
106 #define SET_ERRNO(v) do { } while (0)
109 /* errno codes all ensure that they will not conflict with a valid pointer
110 * because they all correspond to the highest addressable memry page.
112 #define MAX_ERRNO 4095
114 /* Declare a few quite common macros and types that usually are in stdlib.h,
115 * stdint.h, ctype.h, unistd.h and a few other common locations.
118 #define NULL ((void *)0)
121 typedef unsigned char uint8_t;
122 typedef signed char int8_t;
123 typedef unsigned short uint16_t;
124 typedef signed short int16_t;
125 typedef unsigned int uint32_t;
126 typedef signed int int32_t;
127 typedef unsigned long long uint64_t;
128 typedef signed long long int64_t;
129 typedef unsigned long size_t;
130 typedef signed long ssize_t
;
131 typedef unsigned long uintptr_t;
132 typedef signed long intptr_t;
133 typedef signed long ptrdiff_t;
136 typedef unsigned int dev_t
;
137 typedef unsigned long ino_t
;
138 typedef unsigned int mode_t
;
139 typedef signed int pid_t
;
140 typedef unsigned int uid_t
;
141 typedef unsigned int gid_t
;
142 typedef unsigned long nlink_t
;
143 typedef signed long off_t
;
144 typedef signed long blksize_t
;
145 typedef signed long blkcnt_t
;
146 typedef signed long time_t;
167 /* for gettimeofday() */
173 /* for getdents64() */
174 struct linux_dirent64
{
177 unsigned short d_reclen
;
178 unsigned char d_type
;
182 /* commonly an fd_set represents 256 FDs */
183 #define FD_SETSIZE 256
184 typedef struct { uint32_t fd32
[FD_SETSIZE
/32]; } fd_set
;
186 /* needed by wait4() */
188 struct timeval ru_utime
;
189 struct timeval ru_stime
;
206 /* stat flags (WARNING, octal here) */
207 #define S_IFDIR 0040000
208 #define S_IFCHR 0020000
209 #define S_IFBLK 0060000
210 #define S_IFREG 0100000
211 #define S_IFIFO 0010000
212 #define S_IFLNK 0120000
213 #define S_IFSOCK 0140000
214 #define S_IFMT 0170000
216 #define S_ISDIR(mode) (((mode) & S_IFDIR) == S_IFDIR)
217 #define S_ISCHR(mode) (((mode) & S_IFCHR) == S_IFCHR)
218 #define S_ISBLK(mode) (((mode) & S_IFBLK) == S_IFBLK)
219 #define S_ISREG(mode) (((mode) & S_IFREG) == S_IFREG)
220 #define S_ISFIFO(mode) (((mode) & S_IFIFO) == S_IFIFO)
221 #define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK)
222 #define S_ISSOCK(mode) (((mode) & S_IFSOCK) == S_IFSOCK)
233 /* all the *at functions */
235 #define AT_FDCWD -100
244 #define LINUX_REBOOT_MAGIC1 0xfee1dead
245 #define LINUX_REBOOT_MAGIC2 0x28121969
246 #define LINUX_REBOOT_CMD_HALT 0xcdef0123
247 #define LINUX_REBOOT_CMD_POWER_OFF 0x4321fedc
248 #define LINUX_REBOOT_CMD_RESTART 0x01234567
249 #define LINUX_REBOOT_CMD_SW_SUSPEND 0xd000fce2
252 /* The format of the struct as returned by the libc to the application, which
253 * significantly differs from the format returned by the stat() syscall flavours.
256 dev_t st_dev
; /* ID of device containing file */
257 ino_t st_ino
; /* inode number */
258 mode_t st_mode
; /* protection */
259 nlink_t st_nlink
; /* number of hard links */
260 uid_t st_uid
; /* user ID of owner */
261 gid_t st_gid
; /* group ID of owner */
262 dev_t st_rdev
; /* device ID (if special file) */
263 off_t st_size
; /* total size, in bytes */
264 blksize_t st_blksize
; /* blocksize for file system I/O */
265 blkcnt_t st_blocks
; /* number of 512B blocks allocated */
266 time_t st_atime
; /* time of last access */
267 time_t st_mtime
; /* time of last modification */
268 time_t st_ctime
; /* time of last status change */
271 #define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
272 #define WIFEXITED(status) (((status) & 0x7f) == 0)
275 /* Below comes the architecture-specific code. For each architecture, we have
276 * the syscall declarations and the _start code definition. This is the only
277 * global part. On all architectures the kernel puts everything in the stack
278 * before jumping to _start just above us, without any return address (_start
279 * is not a function but an entry pint). So at the stack pointer we find argc.
280 * Then argv[] begins, and ends at the first NULL. Then we have envp which
281 * starts and ends with a NULL as well. So envp=argv+argc+1.
284 #if defined(__x86_64__)
285 /* Syscalls for x86_64 :
286 * - registers are 64-bit
287 * - syscall number is passed in rax
288 * - arguments are in rdi, rsi, rdx, r10, r8, r9 respectively
289 * - the system call is performed by calling the syscall instruction
290 * - syscall return comes in rax
291 * - rcx and r8..r11 may be clobbered, others are preserved.
292 * - the arguments are cast to long and assigned into the target registers
293 * which are then simply passed as registers to the asm code, so that we
294 * don't have to experience issues with register constraints.
295 * - the syscall number is always specified last in order to allow to force
296 * some registers before (gcc refuses a %-register at the last position).
299 #define my_syscall0(num) \
302 register long _num asm("rax") = (num); \
308 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \
313 #define my_syscall1(num, arg1) \
316 register long _num asm("rax") = (num); \
317 register long _arg1 asm("rdi") = (long)(arg1); \
324 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \
329 #define my_syscall2(num, arg1, arg2) \
332 register long _num asm("rax") = (num); \
333 register long _arg1 asm("rdi") = (long)(arg1); \
334 register long _arg2 asm("rsi") = (long)(arg2); \
339 : "r"(_arg1), "r"(_arg2), \
341 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \
346 #define my_syscall3(num, arg1, arg2, arg3) \
349 register long _num asm("rax") = (num); \
350 register long _arg1 asm("rdi") = (long)(arg1); \
351 register long _arg2 asm("rsi") = (long)(arg2); \
352 register long _arg3 asm("rdx") = (long)(arg3); \
357 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
359 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \
364 #define my_syscall4(num, arg1, arg2, arg3, arg4) \
367 register long _num asm("rax") = (num); \
368 register long _arg1 asm("rdi") = (long)(arg1); \
369 register long _arg2 asm("rsi") = (long)(arg2); \
370 register long _arg3 asm("rdx") = (long)(arg3); \
371 register long _arg4 asm("r10") = (long)(arg4); \
375 : "=a" (_ret), "=r"(_arg4) \
376 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
378 : "rcx", "r8", "r9", "r11", "memory", "cc" \
383 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
386 register long _num asm("rax") = (num); \
387 register long _arg1 asm("rdi") = (long)(arg1); \
388 register long _arg2 asm("rsi") = (long)(arg2); \
389 register long _arg3 asm("rdx") = (long)(arg3); \
390 register long _arg4 asm("r10") = (long)(arg4); \
391 register long _arg5 asm("r8") = (long)(arg5); \
395 : "=a" (_ret), "=r"(_arg4), "=r"(_arg5) \
396 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
398 : "rcx", "r9", "r11", "memory", "cc" \
403 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
406 register long _num asm("rax") = (num); \
407 register long _arg1 asm("rdi") = (long)(arg1); \
408 register long _arg2 asm("rsi") = (long)(arg2); \
409 register long _arg3 asm("rdx") = (long)(arg3); \
410 register long _arg4 asm("r10") = (long)(arg4); \
411 register long _arg5 asm("r8") = (long)(arg5); \
412 register long _arg6 asm("r9") = (long)(arg6); \
416 : "=a" (_ret), "=r"(_arg4), "=r"(_arg5) \
417 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
418 "r"(_arg6), "0"(_num) \
419 : "rcx", "r11", "memory", "cc" \
425 asm(".section .text\n"
428 "pop %rdi\n" // argc (first arg, %rdi)
429 "mov %rsp, %rsi\n" // argv[] (second arg, %rsi)
430 "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx)
431 "and $-16, %rsp\n" // x86 ABI : esp must be 16-byte aligned when
432 "sub $8, %rsp\n" // entering the callee
433 "call main\n" // main() returns the status code, we'll exit with it.
434 "movzb %al, %rdi\n" // retrieve exit code from 8 lower bits
435 "mov $60, %rax\n" // NR_exit == 60
436 "syscall\n" // really exit
437 "hlt\n" // ensure it does not return
446 #define O_NOCTTY 0x100
447 #define O_TRUNC 0x200
448 #define O_APPEND 0x400
449 #define O_NONBLOCK 0x800
450 #define O_DIRECTORY 0x10000
452 /* The struct returned by the stat() syscall, equivalent to stat64(). The
453 * syscall returns 116 bytes and stops in the middle of __unused.
455 struct sys_stat_struct
{
456 unsigned long st_dev
;
457 unsigned long st_ino
;
458 unsigned long st_nlink
;
459 unsigned int st_mode
;
464 unsigned long st_rdev
;
469 unsigned long st_atime
;
470 unsigned long st_atime_nsec
;
471 unsigned long st_mtime
;
473 unsigned long st_mtime_nsec
;
474 unsigned long st_ctime
;
475 unsigned long st_ctime_nsec
;
479 #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
480 /* Syscalls for i386 :
481 * - mostly similar to x86_64
482 * - registers are 32-bit
483 * - syscall number is passed in eax
484 * - arguments are in ebx, ecx, edx, esi, edi, ebp respectively
485 * - all registers are preserved (except eax of course)
486 * - the system call is performed by calling int $0x80
487 * - syscall return comes in eax
488 * - the arguments are cast to long and assigned into the target registers
489 * which are then simply passed as registers to the asm code, so that we
490 * don't have to experience issues with register constraints.
491 * - the syscall number is always specified last in order to allow to force
492 * some registers before (gcc refuses a %-register at the last position).
494 * Also, i386 supports the old_select syscall if newselect is not available
496 #define __ARCH_WANT_SYS_OLD_SELECT
498 #define my_syscall0(num) \
501 register long _num asm("eax") = (num); \
512 #define my_syscall1(num, arg1) \
515 register long _num asm("eax") = (num); \
516 register long _arg1 asm("ebx") = (long)(arg1); \
528 #define my_syscall2(num, arg1, arg2) \
531 register long _num asm("eax") = (num); \
532 register long _arg1 asm("ebx") = (long)(arg1); \
533 register long _arg2 asm("ecx") = (long)(arg2); \
538 : "r"(_arg1), "r"(_arg2), \
545 #define my_syscall3(num, arg1, arg2, arg3) \
548 register long _num asm("eax") = (num); \
549 register long _arg1 asm("ebx") = (long)(arg1); \
550 register long _arg2 asm("ecx") = (long)(arg2); \
551 register long _arg3 asm("edx") = (long)(arg3); \
556 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
563 #define my_syscall4(num, arg1, arg2, arg3, arg4) \
566 register long _num asm("eax") = (num); \
567 register long _arg1 asm("ebx") = (long)(arg1); \
568 register long _arg2 asm("ecx") = (long)(arg2); \
569 register long _arg3 asm("edx") = (long)(arg3); \
570 register long _arg4 asm("esi") = (long)(arg4); \
575 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
582 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
585 register long _num asm("eax") = (num); \
586 register long _arg1 asm("ebx") = (long)(arg1); \
587 register long _arg2 asm("ecx") = (long)(arg2); \
588 register long _arg3 asm("edx") = (long)(arg3); \
589 register long _arg4 asm("esi") = (long)(arg4); \
590 register long _arg5 asm("edi") = (long)(arg5); \
595 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
603 asm(".section .text\n"
606 "pop %eax\n" // argc (first arg, %eax)
607 "mov %esp, %ebx\n" // argv[] (second arg, %ebx)
608 "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx)
609 "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned when
610 "push %ecx\n" // push all registers on the stack so that we
611 "push %ebx\n" // support both regparm and plain stack modes
613 "call main\n" // main() returns the status code in %eax
614 "movzbl %al, %ebx\n" // retrieve exit code from lower 8 bits
615 "movl $1, %eax\n" // NR_exit == 1
616 "int $0x80\n" // exit now
617 "hlt\n" // ensure it does not
626 #define O_NOCTTY 0x100
627 #define O_TRUNC 0x200
628 #define O_APPEND 0x400
629 #define O_NONBLOCK 0x800
630 #define O_DIRECTORY 0x10000
632 /* The struct returned by the stat() syscall, 32-bit only, the syscall returns
633 * exactly 56 bytes (stops before the unused array).
635 struct sys_stat_struct
{
636 unsigned long st_dev
;
637 unsigned long st_ino
;
638 unsigned short st_mode
;
639 unsigned short st_nlink
;
640 unsigned short st_uid
;
641 unsigned short st_gid
;
643 unsigned long st_rdev
;
644 unsigned long st_size
;
645 unsigned long st_blksize
;
646 unsigned long st_blocks
;
648 unsigned long st_atime
;
649 unsigned long st_atime_nsec
;
650 unsigned long st_mtime
;
651 unsigned long st_mtime_nsec
;
653 unsigned long st_ctime
;
654 unsigned long st_ctime_nsec
;
655 unsigned long __unused
[2];
658 #elif defined(__ARM_EABI__)
659 /* Syscalls for ARM in ARM or Thumb modes :
660 * - registers are 32-bit
661 * - stack is 8-byte aligned
662 * ( http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html)
663 * - syscall number is passed in r7
664 * - arguments are in r0, r1, r2, r3, r4, r5
665 * - the system call is performed by calling svc #0
666 * - syscall return comes in r0.
667 * - only lr is clobbered.
668 * - the arguments are cast to long and assigned into the target registers
669 * which are then simply passed as registers to the asm code, so that we
670 * don't have to experience issues with register constraints.
671 * - the syscall number is always specified last in order to allow to force
672 * some registers before (gcc refuses a %-register at the last position).
674 * Also, ARM supports the old_select syscall if newselect is not available
676 #define __ARCH_WANT_SYS_OLD_SELECT
678 #define my_syscall0(num) \
680 register long _num asm("r7") = (num); \
681 register long _arg1 asm("r0"); \
687 : "memory", "cc", "lr" \
692 #define my_syscall1(num, arg1) \
694 register long _num asm("r7") = (num); \
695 register long _arg1 asm("r0") = (long)(arg1); \
702 : "memory", "cc", "lr" \
707 #define my_syscall2(num, arg1, arg2) \
709 register long _num asm("r7") = (num); \
710 register long _arg1 asm("r0") = (long)(arg1); \
711 register long _arg2 asm("r1") = (long)(arg2); \
716 : "r"(_arg1), "r"(_arg2), \
718 : "memory", "cc", "lr" \
723 #define my_syscall3(num, arg1, arg2, arg3) \
725 register long _num asm("r7") = (num); \
726 register long _arg1 asm("r0") = (long)(arg1); \
727 register long _arg2 asm("r1") = (long)(arg2); \
728 register long _arg3 asm("r2") = (long)(arg3); \
733 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
735 : "memory", "cc", "lr" \
740 #define my_syscall4(num, arg1, arg2, arg3, arg4) \
742 register long _num asm("r7") = (num); \
743 register long _arg1 asm("r0") = (long)(arg1); \
744 register long _arg2 asm("r1") = (long)(arg2); \
745 register long _arg3 asm("r2") = (long)(arg3); \
746 register long _arg4 asm("r3") = (long)(arg4); \
751 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
753 : "memory", "cc", "lr" \
758 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
760 register long _num asm("r7") = (num); \
761 register long _arg1 asm("r0") = (long)(arg1); \
762 register long _arg2 asm("r1") = (long)(arg2); \
763 register long _arg3 asm("r2") = (long)(arg3); \
764 register long _arg4 asm("r3") = (long)(arg4); \
765 register long _arg5 asm("r4") = (long)(arg5); \
770 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
772 : "memory", "cc", "lr" \
778 asm(".section .text\n"
781 #if defined(__THUMBEB__) || defined(__THUMBEL__)
782 /* We enter here in 32-bit mode but if some previous functions were in
783 * 16-bit mode, the assembler cannot know, so we need to tell it we're in
784 * 32-bit now, then switch to 16-bit (is there a better way to do it than
785 * adding 1 by hand ?) and tell the asm we're now in 16-bit mode so that
786 * it generates correct instructions. Note that we do not support thumb1.
793 "pop {%r0}\n" // argc was in the stack
794 "mov %r1, %sp\n" // argv = sp
795 "add %r2, %r1, %r0, lsl #2\n" // envp = argv + 4*argc ...
796 "add %r2, %r2, $4\n" // ... + 4
797 "and %r3, %r1, $-8\n" // AAPCS : sp must be 8-byte aligned in the
798 "mov %sp, %r3\n" // callee, an bl doesn't push (lr=pc)
799 "bl main\n" // main() returns the status code, we'll exit with it.
800 "and %r0, %r0, $0xff\n" // limit exit code to 8 bits
801 "movs r7, $1\n" // NR_exit == 1
811 #define O_NOCTTY 0x100
812 #define O_TRUNC 0x200
813 #define O_APPEND 0x400
814 #define O_NONBLOCK 0x800
815 #define O_DIRECTORY 0x4000
817 /* The struct returned by the stat() syscall, 32-bit only, the syscall returns
818 * exactly 56 bytes (stops before the unused array). In big endian, the format
819 * differs as devices are returned as short only.
821 struct sys_stat_struct
{
822 #if defined(__ARMEB__)
823 unsigned short st_dev
;
824 unsigned short __pad1
;
826 unsigned long st_dev
;
828 unsigned long st_ino
;
829 unsigned short st_mode
;
830 unsigned short st_nlink
;
831 unsigned short st_uid
;
832 unsigned short st_gid
;
833 #if defined(__ARMEB__)
834 unsigned short st_rdev
;
835 unsigned short __pad2
;
837 unsigned long st_rdev
;
839 unsigned long st_size
;
840 unsigned long st_blksize
;
841 unsigned long st_blocks
;
842 unsigned long st_atime
;
843 unsigned long st_atime_nsec
;
844 unsigned long st_mtime
;
845 unsigned long st_mtime_nsec
;
846 unsigned long st_ctime
;
847 unsigned long st_ctime_nsec
;
848 unsigned long __unused
[2];
851 #elif defined(__aarch64__)
852 /* Syscalls for AARCH64 :
853 * - registers are 64-bit
854 * - stack is 16-byte aligned
855 * - syscall number is passed in x8
856 * - arguments are in x0, x1, x2, x3, x4, x5
857 * - the system call is performed by calling svc 0
858 * - syscall return comes in x0.
859 * - the arguments are cast to long and assigned into the target registers
860 * which are then simply passed as registers to the asm code, so that we
861 * don't have to experience issues with register constraints.
863 * On aarch64, select() is not implemented so we have to use pselect6().
865 #define __ARCH_WANT_SYS_PSELECT6
867 #define my_syscall0(num) \
869 register long _num asm("x8") = (num); \
870 register long _arg1 asm("x0"); \
881 #define my_syscall1(num, arg1) \
883 register long _num asm("x8") = (num); \
884 register long _arg1 asm("x0") = (long)(arg1); \
896 #define my_syscall2(num, arg1, arg2) \
898 register long _num asm("x8") = (num); \
899 register long _arg1 asm("x0") = (long)(arg1); \
900 register long _arg2 asm("x1") = (long)(arg2); \
905 : "r"(_arg1), "r"(_arg2), \
912 #define my_syscall3(num, arg1, arg2, arg3) \
914 register long _num asm("x8") = (num); \
915 register long _arg1 asm("x0") = (long)(arg1); \
916 register long _arg2 asm("x1") = (long)(arg2); \
917 register long _arg3 asm("x2") = (long)(arg3); \
922 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
929 #define my_syscall4(num, arg1, arg2, arg3, arg4) \
931 register long _num asm("x8") = (num); \
932 register long _arg1 asm("x0") = (long)(arg1); \
933 register long _arg2 asm("x1") = (long)(arg2); \
934 register long _arg3 asm("x2") = (long)(arg3); \
935 register long _arg4 asm("x3") = (long)(arg4); \
940 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
947 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
949 register long _num asm("x8") = (num); \
950 register long _arg1 asm("x0") = (long)(arg1); \
951 register long _arg2 asm("x1") = (long)(arg2); \
952 register long _arg3 asm("x2") = (long)(arg3); \
953 register long _arg4 asm("x3") = (long)(arg4); \
954 register long _arg5 asm("x4") = (long)(arg5); \
959 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
966 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
968 register long _num asm("x8") = (num); \
969 register long _arg1 asm("x0") = (long)(arg1); \
970 register long _arg2 asm("x1") = (long)(arg2); \
971 register long _arg3 asm("x2") = (long)(arg3); \
972 register long _arg4 asm("x3") = (long)(arg4); \
973 register long _arg5 asm("x4") = (long)(arg5); \
974 register long _arg6 asm("x5") = (long)(arg6); \
979 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
980 "r"(_arg6), "r"(_num) \
987 asm(".section .text\n"
990 "ldr x0, [sp]\n" // argc (x0) was in the stack
991 "add x1, sp, 8\n" // argv (x1) = sp
992 "lsl x2, x0, 3\n" // envp (x2) = 8*argc ...
993 "add x2, x2, 8\n" // + 8 (skip null)
994 "add x2, x2, x1\n" // + argv
995 "and sp, x1, -16\n" // sp must be 16-byte aligned in the callee
996 "bl main\n" // main() returns the status code, we'll exit with it.
997 "and x0, x0, 0xff\n" // limit exit code to 8 bits
998 "mov x8, 93\n" // NR_exit == 93
1006 #define O_CREAT 0x40
1008 #define O_NOCTTY 0x100
1009 #define O_TRUNC 0x200
1010 #define O_APPEND 0x400
1011 #define O_NONBLOCK 0x800
1012 #define O_DIRECTORY 0x4000
1014 /* The struct returned by the newfstatat() syscall. Differs slightly from the
1015 * x86_64's stat one by field ordering, so be careful.
1017 struct sys_stat_struct
{
1018 unsigned long st_dev
;
1019 unsigned long st_ino
;
1020 unsigned int st_mode
;
1021 unsigned int st_nlink
;
1022 unsigned int st_uid
;
1023 unsigned int st_gid
;
1025 unsigned long st_rdev
;
1026 unsigned long __pad1
;
1033 unsigned long st_atime_nsec
;
1036 unsigned long st_mtime_nsec
;
1038 unsigned long st_ctime_nsec
;
1039 unsigned int __unused
[2];
1042 #elif defined(__mips__) && defined(_ABIO32)
1043 /* Syscalls for MIPS ABI O32 :
1044 * - WARNING! there's always a delayed slot!
1045 * - WARNING again, the syntax is different, registers take a '$' and numbers
1047 * - registers are 32-bit
1048 * - stack is 8-byte aligned
1049 * - syscall number is passed in v0 (starts at 0xfa0).
1050 * - arguments are in a0, a1, a2, a3, then the stack. The caller needs to
1051 * leave some room in the stack for the callee to save a0..a3 if needed.
1052 * - Many registers are clobbered, in fact only a0..a2 and s0..s8 are
1053 * preserved. See: https://www.linux-mips.org/wiki/Syscall as well as
1054 * scall32-o32.S in the kernel sources.
1055 * - the system call is performed by calling "syscall"
1056 * - syscall return comes in v0, and register a3 needs to be checked to know
1057 * if an error occured, in which case errno is in v0.
1058 * - the arguments are cast to long and assigned into the target registers
1059 * which are then simply passed as registers to the asm code, so that we
1060 * don't have to experience issues with register constraints.
1063 #define my_syscall0(num) \
1065 register long _num asm("v0") = (num); \
1066 register long _arg4 asm("a3"); \
1069 "addiu $sp, $sp, -32\n" \
1071 "addiu $sp, $sp, 32\n" \
1072 : "=r"(_num), "=r"(_arg4) \
1074 : "memory", "cc", "at", "v1", "hi", "lo", \
1075 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
1077 _arg4 ? -_num : _num; \
1080 #define my_syscall1(num, arg1) \
1082 register long _num asm("v0") = (num); \
1083 register long _arg1 asm("a0") = (long)(arg1); \
1084 register long _arg4 asm("a3"); \
1087 "addiu $sp, $sp, -32\n" \
1089 "addiu $sp, $sp, 32\n" \
1090 : "=r"(_num), "=r"(_arg4) \
1093 : "memory", "cc", "at", "v1", "hi", "lo", \
1094 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
1096 _arg4 ? -_num : _num; \
1099 #define my_syscall2(num, arg1, arg2) \
1101 register long _num asm("v0") = (num); \
1102 register long _arg1 asm("a0") = (long)(arg1); \
1103 register long _arg2 asm("a1") = (long)(arg2); \
1104 register long _arg4 asm("a3"); \
1107 "addiu $sp, $sp, -32\n" \
1109 "addiu $sp, $sp, 32\n" \
1110 : "=r"(_num), "=r"(_arg4) \
1112 "r"(_arg1), "r"(_arg2) \
1113 : "memory", "cc", "at", "v1", "hi", "lo", \
1114 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
1116 _arg4 ? -_num : _num; \
1119 #define my_syscall3(num, arg1, arg2, arg3) \
1121 register long _num asm("v0") = (num); \
1122 register long _arg1 asm("a0") = (long)(arg1); \
1123 register long _arg2 asm("a1") = (long)(arg2); \
1124 register long _arg3 asm("a2") = (long)(arg3); \
1125 register long _arg4 asm("a3"); \
1128 "addiu $sp, $sp, -32\n" \
1130 "addiu $sp, $sp, 32\n" \
1131 : "=r"(_num), "=r"(_arg4) \
1133 "r"(_arg1), "r"(_arg2), "r"(_arg3) \
1134 : "memory", "cc", "at", "v1", "hi", "lo", \
1135 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
1137 _arg4 ? -_num : _num; \
1140 #define my_syscall4(num, arg1, arg2, arg3, arg4) \
1142 register long _num asm("v0") = (num); \
1143 register long _arg1 asm("a0") = (long)(arg1); \
1144 register long _arg2 asm("a1") = (long)(arg2); \
1145 register long _arg3 asm("a2") = (long)(arg3); \
1146 register long _arg4 asm("a3") = (long)(arg4); \
1149 "addiu $sp, $sp, -32\n" \
1151 "addiu $sp, $sp, 32\n" \
1152 : "=r" (_num), "=r"(_arg4) \
1154 "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \
1155 : "memory", "cc", "at", "v1", "hi", "lo", \
1156 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
1158 _arg4 ? -_num : _num; \
1161 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
1163 register long _num asm("v0") = (num); \
1164 register long _arg1 asm("a0") = (long)(arg1); \
1165 register long _arg2 asm("a1") = (long)(arg2); \
1166 register long _arg3 asm("a2") = (long)(arg3); \
1167 register long _arg4 asm("a3") = (long)(arg4); \
1168 register long _arg5 = (long)(arg5); \
1171 "addiu $sp, $sp, -32\n" \
1172 "sw %7, 16($sp)\n" \
1174 "addiu $sp, $sp, 32\n" \
1175 : "=r" (_num), "=r"(_arg4) \
1177 "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \
1178 : "memory", "cc", "at", "v1", "hi", "lo", \
1179 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
1181 _arg4 ? -_num : _num; \
1184 /* startup code, note that it's called __start on MIPS */
1185 asm(".section .text\n"
1192 "lw $a0,($sp)\n" // argc was in the stack
1193 "addiu $a1, $sp, 4\n" // argv = sp + 4
1194 "sll $a2, $a0, 2\n" // a2 = argc * 4
1195 "add $a2, $a2, $a1\n" // envp = argv + 4*argc ...
1196 "addiu $a2, $a2, 4\n" // ... + 4
1198 "and $sp, $sp, $t0\n" // sp must be 8-byte aligned
1199 "addiu $sp,$sp,-16\n" // the callee expects to save a0..a3 there!
1200 "jal main\n" // main() returns the status code, we'll exit with it.
1201 "nop\n" // delayed slot
1202 "and $a0, $v0, 0xff\n" // limit exit code to 8 bits
1203 "li $v0, 4001\n" // NR_exit == 4001
1212 #define O_APPEND 0x0008
1213 #define O_NONBLOCK 0x0080
1214 #define O_CREAT 0x0100
1215 #define O_TRUNC 0x0200
1216 #define O_EXCL 0x0400
1217 #define O_NOCTTY 0x0800
1218 #define O_DIRECTORY 0x10000
1220 /* The struct returned by the stat() syscall. 88 bytes are returned by the
1223 struct sys_stat_struct
{
1224 unsigned int st_dev
;
1226 unsigned long st_ino
;
1227 unsigned int st_mode
;
1228 unsigned int st_nlink
;
1229 unsigned int st_uid
;
1230 unsigned int st_gid
;
1231 unsigned int st_rdev
;
1246 #elif defined(__riscv)
1248 #if __riscv_xlen == 64
1251 #elif __riscv_xlen == 32
1256 /* Syscalls for RISCV :
1257 * - stack is 16-byte aligned
1258 * - syscall number is passed in a7
1259 * - arguments are in a0, a1, a2, a3, a4, a5
1260 * - the system call is performed by calling ecall
1261 * - syscall return comes in a0
1262 * - the arguments are cast to long and assigned into the target
1263 * registers which are then simply passed as registers to the asm code,
1264 * so that we don't have to experience issues with register constraints.
1267 #define my_syscall0(num) \
1269 register long _num asm("a7") = (num); \
1270 register long _arg1 asm("a0"); \
1281 #define my_syscall1(num, arg1) \
1283 register long _num asm("a7") = (num); \
1284 register long _arg1 asm("a0") = (long)(arg1); \
1295 #define my_syscall2(num, arg1, arg2) \
1297 register long _num asm("a7") = (num); \
1298 register long _arg1 asm("a0") = (long)(arg1); \
1299 register long _arg2 asm("a1") = (long)(arg2); \
1311 #define my_syscall3(num, arg1, arg2, arg3) \
1313 register long _num asm("a7") = (num); \
1314 register long _arg1 asm("a0") = (long)(arg1); \
1315 register long _arg2 asm("a1") = (long)(arg2); \
1316 register long _arg3 asm("a2") = (long)(arg3); \
1321 : "r"(_arg2), "r"(_arg3), \
1328 #define my_syscall4(num, arg1, arg2, arg3, arg4) \
1330 register long _num asm("a7") = (num); \
1331 register long _arg1 asm("a0") = (long)(arg1); \
1332 register long _arg2 asm("a1") = (long)(arg2); \
1333 register long _arg3 asm("a2") = (long)(arg3); \
1334 register long _arg4 asm("a3") = (long)(arg4); \
1339 : "r"(_arg2), "r"(_arg3), "r"(_arg4), \
1346 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
1348 register long _num asm("a7") = (num); \
1349 register long _arg1 asm("a0") = (long)(arg1); \
1350 register long _arg2 asm("a1") = (long)(arg2); \
1351 register long _arg3 asm("a2") = (long)(arg3); \
1352 register long _arg4 asm("a3") = (long)(arg4); \
1353 register long _arg5 asm("a4") = (long)(arg5); \
1358 : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
1365 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
1367 register long _num asm("a7") = (num); \
1368 register long _arg1 asm("a0") = (long)(arg1); \
1369 register long _arg2 asm("a1") = (long)(arg2); \
1370 register long _arg3 asm("a2") = (long)(arg3); \
1371 register long _arg4 asm("a3") = (long)(arg4); \
1372 register long _arg5 asm("a4") = (long)(arg5); \
1373 register long _arg6 asm("a5") = (long)(arg6); \
1378 : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
1386 asm(".section .text\n"
1391 "lla gp, __global_pointer$\n"
1393 "ld a0, 0(sp)\n" // argc (a0) was in the stack
1394 "add a1, sp, "SZREG
"\n" // argv (a1) = sp
1395 "slli a2, a0, "PTRLOG
"\n" // envp (a2) = SZREG*argc ...
1396 "add a2, a2, "SZREG
"\n" // + SZREG (skip null)
1397 "add a2,a2,a1\n" // + argv
1398 "andi sp,a1,-16\n" // sp must be 16-byte aligned
1399 "call main\n" // main() returns the status code, we'll exit with it.
1400 "andi a0, a0, 0xff\n" // limit exit code to 8 bits
1401 "li a7, 93\n" // NR_exit == 93
1409 #define O_CREAT 0x100
1410 #define O_EXCL 0x200
1411 #define O_NOCTTY 0x400
1412 #define O_TRUNC 0x1000
1413 #define O_APPEND 0x2000
1414 #define O_NONBLOCK 0x4000
1415 #define O_DIRECTORY 0x200000
1417 struct sys_stat_struct
{
1418 unsigned long st_dev
; /* Device. */
1419 unsigned long st_ino
; /* File serial number. */
1420 unsigned int st_mode
; /* File mode. */
1421 unsigned int st_nlink
; /* Link count. */
1422 unsigned int st_uid
; /* User ID of the file's owner. */
1423 unsigned int st_gid
; /* Group ID of the file's group. */
1424 unsigned long st_rdev
; /* Device number, if device. */
1425 unsigned long __pad1
;
1426 long st_size
; /* Size of file, in bytes. */
1427 int st_blksize
; /* Optimal block size for I/O. */
1429 long st_blocks
; /* Number 512-byte blocks allocated. */
1430 long st_atime
; /* Time of last access. */
1431 unsigned long st_atime_nsec
;
1432 long st_mtime
; /* Time of last modification. */
1433 unsigned long st_mtime_nsec
;
1434 long st_ctime
; /* Time of last status change. */
1435 unsigned long st_ctime_nsec
;
1436 unsigned int __unused4
;
1437 unsigned int __unused5
;
1443 /* Below are the C functions used to declare the raw syscalls. They try to be
1444 * architecture-agnostic, and return either a success or -errno. Declaring them
1445 * static will lead to them being inlined in most cases, but it's still possible
1446 * to reference them by a pointer if needed.
1448 static __attribute__((unused
))
1449 void *sys_brk(void *addr
)
1451 return (void *)my_syscall1(__NR_brk
, addr
);
1454 static __attribute__((noreturn
,unused
))
1455 void sys_exit(int status
)
1457 my_syscall1(__NR_exit
, status
& 255);
1458 while(1); // shut the "noreturn" warnings.
1461 static __attribute__((unused
))
1462 int sys_chdir(const char *path
)
1464 return my_syscall1(__NR_chdir
, path
);
1467 static __attribute__((unused
))
1468 int sys_chmod(const char *path
, mode_t mode
)
1470 #ifdef __NR_fchmodat
1471 return my_syscall4(__NR_fchmodat
, AT_FDCWD
, path
, mode
, 0);
1473 return my_syscall2(__NR_chmod
, path
, mode
);
1477 static __attribute__((unused
))
1478 int sys_chown(const char *path
, uid_t owner
, gid_t group
)
1480 #ifdef __NR_fchownat
1481 return my_syscall5(__NR_fchownat
, AT_FDCWD
, path
, owner
, group
, 0);
1483 return my_syscall3(__NR_chown
, path
, owner
, group
);
1487 static __attribute__((unused
))
1488 int sys_chroot(const char *path
)
1490 return my_syscall1(__NR_chroot
, path
);
1493 static __attribute__((unused
))
1494 int sys_close(int fd
)
1496 return my_syscall1(__NR_close
, fd
);
1499 static __attribute__((unused
))
1502 return my_syscall1(__NR_dup
, fd
);
1505 static __attribute__((unused
))
1506 int sys_dup2(int old
, int new)
1508 return my_syscall2(__NR_dup2
, old
, new);
1511 static __attribute__((unused
))
1512 int sys_execve(const char *filename
, char *const argv
[], char *const envp
[])
1514 return my_syscall3(__NR_execve
, filename
, argv
, envp
);
1517 static __attribute__((unused
))
1518 pid_t
sys_fork(void)
1520 return my_syscall0(__NR_fork
);
1523 static __attribute__((unused
))
1524 int sys_fsync(int fd
)
1526 return my_syscall1(__NR_fsync
, fd
);
1529 static __attribute__((unused
))
1530 int sys_getdents64(int fd
, struct linux_dirent64
*dirp
, int count
)
1532 return my_syscall3(__NR_getdents64
, fd
, dirp
, count
);
1535 static __attribute__((unused
))
1536 pid_t
sys_getpgrp(void)
1538 return my_syscall0(__NR_getpgrp
);
1541 static __attribute__((unused
))
1542 pid_t
sys_getpid(void)
1544 return my_syscall0(__NR_getpid
);
1547 static __attribute__((unused
))
1548 int sys_gettimeofday(struct timeval
*tv
, struct timezone
*tz
)
1550 return my_syscall2(__NR_gettimeofday
, tv
, tz
);
1553 static __attribute__((unused
))
1554 int sys_ioctl(int fd
, unsigned long req
, void *value
)
1556 return my_syscall3(__NR_ioctl
, fd
, req
, value
);
1559 static __attribute__((unused
))
1560 int sys_kill(pid_t pid
, int signal
)
1562 return my_syscall2(__NR_kill
, pid
, signal
);
1565 static __attribute__((unused
))
1566 int sys_link(const char *old
, const char *new)
1569 return my_syscall5(__NR_linkat
, AT_FDCWD
, old
, AT_FDCWD
, new, 0);
1571 return my_syscall2(__NR_link
, old
, new);
1575 static __attribute__((unused
))
1576 off_t
sys_lseek(int fd
, off_t offset
, int whence
)
1578 return my_syscall3(__NR_lseek
, fd
, offset
, whence
);
1581 static __attribute__((unused
))
1582 int sys_mkdir(const char *path
, mode_t mode
)
1585 return my_syscall3(__NR_mkdirat
, AT_FDCWD
, path
, mode
);
1587 return my_syscall2(__NR_mkdir
, path
, mode
);
1591 static __attribute__((unused
))
1592 long sys_mknod(const char *path
, mode_t mode
, dev_t dev
)
1595 return my_syscall4(__NR_mknodat
, AT_FDCWD
, path
, mode
, dev
);
1597 return my_syscall3(__NR_mknod
, path
, mode
, dev
);
1601 static __attribute__((unused
))
1602 int sys_mount(const char *src
, const char *tgt
, const char *fst
,
1603 unsigned long flags
, const void *data
)
1605 return my_syscall5(__NR_mount
, src
, tgt
, fst
, flags
, data
);
1608 static __attribute__((unused
))
1609 int sys_open(const char *path
, int flags
, mode_t mode
)
1612 return my_syscall4(__NR_openat
, AT_FDCWD
, path
, flags
, mode
);
1614 return my_syscall3(__NR_open
, path
, flags
, mode
);
1618 static __attribute__((unused
))
1619 int sys_pivot_root(const char *new, const char *old
)
1621 return my_syscall2(__NR_pivot_root
, new, old
);
1624 static __attribute__((unused
))
1625 int sys_poll(struct pollfd
*fds
, int nfds
, int timeout
)
1627 return my_syscall3(__NR_poll
, fds
, nfds
, timeout
);
1630 static __attribute__((unused
))
1631 ssize_t
sys_read(int fd
, void *buf
, size_t count
)
1633 return my_syscall3(__NR_read
, fd
, buf
, count
);
1636 static __attribute__((unused
))
1637 ssize_t
sys_reboot(int magic1
, int magic2
, int cmd
, void *arg
)
1639 return my_syscall4(__NR_reboot
, magic1
, magic2
, cmd
, arg
);
1642 static __attribute__((unused
))
1643 int sys_sched_yield(void)
1645 return my_syscall0(__NR_sched_yield
);
1648 static __attribute__((unused
))
1649 int sys_select(int nfds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efds
, struct timeval
*timeout
)
1651 #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect)
1652 struct sel_arg_struct
{
1656 } arg
= { .n
= nfds
, .r
= rfds
, .w
= wfds
, .e
= efds
, .t
= timeout
};
1657 return my_syscall1(__NR_select
, &arg
);
1658 #elif defined(__ARCH_WANT_SYS_PSELECT6) && defined(__NR_pselect6)
1662 t
.tv_sec
= timeout
->tv_sec
;
1663 t
.tv_nsec
= timeout
->tv_usec
* 1000;
1665 return my_syscall6(__NR_pselect6
, nfds
, rfds
, wfds
, efds
, timeout
? &t
: NULL
, NULL
);
1667 #ifndef __NR__newselect
1668 #define __NR__newselect __NR_select
1670 return my_syscall5(__NR__newselect
, nfds
, rfds
, wfds
, efds
, timeout
);
1674 static __attribute__((unused
))
1675 int sys_setpgid(pid_t pid
, pid_t pgid
)
1677 return my_syscall2(__NR_setpgid
, pid
, pgid
);
1680 static __attribute__((unused
))
1681 pid_t
sys_setsid(void)
1683 return my_syscall0(__NR_setsid
);
1686 static __attribute__((unused
))
1687 int sys_stat(const char *path
, struct stat
*buf
)
1689 struct sys_stat_struct stat
;
1692 #ifdef __NR_newfstatat
1693 /* only solution for arm64 */
1694 ret
= my_syscall4(__NR_newfstatat
, AT_FDCWD
, path
, &stat
, 0);
1696 ret
= my_syscall2(__NR_stat
, path
, &stat
);
1698 buf
->st_dev
= stat
.st_dev
;
1699 buf
->st_ino
= stat
.st_ino
;
1700 buf
->st_mode
= stat
.st_mode
;
1701 buf
->st_nlink
= stat
.st_nlink
;
1702 buf
->st_uid
= stat
.st_uid
;
1703 buf
->st_gid
= stat
.st_gid
;
1704 buf
->st_rdev
= stat
.st_rdev
;
1705 buf
->st_size
= stat
.st_size
;
1706 buf
->st_blksize
= stat
.st_blksize
;
1707 buf
->st_blocks
= stat
.st_blocks
;
1708 buf
->st_atime
= stat
.st_atime
;
1709 buf
->st_mtime
= stat
.st_mtime
;
1710 buf
->st_ctime
= stat
.st_ctime
;
1715 static __attribute__((unused
))
1716 int sys_symlink(const char *old
, const char *new)
1718 #ifdef __NR_symlinkat
1719 return my_syscall3(__NR_symlinkat
, old
, AT_FDCWD
, new);
1721 return my_syscall2(__NR_symlink
, old
, new);
1725 static __attribute__((unused
))
1726 mode_t
sys_umask(mode_t mode
)
1728 return my_syscall1(__NR_umask
, mode
);
1731 static __attribute__((unused
))
1732 int sys_umount2(const char *path
, int flags
)
1734 return my_syscall2(__NR_umount2
, path
, flags
);
1737 static __attribute__((unused
))
1738 int sys_unlink(const char *path
)
1740 #ifdef __NR_unlinkat
1741 return my_syscall3(__NR_unlinkat
, AT_FDCWD
, path
, 0);
1743 return my_syscall1(__NR_unlink
, path
);
1747 static __attribute__((unused
))
1748 pid_t
sys_wait4(pid_t pid
, int *status
, int options
, struct rusage
*rusage
)
1750 return my_syscall4(__NR_wait4
, pid
, status
, options
, rusage
);
1753 static __attribute__((unused
))
1754 pid_t
sys_waitpid(pid_t pid
, int *status
, int options
)
1756 return sys_wait4(pid
, status
, options
, 0);
1759 static __attribute__((unused
))
1760 pid_t
sys_wait(int *status
)
1762 return sys_waitpid(-1, status
, 0);
1765 static __attribute__((unused
))
1766 ssize_t
sys_write(int fd
, const void *buf
, size_t count
)
1768 return my_syscall3(__NR_write
, fd
, buf
, count
);
1772 /* Below are the libc-compatible syscalls which return x or -1 and set errno.
1773 * They rely on the functions above. Similarly they're marked static so that it
1774 * is possible to assign pointers to them if needed.
1777 static __attribute__((unused
))
1780 void *ret
= sys_brk(addr
);
1789 static __attribute__((noreturn
,unused
))
1790 void exit(int status
)
1795 static __attribute__((unused
))
1796 int chdir(const char *path
)
1798 int ret
= sys_chdir(path
);
1807 static __attribute__((unused
))
1808 int chmod(const char *path
, mode_t mode
)
1810 int ret
= sys_chmod(path
, mode
);
1819 static __attribute__((unused
))
1820 int chown(const char *path
, uid_t owner
, gid_t group
)
1822 int ret
= sys_chown(path
, owner
, group
);
1831 static __attribute__((unused
))
1832 int chroot(const char *path
)
1834 int ret
= sys_chroot(path
);
1843 static __attribute__((unused
))
1846 int ret
= sys_close(fd
);
1855 static __attribute__((unused
))
1856 int dup2(int old
, int new)
1858 int ret
= sys_dup2(old
, new);
1867 static __attribute__((unused
))
1868 int execve(const char *filename
, char *const argv
[], char *const envp
[])
1870 int ret
= sys_execve(filename
, argv
, envp
);
1879 static __attribute__((unused
))
1882 pid_t ret
= sys_fork();
1891 static __attribute__((unused
))
1894 int ret
= sys_fsync(fd
);
1903 static __attribute__((unused
))
1904 int getdents64(int fd
, struct linux_dirent64
*dirp
, int count
)
1906 int ret
= sys_getdents64(fd
, dirp
, count
);
1915 static __attribute__((unused
))
1918 pid_t ret
= sys_getpgrp();
1927 static __attribute__((unused
))
1930 pid_t ret
= sys_getpid();
1939 static __attribute__((unused
))
1940 int gettimeofday(struct timeval
*tv
, struct timezone
*tz
)
1942 int ret
= sys_gettimeofday(tv
, tz
);
1951 static __attribute__((unused
))
1952 int ioctl(int fd
, unsigned long req
, void *value
)
1954 int ret
= sys_ioctl(fd
, req
, value
);
1963 static __attribute__((unused
))
1964 int kill(pid_t pid
, int signal
)
1966 int ret
= sys_kill(pid
, signal
);
1975 static __attribute__((unused
))
1976 int link(const char *old
, const char *new)
1978 int ret
= sys_link(old
, new);
1987 static __attribute__((unused
))
1988 off_t
lseek(int fd
, off_t offset
, int whence
)
1990 off_t ret
= sys_lseek(fd
, offset
, whence
);
1999 static __attribute__((unused
))
2000 int mkdir(const char *path
, mode_t mode
)
2002 int ret
= sys_mkdir(path
, mode
);
2011 static __attribute__((unused
))
2012 int mknod(const char *path
, mode_t mode
, dev_t dev
)
2014 int ret
= sys_mknod(path
, mode
, dev
);
2023 static __attribute__((unused
))
2024 int mount(const char *src
, const char *tgt
,
2025 const char *fst
, unsigned long flags
,
2028 int ret
= sys_mount(src
, tgt
, fst
, flags
, data
);
2037 static __attribute__((unused
))
2038 int open(const char *path
, int flags
, mode_t mode
)
2040 int ret
= sys_open(path
, flags
, mode
);
2049 static __attribute__((unused
))
2050 int pivot_root(const char *new, const char *old
)
2052 int ret
= sys_pivot_root(new, old
);
2061 static __attribute__((unused
))
2062 int poll(struct pollfd
*fds
, int nfds
, int timeout
)
2064 int ret
= sys_poll(fds
, nfds
, timeout
);
2073 static __attribute__((unused
))
2074 ssize_t
read(int fd
, void *buf
, size_t count
)
2076 ssize_t ret
= sys_read(fd
, buf
, count
);
2085 static __attribute__((unused
))
2088 int ret
= sys_reboot(LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
, cmd
, 0);
2097 static __attribute__((unused
))
2098 void *sbrk(intptr_t inc
)
2102 /* first call to find current end */
2103 if ((ret
= sys_brk(0)) && (sys_brk(ret
+ inc
) == ret
+ inc
))
2110 static __attribute__((unused
))
2111 int sched_yield(void)
2113 int ret
= sys_sched_yield();
2122 static __attribute__((unused
))
2123 int select(int nfds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efds
, struct timeval
*timeout
)
2125 int ret
= sys_select(nfds
, rfds
, wfds
, efds
, timeout
);
2134 static __attribute__((unused
))
2135 int setpgid(pid_t pid
, pid_t pgid
)
2137 int ret
= sys_setpgid(pid
, pgid
);
2146 static __attribute__((unused
))
2149 pid_t ret
= sys_setsid();
2158 static __attribute__((unused
))
2159 unsigned int sleep(unsigned int seconds
)
2161 struct timeval my_timeval
= { seconds
, 0 };
2163 if (sys_select(0, 0, 0, 0, &my_timeval
) < 0)
2164 return my_timeval
.tv_sec
+ !!my_timeval
.tv_usec
;
2169 static __attribute__((unused
))
2170 int stat(const char *path
, struct stat
*buf
)
2172 int ret
= sys_stat(path
, buf
);
2181 static __attribute__((unused
))
2182 int symlink(const char *old
, const char *new)
2184 int ret
= sys_symlink(old
, new);
2193 static __attribute__((unused
))
2194 int tcsetpgrp(int fd
, pid_t pid
)
2196 return ioctl(fd
, TIOCSPGRP
, &pid
);
2199 static __attribute__((unused
))
2200 mode_t
umask(mode_t mode
)
2202 return sys_umask(mode
);
2205 static __attribute__((unused
))
2206 int umount2(const char *path
, int flags
)
2208 int ret
= sys_umount2(path
, flags
);
2217 static __attribute__((unused
))
2218 int unlink(const char *path
)
2220 int ret
= sys_unlink(path
);
2229 static __attribute__((unused
))
2230 pid_t
wait4(pid_t pid
, int *status
, int options
, struct rusage
*rusage
)
2232 pid_t ret
= sys_wait4(pid
, status
, options
, rusage
);
2241 static __attribute__((unused
))
2242 pid_t
waitpid(pid_t pid
, int *status
, int options
)
2244 pid_t ret
= sys_waitpid(pid
, status
, options
);
2253 static __attribute__((unused
))
2254 pid_t
wait(int *status
)
2256 pid_t ret
= sys_wait(status
);
2265 static __attribute__((unused
))
2266 ssize_t
write(int fd
, const void *buf
, size_t count
)
2268 ssize_t ret
= sys_write(fd
, buf
, count
);
2277 /* some size-optimized reimplementations of a few common str* and mem*
2278 * functions. They're marked static, except memcpy() and raise() which are used
2279 * by libgcc on ARM, so they are marked weak instead in order not to cause an
2280 * error when building a program made of multiple files (not recommended).
2283 static __attribute__((unused
))
2284 void *memmove(void *dst
, const void *src
, size_t len
)
2286 ssize_t pos
= (dst
<= src
) ? -1 : (long)len
;
2290 pos
+= (dst
<= src
) ? 1 : -1;
2291 ((char *)dst
)[pos
] = ((char *)src
)[pos
];
2296 static __attribute__((unused
))
2297 void *memset(void *dst
, int b
, size_t len
)
2306 static __attribute__((unused
))
2307 int memcmp(const void *s1
, const void *s2
, size_t n
)
2312 while (ofs
< n
&& !(c1
= ((char *)s1
)[ofs
] - ((char *)s2
)[ofs
])) {
2318 static __attribute__((unused
))
2319 char *strcpy(char *dst
, const char *src
)
2323 while ((*dst
++ = *src
++));
2327 static __attribute__((unused
))
2328 char *strchr(const char *s
, int c
)
2338 static __attribute__((unused
))
2339 char *strrchr(const char *s
, int c
)
2341 const char *ret
= NULL
;
2351 static __attribute__((unused
))
2352 size_t nolibc_strlen(const char *str
)
2356 for (len
= 0; str
[len
]; len
++);
2360 #define strlen(str) ({ \
2361 __builtin_constant_p((str)) ? \
2362 __builtin_strlen((str)) : \
2363 nolibc_strlen((str)); \
2366 static __attribute__((unused
))
2369 return (unsigned int)(c
- '0') <= 9;
2372 static __attribute__((unused
))
2373 long atol(const char *s
)
2375 unsigned long ret
= 0;
2392 return neg
? -ret
: ret
;
2395 static __attribute__((unused
))
2396 int atoi(const char *s
)
2401 static __attribute__((unused
))
2402 const char *ltoa(long in
)
2404 /* large enough for -9223372036854775808 */
2405 static char buffer
[21];
2406 char *pos
= buffer
+ sizeof(buffer
) - 1;
2408 unsigned long n
= neg
? -in
: in
;
2412 *pos
-- = '0' + n
% 10;
2423 __attribute__((weak
,unused
))
2424 void *memcpy(void *dst
, const void *src
, size_t len
)
2426 return memmove(dst
, src
, len
);
2429 /* needed by libgcc for divide by zero */
2430 __attribute__((weak
,unused
))
2431 int raise(int signal
)
2433 return kill(getpid(), signal
);
2436 /* Here come a few helper functions */
2438 static __attribute__((unused
))
2439 void FD_ZERO(fd_set
*set
)
2441 memset(set
, 0, sizeof(*set
));
2444 static __attribute__((unused
))
2445 void FD_SET(int fd
, fd_set
*set
)
2447 if (fd
< 0 || fd
>= FD_SETSIZE
)
2449 set
->fd32
[fd
/ 32] |= 1 << (fd
& 31);
2452 /* WARNING, it only deals with the 4096 first majors and 256 first minors */
2453 static __attribute__((unused
))
2454 dev_t
makedev(unsigned int major
, unsigned int minor
)
2456 return ((major
& 0xfff) << 8) | (minor
& 0xff);