root/tools/include/nolibc/nolibc.h

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sys_brk
  2. sys_exit
  3. sys_chdir
  4. sys_chmod
  5. sys_chown
  6. sys_chroot
  7. sys_close
  8. sys_dup
  9. sys_dup2
  10. sys_execve
  11. sys_fork
  12. sys_fsync
  13. sys_getdents64
  14. sys_getpgrp
  15. sys_getpid
  16. sys_gettimeofday
  17. sys_ioctl
  18. sys_kill
  19. sys_link
  20. sys_lseek
  21. sys_mkdir
  22. sys_mknod
  23. sys_mount
  24. sys_open
  25. sys_pivot_root
  26. sys_poll
  27. sys_read
  28. sys_reboot
  29. sys_sched_yield
  30. sys_select
  31. sys_setpgid
  32. sys_setsid
  33. sys_stat
  34. sys_symlink
  35. sys_umask
  36. sys_umount2
  37. sys_unlink
  38. sys_wait4
  39. sys_waitpid
  40. sys_wait
  41. sys_write
  42. brk
  43. exit
  44. chdir
  45. chmod
  46. chown
  47. chroot
  48. close
  49. dup2
  50. execve
  51. fork
  52. fsync
  53. getdents64
  54. getpgrp
  55. getpid
  56. gettimeofday
  57. ioctl
  58. kill
  59. link
  60. lseek
  61. mkdir
  62. mknod
  63. mount
  64. open
  65. pivot_root
  66. poll
  67. read
  68. reboot
  69. sbrk
  70. sched_yield
  71. select
  72. setpgid
  73. setsid
  74. sleep
  75. stat
  76. symlink
  77. tcsetpgrp
  78. umask
  79. umount2
  80. unlink
  81. wait4
  82. waitpid
  83. wait
  84. write
  85. memmove
  86. memset
  87. memcmp
  88. strcpy
  89. strchr
  90. strrchr
  91. nolibc_strlen
  92. isdigit
  93. atol
  94. atoi
  95. ltoa
  96. memcpy
  97. raise
  98. FD_ZERO
  99. FD_SET
  100. makedev

   1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
   2 /* nolibc.h
   3  * Copyright (C) 2017-2018 Willy Tarreau <w@1wt.eu>
   4  */
   5 
   6 /*
   7  * This file is designed to be used as a libc alternative for minimal programs
   8  * with very limited requirements. It consists of a small number of syscall and
   9  * type definitions, and the minimal startup code needed to call main().
  10  * All syscalls are declared as static functions so that they can be optimized
  11  * away by the compiler when not used.
  12  *
  13  * Syscalls are split into 3 levels:
  14  *   - The lower level is the arch-specific syscall() definition, consisting in
  15  *     assembly code in compound expressions. These are called my_syscall0() to
  16  *     my_syscall6() depending on the number of arguments. The MIPS
  17  *     implementation is limited to 5 arguments. All input arguments are cast
  18  *     to a long stored in a register. These expressions always return the
  19  *     syscall's return value as a signed long value which is often either a
  20  *     pointer or the negated errno value.
  21  *
  22  *   - The second level is mostly architecture-independent. It is made of
  23  *     static functions called sys_<name>() which rely on my_syscallN()
  24  *     depending on the syscall definition. These functions are responsible
  25  *     for exposing the appropriate types for the syscall arguments (int,
  26  *     pointers, etc) and for setting the appropriate return type (often int).
  27  *     A few of them are architecture-specific because the syscalls are not all
  28  *     mapped exactly the same among architectures. For example, some archs do
  29  *     not implement select() and need pselect6() instead, so the sys_select()
  30  *     function will have to abstract this.
  31  *
  32  *   - The third level is the libc call definition. It exposes the lower raw
  33  *     sys_<name>() calls in a way that looks like what a libc usually does,
  34  *     takes care of specific input values, and of setting errno upon error.
  35  *     There can be minor variations compared to standard libc calls. For
  36  *     example the open() call always takes 3 args here.
  37  *
  38  * The errno variable is declared static and unused. This way it can be
  39  * optimized away if not used. However this means that a program made of
  40  * multiple C files may observe different errno values (one per C file). For
  41  * the type of programs this project targets it usually is not a problem. The
  42  * resulting program may even be reduced by defining the NOLIBC_IGNORE_ERRNO
  43  * macro, in which case the errno value will never be assigned.
  44  *
  45  * Some stdint-like integer types are defined. These are valid on all currently
  46  * supported architectures, because signs are enforced, ints are assumed to be
  47  * 32 bits, longs the size of a pointer and long long 64 bits. If more
  48  * architectures have to be supported, this may need to be adapted.
  49  *
  50  * Some macro definitions like the O_* values passed to open(), and some
  51  * structures like the sys_stat struct depend on the architecture.
  52  *
  53  * The definitions start with the architecture-specific parts, which are picked
  54  * based on what the compiler knows about the target architecture, and are
  55  * completed with the generic code. Since it is the compiler which sets the
  56  * target architecture, cross-compiling normally works out of the box without
  57  * having to specify anything.
  58  *
  59  * Finally some very common libc-level functions are provided. It is the case
  60  * for a few functions usually found in string.h, ctype.h, or stdlib.h. Nothing
  61  * is currently provided regarding stdio emulation.
  62  *
  63  * The macro NOLIBC is always defined, so that it is possible for a program to
  64  * check this macro to know if it is being built against and decide to disable
  65  * some features or simply not to include some standard libc files.
  66  *
  67  * Ideally this file should be split in multiple files for easier long term
  68  * maintenance, but provided as a single file as it is now, it's quite
  69  * convenient to use. Maybe some variations involving a set of includes at the
  70  * top could work.
  71  *
  72  * A simple static executable may be built this way :
  73  *      $ gcc -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \
  74  *            -static -include nolibc.h -lgcc -o hello hello.c
  75  *
  76  * A very useful calling convention table may be found here :
  77  *      http://man7.org/linux/man-pages/man2/syscall.2.html
  78  *
  79  * This doc is quite convenient though not necessarily up to date :
  80  *      https://w3challs.com/syscalls/
  81  *
  82  */
  83 
  84 /* Some archs (at least aarch64) don't expose the regular syscalls anymore by
  85  * default, either because they have an "_at" replacement, or because there are
  86  * more modern alternatives. For now we'd rather still use them.
  87  */
  88 #define __ARCH_WANT_SYSCALL_NO_AT
  89 #define __ARCH_WANT_SYSCALL_NO_FLAGS
  90 #define __ARCH_WANT_SYSCALL_DEPRECATED
  91 
  92 #include <asm/unistd.h>
  93 #include <asm/ioctls.h>
  94 #include <asm/errno.h>
  95 #include <linux/fs.h>
  96 #include <linux/loop.h>
  97 
  98 #define NOLIBC
  99 
 100 /* this way it will be removed if unused */
 101 static int errno;
 102 
 103 #ifndef NOLIBC_IGNORE_ERRNO
 104 #define SET_ERRNO(v) do { errno = (v); } while (0)
 105 #else
 106 #define SET_ERRNO(v) do { } while (0)
 107 #endif
 108 
 109 /* errno codes all ensure that they will not conflict with a valid pointer
 110  * because they all correspond to the highest addressable memry page.
 111  */
 112 #define MAX_ERRNO 4095
 113 
 114 /* Declare a few quite common macros and types that usually are in stdlib.h,
 115  * stdint.h, ctype.h, unistd.h and a few other common locations.
 116  */
 117 
 118 #define NULL ((void *)0)
 119 
 120 /* stdint types */
 121 typedef unsigned char       uint8_t;
 122 typedef   signed char        int8_t;
 123 typedef unsigned short     uint16_t;
 124 typedef   signed short      int16_t;
 125 typedef unsigned int       uint32_t;
 126 typedef   signed int        int32_t;
 127 typedef unsigned long long uint64_t;
 128 typedef   signed long long  int64_t;
 129 typedef unsigned long        size_t;
 130 typedef   signed long       ssize_t;
 131 typedef unsigned long     uintptr_t;
 132 typedef   signed long      intptr_t;
 133 typedef   signed long     ptrdiff_t;
 134 
 135 /* for stat() */
 136 typedef unsigned int          dev_t;
 137 typedef unsigned long         ino_t;
 138 typedef unsigned int         mode_t;
 139 typedef   signed int          pid_t;
 140 typedef unsigned int          uid_t;
 141 typedef unsigned int          gid_t;
 142 typedef unsigned long       nlink_t;
 143 typedef   signed long         off_t;
 144 typedef   signed long     blksize_t;
 145 typedef   signed long      blkcnt_t;
 146 typedef   signed long        time_t;
 147 
 148 /* for poll() */
 149 struct pollfd {
 150         int fd;
 151         short int events;
 152         short int revents;
 153 };
 154 
 155 /* for select() */
 156 struct timeval {
 157         long    tv_sec;
 158         long    tv_usec;
 159 };
 160 
 161 /* for pselect() */
 162 struct timespec {
 163         long    tv_sec;
 164         long    tv_nsec;
 165 };
 166 
 167 /* for gettimeofday() */
 168 struct timezone {
 169         int tz_minuteswest;
 170         int tz_dsttime;
 171 };
 172 
 173 /* for getdents64() */
 174 struct linux_dirent64 {
 175         uint64_t       d_ino;
 176         int64_t        d_off;
 177         unsigned short d_reclen;
 178         unsigned char  d_type;
 179         char           d_name[];
 180 };
 181 
 182 /* commonly an fd_set represents 256 FDs */
 183 #define FD_SETSIZE 256
 184 typedef struct { uint32_t fd32[FD_SETSIZE/32]; } fd_set;
 185 
 186 /* needed by wait4() */
 187 struct rusage {
 188         struct timeval ru_utime;
 189         struct timeval ru_stime;
 190         long   ru_maxrss;
 191         long   ru_ixrss;
 192         long   ru_idrss;
 193         long   ru_isrss;
 194         long   ru_minflt;
 195         long   ru_majflt;
 196         long   ru_nswap;
 197         long   ru_inblock;
 198         long   ru_oublock;
 199         long   ru_msgsnd;
 200         long   ru_msgrcv;
 201         long   ru_nsignals;
 202         long   ru_nvcsw;
 203         long   ru_nivcsw;
 204 };
 205 
 206 /* stat flags (WARNING, octal here) */
 207 #define S_IFDIR       0040000
 208 #define S_IFCHR       0020000
 209 #define S_IFBLK       0060000
 210 #define S_IFREG       0100000
 211 #define S_IFIFO       0010000
 212 #define S_IFLNK       0120000
 213 #define S_IFSOCK      0140000
 214 #define S_IFMT        0170000
 215 
 216 #define S_ISDIR(mode)  (((mode) & S_IFDIR) == S_IFDIR)
 217 #define S_ISCHR(mode)  (((mode) & S_IFCHR) == S_IFCHR)
 218 #define S_ISBLK(mode)  (((mode) & S_IFBLK) == S_IFBLK)
 219 #define S_ISREG(mode)  (((mode) & S_IFREG) == S_IFREG)
 220 #define S_ISFIFO(mode) (((mode) & S_IFIFO) == S_IFIFO)
 221 #define S_ISLNK(mode)  (((mode) & S_IFLNK) == S_IFLNK)
 222 #define S_ISSOCK(mode) (((mode) & S_IFSOCK) == S_IFSOCK)
 223 
 224 #define DT_UNKNOWN 0
 225 #define DT_FIFO    1
 226 #define DT_CHR     2
 227 #define DT_DIR     4
 228 #define DT_BLK     6
 229 #define DT_REG     8
 230 #define DT_LNK    10
 231 #define DT_SOCK   12
 232 
 233 /* all the *at functions */
 234 #ifndef AT_FDWCD
 235 #define AT_FDCWD             -100
 236 #endif
 237 
 238 /* lseek */
 239 #define SEEK_SET        0
 240 #define SEEK_CUR        1
 241 #define SEEK_END        2
 242 
 243 /* reboot */
 244 #define LINUX_REBOOT_MAGIC1         0xfee1dead
 245 #define LINUX_REBOOT_MAGIC2         0x28121969
 246 #define LINUX_REBOOT_CMD_HALT       0xcdef0123
 247 #define LINUX_REBOOT_CMD_POWER_OFF  0x4321fedc
 248 #define LINUX_REBOOT_CMD_RESTART    0x01234567
 249 #define LINUX_REBOOT_CMD_SW_SUSPEND 0xd000fce2
 250 
 251 
 252 /* The format of the struct as returned by the libc to the application, which
 253  * significantly differs from the format returned by the stat() syscall flavours.
 254  */
 255 struct stat {
 256         dev_t     st_dev;     /* ID of device containing file */
 257         ino_t     st_ino;     /* inode number */
 258         mode_t    st_mode;    /* protection */
 259         nlink_t   st_nlink;   /* number of hard links */
 260         uid_t     st_uid;     /* user ID of owner */
 261         gid_t     st_gid;     /* group ID of owner */
 262         dev_t     st_rdev;    /* device ID (if special file) */
 263         off_t     st_size;    /* total size, in bytes */
 264         blksize_t st_blksize; /* blocksize for file system I/O */
 265         blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
 266         time_t    st_atime;   /* time of last access */
 267         time_t    st_mtime;   /* time of last modification */
 268         time_t    st_ctime;   /* time of last status change */
 269 };
 270 
 271 #define WEXITSTATUS(status)   (((status) & 0xff00) >> 8)
 272 #define WIFEXITED(status)     (((status) & 0x7f) == 0)
 273 
 274 
 275 /* Below comes the architecture-specific code. For each architecture, we have
 276  * the syscall declarations and the _start code definition. This is the only
 277  * global part. On all architectures the kernel puts everything in the stack
 278  * before jumping to _start just above us, without any return address (_start
 279  * is not a function but an entry pint). So at the stack pointer we find argc.
 280  * Then argv[] begins, and ends at the first NULL. Then we have envp which
 281  * starts and ends with a NULL as well. So envp=argv+argc+1.
 282  */
 283 
 284 #if defined(__x86_64__)
 285 /* Syscalls for x86_64 :
 286  *   - registers are 64-bit
 287  *   - syscall number is passed in rax
 288  *   - arguments are in rdi, rsi, rdx, r10, r8, r9 respectively
 289  *   - the system call is performed by calling the syscall instruction
 290  *   - syscall return comes in rax
 291  *   - rcx and r8..r11 may be clobbered, others are preserved.
 292  *   - the arguments are cast to long and assigned into the target registers
 293  *     which are then simply passed as registers to the asm code, so that we
 294  *     don't have to experience issues with register constraints.
 295  *   - the syscall number is always specified last in order to allow to force
 296  *     some registers before (gcc refuses a %-register at the last position).
 297  */
 298 
 299 #define my_syscall0(num)                                                      \
 300 ({                                                                            \
 301         long _ret;                                                            \
 302         register long _num  asm("rax") = (num);                               \
 303                                                                               \
 304         asm volatile (                                                        \
 305                 "syscall\n"                                                   \
 306                 : "=a" (_ret)                                                 \
 307                 : "0"(_num)                                                   \
 308                 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc"             \
 309         );                                                                    \
 310         _ret;                                                                 \
 311 })
 312 
 313 #define my_syscall1(num, arg1)                                                \
 314 ({                                                                            \
 315         long _ret;                                                            \
 316         register long _num  asm("rax") = (num);                               \
 317         register long _arg1 asm("rdi") = (long)(arg1);                        \
 318                                                                               \
 319         asm volatile (                                                        \
 320                 "syscall\n"                                                   \
 321                 : "=a" (_ret)                                                 \
 322                 : "r"(_arg1),                                                 \
 323                   "0"(_num)                                                   \
 324                 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc"             \
 325         );                                                                    \
 326         _ret;                                                                 \
 327 })
 328 
 329 #define my_syscall2(num, arg1, arg2)                                          \
 330 ({                                                                            \
 331         long _ret;                                                            \
 332         register long _num  asm("rax") = (num);                               \
 333         register long _arg1 asm("rdi") = (long)(arg1);                        \
 334         register long _arg2 asm("rsi") = (long)(arg2);                        \
 335                                                                               \
 336         asm volatile (                                                        \
 337                 "syscall\n"                                                   \
 338                 : "=a" (_ret)                                                 \
 339                 : "r"(_arg1), "r"(_arg2),                                     \
 340                   "0"(_num)                                                   \
 341                 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc"             \
 342         );                                                                    \
 343         _ret;                                                                 \
 344 })
 345 
 346 #define my_syscall3(num, arg1, arg2, arg3)                                    \
 347 ({                                                                            \
 348         long _ret;                                                            \
 349         register long _num  asm("rax") = (num);                               \
 350         register long _arg1 asm("rdi") = (long)(arg1);                        \
 351         register long _arg2 asm("rsi") = (long)(arg2);                        \
 352         register long _arg3 asm("rdx") = (long)(arg3);                        \
 353                                                                               \
 354         asm volatile (                                                        \
 355                 "syscall\n"                                                   \
 356                 : "=a" (_ret)                                                 \
 357                 : "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
 358                   "0"(_num)                                                   \
 359                 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc"             \
 360         );                                                                    \
 361         _ret;                                                                 \
 362 })
 363 
 364 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
 365 ({                                                                            \
 366         long _ret;                                                            \
 367         register long _num  asm("rax") = (num);                               \
 368         register long _arg1 asm("rdi") = (long)(arg1);                        \
 369         register long _arg2 asm("rsi") = (long)(arg2);                        \
 370         register long _arg3 asm("rdx") = (long)(arg3);                        \
 371         register long _arg4 asm("r10") = (long)(arg4);                        \
 372                                                                               \
 373         asm volatile (                                                        \
 374                 "syscall\n"                                                   \
 375                 : "=a" (_ret), "=r"(_arg4)                                    \
 376                 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
 377                   "0"(_num)                                                   \
 378                 : "rcx", "r8", "r9", "r11", "memory", "cc"                    \
 379         );                                                                    \
 380         _ret;                                                                 \
 381 })
 382 
 383 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
 384 ({                                                                            \
 385         long _ret;                                                            \
 386         register long _num  asm("rax") = (num);                               \
 387         register long _arg1 asm("rdi") = (long)(arg1);                        \
 388         register long _arg2 asm("rsi") = (long)(arg2);                        \
 389         register long _arg3 asm("rdx") = (long)(arg3);                        \
 390         register long _arg4 asm("r10") = (long)(arg4);                        \
 391         register long _arg5 asm("r8")  = (long)(arg5);                        \
 392                                                                               \
 393         asm volatile (                                                        \
 394                 "syscall\n"                                                   \
 395                 : "=a" (_ret), "=r"(_arg4), "=r"(_arg5)                       \
 396                 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
 397                   "0"(_num)                                                   \
 398                 : "rcx", "r9", "r11", "memory", "cc"                          \
 399         );                                                                    \
 400         _ret;                                                                 \
 401 })
 402 
 403 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
 404 ({                                                                            \
 405         long _ret;                                                            \
 406         register long _num  asm("rax") = (num);                               \
 407         register long _arg1 asm("rdi") = (long)(arg1);                        \
 408         register long _arg2 asm("rsi") = (long)(arg2);                        \
 409         register long _arg3 asm("rdx") = (long)(arg3);                        \
 410         register long _arg4 asm("r10") = (long)(arg4);                        \
 411         register long _arg5 asm("r8")  = (long)(arg5);                        \
 412         register long _arg6 asm("r9")  = (long)(arg6);                        \
 413                                                                               \
 414         asm volatile (                                                        \
 415                 "syscall\n"                                                   \
 416                 : "=a" (_ret), "=r"(_arg4), "=r"(_arg5)                       \
 417                 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
 418                   "r"(_arg6), "0"(_num)                                       \
 419                 : "rcx", "r11", "memory", "cc"                                \
 420         );                                                                    \
 421         _ret;                                                                 \
 422 })
 423 
 424 /* startup code */
 425 asm(".section .text\n"
 426     ".global _start\n"
 427     "_start:\n"
 428     "pop %rdi\n"                // argc   (first arg, %rdi)
 429     "mov %rsp, %rsi\n"          // argv[] (second arg, %rsi)
 430     "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx)
 431     "and $-16, %rsp\n"          // x86 ABI : esp must be 16-byte aligned when
 432     "sub $8, %rsp\n"            // entering the callee
 433     "call main\n"               // main() returns the status code, we'll exit with it.
 434     "movzb %al, %rdi\n"         // retrieve exit code from 8 lower bits
 435     "mov $60, %rax\n"           // NR_exit == 60
 436     "syscall\n"                 // really exit
 437     "hlt\n"                     // ensure it does not return
 438     "");
 439 
 440 /* fcntl / open */
 441 #define O_RDONLY            0
 442 #define O_WRONLY            1
 443 #define O_RDWR              2
 444 #define O_CREAT          0x40
 445 #define O_EXCL           0x80
 446 #define O_NOCTTY        0x100
 447 #define O_TRUNC         0x200
 448 #define O_APPEND        0x400
 449 #define O_NONBLOCK      0x800
 450 #define O_DIRECTORY   0x10000
 451 
 452 /* The struct returned by the stat() syscall, equivalent to stat64(). The
 453  * syscall returns 116 bytes and stops in the middle of __unused.
 454  */
 455 struct sys_stat_struct {
 456         unsigned long st_dev;
 457         unsigned long st_ino;
 458         unsigned long st_nlink;
 459         unsigned int  st_mode;
 460         unsigned int  st_uid;
 461 
 462         unsigned int  st_gid;
 463         unsigned int  __pad0;
 464         unsigned long st_rdev;
 465         long          st_size;
 466         long          st_blksize;
 467 
 468         long          st_blocks;
 469         unsigned long st_atime;
 470         unsigned long st_atime_nsec;
 471         unsigned long st_mtime;
 472 
 473         unsigned long st_mtime_nsec;
 474         unsigned long st_ctime;
 475         unsigned long st_ctime_nsec;
 476         long          __unused[3];
 477 };
 478 
 479 #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
 480 /* Syscalls for i386 :
 481  *   - mostly similar to x86_64
 482  *   - registers are 32-bit
 483  *   - syscall number is passed in eax
 484  *   - arguments are in ebx, ecx, edx, esi, edi, ebp respectively
 485  *   - all registers are preserved (except eax of course)
 486  *   - the system call is performed by calling int $0x80
 487  *   - syscall return comes in eax
 488  *   - the arguments are cast to long and assigned into the target registers
 489  *     which are then simply passed as registers to the asm code, so that we
 490  *     don't have to experience issues with register constraints.
 491  *   - the syscall number is always specified last in order to allow to force
 492  *     some registers before (gcc refuses a %-register at the last position).
 493  *
 494  * Also, i386 supports the old_select syscall if newselect is not available
 495  */
 496 #define __ARCH_WANT_SYS_OLD_SELECT
 497 
 498 #define my_syscall0(num)                                                      \
 499 ({                                                                            \
 500         long _ret;                                                            \
 501         register long _num asm("eax") = (num);                                \
 502                                                                               \
 503         asm volatile (                                                        \
 504                 "int $0x80\n"                                                 \
 505                 : "=a" (_ret)                                                 \
 506                 : "0"(_num)                                                   \
 507                 : "memory", "cc"                                              \
 508         );                                                                    \
 509         _ret;                                                                 \
 510 })
 511 
 512 #define my_syscall1(num, arg1)                                                \
 513 ({                                                                            \
 514         long _ret;                                                            \
 515         register long _num asm("eax") = (num);                                \
 516         register long _arg1 asm("ebx") = (long)(arg1);                        \
 517                                                                               \
 518         asm volatile (                                                        \
 519                 "int $0x80\n"                                                 \
 520                 : "=a" (_ret)                                                 \
 521                 : "r"(_arg1),                                                 \
 522                   "0"(_num)                                                   \
 523                 : "memory", "cc"                                              \
 524         );                                                                    \
 525         _ret;                                                                 \
 526 })
 527 
 528 #define my_syscall2(num, arg1, arg2)                                          \
 529 ({                                                                            \
 530         long _ret;                                                            \
 531         register long _num asm("eax") = (num);                                \
 532         register long _arg1 asm("ebx") = (long)(arg1);                        \
 533         register long _arg2 asm("ecx") = (long)(arg2);                        \
 534                                                                               \
 535         asm volatile (                                                        \
 536                 "int $0x80\n"                                                 \
 537                 : "=a" (_ret)                                                 \
 538                 : "r"(_arg1), "r"(_arg2),                                     \
 539                   "0"(_num)                                                   \
 540                 : "memory", "cc"                                              \
 541         );                                                                    \
 542         _ret;                                                                 \
 543 })
 544 
 545 #define my_syscall3(num, arg1, arg2, arg3)                                    \
 546 ({                                                                            \
 547         long _ret;                                                            \
 548         register long _num asm("eax") = (num);                                \
 549         register long _arg1 asm("ebx") = (long)(arg1);                        \
 550         register long _arg2 asm("ecx") = (long)(arg2);                        \
 551         register long _arg3 asm("edx") = (long)(arg3);                        \
 552                                                                               \
 553         asm volatile (                                                        \
 554                 "int $0x80\n"                                                 \
 555                 : "=a" (_ret)                                                 \
 556                 : "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
 557                   "0"(_num)                                                   \
 558                 : "memory", "cc"                                              \
 559         );                                                                    \
 560         _ret;                                                                 \
 561 })
 562 
 563 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
 564 ({                                                                            \
 565         long _ret;                                                            \
 566         register long _num asm("eax") = (num);                                \
 567         register long _arg1 asm("ebx") = (long)(arg1);                        \
 568         register long _arg2 asm("ecx") = (long)(arg2);                        \
 569         register long _arg3 asm("edx") = (long)(arg3);                        \
 570         register long _arg4 asm("esi") = (long)(arg4);                        \
 571                                                                               \
 572         asm volatile (                                                        \
 573                 "int $0x80\n"                                                 \
 574                 : "=a" (_ret)                                                 \
 575                 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
 576                   "0"(_num)                                                   \
 577                 : "memory", "cc"                                              \
 578         );                                                                    \
 579         _ret;                                                                 \
 580 })
 581 
 582 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
 583 ({                                                                            \
 584         long _ret;                                                            \
 585         register long _num asm("eax") = (num);                                \
 586         register long _arg1 asm("ebx") = (long)(arg1);                        \
 587         register long _arg2 asm("ecx") = (long)(arg2);                        \
 588         register long _arg3 asm("edx") = (long)(arg3);                        \
 589         register long _arg4 asm("esi") = (long)(arg4);                        \
 590         register long _arg5 asm("edi") = (long)(arg5);                        \
 591                                                                               \
 592         asm volatile (                                                        \
 593                 "int $0x80\n"                                                 \
 594                 : "=a" (_ret)                                                 \
 595                 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
 596                   "0"(_num)                                                   \
 597                 : "memory", "cc"                                              \
 598         );                                                                    \
 599         _ret;                                                                 \
 600 })
 601 
 602 /* startup code */
 603 asm(".section .text\n"
 604     ".global _start\n"
 605     "_start:\n"
 606     "pop %eax\n"                // argc   (first arg, %eax)
 607     "mov %esp, %ebx\n"          // argv[] (second arg, %ebx)
 608     "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx)
 609     "and $-16, %esp\n"          // x86 ABI : esp must be 16-byte aligned when
 610     "push %ecx\n"               // push all registers on the stack so that we
 611     "push %ebx\n"               // support both regparm and plain stack modes
 612     "push %eax\n"
 613     "call main\n"               // main() returns the status code in %eax
 614     "movzbl %al, %ebx\n"        // retrieve exit code from lower 8 bits
 615     "movl   $1, %eax\n"         // NR_exit == 1
 616     "int    $0x80\n"            // exit now
 617     "hlt\n"                     // ensure it does not
 618     "");
 619 
 620 /* fcntl / open */
 621 #define O_RDONLY            0
 622 #define O_WRONLY            1
 623 #define O_RDWR              2
 624 #define O_CREAT          0x40
 625 #define O_EXCL           0x80
 626 #define O_NOCTTY        0x100
 627 #define O_TRUNC         0x200
 628 #define O_APPEND        0x400
 629 #define O_NONBLOCK      0x800
 630 #define O_DIRECTORY   0x10000
 631 
 632 /* The struct returned by the stat() syscall, 32-bit only, the syscall returns
 633  * exactly 56 bytes (stops before the unused array).
 634  */
 635 struct sys_stat_struct {
 636         unsigned long  st_dev;
 637         unsigned long  st_ino;
 638         unsigned short st_mode;
 639         unsigned short st_nlink;
 640         unsigned short st_uid;
 641         unsigned short st_gid;
 642 
 643         unsigned long  st_rdev;
 644         unsigned long  st_size;
 645         unsigned long  st_blksize;
 646         unsigned long  st_blocks;
 647 
 648         unsigned long  st_atime;
 649         unsigned long  st_atime_nsec;
 650         unsigned long  st_mtime;
 651         unsigned long  st_mtime_nsec;
 652 
 653         unsigned long  st_ctime;
 654         unsigned long  st_ctime_nsec;
 655         unsigned long  __unused[2];
 656 };
 657 
 658 #elif defined(__ARM_EABI__)
 659 /* Syscalls for ARM in ARM or Thumb modes :
 660  *   - registers are 32-bit
 661  *   - stack is 8-byte aligned
 662  *     ( http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html)
 663  *   - syscall number is passed in r7
 664  *   - arguments are in r0, r1, r2, r3, r4, r5
 665  *   - the system call is performed by calling svc #0
 666  *   - syscall return comes in r0.
 667  *   - only lr is clobbered.
 668  *   - the arguments are cast to long and assigned into the target registers
 669  *     which are then simply passed as registers to the asm code, so that we
 670  *     don't have to experience issues with register constraints.
 671  *   - the syscall number is always specified last in order to allow to force
 672  *     some registers before (gcc refuses a %-register at the last position).
 673  *
 674  * Also, ARM supports the old_select syscall if newselect is not available
 675  */
 676 #define __ARCH_WANT_SYS_OLD_SELECT
 677 
 678 #define my_syscall0(num)                                                      \
 679 ({                                                                            \
 680         register long _num asm("r7") = (num);                                 \
 681         register long _arg1 asm("r0");                                        \
 682                                                                               \
 683         asm volatile (                                                        \
 684                 "svc #0\n"                                                    \
 685                 : "=r"(_arg1)                                                 \
 686                 : "r"(_num)                                                   \
 687                 : "memory", "cc", "lr"                                        \
 688         );                                                                    \
 689         _arg1;                                                                \
 690 })
 691 
 692 #define my_syscall1(num, arg1)                                                \
 693 ({                                                                            \
 694         register long _num asm("r7") = (num);                                 \
 695         register long _arg1 asm("r0") = (long)(arg1);                         \
 696                                                                               \
 697         asm volatile (                                                        \
 698                 "svc #0\n"                                                    \
 699                 : "=r"(_arg1)                                                 \
 700                 : "r"(_arg1),                                                 \
 701                   "r"(_num)                                                   \
 702                 : "memory", "cc", "lr"                                        \
 703         );                                                                    \
 704         _arg1;                                                                \
 705 })
 706 
 707 #define my_syscall2(num, arg1, arg2)                                          \
 708 ({                                                                            \
 709         register long _num asm("r7") = (num);                                 \
 710         register long _arg1 asm("r0") = (long)(arg1);                         \
 711         register long _arg2 asm("r1") = (long)(arg2);                         \
 712                                                                               \
 713         asm volatile (                                                        \
 714                 "svc #0\n"                                                    \
 715                 : "=r"(_arg1)                                                 \
 716                 : "r"(_arg1), "r"(_arg2),                                     \
 717                   "r"(_num)                                                   \
 718                 : "memory", "cc", "lr"                                        \
 719         );                                                                    \
 720         _arg1;                                                                \
 721 })
 722 
 723 #define my_syscall3(num, arg1, arg2, arg3)                                    \
 724 ({                                                                            \
 725         register long _num asm("r7") = (num);                                 \
 726         register long _arg1 asm("r0") = (long)(arg1);                         \
 727         register long _arg2 asm("r1") = (long)(arg2);                         \
 728         register long _arg3 asm("r2") = (long)(arg3);                         \
 729                                                                               \
 730         asm volatile (                                                        \
 731                 "svc #0\n"                                                    \
 732                 : "=r"(_arg1)                                                 \
 733                 : "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
 734                   "r"(_num)                                                   \
 735                 : "memory", "cc", "lr"                                        \
 736         );                                                                    \
 737         _arg1;                                                                \
 738 })
 739 
 740 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
 741 ({                                                                            \
 742         register long _num asm("r7") = (num);                                 \
 743         register long _arg1 asm("r0") = (long)(arg1);                         \
 744         register long _arg2 asm("r1") = (long)(arg2);                         \
 745         register long _arg3 asm("r2") = (long)(arg3);                         \
 746         register long _arg4 asm("r3") = (long)(arg4);                         \
 747                                                                               \
 748         asm volatile (                                                        \
 749                 "svc #0\n"                                                    \
 750                 : "=r"(_arg1)                                                 \
 751                 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
 752                   "r"(_num)                                                   \
 753                 : "memory", "cc", "lr"                                        \
 754         );                                                                    \
 755         _arg1;                                                                \
 756 })
 757 
 758 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
 759 ({                                                                            \
 760         register long _num asm("r7") = (num);                                 \
 761         register long _arg1 asm("r0") = (long)(arg1);                         \
 762         register long _arg2 asm("r1") = (long)(arg2);                         \
 763         register long _arg3 asm("r2") = (long)(arg3);                         \
 764         register long _arg4 asm("r3") = (long)(arg4);                         \
 765         register long _arg5 asm("r4") = (long)(arg5);                         \
 766                                                                               \
 767         asm volatile (                                                        \
 768                 "svc #0\n"                                                    \
 769                 : "=r" (_arg1)                                                \
 770                 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
 771                   "r"(_num)                                                   \
 772                 : "memory", "cc", "lr"                                        \
 773         );                                                                    \
 774         _arg1;                                                                \
 775 })
 776 
 777 /* startup code */
 778 asm(".section .text\n"
 779     ".global _start\n"
 780     "_start:\n"
 781 #if defined(__THUMBEB__) || defined(__THUMBEL__)
 782     /* We enter here in 32-bit mode but if some previous functions were in
 783      * 16-bit mode, the assembler cannot know, so we need to tell it we're in
 784      * 32-bit now, then switch to 16-bit (is there a better way to do it than
 785      * adding 1 by hand ?) and tell the asm we're now in 16-bit mode so that
 786      * it generates correct instructions. Note that we do not support thumb1.
 787      */
 788     ".code 32\n"
 789     "add     r0, pc, #1\n"
 790     "bx      r0\n"
 791     ".code 16\n"
 792 #endif
 793     "pop {%r0}\n"                 // argc was in the stack
 794     "mov %r1, %sp\n"              // argv = sp
 795     "add %r2, %r1, %r0, lsl #2\n" // envp = argv + 4*argc ...
 796     "add %r2, %r2, $4\n"          //        ... + 4
 797     "and %r3, %r1, $-8\n"         // AAPCS : sp must be 8-byte aligned in the
 798     "mov %sp, %r3\n"              //         callee, an bl doesn't push (lr=pc)
 799     "bl main\n"                   // main() returns the status code, we'll exit with it.
 800     "and %r0, %r0, $0xff\n"       // limit exit code to 8 bits
 801     "movs r7, $1\n"               // NR_exit == 1
 802     "svc $0x00\n"
 803     "");
 804 
 805 /* fcntl / open */
 806 #define O_RDONLY            0
 807 #define O_WRONLY            1
 808 #define O_RDWR              2
 809 #define O_CREAT          0x40
 810 #define O_EXCL           0x80
 811 #define O_NOCTTY        0x100
 812 #define O_TRUNC         0x200
 813 #define O_APPEND        0x400
 814 #define O_NONBLOCK      0x800
 815 #define O_DIRECTORY    0x4000
 816 
 817 /* The struct returned by the stat() syscall, 32-bit only, the syscall returns
 818  * exactly 56 bytes (stops before the unused array). In big endian, the format
 819  * differs as devices are returned as short only.
 820  */
 821 struct sys_stat_struct {
 822 #if defined(__ARMEB__)
 823         unsigned short st_dev;
 824         unsigned short __pad1;
 825 #else
 826         unsigned long  st_dev;
 827 #endif
 828         unsigned long  st_ino;
 829         unsigned short st_mode;
 830         unsigned short st_nlink;
 831         unsigned short st_uid;
 832         unsigned short st_gid;
 833 #if defined(__ARMEB__)
 834         unsigned short st_rdev;
 835         unsigned short __pad2;
 836 #else
 837         unsigned long  st_rdev;
 838 #endif
 839         unsigned long  st_size;
 840         unsigned long  st_blksize;
 841         unsigned long  st_blocks;
 842         unsigned long  st_atime;
 843         unsigned long  st_atime_nsec;
 844         unsigned long  st_mtime;
 845         unsigned long  st_mtime_nsec;
 846         unsigned long  st_ctime;
 847         unsigned long  st_ctime_nsec;
 848         unsigned long  __unused[2];
 849 };
 850 
 851 #elif defined(__aarch64__)
 852 /* Syscalls for AARCH64 :
 853  *   - registers are 64-bit
 854  *   - stack is 16-byte aligned
 855  *   - syscall number is passed in x8
 856  *   - arguments are in x0, x1, x2, x3, x4, x5
 857  *   - the system call is performed by calling svc 0
 858  *   - syscall return comes in x0.
 859  *   - the arguments are cast to long and assigned into the target registers
 860  *     which are then simply passed as registers to the asm code, so that we
 861  *     don't have to experience issues with register constraints.
 862  *
 863  * On aarch64, select() is not implemented so we have to use pselect6().
 864  */
 865 #define __ARCH_WANT_SYS_PSELECT6
 866 
 867 #define my_syscall0(num)                                                      \
 868 ({                                                                            \
 869         register long _num  asm("x8") = (num);                                \
 870         register long _arg1 asm("x0");                                        \
 871                                                                               \
 872         asm volatile (                                                        \
 873                 "svc #0\n"                                                    \
 874                 : "=r"(_arg1)                                                 \
 875                 : "r"(_num)                                                   \
 876                 : "memory", "cc"                                              \
 877         );                                                                    \
 878         _arg1;                                                                \
 879 })
 880 
 881 #define my_syscall1(num, arg1)                                                \
 882 ({                                                                            \
 883         register long _num  asm("x8") = (num);                                \
 884         register long _arg1 asm("x0") = (long)(arg1);                         \
 885                                                                               \
 886         asm volatile (                                                        \
 887                 "svc #0\n"                                                    \
 888                 : "=r"(_arg1)                                                 \
 889                 : "r"(_arg1),                                                 \
 890                   "r"(_num)                                                   \
 891                 : "memory", "cc"                                              \
 892         );                                                                    \
 893         _arg1;                                                                \
 894 })
 895 
 896 #define my_syscall2(num, arg1, arg2)                                          \
 897 ({                                                                            \
 898         register long _num  asm("x8") = (num);                                \
 899         register long _arg1 asm("x0") = (long)(arg1);                         \
 900         register long _arg2 asm("x1") = (long)(arg2);                         \
 901                                                                               \
 902         asm volatile (                                                        \
 903                 "svc #0\n"                                                    \
 904                 : "=r"(_arg1)                                                 \
 905                 : "r"(_arg1), "r"(_arg2),                                     \
 906                   "r"(_num)                                                   \
 907                 : "memory", "cc"                                              \
 908         );                                                                    \
 909         _arg1;                                                                \
 910 })
 911 
 912 #define my_syscall3(num, arg1, arg2, arg3)                                    \
 913 ({                                                                            \
 914         register long _num  asm("x8") = (num);                                \
 915         register long _arg1 asm("x0") = (long)(arg1);                         \
 916         register long _arg2 asm("x1") = (long)(arg2);                         \
 917         register long _arg3 asm("x2") = (long)(arg3);                         \
 918                                                                               \
 919         asm volatile (                                                        \
 920                 "svc #0\n"                                                    \
 921                 : "=r"(_arg1)                                                 \
 922                 : "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
 923                   "r"(_num)                                                   \
 924                 : "memory", "cc"                                              \
 925         );                                                                    \
 926         _arg1;                                                                \
 927 })
 928 
 929 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
 930 ({                                                                            \
 931         register long _num  asm("x8") = (num);                                \
 932         register long _arg1 asm("x0") = (long)(arg1);                         \
 933         register long _arg2 asm("x1") = (long)(arg2);                         \
 934         register long _arg3 asm("x2") = (long)(arg3);                         \
 935         register long _arg4 asm("x3") = (long)(arg4);                         \
 936                                                                               \
 937         asm volatile (                                                        \
 938                 "svc #0\n"                                                    \
 939                 : "=r"(_arg1)                                                 \
 940                 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
 941                   "r"(_num)                                                   \
 942                 : "memory", "cc"                                              \
 943         );                                                                    \
 944         _arg1;                                                                \
 945 })
 946 
 947 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
 948 ({                                                                            \
 949         register long _num  asm("x8") = (num);                                \
 950         register long _arg1 asm("x0") = (long)(arg1);                         \
 951         register long _arg2 asm("x1") = (long)(arg2);                         \
 952         register long _arg3 asm("x2") = (long)(arg3);                         \
 953         register long _arg4 asm("x3") = (long)(arg4);                         \
 954         register long _arg5 asm("x4") = (long)(arg5);                         \
 955                                                                               \
 956         asm volatile (                                                        \
 957                 "svc #0\n"                                                    \
 958                 : "=r" (_arg1)                                                \
 959                 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
 960                   "r"(_num)                                                   \
 961                 : "memory", "cc"                                              \
 962         );                                                                    \
 963         _arg1;                                                                \
 964 })
 965 
 966 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
 967 ({                                                                            \
 968         register long _num  asm("x8") = (num);                                \
 969         register long _arg1 asm("x0") = (long)(arg1);                         \
 970         register long _arg2 asm("x1") = (long)(arg2);                         \
 971         register long _arg3 asm("x2") = (long)(arg3);                         \
 972         register long _arg4 asm("x3") = (long)(arg4);                         \
 973         register long _arg5 asm("x4") = (long)(arg5);                         \
 974         register long _arg6 asm("x5") = (long)(arg6);                         \
 975                                                                               \
 976         asm volatile (                                                        \
 977                 "svc #0\n"                                                    \
 978                 : "=r" (_arg1)                                                \
 979                 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
 980                   "r"(_arg6), "r"(_num)                                       \
 981                 : "memory", "cc"                                              \
 982         );                                                                    \
 983         _arg1;                                                                \
 984 })
 985 
 986 /* startup code */
 987 asm(".section .text\n"
 988     ".global _start\n"
 989     "_start:\n"
 990     "ldr x0, [sp]\n"              // argc (x0) was in the stack
 991     "add x1, sp, 8\n"             // argv (x1) = sp
 992     "lsl x2, x0, 3\n"             // envp (x2) = 8*argc ...
 993     "add x2, x2, 8\n"             //           + 8 (skip null)
 994     "add x2, x2, x1\n"            //           + argv
 995     "and sp, x1, -16\n"           // sp must be 16-byte aligned in the callee
 996     "bl main\n"                   // main() returns the status code, we'll exit with it.
 997     "and x0, x0, 0xff\n"          // limit exit code to 8 bits
 998     "mov x8, 93\n"                // NR_exit == 93
 999     "svc #0\n"
1000     "");
1001 
1002 /* fcntl / open */
1003 #define O_RDONLY            0
1004 #define O_WRONLY            1
1005 #define O_RDWR              2
1006 #define O_CREAT          0x40
1007 #define O_EXCL           0x80
1008 #define O_NOCTTY        0x100
1009 #define O_TRUNC         0x200
1010 #define O_APPEND        0x400
1011 #define O_NONBLOCK      0x800
1012 #define O_DIRECTORY    0x4000
1013 
1014 /* The struct returned by the newfstatat() syscall. Differs slightly from the
1015  * x86_64's stat one by field ordering, so be careful.
1016  */
1017 struct sys_stat_struct {
1018         unsigned long   st_dev;
1019         unsigned long   st_ino;
1020         unsigned int    st_mode;
1021         unsigned int    st_nlink;
1022         unsigned int    st_uid;
1023         unsigned int    st_gid;
1024 
1025         unsigned long   st_rdev;
1026         unsigned long   __pad1;
1027         long            st_size;
1028         int             st_blksize;
1029         int             __pad2;
1030 
1031         long            st_blocks;
1032         long            st_atime;
1033         unsigned long   st_atime_nsec;
1034         long            st_mtime;
1035 
1036         unsigned long   st_mtime_nsec;
1037         long            st_ctime;
1038         unsigned long   st_ctime_nsec;
1039         unsigned int    __unused[2];
1040 };
1041 
1042 #elif defined(__mips__) && defined(_ABIO32)
1043 /* Syscalls for MIPS ABI O32 :
1044  *   - WARNING! there's always a delayed slot!
1045  *   - WARNING again, the syntax is different, registers take a '$' and numbers
1046  *     do not.
1047  *   - registers are 32-bit
1048  *   - stack is 8-byte aligned
1049  *   - syscall number is passed in v0 (starts at 0xfa0).
1050  *   - arguments are in a0, a1, a2, a3, then the stack. The caller needs to
1051  *     leave some room in the stack for the callee to save a0..a3 if needed.
1052  *   - Many registers are clobbered, in fact only a0..a2 and s0..s8 are
1053  *     preserved. See: https://www.linux-mips.org/wiki/Syscall as well as
1054  *     scall32-o32.S in the kernel sources.
1055  *   - the system call is performed by calling "syscall"
1056  *   - syscall return comes in v0, and register a3 needs to be checked to know
1057  *     if an error occured, in which case errno is in v0.
1058  *   - the arguments are cast to long and assigned into the target registers
1059  *     which are then simply passed as registers to the asm code, so that we
1060  *     don't have to experience issues with register constraints.
1061  */
1062 
1063 #define my_syscall0(num)                                                      \
1064 ({                                                                            \
1065         register long _num asm("v0") = (num);                                 \
1066         register long _arg4 asm("a3");                                        \
1067                                                                               \
1068         asm volatile (                                                        \
1069                 "addiu $sp, $sp, -32\n"                                       \
1070                 "syscall\n"                                                   \
1071                 "addiu $sp, $sp, 32\n"                                        \
1072                 : "=r"(_num), "=r"(_arg4)                                     \
1073                 : "r"(_num)                                                   \
1074                 : "memory", "cc", "at", "v1", "hi", "lo",                     \
1075                   "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
1076         );                                                                    \
1077         _arg4 ? -_num : _num;                                                 \
1078 })
1079 
1080 #define my_syscall1(num, arg1)                                                \
1081 ({                                                                            \
1082         register long _num asm("v0") = (num);                                 \
1083         register long _arg1 asm("a0") = (long)(arg1);                         \
1084         register long _arg4 asm("a3");                                        \
1085                                                                               \
1086         asm volatile (                                                        \
1087                 "addiu $sp, $sp, -32\n"                                       \
1088                 "syscall\n"                                                   \
1089                 "addiu $sp, $sp, 32\n"                                        \
1090                 : "=r"(_num), "=r"(_arg4)                                     \
1091                 : "0"(_num),                                                  \
1092                   "r"(_arg1)                                                  \
1093                 : "memory", "cc", "at", "v1", "hi", "lo",                     \
1094                   "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
1095         );                                                                    \
1096         _arg4 ? -_num : _num;                                                 \
1097 })
1098 
1099 #define my_syscall2(num, arg1, arg2)                                          \
1100 ({                                                                            \
1101         register long _num asm("v0") = (num);                                 \
1102         register long _arg1 asm("a0") = (long)(arg1);                         \
1103         register long _arg2 asm("a1") = (long)(arg2);                         \
1104         register long _arg4 asm("a3");                                        \
1105                                                                               \
1106         asm volatile (                                                        \
1107                 "addiu $sp, $sp, -32\n"                                       \
1108                 "syscall\n"                                                   \
1109                 "addiu $sp, $sp, 32\n"                                        \
1110                 : "=r"(_num), "=r"(_arg4)                                     \
1111                 : "0"(_num),                                                  \
1112                   "r"(_arg1), "r"(_arg2)                                      \
1113                 : "memory", "cc", "at", "v1", "hi", "lo",                     \
1114                   "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
1115         );                                                                    \
1116         _arg4 ? -_num : _num;                                                 \
1117 })
1118 
1119 #define my_syscall3(num, arg1, arg2, arg3)                                    \
1120 ({                                                                            \
1121         register long _num asm("v0")  = (num);                                \
1122         register long _arg1 asm("a0") = (long)(arg1);                         \
1123         register long _arg2 asm("a1") = (long)(arg2);                         \
1124         register long _arg3 asm("a2") = (long)(arg3);                         \
1125         register long _arg4 asm("a3");                                        \
1126                                                                               \
1127         asm volatile (                                                        \
1128                 "addiu $sp, $sp, -32\n"                                       \
1129                 "syscall\n"                                                   \
1130                 "addiu $sp, $sp, 32\n"                                        \
1131                 : "=r"(_num), "=r"(_arg4)                                     \
1132                 : "0"(_num),                                                  \
1133                   "r"(_arg1), "r"(_arg2), "r"(_arg3)                          \
1134                 : "memory", "cc", "at", "v1", "hi", "lo",                     \
1135                   "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
1136         );                                                                    \
1137         _arg4 ? -_num : _num;                                                 \
1138 })
1139 
1140 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
1141 ({                                                                            \
1142         register long _num asm("v0") = (num);                                 \
1143         register long _arg1 asm("a0") = (long)(arg1);                         \
1144         register long _arg2 asm("a1") = (long)(arg2);                         \
1145         register long _arg3 asm("a2") = (long)(arg3);                         \
1146         register long _arg4 asm("a3") = (long)(arg4);                         \
1147                                                                               \
1148         asm volatile (                                                        \
1149                 "addiu $sp, $sp, -32\n"                                       \
1150                 "syscall\n"                                                   \
1151                 "addiu $sp, $sp, 32\n"                                        \
1152                 : "=r" (_num), "=r"(_arg4)                                    \
1153                 : "0"(_num),                                                  \
1154                   "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4)              \
1155                 : "memory", "cc", "at", "v1", "hi", "lo",                     \
1156                   "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
1157         );                                                                    \
1158         _arg4 ? -_num : _num;                                                 \
1159 })
1160 
1161 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
1162 ({                                                                            \
1163         register long _num asm("v0") = (num);                                 \
1164         register long _arg1 asm("a0") = (long)(arg1);                         \
1165         register long _arg2 asm("a1") = (long)(arg2);                         \
1166         register long _arg3 asm("a2") = (long)(arg3);                         \
1167         register long _arg4 asm("a3") = (long)(arg4);                         \
1168         register long _arg5 = (long)(arg5);                                   \
1169                                                                               \
1170         asm volatile (                                                        \
1171                 "addiu $sp, $sp, -32\n"                                       \
1172                 "sw %7, 16($sp)\n"                                            \
1173                 "syscall\n  "                                                 \
1174                 "addiu $sp, $sp, 32\n"                                        \
1175                 : "=r" (_num), "=r"(_arg4)                                    \
1176                 : "0"(_num),                                                  \
1177                   "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5)  \
1178                 : "memory", "cc", "at", "v1", "hi", "lo",                     \
1179                   "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
1180         );                                                                    \
1181         _arg4 ? -_num : _num;                                                 \
1182 })
1183 
1184 /* startup code, note that it's called __start on MIPS */
1185 asm(".section .text\n"
1186     ".set nomips16\n"
1187     ".global __start\n"
1188     ".set    noreorder\n"
1189     ".option pic0\n"
1190     ".ent __start\n"
1191     "__start:\n"
1192     "lw $a0,($sp)\n"              // argc was in the stack
1193     "addiu  $a1, $sp, 4\n"        // argv = sp + 4
1194     "sll $a2, $a0, 2\n"           // a2 = argc * 4
1195     "add   $a2, $a2, $a1\n"       // envp = argv + 4*argc ...
1196     "addiu $a2, $a2, 4\n"         //        ... + 4
1197     "li $t0, -8\n"
1198     "and $sp, $sp, $t0\n"         // sp must be 8-byte aligned
1199     "addiu $sp,$sp,-16\n"         // the callee expects to save a0..a3 there!
1200     "jal main\n"                  // main() returns the status code, we'll exit with it.
1201     "nop\n"                       // delayed slot
1202     "and $a0, $v0, 0xff\n"        // limit exit code to 8 bits
1203     "li $v0, 4001\n"              // NR_exit == 4001
1204     "syscall\n"
1205     ".end __start\n"
1206     "");
1207 
1208 /* fcntl / open */
1209 #define O_RDONLY            0
1210 #define O_WRONLY            1
1211 #define O_RDWR              2
1212 #define O_APPEND       0x0008
1213 #define O_NONBLOCK     0x0080
1214 #define O_CREAT        0x0100
1215 #define O_TRUNC        0x0200
1216 #define O_EXCL         0x0400
1217 #define O_NOCTTY       0x0800
1218 #define O_DIRECTORY   0x10000
1219 
1220 /* The struct returned by the stat() syscall. 88 bytes are returned by the
1221  * syscall.
1222  */
1223 struct sys_stat_struct {
1224         unsigned int  st_dev;
1225         long          st_pad1[3];
1226         unsigned long st_ino;
1227         unsigned int  st_mode;
1228         unsigned int  st_nlink;
1229         unsigned int  st_uid;
1230         unsigned int  st_gid;
1231         unsigned int  st_rdev;
1232         long          st_pad2[2];
1233         long          st_size;
1234         long          st_pad3;
1235         long          st_atime;
1236         long          st_atime_nsec;
1237         long          st_mtime;
1238         long          st_mtime_nsec;
1239         long          st_ctime;
1240         long          st_ctime_nsec;
1241         long          st_blksize;
1242         long          st_blocks;
1243         long          st_pad4[14];
1244 };
1245 
1246 #elif defined(__riscv)
1247 
1248 #if   __riscv_xlen == 64
1249 #define PTRLOG "3"
1250 #define SZREG  "8"
1251 #elif __riscv_xlen == 32
1252 #define PTRLOG "2"
1253 #define SZREG  "4"
1254 #endif
1255 
1256 /* Syscalls for RISCV :
1257  *   - stack is 16-byte aligned
1258  *   - syscall number is passed in a7
1259  *   - arguments are in a0, a1, a2, a3, a4, a5
1260  *   - the system call is performed by calling ecall
1261  *   - syscall return comes in a0
1262  *   - the arguments are cast to long and assigned into the target
1263  *     registers which are then simply passed as registers to the asm code,
1264  *     so that we don't have to experience issues with register constraints.
1265  */
1266 
1267 #define my_syscall0(num)                                                      \
1268 ({                                                                            \
1269         register long _num  asm("a7") = (num);                                \
1270         register long _arg1 asm("a0");                                        \
1271                                                                               \
1272         asm volatile (                                                        \
1273                 "ecall\n\t"                                                   \
1274                 : "=r"(_arg1)                                                 \
1275                 : "r"(_num)                                                   \
1276                 : "memory", "cc"                                              \
1277         );                                                                    \
1278         _arg1;                                                                \
1279 })
1280 
1281 #define my_syscall1(num, arg1)                                                \
1282 ({                                                                            \
1283         register long _num  asm("a7") = (num);                                \
1284         register long _arg1 asm("a0") = (long)(arg1);                         \
1285                                                                               \
1286         asm volatile (                                                        \
1287                 "ecall\n"                                                     \
1288                 : "+r"(_arg1)                                                 \
1289                 : "r"(_num)                                                   \
1290                 : "memory", "cc"                                              \
1291         );                                                                    \
1292         _arg1;                                                                \
1293 })
1294 
1295 #define my_syscall2(num, arg1, arg2)                                          \
1296 ({                                                                            \
1297         register long _num  asm("a7") = (num);                                \
1298         register long _arg1 asm("a0") = (long)(arg1);                         \
1299         register long _arg2 asm("a1") = (long)(arg2);                         \
1300                                                                               \
1301         asm volatile (                                                        \
1302                 "ecall\n"                                                     \
1303                 : "+r"(_arg1)                                                 \
1304                 : "r"(_arg2),                                                 \
1305                   "r"(_num)                                                   \
1306                 : "memory", "cc"                                              \
1307         );                                                                    \
1308         _arg1;                                                                \
1309 })
1310 
1311 #define my_syscall3(num, arg1, arg2, arg3)                                    \
1312 ({                                                                            \
1313         register long _num  asm("a7") = (num);                                \
1314         register long _arg1 asm("a0") = (long)(arg1);                         \
1315         register long _arg2 asm("a1") = (long)(arg2);                         \
1316         register long _arg3 asm("a2") = (long)(arg3);                         \
1317                                                                               \
1318         asm volatile (                                                        \
1319                 "ecall\n\t"                                                   \
1320                 : "+r"(_arg1)                                                 \
1321                 : "r"(_arg2), "r"(_arg3),                                     \
1322                   "r"(_num)                                                   \
1323                 : "memory", "cc"                                              \
1324         );                                                                    \
1325         _arg1;                                                                \
1326 })
1327 
1328 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
1329 ({                                                                            \
1330         register long _num  asm("a7") = (num);                                \
1331         register long _arg1 asm("a0") = (long)(arg1);                         \
1332         register long _arg2 asm("a1") = (long)(arg2);                         \
1333         register long _arg3 asm("a2") = (long)(arg3);                         \
1334         register long _arg4 asm("a3") = (long)(arg4);                         \
1335                                                                               \
1336         asm volatile (                                                        \
1337                 "ecall\n"                                                     \
1338                 : "+r"(_arg1)                                                 \
1339                 : "r"(_arg2), "r"(_arg3), "r"(_arg4),                         \
1340                   "r"(_num)                                                   \
1341                 : "memory", "cc"                                              \
1342         );                                                                    \
1343         _arg1;                                                                \
1344 })
1345 
1346 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
1347 ({                                                                            \
1348         register long _num  asm("a7") = (num);                                \
1349         register long _arg1 asm("a0") = (long)(arg1);                         \
1350         register long _arg2 asm("a1") = (long)(arg2);                         \
1351         register long _arg3 asm("a2") = (long)(arg3);                         \
1352         register long _arg4 asm("a3") = (long)(arg4);                         \
1353         register long _arg5 asm("a4") = (long)(arg5);                         \
1354                                                                               \
1355         asm volatile (                                                        \
1356                 "ecall\n"                                                     \
1357                 : "+r"(_arg1)                                                 \
1358                 : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5),             \
1359                   "r"(_num)                                                   \
1360                 : "memory", "cc"                                              \
1361         );                                                                    \
1362         _arg1;                                                                \
1363 })
1364 
1365 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
1366 ({                                                                            \
1367         register long _num  asm("a7") = (num);                                \
1368         register long _arg1 asm("a0") = (long)(arg1);                         \
1369         register long _arg2 asm("a1") = (long)(arg2);                         \
1370         register long _arg3 asm("a2") = (long)(arg3);                         \
1371         register long _arg4 asm("a3") = (long)(arg4);                         \
1372         register long _arg5 asm("a4") = (long)(arg5);                         \
1373         register long _arg6 asm("a5") = (long)(arg6);                         \
1374                                                                               \
1375         asm volatile (                                                        \
1376                 "ecall\n"                                                     \
1377                 : "+r"(_arg1)                                                 \
1378                 : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
1379                   "r"(_num)                                                   \
1380                 : "memory", "cc"                                              \
1381         );                                                                    \
1382         _arg1;                                                                \
1383 })
1384 
1385 /* startup code */
1386 asm(".section .text\n"
1387     ".global _start\n"
1388     "_start:\n"
1389     ".option push\n"
1390     ".option norelax\n"
1391     "lla   gp, __global_pointer$\n"
1392     ".option pop\n"
1393     "ld    a0, 0(sp)\n"          // argc (a0) was in the stack
1394     "add   a1, sp, "SZREG"\n"    // argv (a1) = sp
1395     "slli  a2, a0, "PTRLOG"\n"   // envp (a2) = SZREG*argc ...
1396     "add   a2, a2, "SZREG"\n"    //             + SZREG (skip null)
1397     "add   a2,a2,a1\n"           //             + argv
1398     "andi  sp,a1,-16\n"          // sp must be 16-byte aligned
1399     "call  main\n"               // main() returns the status code, we'll exit with it.
1400     "andi  a0, a0, 0xff\n"       // limit exit code to 8 bits
1401     "li a7, 93\n"                // NR_exit == 93
1402     "ecall\n"
1403     "");
1404 
1405 /* fcntl / open */
1406 #define O_RDONLY            0
1407 #define O_WRONLY            1
1408 #define O_RDWR              2
1409 #define O_CREAT         0x100
1410 #define O_EXCL          0x200
1411 #define O_NOCTTY        0x400
1412 #define O_TRUNC        0x1000
1413 #define O_APPEND       0x2000
1414 #define O_NONBLOCK     0x4000
1415 #define O_DIRECTORY  0x200000
1416 
1417 struct sys_stat_struct {
1418         unsigned long   st_dev;         /* Device.  */
1419         unsigned long   st_ino;         /* File serial number.  */
1420         unsigned int    st_mode;        /* File mode.  */
1421         unsigned int    st_nlink;       /* Link count.  */
1422         unsigned int    st_uid;         /* User ID of the file's owner.  */
1423         unsigned int    st_gid;         /* Group ID of the file's group. */
1424         unsigned long   st_rdev;        /* Device number, if device.  */
1425         unsigned long   __pad1;
1426         long            st_size;        /* Size of file, in bytes.  */
1427         int             st_blksize;     /* Optimal block size for I/O.  */
1428         int             __pad2;
1429         long            st_blocks;      /* Number 512-byte blocks allocated. */
1430         long            st_atime;       /* Time of last access.  */
1431         unsigned long   st_atime_nsec;
1432         long            st_mtime;       /* Time of last modification.  */
1433         unsigned long   st_mtime_nsec;
1434         long            st_ctime;       /* Time of last status change.  */
1435         unsigned long   st_ctime_nsec;
1436         unsigned int    __unused4;
1437         unsigned int    __unused5;
1438 };
1439 
1440 #endif
1441 
1442 
1443 /* Below are the C functions used to declare the raw syscalls. They try to be
1444  * architecture-agnostic, and return either a success or -errno. Declaring them
1445  * static will lead to them being inlined in most cases, but it's still possible
1446  * to reference them by a pointer if needed.
1447  */
1448 static __attribute__((unused))
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 - '0') <= 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++) - '0';
2386                 if (d > 9)
2387                         break;
2388                 ret *= 10;
2389                 ret += d;
2390         }
2391 
2392         return neg ? -ret : ret;
2393 }
2394 
2395 static __attribute__((unused))
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-- = '0' + n % 10;
2413                 n /= 10;
2414                 if (pos < buffer)
2415                         return pos + 1;
2416         } while (n);
2417 
2418         if (neg)
2419                 *pos-- = '-';
2420         return pos + 1;
2421 }
2422 
2423 __attribute__((weak,unused))
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 }

/* [<][>][^][v][top][bottom][index][help] */