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