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