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