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