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