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