xref: /openbmc/linux/tools/include/nolibc/nolibc.h (revision e2aa5e65)
1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2 /* nolibc.h
3  * Copyright (C) 2017-2018 Willy Tarreau <w@1wt.eu>
4  */
5 
6 /*
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.
12  *
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.
21  *
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.
31  *
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.
37  *
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.
44  *
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.
49  *
50  * Some macro definitions like the O_* values passed to open(), and some
51  * structures like the sys_stat struct depend on the architecture.
52  *
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.
58  *
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.
62  *
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.
66  *
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
70  * top could work.
71  *
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 -o hello hello.c -lgcc
75  *
76  * A very useful calling convention table may be found here :
77  *      http://man7.org/linux/man-pages/man2/syscall.2.html
78  *
79  * This doc is quite convenient though not necessarily up to date :
80  *      https://w3challs.com/syscalls/
81  *
82  */
83 
84 #include <asm/unistd.h>
85 #include <asm/ioctls.h>
86 #include <asm/errno.h>
87 #include <linux/fs.h>
88 #include <linux/loop.h>
89 #include <linux/time.h>
90 
91 #define NOLIBC
92 
93 /* this way it will be removed if unused */
94 static int errno;
95 
96 #ifndef NOLIBC_IGNORE_ERRNO
97 #define SET_ERRNO(v) do { errno = (v); } while (0)
98 #else
99 #define SET_ERRNO(v) do { } while (0)
100 #endif
101 
102 /* errno codes all ensure that they will not conflict with a valid pointer
103  * because they all correspond to the highest addressable memory page.
104  */
105 #define MAX_ERRNO 4095
106 
107 /* Declare a few quite common macros and types that usually are in stdlib.h,
108  * stdint.h, ctype.h, unistd.h and a few other common locations.
109  */
110 
111 #define NULL ((void *)0)
112 
113 /* stdint types */
114 typedef unsigned char       uint8_t;
115 typedef   signed char        int8_t;
116 typedef unsigned short     uint16_t;
117 typedef   signed short      int16_t;
118 typedef unsigned int       uint32_t;
119 typedef   signed int        int32_t;
120 typedef unsigned long long uint64_t;
121 typedef   signed long long  int64_t;
122 typedef unsigned long        size_t;
123 typedef   signed long       ssize_t;
124 typedef unsigned long     uintptr_t;
125 typedef   signed long      intptr_t;
126 typedef   signed long     ptrdiff_t;
127 
128 /* for stat() */
129 typedef unsigned int          dev_t;
130 typedef unsigned long         ino_t;
131 typedef unsigned int         mode_t;
132 typedef   signed int          pid_t;
133 typedef unsigned int          uid_t;
134 typedef unsigned int          gid_t;
135 typedef unsigned long       nlink_t;
136 typedef   signed long         off_t;
137 typedef   signed long     blksize_t;
138 typedef   signed long      blkcnt_t;
139 typedef   signed long        time_t;
140 
141 /* for poll() */
142 struct pollfd {
143 	int fd;
144 	short int events;
145 	short int revents;
146 };
147 
148 /* for getdents64() */
149 struct linux_dirent64 {
150 	uint64_t       d_ino;
151 	int64_t        d_off;
152 	unsigned short d_reclen;
153 	unsigned char  d_type;
154 	char           d_name[];
155 };
156 
157 /* commonly an fd_set represents 256 FDs */
158 #define FD_SETSIZE 256
159 typedef struct { uint32_t fd32[FD_SETSIZE/32]; } fd_set;
160 
161 /* needed by wait4() */
162 struct rusage {
163 	struct timeval ru_utime;
164 	struct timeval ru_stime;
165 	long   ru_maxrss;
166 	long   ru_ixrss;
167 	long   ru_idrss;
168 	long   ru_isrss;
169 	long   ru_minflt;
170 	long   ru_majflt;
171 	long   ru_nswap;
172 	long   ru_inblock;
173 	long   ru_oublock;
174 	long   ru_msgsnd;
175 	long   ru_msgrcv;
176 	long   ru_nsignals;
177 	long   ru_nvcsw;
178 	long   ru_nivcsw;
179 };
180 
181 /* stat flags (WARNING, octal here) */
182 #define S_IFDIR       0040000
183 #define S_IFCHR       0020000
184 #define S_IFBLK       0060000
185 #define S_IFREG       0100000
186 #define S_IFIFO       0010000
187 #define S_IFLNK       0120000
188 #define S_IFSOCK      0140000
189 #define S_IFMT        0170000
190 
191 #define S_ISDIR(mode)  (((mode) & S_IFDIR) == S_IFDIR)
192 #define S_ISCHR(mode)  (((mode) & S_IFCHR) == S_IFCHR)
193 #define S_ISBLK(mode)  (((mode) & S_IFBLK) == S_IFBLK)
194 #define S_ISREG(mode)  (((mode) & S_IFREG) == S_IFREG)
195 #define S_ISFIFO(mode) (((mode) & S_IFIFO) == S_IFIFO)
196 #define S_ISLNK(mode)  (((mode) & S_IFLNK) == S_IFLNK)
197 #define S_ISSOCK(mode) (((mode) & S_IFSOCK) == S_IFSOCK)
198 
199 #define DT_UNKNOWN 0
200 #define DT_FIFO    1
201 #define DT_CHR     2
202 #define DT_DIR     4
203 #define DT_BLK     6
204 #define DT_REG     8
205 #define DT_LNK    10
206 #define DT_SOCK   12
207 
208 /* all the *at functions */
209 #ifndef AT_FDCWD
210 #define AT_FDCWD             -100
211 #endif
212 
213 /* lseek */
214 #define SEEK_SET        0
215 #define SEEK_CUR        1
216 #define SEEK_END        2
217 
218 /* reboot */
219 #define LINUX_REBOOT_MAGIC1         0xfee1dead
220 #define LINUX_REBOOT_MAGIC2         0x28121969
221 #define LINUX_REBOOT_CMD_HALT       0xcdef0123
222 #define LINUX_REBOOT_CMD_POWER_OFF  0x4321fedc
223 #define LINUX_REBOOT_CMD_RESTART    0x01234567
224 #define LINUX_REBOOT_CMD_SW_SUSPEND 0xd000fce2
225 
226 
227 /* The format of the struct as returned by the libc to the application, which
228  * significantly differs from the format returned by the stat() syscall flavours.
229  */
230 struct stat {
231 	dev_t     st_dev;     /* ID of device containing file */
232 	ino_t     st_ino;     /* inode number */
233 	mode_t    st_mode;    /* protection */
234 	nlink_t   st_nlink;   /* number of hard links */
235 	uid_t     st_uid;     /* user ID of owner */
236 	gid_t     st_gid;     /* group ID of owner */
237 	dev_t     st_rdev;    /* device ID (if special file) */
238 	off_t     st_size;    /* total size, in bytes */
239 	blksize_t st_blksize; /* blocksize for file system I/O */
240 	blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
241 	time_t    st_atime;   /* time of last access */
242 	time_t    st_mtime;   /* time of last modification */
243 	time_t    st_ctime;   /* time of last status change */
244 };
245 
246 #define WEXITSTATUS(status)   (((status) & 0xff00) >> 8)
247 #define WIFEXITED(status)     (((status) & 0x7f) == 0)
248 
249 /* for SIGCHLD */
250 #include <asm/signal.h>
251 
252 /* Below comes the architecture-specific code. For each architecture, we have
253  * the syscall declarations and the _start code definition. This is the only
254  * global part. On all architectures the kernel puts everything in the stack
255  * before jumping to _start just above us, without any return address (_start
256  * is not a function but an entry pint). So at the stack pointer we find argc.
257  * Then argv[] begins, and ends at the first NULL. Then we have envp which
258  * starts and ends with a NULL as well. So envp=argv+argc+1.
259  */
260 
261 #if defined(__x86_64__)
262 /* Syscalls for x86_64 :
263  *   - registers are 64-bit
264  *   - syscall number is passed in rax
265  *   - arguments are in rdi, rsi, rdx, r10, r8, r9 respectively
266  *   - the system call is performed by calling the syscall instruction
267  *   - syscall return comes in rax
268  *   - rcx and r11 are clobbered, others are preserved.
269  *   - the arguments are cast to long and assigned into the target registers
270  *     which are then simply passed as registers to the asm code, so that we
271  *     don't have to experience issues with register constraints.
272  *   - the syscall number is always specified last in order to allow to force
273  *     some registers before (gcc refuses a %-register at the last position).
274  *   - see also x86-64 ABI section A.2 AMD64 Linux Kernel Conventions, A.2.1
275  *     Calling Conventions.
276  *
277  * Link x86-64 ABI: https://gitlab.com/x86-psABIs/x86-64-ABI/-/wikis/x86-64-psABI
278  *
279  */
280 
281 #define my_syscall0(num)                                                      \
282 ({                                                                            \
283 	long _ret;                                                            \
284 	register long _num  asm("rax") = (num);                               \
285 									      \
286 	asm volatile (                                                        \
287 		"syscall\n"                                                   \
288 		: "=a"(_ret)                                                  \
289 		: "0"(_num)                                                   \
290 		: "rcx", "r11", "memory", "cc"                                \
291 	);                                                                    \
292 	_ret;                                                                 \
293 })
294 
295 #define my_syscall1(num, arg1)                                                \
296 ({                                                                            \
297 	long _ret;                                                            \
298 	register long _num  asm("rax") = (num);                               \
299 	register long _arg1 asm("rdi") = (long)(arg1);                        \
300 									      \
301 	asm volatile (                                                        \
302 		"syscall\n"                                                   \
303 		: "=a"(_ret)                                                  \
304 		: "r"(_arg1),                                                 \
305 		  "0"(_num)                                                   \
306 		: "rcx", "r11", "memory", "cc"                                \
307 	);                                                                    \
308 	_ret;                                                                 \
309 })
310 
311 #define my_syscall2(num, arg1, arg2)                                          \
312 ({                                                                            \
313 	long _ret;                                                            \
314 	register long _num  asm("rax") = (num);                               \
315 	register long _arg1 asm("rdi") = (long)(arg1);                        \
316 	register long _arg2 asm("rsi") = (long)(arg2);                        \
317 									      \
318 	asm volatile (                                                        \
319 		"syscall\n"                                                   \
320 		: "=a"(_ret)                                                  \
321 		: "r"(_arg1), "r"(_arg2),                                     \
322 		  "0"(_num)                                                   \
323 		: "rcx", "r11", "memory", "cc"                                \
324 	);                                                                    \
325 	_ret;                                                                 \
326 })
327 
328 #define my_syscall3(num, arg1, arg2, arg3)                                    \
329 ({                                                                            \
330 	long _ret;                                                            \
331 	register long _num  asm("rax") = (num);                               \
332 	register long _arg1 asm("rdi") = (long)(arg1);                        \
333 	register long _arg2 asm("rsi") = (long)(arg2);                        \
334 	register long _arg3 asm("rdx") = (long)(arg3);                        \
335 									      \
336 	asm volatile (                                                        \
337 		"syscall\n"                                                   \
338 		: "=a"(_ret)                                                  \
339 		: "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
340 		  "0"(_num)                                                   \
341 		: "rcx", "r11", "memory", "cc"                                \
342 	);                                                                    \
343 	_ret;                                                                 \
344 })
345 
346 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
347 ({                                                                            \
348 	long _ret;                                                            \
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);                        \
353 	register long _arg4 asm("r10") = (long)(arg4);                        \
354 									      \
355 	asm volatile (                                                        \
356 		"syscall\n"                                                   \
357 		: "=a"(_ret)                                                  \
358 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
359 		  "0"(_num)                                                   \
360 		: "rcx", "r11", "memory", "cc"                                \
361 	);                                                                    \
362 	_ret;                                                                 \
363 })
364 
365 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
366 ({                                                                            \
367 	long _ret;                                                            \
368 	register long _num  asm("rax") = (num);                               \
369 	register long _arg1 asm("rdi") = (long)(arg1);                        \
370 	register long _arg2 asm("rsi") = (long)(arg2);                        \
371 	register long _arg3 asm("rdx") = (long)(arg3);                        \
372 	register long _arg4 asm("r10") = (long)(arg4);                        \
373 	register long _arg5 asm("r8")  = (long)(arg5);                        \
374 									      \
375 	asm volatile (                                                        \
376 		"syscall\n"                                                   \
377 		: "=a"(_ret)                                                  \
378 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
379 		  "0"(_num)                                                   \
380 		: "rcx", "r11", "memory", "cc"                                \
381 	);                                                                    \
382 	_ret;                                                                 \
383 })
384 
385 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
386 ({                                                                            \
387 	long _ret;                                                            \
388 	register long _num  asm("rax") = (num);                               \
389 	register long _arg1 asm("rdi") = (long)(arg1);                        \
390 	register long _arg2 asm("rsi") = (long)(arg2);                        \
391 	register long _arg3 asm("rdx") = (long)(arg3);                        \
392 	register long _arg4 asm("r10") = (long)(arg4);                        \
393 	register long _arg5 asm("r8")  = (long)(arg5);                        \
394 	register long _arg6 asm("r9")  = (long)(arg6);                        \
395 									      \
396 	asm volatile (                                                        \
397 		"syscall\n"                                                   \
398 		: "=a"(_ret)                                                  \
399 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
400 		  "r"(_arg6), "0"(_num)                                       \
401 		: "rcx", "r11", "memory", "cc"                                \
402 	);                                                                    \
403 	_ret;                                                                 \
404 })
405 
406 /* startup code */
407 /*
408  * x86-64 System V ABI mandates:
409  * 1) %rsp must be 16-byte aligned right before the function call.
410  * 2) The deepest stack frame should be zero (the %rbp).
411  *
412  */
413 asm(".section .text\n"
414     ".global _start\n"
415     "_start:\n"
416     "pop %rdi\n"                // argc   (first arg, %rdi)
417     "mov %rsp, %rsi\n"          // argv[] (second arg, %rsi)
418     "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx)
419     "xor %ebp, %ebp\n"          // zero the stack frame
420     "and $-16, %rsp\n"          // x86 ABI : esp must be 16-byte aligned before call
421     "call main\n"               // main() returns the status code, we'll exit with it.
422     "mov %eax, %edi\n"          // retrieve exit code (32 bit)
423     "mov $60, %eax\n"           // NR_exit == 60
424     "syscall\n"                 // really exit
425     "hlt\n"                     // ensure it does not return
426     "");
427 
428 /* fcntl / open */
429 #define O_RDONLY            0
430 #define O_WRONLY            1
431 #define O_RDWR              2
432 #define O_CREAT          0x40
433 #define O_EXCL           0x80
434 #define O_NOCTTY        0x100
435 #define O_TRUNC         0x200
436 #define O_APPEND        0x400
437 #define O_NONBLOCK      0x800
438 #define O_DIRECTORY   0x10000
439 
440 /* The struct returned by the stat() syscall, equivalent to stat64(). The
441  * syscall returns 116 bytes and stops in the middle of __unused.
442  */
443 struct sys_stat_struct {
444 	unsigned long st_dev;
445 	unsigned long st_ino;
446 	unsigned long st_nlink;
447 	unsigned int  st_mode;
448 	unsigned int  st_uid;
449 
450 	unsigned int  st_gid;
451 	unsigned int  __pad0;
452 	unsigned long st_rdev;
453 	long          st_size;
454 	long          st_blksize;
455 
456 	long          st_blocks;
457 	unsigned long st_atime;
458 	unsigned long st_atime_nsec;
459 	unsigned long st_mtime;
460 
461 	unsigned long st_mtime_nsec;
462 	unsigned long st_ctime;
463 	unsigned long st_ctime_nsec;
464 	long          __unused[3];
465 };
466 
467 #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
468 /* Syscalls for i386 :
469  *   - mostly similar to x86_64
470  *   - registers are 32-bit
471  *   - syscall number is passed in eax
472  *   - arguments are in ebx, ecx, edx, esi, edi, ebp respectively
473  *   - all registers are preserved (except eax of course)
474  *   - the system call is performed by calling int $0x80
475  *   - syscall return comes in eax
476  *   - the arguments are cast to long and assigned into the target registers
477  *     which are then simply passed as registers to the asm code, so that we
478  *     don't have to experience issues with register constraints.
479  *   - the syscall number is always specified last in order to allow to force
480  *     some registers before (gcc refuses a %-register at the last position).
481  *
482  * Also, i386 supports the old_select syscall if newselect is not available
483  */
484 #define __ARCH_WANT_SYS_OLD_SELECT
485 
486 #define my_syscall0(num)                                                      \
487 ({                                                                            \
488 	long _ret;                                                            \
489 	register long _num asm("eax") = (num);                                \
490 									      \
491 	asm volatile (                                                        \
492 		"int $0x80\n"                                                 \
493 		: "=a" (_ret)                                                 \
494 		: "0"(_num)                                                   \
495 		: "memory", "cc"                                              \
496 	);                                                                    \
497 	_ret;                                                                 \
498 })
499 
500 #define my_syscall1(num, arg1)                                                \
501 ({                                                                            \
502 	long _ret;                                                            \
503 	register long _num asm("eax") = (num);                                \
504 	register long _arg1 asm("ebx") = (long)(arg1);                        \
505 									      \
506 	asm volatile (                                                        \
507 		"int $0x80\n"                                                 \
508 		: "=a" (_ret)                                                 \
509 		: "r"(_arg1),                                                 \
510 		  "0"(_num)                                                   \
511 		: "memory", "cc"                                              \
512 	);                                                                    \
513 	_ret;                                                                 \
514 })
515 
516 #define my_syscall2(num, arg1, arg2)                                          \
517 ({                                                                            \
518 	long _ret;                                                            \
519 	register long _num asm("eax") = (num);                                \
520 	register long _arg1 asm("ebx") = (long)(arg1);                        \
521 	register long _arg2 asm("ecx") = (long)(arg2);                        \
522 									      \
523 	asm volatile (                                                        \
524 		"int $0x80\n"                                                 \
525 		: "=a" (_ret)                                                 \
526 		: "r"(_arg1), "r"(_arg2),                                     \
527 		  "0"(_num)                                                   \
528 		: "memory", "cc"                                              \
529 	);                                                                    \
530 	_ret;                                                                 \
531 })
532 
533 #define my_syscall3(num, arg1, arg2, arg3)                                    \
534 ({                                                                            \
535 	long _ret;                                                            \
536 	register long _num asm("eax") = (num);                                \
537 	register long _arg1 asm("ebx") = (long)(arg1);                        \
538 	register long _arg2 asm("ecx") = (long)(arg2);                        \
539 	register long _arg3 asm("edx") = (long)(arg3);                        \
540 									      \
541 	asm volatile (                                                        \
542 		"int $0x80\n"                                                 \
543 		: "=a" (_ret)                                                 \
544 		: "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
545 		  "0"(_num)                                                   \
546 		: "memory", "cc"                                              \
547 	);                                                                    \
548 	_ret;                                                                 \
549 })
550 
551 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
552 ({                                                                            \
553 	long _ret;                                                            \
554 	register long _num asm("eax") = (num);                                \
555 	register long _arg1 asm("ebx") = (long)(arg1);                        \
556 	register long _arg2 asm("ecx") = (long)(arg2);                        \
557 	register long _arg3 asm("edx") = (long)(arg3);                        \
558 	register long _arg4 asm("esi") = (long)(arg4);                        \
559 									      \
560 	asm volatile (                                                        \
561 		"int $0x80\n"                                                 \
562 		: "=a" (_ret)                                                 \
563 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
564 		  "0"(_num)                                                   \
565 		: "memory", "cc"                                              \
566 	);                                                                    \
567 	_ret;                                                                 \
568 })
569 
570 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
571 ({                                                                            \
572 	long _ret;                                                            \
573 	register long _num asm("eax") = (num);                                \
574 	register long _arg1 asm("ebx") = (long)(arg1);                        \
575 	register long _arg2 asm("ecx") = (long)(arg2);                        \
576 	register long _arg3 asm("edx") = (long)(arg3);                        \
577 	register long _arg4 asm("esi") = (long)(arg4);                        \
578 	register long _arg5 asm("edi") = (long)(arg5);                        \
579 									      \
580 	asm volatile (                                                        \
581 		"int $0x80\n"                                                 \
582 		: "=a" (_ret)                                                 \
583 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
584 		  "0"(_num)                                                   \
585 		: "memory", "cc"                                              \
586 	);                                                                    \
587 	_ret;                                                                 \
588 })
589 
590 /* startup code */
591 /*
592  * i386 System V ABI mandates:
593  * 1) last pushed argument must be 16-byte aligned.
594  * 2) The deepest stack frame should be set to zero
595  *
596  */
597 asm(".section .text\n"
598     ".global _start\n"
599     "_start:\n"
600     "pop %eax\n"                // argc   (first arg, %eax)
601     "mov %esp, %ebx\n"          // argv[] (second arg, %ebx)
602     "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx)
603     "xor %ebp, %ebp\n"          // zero the stack frame
604     "and $-16, %esp\n"          // x86 ABI : esp must be 16-byte aligned before
605     "sub $4, %esp\n"            // the call instruction (args are aligned)
606     "push %ecx\n"               // push all registers on the stack so that we
607     "push %ebx\n"               // support both regparm and plain stack modes
608     "push %eax\n"
609     "call main\n"               // main() returns the status code in %eax
610     "mov %eax, %ebx\n"          // retrieve exit code (32-bit int)
611     "movl $1, %eax\n"           // NR_exit == 1
612     "int $0x80\n"               // exit now
613     "hlt\n"                     // ensure it does not
614     "");
615 
616 /* fcntl / open */
617 #define O_RDONLY            0
618 #define O_WRONLY            1
619 #define O_RDWR              2
620 #define O_CREAT          0x40
621 #define O_EXCL           0x80
622 #define O_NOCTTY        0x100
623 #define O_TRUNC         0x200
624 #define O_APPEND        0x400
625 #define O_NONBLOCK      0x800
626 #define O_DIRECTORY   0x10000
627 
628 /* The struct returned by the stat() syscall, 32-bit only, the syscall returns
629  * exactly 56 bytes (stops before the unused array).
630  */
631 struct sys_stat_struct {
632 	unsigned long  st_dev;
633 	unsigned long  st_ino;
634 	unsigned short st_mode;
635 	unsigned short st_nlink;
636 	unsigned short st_uid;
637 	unsigned short st_gid;
638 
639 	unsigned long  st_rdev;
640 	unsigned long  st_size;
641 	unsigned long  st_blksize;
642 	unsigned long  st_blocks;
643 
644 	unsigned long  st_atime;
645 	unsigned long  st_atime_nsec;
646 	unsigned long  st_mtime;
647 	unsigned long  st_mtime_nsec;
648 
649 	unsigned long  st_ctime;
650 	unsigned long  st_ctime_nsec;
651 	unsigned long  __unused[2];
652 };
653 
654 #elif defined(__ARM_EABI__)
655 /* Syscalls for ARM in ARM or Thumb modes :
656  *   - registers are 32-bit
657  *   - stack is 8-byte aligned
658  *     ( http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html)
659  *   - syscall number is passed in r7
660  *   - arguments are in r0, r1, r2, r3, r4, r5
661  *   - the system call is performed by calling svc #0
662  *   - syscall return comes in r0.
663  *   - only lr is clobbered.
664  *   - the arguments are cast to long and assigned into the target registers
665  *     which are then simply passed as registers to the asm code, so that we
666  *     don't have to experience issues with register constraints.
667  *   - the syscall number is always specified last in order to allow to force
668  *     some registers before (gcc refuses a %-register at the last position).
669  *
670  * Also, ARM supports the old_select syscall if newselect is not available
671  */
672 #define __ARCH_WANT_SYS_OLD_SELECT
673 
674 #define my_syscall0(num)                                                      \
675 ({                                                                            \
676 	register long _num asm("r7") = (num);                                 \
677 	register long _arg1 asm("r0");                                        \
678 									      \
679 	asm volatile (                                                        \
680 		"svc #0\n"                                                    \
681 		: "=r"(_arg1)                                                 \
682 		: "r"(_num)                                                   \
683 		: "memory", "cc", "lr"                                        \
684 	);                                                                    \
685 	_arg1;                                                                \
686 })
687 
688 #define my_syscall1(num, arg1)                                                \
689 ({                                                                            \
690 	register long _num asm("r7") = (num);                                 \
691 	register long _arg1 asm("r0") = (long)(arg1);                         \
692 									      \
693 	asm volatile (                                                        \
694 		"svc #0\n"                                                    \
695 		: "=r"(_arg1)                                                 \
696 		: "r"(_arg1),                                                 \
697 		  "r"(_num)                                                   \
698 		: "memory", "cc", "lr"                                        \
699 	);                                                                    \
700 	_arg1;                                                                \
701 })
702 
703 #define my_syscall2(num, arg1, arg2)                                          \
704 ({                                                                            \
705 	register long _num asm("r7") = (num);                                 \
706 	register long _arg1 asm("r0") = (long)(arg1);                         \
707 	register long _arg2 asm("r1") = (long)(arg2);                         \
708 									      \
709 	asm volatile (                                                        \
710 		"svc #0\n"                                                    \
711 		: "=r"(_arg1)                                                 \
712 		: "r"(_arg1), "r"(_arg2),                                     \
713 		  "r"(_num)                                                   \
714 		: "memory", "cc", "lr"                                        \
715 	);                                                                    \
716 	_arg1;                                                                \
717 })
718 
719 #define my_syscall3(num, arg1, arg2, arg3)                                    \
720 ({                                                                            \
721 	register long _num asm("r7") = (num);                                 \
722 	register long _arg1 asm("r0") = (long)(arg1);                         \
723 	register long _arg2 asm("r1") = (long)(arg2);                         \
724 	register long _arg3 asm("r2") = (long)(arg3);                         \
725 									      \
726 	asm volatile (                                                        \
727 		"svc #0\n"                                                    \
728 		: "=r"(_arg1)                                                 \
729 		: "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
730 		  "r"(_num)                                                   \
731 		: "memory", "cc", "lr"                                        \
732 	);                                                                    \
733 	_arg1;                                                                \
734 })
735 
736 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
737 ({                                                                            \
738 	register long _num asm("r7") = (num);                                 \
739 	register long _arg1 asm("r0") = (long)(arg1);                         \
740 	register long _arg2 asm("r1") = (long)(arg2);                         \
741 	register long _arg3 asm("r2") = (long)(arg3);                         \
742 	register long _arg4 asm("r3") = (long)(arg4);                         \
743 									      \
744 	asm volatile (                                                        \
745 		"svc #0\n"                                                    \
746 		: "=r"(_arg1)                                                 \
747 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
748 		  "r"(_num)                                                   \
749 		: "memory", "cc", "lr"                                        \
750 	);                                                                    \
751 	_arg1;                                                                \
752 })
753 
754 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
755 ({                                                                            \
756 	register long _num asm("r7") = (num);                                 \
757 	register long _arg1 asm("r0") = (long)(arg1);                         \
758 	register long _arg2 asm("r1") = (long)(arg2);                         \
759 	register long _arg3 asm("r2") = (long)(arg3);                         \
760 	register long _arg4 asm("r3") = (long)(arg4);                         \
761 	register long _arg5 asm("r4") = (long)(arg5);                         \
762 									      \
763 	asm volatile (                                                        \
764 		"svc #0\n"                                                    \
765 		: "=r" (_arg1)                                                \
766 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
767 		  "r"(_num)                                                   \
768 		: "memory", "cc", "lr"                                        \
769 	);                                                                    \
770 	_arg1;                                                                \
771 })
772 
773 /* startup code */
774 asm(".section .text\n"
775     ".global _start\n"
776     "_start:\n"
777 #if defined(__THUMBEB__) || defined(__THUMBEL__)
778     /* We enter here in 32-bit mode but if some previous functions were in
779      * 16-bit mode, the assembler cannot know, so we need to tell it we're in
780      * 32-bit now, then switch to 16-bit (is there a better way to do it than
781      * adding 1 by hand ?) and tell the asm we're now in 16-bit mode so that
782      * it generates correct instructions. Note that we do not support thumb1.
783      */
784     ".code 32\n"
785     "add     r0, pc, #1\n"
786     "bx      r0\n"
787     ".code 16\n"
788 #endif
789     "pop {%r0}\n"                 // argc was in the stack
790     "mov %r1, %sp\n"              // argv = sp
791     "add %r2, %r1, %r0, lsl #2\n" // envp = argv + 4*argc ...
792     "add %r2, %r2, $4\n"          //        ... + 4
793     "and %r3, %r1, $-8\n"         // AAPCS : sp must be 8-byte aligned in the
794     "mov %sp, %r3\n"              //         callee, an bl doesn't push (lr=pc)
795     "bl main\n"                   // main() returns the status code, we'll exit with it.
796     "movs r7, $1\n"               // NR_exit == 1
797     "svc $0x00\n"
798     "");
799 
800 /* fcntl / open */
801 #define O_RDONLY            0
802 #define O_WRONLY            1
803 #define O_RDWR              2
804 #define O_CREAT          0x40
805 #define O_EXCL           0x80
806 #define O_NOCTTY        0x100
807 #define O_TRUNC         0x200
808 #define O_APPEND        0x400
809 #define O_NONBLOCK      0x800
810 #define O_DIRECTORY    0x4000
811 
812 /* The struct returned by the stat() syscall, 32-bit only, the syscall returns
813  * exactly 56 bytes (stops before the unused array). In big endian, the format
814  * differs as devices are returned as short only.
815  */
816 struct sys_stat_struct {
817 #if defined(__ARMEB__)
818 	unsigned short st_dev;
819 	unsigned short __pad1;
820 #else
821 	unsigned long  st_dev;
822 #endif
823 	unsigned long  st_ino;
824 	unsigned short st_mode;
825 	unsigned short st_nlink;
826 	unsigned short st_uid;
827 	unsigned short st_gid;
828 #if defined(__ARMEB__)
829 	unsigned short st_rdev;
830 	unsigned short __pad2;
831 #else
832 	unsigned long  st_rdev;
833 #endif
834 	unsigned long  st_size;
835 	unsigned long  st_blksize;
836 	unsigned long  st_blocks;
837 	unsigned long  st_atime;
838 	unsigned long  st_atime_nsec;
839 	unsigned long  st_mtime;
840 	unsigned long  st_mtime_nsec;
841 	unsigned long  st_ctime;
842 	unsigned long  st_ctime_nsec;
843 	unsigned long  __unused[2];
844 };
845 
846 #elif defined(__aarch64__)
847 /* Syscalls for AARCH64 :
848  *   - registers are 64-bit
849  *   - stack is 16-byte aligned
850  *   - syscall number is passed in x8
851  *   - arguments are in x0, x1, x2, x3, x4, x5
852  *   - the system call is performed by calling svc 0
853  *   - syscall return comes in x0.
854  *   - the arguments are cast to long and assigned into the target registers
855  *     which are then simply passed as registers to the asm code, so that we
856  *     don't have to experience issues with register constraints.
857  *
858  * On aarch64, select() is not implemented so we have to use pselect6().
859  */
860 #define __ARCH_WANT_SYS_PSELECT6
861 
862 #define my_syscall0(num)                                                      \
863 ({                                                                            \
864 	register long _num  asm("x8") = (num);                                \
865 	register long _arg1 asm("x0");                                        \
866 									      \
867 	asm volatile (                                                        \
868 		"svc #0\n"                                                    \
869 		: "=r"(_arg1)                                                 \
870 		: "r"(_num)                                                   \
871 		: "memory", "cc"                                              \
872 	);                                                                    \
873 	_arg1;                                                                \
874 })
875 
876 #define my_syscall1(num, arg1)                                                \
877 ({                                                                            \
878 	register long _num  asm("x8") = (num);                                \
879 	register long _arg1 asm("x0") = (long)(arg1);                         \
880 									      \
881 	asm volatile (                                                        \
882 		"svc #0\n"                                                    \
883 		: "=r"(_arg1)                                                 \
884 		: "r"(_arg1),                                                 \
885 		  "r"(_num)                                                   \
886 		: "memory", "cc"                                              \
887 	);                                                                    \
888 	_arg1;                                                                \
889 })
890 
891 #define my_syscall2(num, arg1, arg2)                                          \
892 ({                                                                            \
893 	register long _num  asm("x8") = (num);                                \
894 	register long _arg1 asm("x0") = (long)(arg1);                         \
895 	register long _arg2 asm("x1") = (long)(arg2);                         \
896 									      \
897 	asm volatile (                                                        \
898 		"svc #0\n"                                                    \
899 		: "=r"(_arg1)                                                 \
900 		: "r"(_arg1), "r"(_arg2),                                     \
901 		  "r"(_num)                                                   \
902 		: "memory", "cc"                                              \
903 	);                                                                    \
904 	_arg1;                                                                \
905 })
906 
907 #define my_syscall3(num, arg1, arg2, arg3)                                    \
908 ({                                                                            \
909 	register long _num  asm("x8") = (num);                                \
910 	register long _arg1 asm("x0") = (long)(arg1);                         \
911 	register long _arg2 asm("x1") = (long)(arg2);                         \
912 	register long _arg3 asm("x2") = (long)(arg3);                         \
913 									      \
914 	asm volatile (                                                        \
915 		"svc #0\n"                                                    \
916 		: "=r"(_arg1)                                                 \
917 		: "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
918 		  "r"(_num)                                                   \
919 		: "memory", "cc"                                              \
920 	);                                                                    \
921 	_arg1;                                                                \
922 })
923 
924 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
925 ({                                                                            \
926 	register long _num  asm("x8") = (num);                                \
927 	register long _arg1 asm("x0") = (long)(arg1);                         \
928 	register long _arg2 asm("x1") = (long)(arg2);                         \
929 	register long _arg3 asm("x2") = (long)(arg3);                         \
930 	register long _arg4 asm("x3") = (long)(arg4);                         \
931 									      \
932 	asm volatile (                                                        \
933 		"svc #0\n"                                                    \
934 		: "=r"(_arg1)                                                 \
935 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
936 		  "r"(_num)                                                   \
937 		: "memory", "cc"                                              \
938 	);                                                                    \
939 	_arg1;                                                                \
940 })
941 
942 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
943 ({                                                                            \
944 	register long _num  asm("x8") = (num);                                \
945 	register long _arg1 asm("x0") = (long)(arg1);                         \
946 	register long _arg2 asm("x1") = (long)(arg2);                         \
947 	register long _arg3 asm("x2") = (long)(arg3);                         \
948 	register long _arg4 asm("x3") = (long)(arg4);                         \
949 	register long _arg5 asm("x4") = (long)(arg5);                         \
950 									      \
951 	asm volatile (                                                        \
952 		"svc #0\n"                                                    \
953 		: "=r" (_arg1)                                                \
954 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
955 		  "r"(_num)                                                   \
956 		: "memory", "cc"                                              \
957 	);                                                                    \
958 	_arg1;                                                                \
959 })
960 
961 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
962 ({                                                                            \
963 	register long _num  asm("x8") = (num);                                \
964 	register long _arg1 asm("x0") = (long)(arg1);                         \
965 	register long _arg2 asm("x1") = (long)(arg2);                         \
966 	register long _arg3 asm("x2") = (long)(arg3);                         \
967 	register long _arg4 asm("x3") = (long)(arg4);                         \
968 	register long _arg5 asm("x4") = (long)(arg5);                         \
969 	register long _arg6 asm("x5") = (long)(arg6);                         \
970 									      \
971 	asm volatile (                                                        \
972 		"svc #0\n"                                                    \
973 		: "=r" (_arg1)                                                \
974 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
975 		  "r"(_arg6), "r"(_num)                                       \
976 		: "memory", "cc"                                              \
977 	);                                                                    \
978 	_arg1;                                                                \
979 })
980 
981 /* startup code */
982 asm(".section .text\n"
983     ".global _start\n"
984     "_start:\n"
985     "ldr x0, [sp]\n"              // argc (x0) was in the stack
986     "add x1, sp, 8\n"             // argv (x1) = sp
987     "lsl x2, x0, 3\n"             // envp (x2) = 8*argc ...
988     "add x2, x2, 8\n"             //           + 8 (skip null)
989     "add x2, x2, x1\n"            //           + argv
990     "and sp, x1, -16\n"           // sp must be 16-byte aligned in the callee
991     "bl main\n"                   // main() returns the status code, we'll exit with it.
992     "mov x8, 93\n"                // NR_exit == 93
993     "svc #0\n"
994     "");
995 
996 /* fcntl / open */
997 #define O_RDONLY            0
998 #define O_WRONLY            1
999 #define O_RDWR              2
1000 #define O_CREAT          0x40
1001 #define O_EXCL           0x80
1002 #define O_NOCTTY        0x100
1003 #define O_TRUNC         0x200
1004 #define O_APPEND        0x400
1005 #define O_NONBLOCK      0x800
1006 #define O_DIRECTORY    0x4000
1007 
1008 /* The struct returned by the newfstatat() syscall. Differs slightly from the
1009  * x86_64's stat one by field ordering, so be careful.
1010  */
1011 struct sys_stat_struct {
1012 	unsigned long   st_dev;
1013 	unsigned long   st_ino;
1014 	unsigned int    st_mode;
1015 	unsigned int    st_nlink;
1016 	unsigned int    st_uid;
1017 	unsigned int    st_gid;
1018 
1019 	unsigned long   st_rdev;
1020 	unsigned long   __pad1;
1021 	long            st_size;
1022 	int             st_blksize;
1023 	int             __pad2;
1024 
1025 	long            st_blocks;
1026 	long            st_atime;
1027 	unsigned long   st_atime_nsec;
1028 	long            st_mtime;
1029 
1030 	unsigned long   st_mtime_nsec;
1031 	long            st_ctime;
1032 	unsigned long   st_ctime_nsec;
1033 	unsigned int    __unused[2];
1034 };
1035 
1036 #elif defined(__mips__) && defined(_ABIO32)
1037 /* Syscalls for MIPS ABI O32 :
1038  *   - WARNING! there's always a delayed slot!
1039  *   - WARNING again, the syntax is different, registers take a '$' and numbers
1040  *     do not.
1041  *   - registers are 32-bit
1042  *   - stack is 8-byte aligned
1043  *   - syscall number is passed in v0 (starts at 0xfa0).
1044  *   - arguments are in a0, a1, a2, a3, then the stack. The caller needs to
1045  *     leave some room in the stack for the callee to save a0..a3 if needed.
1046  *   - Many registers are clobbered, in fact only a0..a2 and s0..s8 are
1047  *     preserved. See: https://www.linux-mips.org/wiki/Syscall as well as
1048  *     scall32-o32.S in the kernel sources.
1049  *   - the system call is performed by calling "syscall"
1050  *   - syscall return comes in v0, and register a3 needs to be checked to know
1051  *     if an error occurred, in which case errno is in v0.
1052  *   - the arguments are cast to long and assigned into the target registers
1053  *     which are then simply passed as registers to the asm code, so that we
1054  *     don't have to experience issues with register constraints.
1055  */
1056 
1057 #define my_syscall0(num)                                                      \
1058 ({                                                                            \
1059 	register long _num asm("v0") = (num);                                 \
1060 	register long _arg4 asm("a3");                                        \
1061 									      \
1062 	asm volatile (                                                        \
1063 		"addiu $sp, $sp, -32\n"                                       \
1064 		"syscall\n"                                                   \
1065 		"addiu $sp, $sp, 32\n"                                        \
1066 		: "=r"(_num), "=r"(_arg4)                                     \
1067 		: "r"(_num)                                                   \
1068 		: "memory", "cc", "at", "v1", "hi", "lo",                     \
1069 		  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
1070 	);                                                                    \
1071 	_arg4 ? -_num : _num;                                                 \
1072 })
1073 
1074 #define my_syscall1(num, arg1)                                                \
1075 ({                                                                            \
1076 	register long _num asm("v0") = (num);                                 \
1077 	register long _arg1 asm("a0") = (long)(arg1);                         \
1078 	register long _arg4 asm("a3");                                        \
1079 									      \
1080 	asm volatile (                                                        \
1081 		"addiu $sp, $sp, -32\n"                                       \
1082 		"syscall\n"                                                   \
1083 		"addiu $sp, $sp, 32\n"                                        \
1084 		: "=r"(_num), "=r"(_arg4)                                     \
1085 		: "0"(_num),                                                  \
1086 		  "r"(_arg1)                                                  \
1087 		: "memory", "cc", "at", "v1", "hi", "lo",                     \
1088 		  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
1089 	);                                                                    \
1090 	_arg4 ? -_num : _num;                                                 \
1091 })
1092 
1093 #define my_syscall2(num, arg1, arg2)                                          \
1094 ({                                                                            \
1095 	register long _num asm("v0") = (num);                                 \
1096 	register long _arg1 asm("a0") = (long)(arg1);                         \
1097 	register long _arg2 asm("a1") = (long)(arg2);                         \
1098 	register long _arg4 asm("a3");                                        \
1099 									      \
1100 	asm volatile (                                                        \
1101 		"addiu $sp, $sp, -32\n"                                       \
1102 		"syscall\n"                                                   \
1103 		"addiu $sp, $sp, 32\n"                                        \
1104 		: "=r"(_num), "=r"(_arg4)                                     \
1105 		: "0"(_num),                                                  \
1106 		  "r"(_arg1), "r"(_arg2)                                      \
1107 		: "memory", "cc", "at", "v1", "hi", "lo",                     \
1108 		  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
1109 	);                                                                    \
1110 	_arg4 ? -_num : _num;                                                 \
1111 })
1112 
1113 #define my_syscall3(num, arg1, arg2, arg3)                                    \
1114 ({                                                                            \
1115 	register long _num asm("v0")  = (num);                                \
1116 	register long _arg1 asm("a0") = (long)(arg1);                         \
1117 	register long _arg2 asm("a1") = (long)(arg2);                         \
1118 	register long _arg3 asm("a2") = (long)(arg3);                         \
1119 	register long _arg4 asm("a3");                                        \
1120 									      \
1121 	asm volatile (                                                        \
1122 		"addiu $sp, $sp, -32\n"                                       \
1123 		"syscall\n"                                                   \
1124 		"addiu $sp, $sp, 32\n"                                        \
1125 		: "=r"(_num), "=r"(_arg4)                                     \
1126 		: "0"(_num),                                                  \
1127 		  "r"(_arg1), "r"(_arg2), "r"(_arg3)                          \
1128 		: "memory", "cc", "at", "v1", "hi", "lo",                     \
1129 		  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
1130 	);                                                                    \
1131 	_arg4 ? -_num : _num;                                                 \
1132 })
1133 
1134 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
1135 ({                                                                            \
1136 	register long _num asm("v0") = (num);                                 \
1137 	register long _arg1 asm("a0") = (long)(arg1);                         \
1138 	register long _arg2 asm("a1") = (long)(arg2);                         \
1139 	register long _arg3 asm("a2") = (long)(arg3);                         \
1140 	register long _arg4 asm("a3") = (long)(arg4);                         \
1141 									      \
1142 	asm volatile (                                                        \
1143 		"addiu $sp, $sp, -32\n"                                       \
1144 		"syscall\n"                                                   \
1145 		"addiu $sp, $sp, 32\n"                                        \
1146 		: "=r" (_num), "=r"(_arg4)                                    \
1147 		: "0"(_num),                                                  \
1148 		  "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4)              \
1149 		: "memory", "cc", "at", "v1", "hi", "lo",                     \
1150 		  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
1151 	);                                                                    \
1152 	_arg4 ? -_num : _num;                                                 \
1153 })
1154 
1155 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
1156 ({                                                                            \
1157 	register long _num asm("v0") = (num);                                 \
1158 	register long _arg1 asm("a0") = (long)(arg1);                         \
1159 	register long _arg2 asm("a1") = (long)(arg2);                         \
1160 	register long _arg3 asm("a2") = (long)(arg3);                         \
1161 	register long _arg4 asm("a3") = (long)(arg4);                         \
1162 	register long _arg5 = (long)(arg5);				      \
1163 									      \
1164 	asm volatile (                                                        \
1165 		"addiu $sp, $sp, -32\n"                                       \
1166 		"sw %7, 16($sp)\n"                                            \
1167 		"syscall\n  "                                                 \
1168 		"addiu $sp, $sp, 32\n"                                        \
1169 		: "=r" (_num), "=r"(_arg4)                                    \
1170 		: "0"(_num),                                                  \
1171 		  "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5)  \
1172 		: "memory", "cc", "at", "v1", "hi", "lo",                     \
1173 		  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
1174 	);                                                                    \
1175 	_arg4 ? -_num : _num;                                                 \
1176 })
1177 
1178 /* startup code, note that it's called __start on MIPS */
1179 asm(".section .text\n"
1180     ".set nomips16\n"
1181     ".global __start\n"
1182     ".set    noreorder\n"
1183     ".option pic0\n"
1184     ".ent __start\n"
1185     "__start:\n"
1186     "lw $a0,($sp)\n"              // argc was in the stack
1187     "addiu  $a1, $sp, 4\n"        // argv = sp + 4
1188     "sll $a2, $a0, 2\n"           // a2 = argc * 4
1189     "add   $a2, $a2, $a1\n"       // envp = argv + 4*argc ...
1190     "addiu $a2, $a2, 4\n"         //        ... + 4
1191     "li $t0, -8\n"
1192     "and $sp, $sp, $t0\n"         // sp must be 8-byte aligned
1193     "addiu $sp,$sp,-16\n"         // the callee expects to save a0..a3 there!
1194     "jal main\n"                  // main() returns the status code, we'll exit with it.
1195     "nop\n"                       // delayed slot
1196     "move $a0, $v0\n"             // retrieve 32-bit exit code from v0
1197     "li $v0, 4001\n"              // NR_exit == 4001
1198     "syscall\n"
1199     ".end __start\n"
1200     "");
1201 
1202 /* fcntl / open */
1203 #define O_RDONLY            0
1204 #define O_WRONLY            1
1205 #define O_RDWR              2
1206 #define O_APPEND       0x0008
1207 #define O_NONBLOCK     0x0080
1208 #define O_CREAT        0x0100
1209 #define O_TRUNC        0x0200
1210 #define O_EXCL         0x0400
1211 #define O_NOCTTY       0x0800
1212 #define O_DIRECTORY   0x10000
1213 
1214 /* The struct returned by the stat() syscall. 88 bytes are returned by the
1215  * syscall.
1216  */
1217 struct sys_stat_struct {
1218 	unsigned int  st_dev;
1219 	long          st_pad1[3];
1220 	unsigned long st_ino;
1221 	unsigned int  st_mode;
1222 	unsigned int  st_nlink;
1223 	unsigned int  st_uid;
1224 	unsigned int  st_gid;
1225 	unsigned int  st_rdev;
1226 	long          st_pad2[2];
1227 	long          st_size;
1228 	long          st_pad3;
1229 	long          st_atime;
1230 	long          st_atime_nsec;
1231 	long          st_mtime;
1232 	long          st_mtime_nsec;
1233 	long          st_ctime;
1234 	long          st_ctime_nsec;
1235 	long          st_blksize;
1236 	long          st_blocks;
1237 	long          st_pad4[14];
1238 };
1239 
1240 #elif defined(__riscv)
1241 
1242 #if   __riscv_xlen == 64
1243 #define PTRLOG "3"
1244 #define SZREG  "8"
1245 #elif __riscv_xlen == 32
1246 #define PTRLOG "2"
1247 #define SZREG  "4"
1248 #endif
1249 
1250 /* Syscalls for RISCV :
1251  *   - stack is 16-byte aligned
1252  *   - syscall number is passed in a7
1253  *   - arguments are in a0, a1, a2, a3, a4, a5
1254  *   - the system call is performed by calling ecall
1255  *   - syscall return comes in a0
1256  *   - the arguments are cast to long and assigned into the target
1257  *     registers which are then simply passed as registers to the asm code,
1258  *     so that we don't have to experience issues with register constraints.
1259  */
1260 
1261 #define my_syscall0(num)                                                      \
1262 ({                                                                            \
1263 	register long _num  asm("a7") = (num);                                \
1264 	register long _arg1 asm("a0");                                        \
1265 									      \
1266 	asm volatile (                                                        \
1267 		"ecall\n\t"                                                   \
1268 		: "=r"(_arg1)                                                 \
1269 		: "r"(_num)                                                   \
1270 		: "memory", "cc"                                              \
1271 	);                                                                    \
1272 	_arg1;                                                                \
1273 })
1274 
1275 #define my_syscall1(num, arg1)                                                \
1276 ({                                                                            \
1277 	register long _num  asm("a7") = (num);                                \
1278 	register long _arg1 asm("a0") = (long)(arg1);		              \
1279 									      \
1280 	asm volatile (                                                        \
1281 		"ecall\n"                                                     \
1282 		: "+r"(_arg1)                                                 \
1283 		: "r"(_num)                                                   \
1284 		: "memory", "cc"                                              \
1285 	);                                                                    \
1286 	_arg1;                                                                \
1287 })
1288 
1289 #define my_syscall2(num, arg1, arg2)                                          \
1290 ({                                                                            \
1291 	register long _num  asm("a7") = (num);                                \
1292 	register long _arg1 asm("a0") = (long)(arg1);                         \
1293 	register long _arg2 asm("a1") = (long)(arg2);                         \
1294 									      \
1295 	asm volatile (                                                        \
1296 		"ecall\n"                                                     \
1297 		: "+r"(_arg1)                                                 \
1298 		: "r"(_arg2),                                                 \
1299 		  "r"(_num)                                                   \
1300 		: "memory", "cc"                                              \
1301 	);                                                                    \
1302 	_arg1;                                                                \
1303 })
1304 
1305 #define my_syscall3(num, arg1, arg2, arg3)                                    \
1306 ({                                                                            \
1307 	register long _num  asm("a7") = (num);                                \
1308 	register long _arg1 asm("a0") = (long)(arg1);                         \
1309 	register long _arg2 asm("a1") = (long)(arg2);                         \
1310 	register long _arg3 asm("a2") = (long)(arg3);                         \
1311 									      \
1312 	asm volatile (                                                        \
1313 		"ecall\n\t"                                                   \
1314 		: "+r"(_arg1)                                                 \
1315 		: "r"(_arg2), "r"(_arg3),                                     \
1316 		  "r"(_num)                                                   \
1317 		: "memory", "cc"                                              \
1318 	);                                                                    \
1319 	_arg1;                                                                \
1320 })
1321 
1322 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
1323 ({                                                                            \
1324 	register long _num  asm("a7") = (num);                                \
1325 	register long _arg1 asm("a0") = (long)(arg1);                         \
1326 	register long _arg2 asm("a1") = (long)(arg2);                         \
1327 	register long _arg3 asm("a2") = (long)(arg3);                         \
1328 	register long _arg4 asm("a3") = (long)(arg4);                         \
1329 									      \
1330 	asm volatile (                                                        \
1331 		"ecall\n"                                                     \
1332 		: "+r"(_arg1)                                                 \
1333 		: "r"(_arg2), "r"(_arg3), "r"(_arg4),                         \
1334 		  "r"(_num)                                                   \
1335 		: "memory", "cc"                                              \
1336 	);                                                                    \
1337 	_arg1;                                                                \
1338 })
1339 
1340 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
1341 ({                                                                            \
1342 	register long _num  asm("a7") = (num);                                \
1343 	register long _arg1 asm("a0") = (long)(arg1);                         \
1344 	register long _arg2 asm("a1") = (long)(arg2);                         \
1345 	register long _arg3 asm("a2") = (long)(arg3);                         \
1346 	register long _arg4 asm("a3") = (long)(arg4);                         \
1347 	register long _arg5 asm("a4") = (long)(arg5);                         \
1348 									      \
1349 	asm volatile (                                                        \
1350 		"ecall\n"                                                     \
1351 		: "+r"(_arg1)                                                 \
1352 		: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5),             \
1353 		  "r"(_num)                                                   \
1354 		: "memory", "cc"                                              \
1355 	);                                                                    \
1356 	_arg1;                                                                \
1357 })
1358 
1359 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
1360 ({                                                                            \
1361 	register long _num  asm("a7") = (num);                                \
1362 	register long _arg1 asm("a0") = (long)(arg1);                         \
1363 	register long _arg2 asm("a1") = (long)(arg2);                         \
1364 	register long _arg3 asm("a2") = (long)(arg3);                         \
1365 	register long _arg4 asm("a3") = (long)(arg4);                         \
1366 	register long _arg5 asm("a4") = (long)(arg5);                         \
1367 	register long _arg6 asm("a5") = (long)(arg6);                         \
1368 									      \
1369 	asm volatile (                                                        \
1370 		"ecall\n"                                                     \
1371 		: "+r"(_arg1)                                                 \
1372 		: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
1373 		  "r"(_num)                                                   \
1374 		: "memory", "cc"                                              \
1375 	);                                                                    \
1376 	_arg1;                                                                \
1377 })
1378 
1379 /* startup code */
1380 asm(".section .text\n"
1381     ".global _start\n"
1382     "_start:\n"
1383     ".option push\n"
1384     ".option norelax\n"
1385     "lla   gp, __global_pointer$\n"
1386     ".option pop\n"
1387     "ld    a0, 0(sp)\n"          // argc (a0) was in the stack
1388     "add   a1, sp, "SZREG"\n"    // argv (a1) = sp
1389     "slli  a2, a0, "PTRLOG"\n"   // envp (a2) = SZREG*argc ...
1390     "add   a2, a2, "SZREG"\n"    //             + SZREG (skip null)
1391     "add   a2,a2,a1\n"           //             + argv
1392     "andi  sp,a1,-16\n"          // sp must be 16-byte aligned
1393     "call  main\n"               // main() returns the status code, we'll exit with it.
1394     "li a7, 93\n"                // NR_exit == 93
1395     "ecall\n"
1396     "");
1397 
1398 /* fcntl / open */
1399 #define O_RDONLY            0
1400 #define O_WRONLY            1
1401 #define O_RDWR              2
1402 #define O_CREAT         0x100
1403 #define O_EXCL          0x200
1404 #define O_NOCTTY        0x400
1405 #define O_TRUNC        0x1000
1406 #define O_APPEND       0x2000
1407 #define O_NONBLOCK     0x4000
1408 #define O_DIRECTORY  0x200000
1409 
1410 struct sys_stat_struct {
1411 	unsigned long	st_dev;		/* Device.  */
1412 	unsigned long	st_ino;		/* File serial number.  */
1413 	unsigned int	st_mode;	/* File mode.  */
1414 	unsigned int	st_nlink;	/* Link count.  */
1415 	unsigned int	st_uid;		/* User ID of the file's owner.  */
1416 	unsigned int	st_gid;		/* Group ID of the file's group. */
1417 	unsigned long	st_rdev;	/* Device number, if device.  */
1418 	unsigned long	__pad1;
1419 	long		st_size;	/* Size of file, in bytes.  */
1420 	int		st_blksize;	/* Optimal block size for I/O.  */
1421 	int		__pad2;
1422 	long		st_blocks;	/* Number 512-byte blocks allocated. */
1423 	long		st_atime;	/* Time of last access.  */
1424 	unsigned long	st_atime_nsec;
1425 	long		st_mtime;	/* Time of last modification.  */
1426 	unsigned long	st_mtime_nsec;
1427 	long		st_ctime;	/* Time of last status change.  */
1428 	unsigned long	st_ctime_nsec;
1429 	unsigned int	__unused4;
1430 	unsigned int	__unused5;
1431 };
1432 
1433 #endif
1434 
1435 
1436 /* Below are the C functions used to declare the raw syscalls. They try to be
1437  * architecture-agnostic, and return either a success or -errno. Declaring them
1438  * static will lead to them being inlined in most cases, but it's still possible
1439  * to reference them by a pointer if needed.
1440  */
1441 static __attribute__((unused))
1442 void *sys_brk(void *addr)
1443 {
1444 	return (void *)my_syscall1(__NR_brk, addr);
1445 }
1446 
1447 static __attribute__((noreturn,unused))
1448 void sys_exit(int status)
1449 {
1450 	my_syscall1(__NR_exit, status & 255);
1451 	while(1); // shut the "noreturn" warnings.
1452 }
1453 
1454 static __attribute__((unused))
1455 int sys_chdir(const char *path)
1456 {
1457 	return my_syscall1(__NR_chdir, path);
1458 }
1459 
1460 static __attribute__((unused))
1461 int sys_chmod(const char *path, mode_t mode)
1462 {
1463 #ifdef __NR_fchmodat
1464 	return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0);
1465 #elif defined(__NR_chmod)
1466 	return my_syscall2(__NR_chmod, path, mode);
1467 #else
1468 #error Neither __NR_fchmodat nor __NR_chmod defined, cannot implement sys_chmod()
1469 #endif
1470 }
1471 
1472 static __attribute__((unused))
1473 int sys_chown(const char *path, uid_t owner, gid_t group)
1474 {
1475 #ifdef __NR_fchownat
1476 	return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0);
1477 #elif defined(__NR_chown)
1478 	return my_syscall3(__NR_chown, path, owner, group);
1479 #else
1480 #error Neither __NR_fchownat nor __NR_chown defined, cannot implement sys_chown()
1481 #endif
1482 }
1483 
1484 static __attribute__((unused))
1485 int sys_chroot(const char *path)
1486 {
1487 	return my_syscall1(__NR_chroot, path);
1488 }
1489 
1490 static __attribute__((unused))
1491 int sys_close(int fd)
1492 {
1493 	return my_syscall1(__NR_close, fd);
1494 }
1495 
1496 static __attribute__((unused))
1497 int sys_dup(int fd)
1498 {
1499 	return my_syscall1(__NR_dup, fd);
1500 }
1501 
1502 #ifdef __NR_dup3
1503 static __attribute__((unused))
1504 int sys_dup3(int old, int new, int flags)
1505 {
1506 	return my_syscall3(__NR_dup3, old, new, flags);
1507 }
1508 #endif
1509 
1510 static __attribute__((unused))
1511 int sys_dup2(int old, int new)
1512 {
1513 #ifdef __NR_dup3
1514 	return my_syscall3(__NR_dup3, old, new, 0);
1515 #elif defined(__NR_dup2)
1516 	return my_syscall2(__NR_dup2, old, new);
1517 #else
1518 #error Neither __NR_dup3 nor __NR_dup2 defined, cannot implement sys_dup2()
1519 #endif
1520 }
1521 
1522 static __attribute__((unused))
1523 int sys_execve(const char *filename, char *const argv[], char *const envp[])
1524 {
1525 	return my_syscall3(__NR_execve, filename, argv, envp);
1526 }
1527 
1528 static __attribute__((unused))
1529 pid_t sys_fork(void)
1530 {
1531 #ifdef __NR_clone
1532 	/* note: some archs only have clone() and not fork(). Different archs
1533 	 * have a different API, but most archs have the flags on first arg and
1534 	 * will not use the rest with no other flag.
1535 	 */
1536 	return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0);
1537 #elif defined(__NR_fork)
1538 	return my_syscall0(__NR_fork);
1539 #else
1540 #error Neither __NR_clone nor __NR_fork defined, cannot implement sys_fork()
1541 #endif
1542 }
1543 
1544 static __attribute__((unused))
1545 int sys_fsync(int fd)
1546 {
1547 	return my_syscall1(__NR_fsync, fd);
1548 }
1549 
1550 static __attribute__((unused))
1551 int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count)
1552 {
1553 	return my_syscall3(__NR_getdents64, fd, dirp, count);
1554 }
1555 
1556 static __attribute__((unused))
1557 pid_t sys_getpgid(pid_t pid)
1558 {
1559 	return my_syscall1(__NR_getpgid, pid);
1560 }
1561 
1562 static __attribute__((unused))
1563 pid_t sys_getpgrp(void)
1564 {
1565 	return sys_getpgid(0);
1566 }
1567 
1568 static __attribute__((unused))
1569 pid_t sys_getpid(void)
1570 {
1571 	return my_syscall0(__NR_getpid);
1572 }
1573 
1574 static __attribute__((unused))
1575 pid_t sys_gettid(void)
1576 {
1577 	return my_syscall0(__NR_gettid);
1578 }
1579 
1580 static __attribute__((unused))
1581 int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
1582 {
1583 	return my_syscall2(__NR_gettimeofday, tv, tz);
1584 }
1585 
1586 static __attribute__((unused))
1587 int sys_ioctl(int fd, unsigned long req, void *value)
1588 {
1589 	return my_syscall3(__NR_ioctl, fd, req, value);
1590 }
1591 
1592 static __attribute__((unused))
1593 int sys_kill(pid_t pid, int signal)
1594 {
1595 	return my_syscall2(__NR_kill, pid, signal);
1596 }
1597 
1598 static __attribute__((unused))
1599 int sys_link(const char *old, const char *new)
1600 {
1601 #ifdef __NR_linkat
1602 	return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0);
1603 #elif defined(__NR_link)
1604 	return my_syscall2(__NR_link, old, new);
1605 #else
1606 #error Neither __NR_linkat nor __NR_link defined, cannot implement sys_link()
1607 #endif
1608 }
1609 
1610 static __attribute__((unused))
1611 off_t sys_lseek(int fd, off_t offset, int whence)
1612 {
1613 	return my_syscall3(__NR_lseek, fd, offset, whence);
1614 }
1615 
1616 static __attribute__((unused))
1617 int sys_mkdir(const char *path, mode_t mode)
1618 {
1619 #ifdef __NR_mkdirat
1620 	return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode);
1621 #elif defined(__NR_mkdir)
1622 	return my_syscall2(__NR_mkdir, path, mode);
1623 #else
1624 #error Neither __NR_mkdirat nor __NR_mkdir defined, cannot implement sys_mkdir()
1625 #endif
1626 }
1627 
1628 static __attribute__((unused))
1629 long sys_mknod(const char *path, mode_t mode, dev_t dev)
1630 {
1631 #ifdef __NR_mknodat
1632 	return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev);
1633 #elif defined(__NR_mknod)
1634 	return my_syscall3(__NR_mknod, path, mode, dev);
1635 #else
1636 #error Neither __NR_mknodat nor __NR_mknod defined, cannot implement sys_mknod()
1637 #endif
1638 }
1639 
1640 static __attribute__((unused))
1641 int sys_mount(const char *src, const char *tgt, const char *fst,
1642 	      unsigned long flags, const void *data)
1643 {
1644 	return my_syscall5(__NR_mount, src, tgt, fst, flags, data);
1645 }
1646 
1647 static __attribute__((unused))
1648 int sys_open(const char *path, int flags, mode_t mode)
1649 {
1650 #ifdef __NR_openat
1651 	return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode);
1652 #elif defined(__NR_open)
1653 	return my_syscall3(__NR_open, path, flags, mode);
1654 #else
1655 #error Neither __NR_openat nor __NR_open defined, cannot implement sys_open()
1656 #endif
1657 }
1658 
1659 static __attribute__((unused))
1660 int sys_pivot_root(const char *new, const char *old)
1661 {
1662 	return my_syscall2(__NR_pivot_root, new, old);
1663 }
1664 
1665 static __attribute__((unused))
1666 int sys_poll(struct pollfd *fds, int nfds, int timeout)
1667 {
1668 #if defined(__NR_ppoll)
1669 	struct timespec t;
1670 
1671 	if (timeout >= 0) {
1672 		t.tv_sec  = timeout / 1000;
1673 		t.tv_nsec = (timeout % 1000) * 1000000;
1674 	}
1675 	return my_syscall4(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL);
1676 #elif defined(__NR_poll)
1677 	return my_syscall3(__NR_poll, fds, nfds, timeout);
1678 #else
1679 #error Neither __NR_ppoll nor __NR_poll defined, cannot implement sys_poll()
1680 #endif
1681 }
1682 
1683 static __attribute__((unused))
1684 ssize_t sys_read(int fd, void *buf, size_t count)
1685 {
1686 	return my_syscall3(__NR_read, fd, buf, count);
1687 }
1688 
1689 static __attribute__((unused))
1690 ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg)
1691 {
1692 	return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg);
1693 }
1694 
1695 static __attribute__((unused))
1696 int sys_sched_yield(void)
1697 {
1698 	return my_syscall0(__NR_sched_yield);
1699 }
1700 
1701 static __attribute__((unused))
1702 int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
1703 {
1704 #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect)
1705 	struct sel_arg_struct {
1706 		unsigned long n;
1707 		fd_set *r, *w, *e;
1708 		struct timeval *t;
1709 	} arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout };
1710 	return my_syscall1(__NR_select, &arg);
1711 #elif defined(__ARCH_WANT_SYS_PSELECT6) && defined(__NR_pselect6)
1712 	struct timespec t;
1713 
1714 	if (timeout) {
1715 		t.tv_sec  = timeout->tv_sec;
1716 		t.tv_nsec = timeout->tv_usec * 1000;
1717 	}
1718 	return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
1719 #elif defined(__NR__newselect) || defined(__NR_select)
1720 #ifndef __NR__newselect
1721 #define __NR__newselect __NR_select
1722 #endif
1723 	return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout);
1724 #else
1725 #error None of __NR_select, __NR_pselect6, nor __NR__newselect defined, cannot implement sys_select()
1726 #endif
1727 }
1728 
1729 static __attribute__((unused))
1730 int sys_setpgid(pid_t pid, pid_t pgid)
1731 {
1732 	return my_syscall2(__NR_setpgid, pid, pgid);
1733 }
1734 
1735 static __attribute__((unused))
1736 pid_t sys_setsid(void)
1737 {
1738 	return my_syscall0(__NR_setsid);
1739 }
1740 
1741 static __attribute__((unused))
1742 int sys_stat(const char *path, struct stat *buf)
1743 {
1744 	struct sys_stat_struct stat;
1745 	long ret;
1746 
1747 #ifdef __NR_newfstatat
1748 	/* only solution for arm64 */
1749 	ret = my_syscall4(__NR_newfstatat, AT_FDCWD, path, &stat, 0);
1750 #elif defined(__NR_stat)
1751 	ret = my_syscall2(__NR_stat, path, &stat);
1752 #else
1753 #error Neither __NR_newfstatat nor __NR_stat defined, cannot implement sys_stat()
1754 #endif
1755 	buf->st_dev     = stat.st_dev;
1756 	buf->st_ino     = stat.st_ino;
1757 	buf->st_mode    = stat.st_mode;
1758 	buf->st_nlink   = stat.st_nlink;
1759 	buf->st_uid     = stat.st_uid;
1760 	buf->st_gid     = stat.st_gid;
1761 	buf->st_rdev    = stat.st_rdev;
1762 	buf->st_size    = stat.st_size;
1763 	buf->st_blksize = stat.st_blksize;
1764 	buf->st_blocks  = stat.st_blocks;
1765 	buf->st_atime   = stat.st_atime;
1766 	buf->st_mtime   = stat.st_mtime;
1767 	buf->st_ctime   = stat.st_ctime;
1768 	return ret;
1769 }
1770 
1771 
1772 static __attribute__((unused))
1773 int sys_symlink(const char *old, const char *new)
1774 {
1775 #ifdef __NR_symlinkat
1776 	return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new);
1777 #elif defined(__NR_symlink)
1778 	return my_syscall2(__NR_symlink, old, new);
1779 #else
1780 #error Neither __NR_symlinkat nor __NR_symlink defined, cannot implement sys_symlink()
1781 #endif
1782 }
1783 
1784 static __attribute__((unused))
1785 mode_t sys_umask(mode_t mode)
1786 {
1787 	return my_syscall1(__NR_umask, mode);
1788 }
1789 
1790 static __attribute__((unused))
1791 int sys_umount2(const char *path, int flags)
1792 {
1793 	return my_syscall2(__NR_umount2, path, flags);
1794 }
1795 
1796 static __attribute__((unused))
1797 int sys_unlink(const char *path)
1798 {
1799 #ifdef __NR_unlinkat
1800 	return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0);
1801 #elif defined(__NR_unlink)
1802 	return my_syscall1(__NR_unlink, path);
1803 #else
1804 #error Neither __NR_unlinkat nor __NR_unlink defined, cannot implement sys_unlink()
1805 #endif
1806 }
1807 
1808 static __attribute__((unused))
1809 pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
1810 {
1811 	return my_syscall4(__NR_wait4, pid, status, options, rusage);
1812 }
1813 
1814 static __attribute__((unused))
1815 pid_t sys_waitpid(pid_t pid, int *status, int options)
1816 {
1817 	return sys_wait4(pid, status, options, 0);
1818 }
1819 
1820 static __attribute__((unused))
1821 pid_t sys_wait(int *status)
1822 {
1823 	return sys_waitpid(-1, status, 0);
1824 }
1825 
1826 static __attribute__((unused))
1827 ssize_t sys_write(int fd, const void *buf, size_t count)
1828 {
1829 	return my_syscall3(__NR_write, fd, buf, count);
1830 }
1831 
1832 
1833 /* Below are the libc-compatible syscalls which return x or -1 and set errno.
1834  * They rely on the functions above. Similarly they're marked static so that it
1835  * is possible to assign pointers to them if needed.
1836  */
1837 
1838 static __attribute__((unused))
1839 int brk(void *addr)
1840 {
1841 	void *ret = sys_brk(addr);
1842 
1843 	if (!ret) {
1844 		SET_ERRNO(ENOMEM);
1845 		return -1;
1846 	}
1847 	return 0;
1848 }
1849 
1850 static __attribute__((noreturn,unused))
1851 void exit(int status)
1852 {
1853 	sys_exit(status);
1854 }
1855 
1856 static __attribute__((unused))
1857 int chdir(const char *path)
1858 {
1859 	int ret = sys_chdir(path);
1860 
1861 	if (ret < 0) {
1862 		SET_ERRNO(-ret);
1863 		ret = -1;
1864 	}
1865 	return ret;
1866 }
1867 
1868 static __attribute__((unused))
1869 int chmod(const char *path, mode_t mode)
1870 {
1871 	int ret = sys_chmod(path, mode);
1872 
1873 	if (ret < 0) {
1874 		SET_ERRNO(-ret);
1875 		ret = -1;
1876 	}
1877 	return ret;
1878 }
1879 
1880 static __attribute__((unused))
1881 int chown(const char *path, uid_t owner, gid_t group)
1882 {
1883 	int ret = sys_chown(path, owner, group);
1884 
1885 	if (ret < 0) {
1886 		SET_ERRNO(-ret);
1887 		ret = -1;
1888 	}
1889 	return ret;
1890 }
1891 
1892 static __attribute__((unused))
1893 int chroot(const char *path)
1894 {
1895 	int ret = sys_chroot(path);
1896 
1897 	if (ret < 0) {
1898 		SET_ERRNO(-ret);
1899 		ret = -1;
1900 	}
1901 	return ret;
1902 }
1903 
1904 static __attribute__((unused))
1905 int close(int fd)
1906 {
1907 	int ret = sys_close(fd);
1908 
1909 	if (ret < 0) {
1910 		SET_ERRNO(-ret);
1911 		ret = -1;
1912 	}
1913 	return ret;
1914 }
1915 
1916 static __attribute__((unused))
1917 int dup(int fd)
1918 {
1919 	int ret = sys_dup(fd);
1920 
1921 	if (ret < 0) {
1922 		SET_ERRNO(-ret);
1923 		ret = -1;
1924 	}
1925 	return ret;
1926 }
1927 
1928 static __attribute__((unused))
1929 int dup2(int old, int new)
1930 {
1931 	int ret = sys_dup2(old, new);
1932 
1933 	if (ret < 0) {
1934 		SET_ERRNO(-ret);
1935 		ret = -1;
1936 	}
1937 	return ret;
1938 }
1939 
1940 #ifdef __NR_dup3
1941 static __attribute__((unused))
1942 int dup3(int old, int new, int flags)
1943 {
1944 	int ret = sys_dup3(old, new, flags);
1945 
1946 	if (ret < 0) {
1947 		SET_ERRNO(-ret);
1948 		ret = -1;
1949 	}
1950 	return ret;
1951 }
1952 #endif
1953 
1954 static __attribute__((unused))
1955 int execve(const char *filename, char *const argv[], char *const envp[])
1956 {
1957 	int ret = sys_execve(filename, argv, envp);
1958 
1959 	if (ret < 0) {
1960 		SET_ERRNO(-ret);
1961 		ret = -1;
1962 	}
1963 	return ret;
1964 }
1965 
1966 static __attribute__((unused))
1967 pid_t fork(void)
1968 {
1969 	pid_t ret = sys_fork();
1970 
1971 	if (ret < 0) {
1972 		SET_ERRNO(-ret);
1973 		ret = -1;
1974 	}
1975 	return ret;
1976 }
1977 
1978 static __attribute__((unused))
1979 int fsync(int fd)
1980 {
1981 	int ret = sys_fsync(fd);
1982 
1983 	if (ret < 0) {
1984 		SET_ERRNO(-ret);
1985 		ret = -1;
1986 	}
1987 	return ret;
1988 }
1989 
1990 static __attribute__((unused))
1991 int getdents64(int fd, struct linux_dirent64 *dirp, int count)
1992 {
1993 	int ret = sys_getdents64(fd, dirp, count);
1994 
1995 	if (ret < 0) {
1996 		SET_ERRNO(-ret);
1997 		ret = -1;
1998 	}
1999 	return ret;
2000 }
2001 
2002 static __attribute__((unused))
2003 pid_t getpgid(pid_t pid)
2004 {
2005 	pid_t ret = sys_getpgid(pid);
2006 
2007 	if (ret < 0) {
2008 		SET_ERRNO(-ret);
2009 		ret = -1;
2010 	}
2011 	return ret;
2012 }
2013 
2014 static __attribute__((unused))
2015 pid_t getpgrp(void)
2016 {
2017 	pid_t ret = sys_getpgrp();
2018 
2019 	if (ret < 0) {
2020 		SET_ERRNO(-ret);
2021 		ret = -1;
2022 	}
2023 	return ret;
2024 }
2025 
2026 static __attribute__((unused))
2027 pid_t getpid(void)
2028 {
2029 	pid_t ret = sys_getpid();
2030 
2031 	if (ret < 0) {
2032 		SET_ERRNO(-ret);
2033 		ret = -1;
2034 	}
2035 	return ret;
2036 }
2037 
2038 static __attribute__((unused))
2039 pid_t gettid(void)
2040 {
2041 	pid_t ret = sys_gettid();
2042 
2043 	if (ret < 0) {
2044 		SET_ERRNO(-ret);
2045 		ret = -1;
2046 	}
2047 	return ret;
2048 }
2049 
2050 static __attribute__((unused))
2051 int gettimeofday(struct timeval *tv, struct timezone *tz)
2052 {
2053 	int ret = sys_gettimeofday(tv, tz);
2054 
2055 	if (ret < 0) {
2056 		SET_ERRNO(-ret);
2057 		ret = -1;
2058 	}
2059 	return ret;
2060 }
2061 
2062 static __attribute__((unused))
2063 int ioctl(int fd, unsigned long req, void *value)
2064 {
2065 	int ret = sys_ioctl(fd, req, value);
2066 
2067 	if (ret < 0) {
2068 		SET_ERRNO(-ret);
2069 		ret = -1;
2070 	}
2071 	return ret;
2072 }
2073 
2074 static __attribute__((unused))
2075 int kill(pid_t pid, int signal)
2076 {
2077 	int ret = sys_kill(pid, signal);
2078 
2079 	if (ret < 0) {
2080 		SET_ERRNO(-ret);
2081 		ret = -1;
2082 	}
2083 	return ret;
2084 }
2085 
2086 static __attribute__((unused))
2087 int link(const char *old, const char *new)
2088 {
2089 	int ret = sys_link(old, new);
2090 
2091 	if (ret < 0) {
2092 		SET_ERRNO(-ret);
2093 		ret = -1;
2094 	}
2095 	return ret;
2096 }
2097 
2098 static __attribute__((unused))
2099 off_t lseek(int fd, off_t offset, int whence)
2100 {
2101 	off_t ret = sys_lseek(fd, offset, whence);
2102 
2103 	if (ret < 0) {
2104 		SET_ERRNO(-ret);
2105 		ret = -1;
2106 	}
2107 	return ret;
2108 }
2109 
2110 static __attribute__((unused))
2111 int mkdir(const char *path, mode_t mode)
2112 {
2113 	int ret = sys_mkdir(path, mode);
2114 
2115 	if (ret < 0) {
2116 		SET_ERRNO(-ret);
2117 		ret = -1;
2118 	}
2119 	return ret;
2120 }
2121 
2122 static __attribute__((unused))
2123 int mknod(const char *path, mode_t mode, dev_t dev)
2124 {
2125 	int ret = sys_mknod(path, mode, dev);
2126 
2127 	if (ret < 0) {
2128 		SET_ERRNO(-ret);
2129 		ret = -1;
2130 	}
2131 	return ret;
2132 }
2133 
2134 static __attribute__((unused))
2135 int mount(const char *src, const char *tgt,
2136 	  const char *fst, unsigned long flags,
2137 	  const void *data)
2138 {
2139 	int ret = sys_mount(src, tgt, fst, flags, data);
2140 
2141 	if (ret < 0) {
2142 		SET_ERRNO(-ret);
2143 		ret = -1;
2144 	}
2145 	return ret;
2146 }
2147 
2148 static __attribute__((unused))
2149 int open(const char *path, int flags, mode_t mode)
2150 {
2151 	int ret = sys_open(path, flags, mode);
2152 
2153 	if (ret < 0) {
2154 		SET_ERRNO(-ret);
2155 		ret = -1;
2156 	}
2157 	return ret;
2158 }
2159 
2160 static __attribute__((unused))
2161 int pivot_root(const char *new, const char *old)
2162 {
2163 	int ret = sys_pivot_root(new, old);
2164 
2165 	if (ret < 0) {
2166 		SET_ERRNO(-ret);
2167 		ret = -1;
2168 	}
2169 	return ret;
2170 }
2171 
2172 static __attribute__((unused))
2173 int poll(struct pollfd *fds, int nfds, int timeout)
2174 {
2175 	int ret = sys_poll(fds, nfds, timeout);
2176 
2177 	if (ret < 0) {
2178 		SET_ERRNO(-ret);
2179 		ret = -1;
2180 	}
2181 	return ret;
2182 }
2183 
2184 static __attribute__((unused))
2185 ssize_t read(int fd, void *buf, size_t count)
2186 {
2187 	ssize_t ret = sys_read(fd, buf, count);
2188 
2189 	if (ret < 0) {
2190 		SET_ERRNO(-ret);
2191 		ret = -1;
2192 	}
2193 	return ret;
2194 }
2195 
2196 static __attribute__((unused))
2197 int reboot(int cmd)
2198 {
2199 	int ret = sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0);
2200 
2201 	if (ret < 0) {
2202 		SET_ERRNO(-ret);
2203 		ret = -1;
2204 	}
2205 	return ret;
2206 }
2207 
2208 static __attribute__((unused))
2209 void *sbrk(intptr_t inc)
2210 {
2211 	void *ret;
2212 
2213 	/* first call to find current end */
2214 	if ((ret = sys_brk(0)) && (sys_brk(ret + inc) == ret + inc))
2215 		return ret + inc;
2216 
2217 	SET_ERRNO(ENOMEM);
2218 	return (void *)-1;
2219 }
2220 
2221 static __attribute__((unused))
2222 int sched_yield(void)
2223 {
2224 	int ret = sys_sched_yield();
2225 
2226 	if (ret < 0) {
2227 		SET_ERRNO(-ret);
2228 		ret = -1;
2229 	}
2230 	return ret;
2231 }
2232 
2233 static __attribute__((unused))
2234 int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
2235 {
2236 	int ret = sys_select(nfds, rfds, wfds, efds, timeout);
2237 
2238 	if (ret < 0) {
2239 		SET_ERRNO(-ret);
2240 		ret = -1;
2241 	}
2242 	return ret;
2243 }
2244 
2245 static __attribute__((unused))
2246 int setpgid(pid_t pid, pid_t pgid)
2247 {
2248 	int ret = sys_setpgid(pid, pgid);
2249 
2250 	if (ret < 0) {
2251 		SET_ERRNO(-ret);
2252 		ret = -1;
2253 	}
2254 	return ret;
2255 }
2256 
2257 static __attribute__((unused))
2258 pid_t setsid(void)
2259 {
2260 	pid_t ret = sys_setsid();
2261 
2262 	if (ret < 0) {
2263 		SET_ERRNO(-ret);
2264 		ret = -1;
2265 	}
2266 	return ret;
2267 }
2268 
2269 static __attribute__((unused))
2270 unsigned int sleep(unsigned int seconds)
2271 {
2272 	struct timeval my_timeval = { seconds, 0 };
2273 
2274 	if (sys_select(0, 0, 0, 0, &my_timeval) < 0)
2275 		return my_timeval.tv_sec + !!my_timeval.tv_usec;
2276 	else
2277 		return 0;
2278 }
2279 
2280 static __attribute__((unused))
2281 int msleep(unsigned int msecs)
2282 {
2283 	struct timeval my_timeval = { msecs / 1000, (msecs % 1000) * 1000 };
2284 
2285 	if (sys_select(0, 0, 0, 0, &my_timeval) < 0)
2286 		return (my_timeval.tv_sec * 1000) +
2287 			(my_timeval.tv_usec / 1000) +
2288 			!!(my_timeval.tv_usec % 1000);
2289 	else
2290 		return 0;
2291 }
2292 
2293 static __attribute__((unused))
2294 int stat(const char *path, struct stat *buf)
2295 {
2296 	int ret = sys_stat(path, buf);
2297 
2298 	if (ret < 0) {
2299 		SET_ERRNO(-ret);
2300 		ret = -1;
2301 	}
2302 	return ret;
2303 }
2304 
2305 static __attribute__((unused))
2306 int symlink(const char *old, const char *new)
2307 {
2308 	int ret = sys_symlink(old, new);
2309 
2310 	if (ret < 0) {
2311 		SET_ERRNO(-ret);
2312 		ret = -1;
2313 	}
2314 	return ret;
2315 }
2316 
2317 static __attribute__((unused))
2318 int tcsetpgrp(int fd, pid_t pid)
2319 {
2320 	return ioctl(fd, TIOCSPGRP, &pid);
2321 }
2322 
2323 static __attribute__((unused))
2324 mode_t umask(mode_t mode)
2325 {
2326 	return sys_umask(mode);
2327 }
2328 
2329 static __attribute__((unused))
2330 int umount2(const char *path, int flags)
2331 {
2332 	int ret = sys_umount2(path, flags);
2333 
2334 	if (ret < 0) {
2335 		SET_ERRNO(-ret);
2336 		ret = -1;
2337 	}
2338 	return ret;
2339 }
2340 
2341 static __attribute__((unused))
2342 int unlink(const char *path)
2343 {
2344 	int ret = sys_unlink(path);
2345 
2346 	if (ret < 0) {
2347 		SET_ERRNO(-ret);
2348 		ret = -1;
2349 	}
2350 	return ret;
2351 }
2352 
2353 static __attribute__((unused))
2354 pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage)
2355 {
2356 	pid_t ret = sys_wait4(pid, status, options, rusage);
2357 
2358 	if (ret < 0) {
2359 		SET_ERRNO(-ret);
2360 		ret = -1;
2361 	}
2362 	return ret;
2363 }
2364 
2365 static __attribute__((unused))
2366 pid_t waitpid(pid_t pid, int *status, int options)
2367 {
2368 	pid_t ret = sys_waitpid(pid, status, options);
2369 
2370 	if (ret < 0) {
2371 		SET_ERRNO(-ret);
2372 		ret = -1;
2373 	}
2374 	return ret;
2375 }
2376 
2377 static __attribute__((unused))
2378 pid_t wait(int *status)
2379 {
2380 	pid_t ret = sys_wait(status);
2381 
2382 	if (ret < 0) {
2383 		SET_ERRNO(-ret);
2384 		ret = -1;
2385 	}
2386 	return ret;
2387 }
2388 
2389 static __attribute__((unused))
2390 ssize_t write(int fd, const void *buf, size_t count)
2391 {
2392 	ssize_t ret = sys_write(fd, buf, count);
2393 
2394 	if (ret < 0) {
2395 		SET_ERRNO(-ret);
2396 		ret = -1;
2397 	}
2398 	return ret;
2399 }
2400 
2401 /* some size-optimized reimplementations of a few common str* and mem*
2402  * functions. They're marked static, except memcpy() and raise() which are used
2403  * by libgcc on ARM, so they are marked weak instead in order not to cause an
2404  * error when building a program made of multiple files (not recommended).
2405  */
2406 
2407 static __attribute__((unused))
2408 void *memmove(void *dst, const void *src, size_t len)
2409 {
2410 	ssize_t pos = (dst <= src) ? -1 : (long)len;
2411 	void *ret = dst;
2412 
2413 	while (len--) {
2414 		pos += (dst <= src) ? 1 : -1;
2415 		((char *)dst)[pos] = ((char *)src)[pos];
2416 	}
2417 	return ret;
2418 }
2419 
2420 static __attribute__((unused))
2421 void *memset(void *dst, int b, size_t len)
2422 {
2423 	char *p = dst;
2424 
2425 	while (len--)
2426 		*(p++) = b;
2427 	return dst;
2428 }
2429 
2430 static __attribute__((unused))
2431 int memcmp(const void *s1, const void *s2, size_t n)
2432 {
2433 	size_t ofs = 0;
2434 	char c1 = 0;
2435 
2436 	while (ofs < n && !(c1 = ((char *)s1)[ofs] - ((char *)s2)[ofs])) {
2437 		ofs++;
2438 	}
2439 	return c1;
2440 }
2441 
2442 static __attribute__((unused))
2443 char *strcpy(char *dst, const char *src)
2444 {
2445 	char *ret = dst;
2446 
2447 	while ((*dst++ = *src++));
2448 	return ret;
2449 }
2450 
2451 static __attribute__((unused))
2452 char *strchr(const char *s, int c)
2453 {
2454 	while (*s) {
2455 		if (*s == (char)c)
2456 			return (char *)s;
2457 		s++;
2458 	}
2459 	return NULL;
2460 }
2461 
2462 static __attribute__((unused))
2463 char *strrchr(const char *s, int c)
2464 {
2465 	const char *ret = NULL;
2466 
2467 	while (*s) {
2468 		if (*s == (char)c)
2469 			ret = s;
2470 		s++;
2471 	}
2472 	return (char *)ret;
2473 }
2474 
2475 static __attribute__((unused))
2476 size_t nolibc_strlen(const char *str)
2477 {
2478 	size_t len;
2479 
2480 	for (len = 0; str[len]; len++);
2481 	return len;
2482 }
2483 
2484 #define strlen(str) ({                          \
2485 	__builtin_constant_p((str)) ?           \
2486 		__builtin_strlen((str)) :       \
2487 		nolibc_strlen((str));           \
2488 })
2489 
2490 static __attribute__((unused))
2491 int isdigit(int c)
2492 {
2493 	return (unsigned int)(c - '0') <= 9;
2494 }
2495 
2496 static __attribute__((unused))
2497 long atol(const char *s)
2498 {
2499 	unsigned long ret = 0;
2500 	unsigned long d;
2501 	int neg = 0;
2502 
2503 	if (*s == '-') {
2504 		neg = 1;
2505 		s++;
2506 	}
2507 
2508 	while (1) {
2509 		d = (*s++) - '0';
2510 		if (d > 9)
2511 			break;
2512 		ret *= 10;
2513 		ret += d;
2514 	}
2515 
2516 	return neg ? -ret : ret;
2517 }
2518 
2519 static __attribute__((unused))
2520 int atoi(const char *s)
2521 {
2522 	return atol(s);
2523 }
2524 
2525 static __attribute__((unused))
2526 const char *ltoa(long in)
2527 {
2528 	/* large enough for -9223372036854775808 */
2529 	static char buffer[21];
2530 	char       *pos = buffer + sizeof(buffer) - 1;
2531 	int         neg = in < 0;
2532 	unsigned long n = neg ? -in : in;
2533 
2534 	*pos-- = '\0';
2535 	do {
2536 		*pos-- = '0' + n % 10;
2537 		n /= 10;
2538 		if (pos < buffer)
2539 			return pos + 1;
2540 	} while (n);
2541 
2542 	if (neg)
2543 		*pos-- = '-';
2544 	return pos + 1;
2545 }
2546 
2547 __attribute__((weak,unused))
2548 void *memcpy(void *dst, const void *src, size_t len)
2549 {
2550 	return memmove(dst, src, len);
2551 }
2552 
2553 /* needed by libgcc for divide by zero */
2554 __attribute__((weak,unused))
2555 int raise(int signal)
2556 {
2557 	return kill(getpid(), signal);
2558 }
2559 
2560 /* Here come a few helper functions */
2561 
2562 static __attribute__((unused))
2563 void FD_ZERO(fd_set *set)
2564 {
2565 	memset(set, 0, sizeof(*set));
2566 }
2567 
2568 static __attribute__((unused))
2569 void FD_SET(int fd, fd_set *set)
2570 {
2571 	if (fd < 0 || fd >= FD_SETSIZE)
2572 		return;
2573 	set->fd32[fd / 32] |= 1 << (fd & 31);
2574 }
2575 
2576 /* WARNING, it only deals with the 4096 first majors and 256 first minors */
2577 static __attribute__((unused))
2578 dev_t makedev(unsigned int major, unsigned int minor)
2579 {
2580 	return ((major & 0xfff) << 8) | (minor & 0xff);
2581 }
2582