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