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