~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/include/nolibc/nolibc.h

Version: ~ [ linux-6.4-rc3 ] ~ [ linux-6.3.4 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.30 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.113 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.180 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.243 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.283 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.315 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp