linux/tools/include/nolibc/nolibc.h
<<
>>
Prefs
   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 */
 101static 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 */
 121typedef unsigned char       uint8_t;
 122typedef   signed char        int8_t;
 123typedef unsigned short     uint16_t;
 124typedef   signed short      int16_t;
 125typedef unsigned int       uint32_t;
 126typedef   signed int        int32_t;
 127typedef unsigned long long uint64_t;
 128typedef   signed long long  int64_t;
 129typedef unsigned long        size_t;
 130typedef   signed long       ssize_t;
 131typedef unsigned long     uintptr_t;
 132typedef   signed long      intptr_t;
 133typedef   signed long     ptrdiff_t;
 134
 135/* for stat() */
 136typedef unsigned int          dev_t;
 137typedef unsigned long         ino_t;
 138typedef unsigned int         mode_t;
 139typedef   signed int          pid_t;
 140typedef unsigned int          uid_t;
 141typedef unsigned int          gid_t;
 142typedef unsigned long       nlink_t;
 143typedef   signed long         off_t;
 144typedef   signed long     blksize_t;
 145typedef   signed long      blkcnt_t;
 146typedef   signed long        time_t;
 147
 148/* for poll() */
 149struct pollfd {
 150        int fd;
 151        short int events;
 152        short int revents;
 153};
 154
 155/* for select() */
 156struct timeval {
 157        long    tv_sec;
 158        long    tv_usec;
 159};
 160
 161/* for pselect() */
 162struct timespec {
 163        long    tv_sec;
 164        long    tv_nsec;
 165};
 166
 167/* for gettimeofday() */
 168struct timezone {
 169        int tz_minuteswest;
 170        int tz_dsttime;
 171};
 172
 173/* for getdents64() */
 174struct 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
 184typedef struct { uint32_t fd32[FD_SETSIZE/32]; } fd_set;
 185
 186/* needed by wait4() */
 187struct 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 */
 255struct 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 */
 425asm(".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 */
 455struct 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 */
 603asm(".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 */
 635struct 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 */
 778asm(".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 */
 821struct 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 */
 987asm(".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 */
1017struct 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 */
1185asm(".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 */
1223struct 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 */
1386asm(".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
1417struct 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 */
1448static __attribute__((unused))
1449void *sys_brk(void *addr)
1450{
1451        return (void *)my_syscall1(__NR_brk, addr);
1452}
1453
1454static __attribute__((noreturn,unused))
1455void sys_exit(int status)
1456{
1457        my_syscall1(__NR_exit, status & 255);
1458        while(1); // shut the "noreturn" warnings.
1459}
1460
1461static __attribute__((unused))
1462int sys_chdir(const char *path)
1463{
1464        return my_syscall1(__NR_chdir, path);
1465}
1466
1467static __attribute__((unused))
1468int 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
1477static __attribute__((unused))
1478int 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
1487static __attribute__((unused))
1488int sys_chroot(const char *path)
1489{
1490        return my_syscall1(__NR_chroot, path);
1491}
1492
1493static __attribute__((unused))
1494int sys_close(int fd)
1495{
1496        return my_syscall1(__NR_close, fd);
1497}
1498
1499static __attribute__((unused))
1500int sys_dup(int fd)
1501{
1502        return my_syscall1(__NR_dup, fd);
1503}
1504
1505static __attribute__((unused))
1506int sys_dup2(int old, int new)
1507{
1508        return my_syscall2(__NR_dup2, old, new);
1509}
1510
1511static __attribute__((unused))
1512int sys_execve(const char *filename, char *const argv[], char *const envp[])
1513{
1514        return my_syscall3(__NR_execve, filename, argv, envp);
1515}
1516
1517static __attribute__((unused))
1518pid_t sys_fork(void)
1519{
1520        return my_syscall0(__NR_fork);
1521}
1522
1523static __attribute__((unused))
1524int sys_fsync(int fd)
1525{
1526        return my_syscall1(__NR_fsync, fd);
1527}
1528
1529static __attribute__((unused))
1530int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count)
1531{
1532        return my_syscall3(__NR_getdents64, fd, dirp, count);
1533}
1534
1535static __attribute__((unused))
1536pid_t sys_getpgrp(void)
1537{
1538        return my_syscall0(__NR_getpgrp);
1539}
1540
1541static __attribute__((unused))
1542pid_t sys_getpid(void)
1543{
1544        return my_syscall0(__NR_getpid);
1545}
1546
1547static __attribute__((unused))
1548int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
1549{
1550        return my_syscall2(__NR_gettimeofday, tv, tz);
1551}
1552
1553static __attribute__((unused))
1554int sys_ioctl(int fd, unsigned long req, void *value)
1555{
1556        return my_syscall3(__NR_ioctl, fd, req, value);
1557}
1558
1559static __attribute__((unused))
1560int sys_kill(pid_t pid, int signal)
1561{
1562        return my_syscall2(__NR_kill, pid, signal);
1563}
1564
1565static __attribute__((unused))
1566int 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
1575static __attribute__((unused))
1576off_t sys_lseek(int fd, off_t offset, int whence)
1577{
1578        return my_syscall3(__NR_lseek, fd, offset, whence);
1579}
1580
1581static __attribute__((unused))
1582int 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
1591static __attribute__((unused))
1592long 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
1601static __attribute__((unused))
1602int 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
1608static __attribute__((unused))
1609int 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
1618static __attribute__((unused))
1619int sys_pivot_root(const char *new, const char *old)
1620{
1621        return my_syscall2(__NR_pivot_root, new, old);
1622}
1623
1624static __attribute__((unused))
1625int sys_poll(struct pollfd *fds, int nfds, int timeout)
1626{
1627        return my_syscall3(__NR_poll, fds, nfds, timeout);
1628}
1629
1630static __attribute__((unused))
1631ssize_t sys_read(int fd, void *buf, size_t count)
1632{
1633        return my_syscall3(__NR_read, fd, buf, count);
1634}
1635
1636static __attribute__((unused))
1637ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg)
1638{
1639        return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg);
1640}
1641
1642static __attribute__((unused))
1643int sys_sched_yield(void)
1644{
1645        return my_syscall0(__NR_sched_yield);
1646}
1647
1648static __attribute__((unused))
1649int 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
1674static __attribute__((unused))
1675int sys_setpgid(pid_t pid, pid_t pgid)
1676{
1677        return my_syscall2(__NR_setpgid, pid, pgid);
1678}
1679
1680static __attribute__((unused))
1681pid_t sys_setsid(void)
1682{
1683        return my_syscall0(__NR_setsid);
1684}
1685
1686static __attribute__((unused))
1687int 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
1715static __attribute__((unused))
1716int 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
1725static __attribute__((unused))
1726mode_t sys_umask(mode_t mode)
1727{
1728        return my_syscall1(__NR_umask, mode);
1729}
1730
1731static __attribute__((unused))
1732int sys_umount2(const char *path, int flags)
1733{
1734        return my_syscall2(__NR_umount2, path, flags);
1735}
1736
1737static __attribute__((unused))
1738int 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
1747static __attribute__((unused))
1748pid_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
1753static __attribute__((unused))
1754pid_t sys_waitpid(pid_t pid, int *status, int options)
1755{
1756        return sys_wait4(pid, status, options, 0);
1757}
1758
1759static __attribute__((unused))
1760pid_t sys_wait(int *status)
1761{
1762        return sys_waitpid(-1, status, 0);
1763}
1764
1765static __attribute__((unused))
1766ssize_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
1777static __attribute__((unused))
1778int 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
1789static __attribute__((noreturn,unused))
1790void exit(int status)
1791{
1792        sys_exit(status);
1793}
1794
1795static __attribute__((unused))
1796int 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
1807static __attribute__((unused))
1808int 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
1819static __attribute__((unused))
1820int 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
1831static __attribute__((unused))
1832int 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
1843static __attribute__((unused))
1844int 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
1855static __attribute__((unused))
1856int 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
1867static __attribute__((unused))
1868int 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
1879static __attribute__((unused))
1880pid_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
1891static __attribute__((unused))
1892int 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
1903static __attribute__((unused))
1904int 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
1915static __attribute__((unused))
1916pid_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
1927static __attribute__((unused))
1928pid_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
1939static __attribute__((unused))
1940int 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
1951static __attribute__((unused))
1952int 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
1963static __attribute__((unused))
1964int 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
1975static __attribute__((unused))
1976int 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
1987static __attribute__((unused))
1988off_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
1999static __attribute__((unused))
2000int 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
2011static __attribute__((unused))
2012int 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
2023static __attribute__((unused))
2024int 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
2037static __attribute__((unused))
2038int 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
2049static __attribute__((unused))
2050int 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
2061static __attribute__((unused))
2062int 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
2073static __attribute__((unused))
2074ssize_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
2085static __attribute__((unused))
2086int 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
2097static __attribute__((unused))
2098void *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
2110static __attribute__((unused))
2111int 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
2122static __attribute__((unused))
2123int 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
2134static __attribute__((unused))
2135int 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
2146static __attribute__((unused))
2147pid_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
2158static __attribute__((unused))
2159unsigned 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
2169static __attribute__((unused))
2170int 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
2181static __attribute__((unused))
2182int 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
2193static __attribute__((unused))
2194int tcsetpgrp(int fd, pid_t pid)
2195{
2196        return ioctl(fd, TIOCSPGRP, &pid);
2197}
2198
2199static __attribute__((unused))
2200mode_t umask(mode_t mode)
2201{
2202        return sys_umask(mode);
2203}
2204
2205static __attribute__((unused))
2206int 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
2217static __attribute__((unused))
2218int 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
2229static __attribute__((unused))
2230pid_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
2241static __attribute__((unused))
2242pid_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
2253static __attribute__((unused))
2254pid_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
2265static __attribute__((unused))
2266ssize_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
2283static __attribute__((unused))
2284void *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
2296static __attribute__((unused))
2297void *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
2306static __attribute__((unused))
2307int 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
2318static __attribute__((unused))
2319char *strcpy(char *dst, const char *src)
2320{
2321        char *ret = dst;
2322
2323        while ((*dst++ = *src++));
2324        return ret;
2325}
2326
2327static __attribute__((unused))
2328char *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
2338static __attribute__((unused))
2339char *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
2351static __attribute__((unused))
2352size_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
2366static __attribute__((unused))
2367int isdigit(int c)
2368{
2369        return (unsigned int)(c - '0') <= 9;
2370}
2371
2372static __attribute__((unused))
2373long 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
2395static __attribute__((unused))
2396int atoi(const char *s)
2397{
2398        return atol(s);
2399}
2400
2401static __attribute__((unused))
2402const 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))
2424void *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))
2431int raise(int signal)
2432{
2433        return kill(getpid(), signal);
2434}
2435
2436/* Here come a few helper functions */
2437
2438static __attribute__((unused))
2439void FD_ZERO(fd_set *set)
2440{
2441        memset(set, 0, sizeof(*set));
2442}
2443
2444static __attribute__((unused))
2445void 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 */
2453static __attribute__((unused))
2454dev_t makedev(unsigned int major, unsigned int minor)
2455{
2456        return ((major & 0xfff) << 8) | (minor & 0xff);
2457}
2458