xref: /openbmc/linux/tools/include/nolibc/nolibc.h (revision 967cce19)
130ca2051SWilly Tarreau /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
230ca2051SWilly Tarreau /* nolibc.h
330ca2051SWilly Tarreau  * Copyright (C) 2017-2018 Willy Tarreau <w@1wt.eu>
430ca2051SWilly Tarreau  */
530ca2051SWilly Tarreau 
630ca2051SWilly Tarreau /*
730ca2051SWilly Tarreau  * This file is designed to be used as a libc alternative for minimal programs
830ca2051SWilly Tarreau  * with very limited requirements. It consists of a small number of syscall and
930ca2051SWilly Tarreau  * type definitions, and the minimal startup code needed to call main().
1030ca2051SWilly Tarreau  * All syscalls are declared as static functions so that they can be optimized
1130ca2051SWilly Tarreau  * away by the compiler when not used.
1230ca2051SWilly Tarreau  *
1330ca2051SWilly Tarreau  * Syscalls are split into 3 levels:
1430ca2051SWilly Tarreau  *   - The lower level is the arch-specific syscall() definition, consisting in
1530ca2051SWilly Tarreau  *     assembly code in compound expressions. These are called my_syscall0() to
1630ca2051SWilly Tarreau  *     my_syscall6() depending on the number of arguments. The MIPS
1730ca2051SWilly Tarreau  *     implementation is limited to 5 arguments. All input arguments are cast
1830ca2051SWilly Tarreau  *     to a long stored in a register. These expressions always return the
1930ca2051SWilly Tarreau  *     syscall's return value as a signed long value which is often either a
2030ca2051SWilly Tarreau  *     pointer or the negated errno value.
2130ca2051SWilly Tarreau  *
2230ca2051SWilly Tarreau  *   - The second level is mostly architecture-independent. It is made of
2330ca2051SWilly Tarreau  *     static functions called sys_<name>() which rely on my_syscallN()
2430ca2051SWilly Tarreau  *     depending on the syscall definition. These functions are responsible
2530ca2051SWilly Tarreau  *     for exposing the appropriate types for the syscall arguments (int,
2630ca2051SWilly Tarreau  *     pointers, etc) and for setting the appropriate return type (often int).
2730ca2051SWilly Tarreau  *     A few of them are architecture-specific because the syscalls are not all
2830ca2051SWilly Tarreau  *     mapped exactly the same among architectures. For example, some archs do
2930ca2051SWilly Tarreau  *     not implement select() and need pselect6() instead, so the sys_select()
3030ca2051SWilly Tarreau  *     function will have to abstract this.
3130ca2051SWilly Tarreau  *
3230ca2051SWilly Tarreau  *   - The third level is the libc call definition. It exposes the lower raw
3330ca2051SWilly Tarreau  *     sys_<name>() calls in a way that looks like what a libc usually does,
3430ca2051SWilly Tarreau  *     takes care of specific input values, and of setting errno upon error.
3530ca2051SWilly Tarreau  *     There can be minor variations compared to standard libc calls. For
3630ca2051SWilly Tarreau  *     example the open() call always takes 3 args here.
3730ca2051SWilly Tarreau  *
3830ca2051SWilly Tarreau  * The errno variable is declared static and unused. This way it can be
3930ca2051SWilly Tarreau  * optimized away if not used. However this means that a program made of
4030ca2051SWilly Tarreau  * multiple C files may observe different errno values (one per C file). For
4130ca2051SWilly Tarreau  * the type of programs this project targets it usually is not a problem. The
4230ca2051SWilly Tarreau  * resulting program may even be reduced by defining the NOLIBC_IGNORE_ERRNO
4330ca2051SWilly Tarreau  * macro, in which case the errno value will never be assigned.
4430ca2051SWilly Tarreau  *
4530ca2051SWilly Tarreau  * Some stdint-like integer types are defined. These are valid on all currently
4630ca2051SWilly Tarreau  * supported architectures, because signs are enforced, ints are assumed to be
4730ca2051SWilly Tarreau  * 32 bits, longs the size of a pointer and long long 64 bits. If more
4830ca2051SWilly Tarreau  * architectures have to be supported, this may need to be adapted.
4930ca2051SWilly Tarreau  *
5030ca2051SWilly Tarreau  * Some macro definitions like the O_* values passed to open(), and some
5130ca2051SWilly Tarreau  * structures like the sys_stat struct depend on the architecture.
5230ca2051SWilly Tarreau  *
5330ca2051SWilly Tarreau  * The definitions start with the architecture-specific parts, which are picked
5430ca2051SWilly Tarreau  * based on what the compiler knows about the target architecture, and are
5530ca2051SWilly Tarreau  * completed with the generic code. Since it is the compiler which sets the
5630ca2051SWilly Tarreau  * target architecture, cross-compiling normally works out of the box without
5730ca2051SWilly Tarreau  * having to specify anything.
5830ca2051SWilly Tarreau  *
5930ca2051SWilly Tarreau  * Finally some very common libc-level functions are provided. It is the case
6030ca2051SWilly Tarreau  * for a few functions usually found in string.h, ctype.h, or stdlib.h. Nothing
6130ca2051SWilly Tarreau  * is currently provided regarding stdio emulation.
6230ca2051SWilly Tarreau  *
6330ca2051SWilly Tarreau  * The macro NOLIBC is always defined, so that it is possible for a program to
6430ca2051SWilly Tarreau  * check this macro to know if it is being built against and decide to disable
6530ca2051SWilly Tarreau  * some features or simply not to include some standard libc files.
6630ca2051SWilly Tarreau  *
6730ca2051SWilly Tarreau  * Ideally this file should be split in multiple files for easier long term
6830ca2051SWilly Tarreau  * maintenance, but provided as a single file as it is now, it's quite
6930ca2051SWilly Tarreau  * convenient to use. Maybe some variations involving a set of includes at the
7030ca2051SWilly Tarreau  * top could work.
7130ca2051SWilly Tarreau  *
7230ca2051SWilly Tarreau  * A simple static executable may be built this way :
7330ca2051SWilly Tarreau  *      $ gcc -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \
743c6ce7a5SWilly Tarreau  *            -static -include nolibc.h -o hello hello.c -lgcc
7530ca2051SWilly Tarreau  *
7630ca2051SWilly Tarreau  * A very useful calling convention table may be found here :
7730ca2051SWilly Tarreau  *      http://man7.org/linux/man-pages/man2/syscall.2.html
7830ca2051SWilly Tarreau  *
7930ca2051SWilly Tarreau  * This doc is quite convenient though not necessarily up to date :
8030ca2051SWilly Tarreau  *      https://w3challs.com/syscalls/
8130ca2051SWilly Tarreau  *
8230ca2051SWilly Tarreau  */
83930c4accSWilly Tarreau #ifndef _NOLIBC_H
84930c4accSWilly Tarreau #define _NOLIBC_H
8530ca2051SWilly Tarreau 
86*967cce19SWilly Tarreau /* standard type definitions */
87*967cce19SWilly Tarreau #include "std.h"
88*967cce19SWilly Tarreau 
89*967cce19SWilly Tarreau /* system includes */
9030ca2051SWilly Tarreau #include <asm/unistd.h>
91*967cce19SWilly Tarreau #include <asm/signal.h>  // for SIGCHLD
9230ca2051SWilly Tarreau #include <asm/ioctls.h>
9330ca2051SWilly Tarreau #include <asm/errno.h>
9430ca2051SWilly Tarreau #include <linux/fs.h>
9530ca2051SWilly Tarreau #include <linux/loop.h>
9670ca7aeaSWilly Tarreau #include <linux/time.h>
9730ca2051SWilly Tarreau 
9830ca2051SWilly Tarreau #define NOLIBC
9930ca2051SWilly Tarreau 
10030ca2051SWilly Tarreau /* this way it will be removed if unused */
10130ca2051SWilly Tarreau static int errno;
10230ca2051SWilly Tarreau 
10330ca2051SWilly Tarreau #ifndef NOLIBC_IGNORE_ERRNO
10430ca2051SWilly Tarreau #define SET_ERRNO(v) do { errno = (v); } while (0)
10530ca2051SWilly Tarreau #else
10630ca2051SWilly Tarreau #define SET_ERRNO(v) do { } while (0)
10730ca2051SWilly Tarreau #endif
10830ca2051SWilly Tarreau 
10930ca2051SWilly Tarreau /* errno codes all ensure that they will not conflict with a valid pointer
11006dc8d45SBhaskar Chowdhury  * because they all correspond to the highest addressable memory page.
11130ca2051SWilly Tarreau  */
11230ca2051SWilly Tarreau #define MAX_ERRNO 4095
11330ca2051SWilly Tarreau 
11430ca2051SWilly Tarreau /* for poll() */
11530ca2051SWilly Tarreau struct pollfd {
11630ca2051SWilly Tarreau 	int fd;
11730ca2051SWilly Tarreau 	short int events;
11830ca2051SWilly Tarreau 	short int revents;
11930ca2051SWilly Tarreau };
12030ca2051SWilly Tarreau 
12130ca2051SWilly Tarreau /* for getdents64() */
12230ca2051SWilly Tarreau struct linux_dirent64 {
12330ca2051SWilly Tarreau 	uint64_t       d_ino;
12430ca2051SWilly Tarreau 	int64_t        d_off;
12530ca2051SWilly Tarreau 	unsigned short d_reclen;
12630ca2051SWilly Tarreau 	unsigned char  d_type;
12730ca2051SWilly Tarreau 	char           d_name[];
12830ca2051SWilly Tarreau };
12930ca2051SWilly Tarreau 
13030ca2051SWilly Tarreau /* commonly an fd_set represents 256 FDs */
13130ca2051SWilly Tarreau #define FD_SETSIZE 256
13230ca2051SWilly Tarreau typedef struct { uint32_t fd32[FD_SETSIZE/32]; } fd_set;
13330ca2051SWilly Tarreau 
13430ca2051SWilly Tarreau /* needed by wait4() */
13530ca2051SWilly Tarreau struct rusage {
13630ca2051SWilly Tarreau 	struct timeval ru_utime;
13730ca2051SWilly Tarreau 	struct timeval ru_stime;
13830ca2051SWilly Tarreau 	long   ru_maxrss;
13930ca2051SWilly Tarreau 	long   ru_ixrss;
14030ca2051SWilly Tarreau 	long   ru_idrss;
14130ca2051SWilly Tarreau 	long   ru_isrss;
14230ca2051SWilly Tarreau 	long   ru_minflt;
14330ca2051SWilly Tarreau 	long   ru_majflt;
14430ca2051SWilly Tarreau 	long   ru_nswap;
14530ca2051SWilly Tarreau 	long   ru_inblock;
14630ca2051SWilly Tarreau 	long   ru_oublock;
14730ca2051SWilly Tarreau 	long   ru_msgsnd;
14830ca2051SWilly Tarreau 	long   ru_msgrcv;
14930ca2051SWilly Tarreau 	long   ru_nsignals;
15030ca2051SWilly Tarreau 	long   ru_nvcsw;
15130ca2051SWilly Tarreau 	long   ru_nivcsw;
15230ca2051SWilly Tarreau };
15330ca2051SWilly Tarreau 
15430ca2051SWilly Tarreau /* stat flags (WARNING, octal here) */
15530ca2051SWilly Tarreau #define S_IFDIR       0040000
15630ca2051SWilly Tarreau #define S_IFCHR       0020000
15730ca2051SWilly Tarreau #define S_IFBLK       0060000
15830ca2051SWilly Tarreau #define S_IFREG       0100000
15930ca2051SWilly Tarreau #define S_IFIFO       0010000
16030ca2051SWilly Tarreau #define S_IFLNK       0120000
16130ca2051SWilly Tarreau #define S_IFSOCK      0140000
16230ca2051SWilly Tarreau #define S_IFMT        0170000
16330ca2051SWilly Tarreau 
16430ca2051SWilly Tarreau #define S_ISDIR(mode)  (((mode) & S_IFDIR) == S_IFDIR)
16530ca2051SWilly Tarreau #define S_ISCHR(mode)  (((mode) & S_IFCHR) == S_IFCHR)
16630ca2051SWilly Tarreau #define S_ISBLK(mode)  (((mode) & S_IFBLK) == S_IFBLK)
16730ca2051SWilly Tarreau #define S_ISREG(mode)  (((mode) & S_IFREG) == S_IFREG)
16830ca2051SWilly Tarreau #define S_ISFIFO(mode) (((mode) & S_IFIFO) == S_IFIFO)
16930ca2051SWilly Tarreau #define S_ISLNK(mode)  (((mode) & S_IFLNK) == S_IFLNK)
17030ca2051SWilly Tarreau #define S_ISSOCK(mode) (((mode) & S_IFSOCK) == S_IFSOCK)
17130ca2051SWilly Tarreau 
17230ca2051SWilly Tarreau #define DT_UNKNOWN 0
17330ca2051SWilly Tarreau #define DT_FIFO    1
17430ca2051SWilly Tarreau #define DT_CHR     2
17530ca2051SWilly Tarreau #define DT_DIR     4
17630ca2051SWilly Tarreau #define DT_BLK     6
17730ca2051SWilly Tarreau #define DT_REG     8
17830ca2051SWilly Tarreau #define DT_LNK    10
17930ca2051SWilly Tarreau #define DT_SOCK   12
18030ca2051SWilly Tarreau 
18130ca2051SWilly Tarreau /* all the *at functions */
1826c5b9de2SSamuel Hernandez #ifndef AT_FDCWD
18330ca2051SWilly Tarreau #define AT_FDCWD             -100
18430ca2051SWilly Tarreau #endif
18530ca2051SWilly Tarreau 
18630ca2051SWilly Tarreau /* lseek */
18730ca2051SWilly Tarreau #define SEEK_SET        0
18830ca2051SWilly Tarreau #define SEEK_CUR        1
18930ca2051SWilly Tarreau #define SEEK_END        2
19030ca2051SWilly Tarreau 
19130ca2051SWilly Tarreau /* reboot */
19230ca2051SWilly Tarreau #define LINUX_REBOOT_MAGIC1         0xfee1dead
19330ca2051SWilly Tarreau #define LINUX_REBOOT_MAGIC2         0x28121969
19430ca2051SWilly Tarreau #define LINUX_REBOOT_CMD_HALT       0xcdef0123
19530ca2051SWilly Tarreau #define LINUX_REBOOT_CMD_POWER_OFF  0x4321fedc
19630ca2051SWilly Tarreau #define LINUX_REBOOT_CMD_RESTART    0x01234567
19730ca2051SWilly Tarreau #define LINUX_REBOOT_CMD_SW_SUSPEND 0xd000fce2
19830ca2051SWilly Tarreau 
19930ca2051SWilly Tarreau 
20030ca2051SWilly Tarreau /* The format of the struct as returned by the libc to the application, which
20130ca2051SWilly Tarreau  * significantly differs from the format returned by the stat() syscall flavours.
20230ca2051SWilly Tarreau  */
20330ca2051SWilly Tarreau struct stat {
20430ca2051SWilly Tarreau 	dev_t     st_dev;     /* ID of device containing file */
20530ca2051SWilly Tarreau 	ino_t     st_ino;     /* inode number */
20630ca2051SWilly Tarreau 	mode_t    st_mode;    /* protection */
20730ca2051SWilly Tarreau 	nlink_t   st_nlink;   /* number of hard links */
20830ca2051SWilly Tarreau 	uid_t     st_uid;     /* user ID of owner */
20930ca2051SWilly Tarreau 	gid_t     st_gid;     /* group ID of owner */
21030ca2051SWilly Tarreau 	dev_t     st_rdev;    /* device ID (if special file) */
21130ca2051SWilly Tarreau 	off_t     st_size;    /* total size, in bytes */
21230ca2051SWilly Tarreau 	blksize_t st_blksize; /* blocksize for file system I/O */
21330ca2051SWilly Tarreau 	blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
21430ca2051SWilly Tarreau 	time_t    st_atime;   /* time of last access */
21530ca2051SWilly Tarreau 	time_t    st_mtime;   /* time of last modification */
21630ca2051SWilly Tarreau 	time_t    st_ctime;   /* time of last status change */
21730ca2051SWilly Tarreau };
21830ca2051SWilly Tarreau 
21930ca2051SWilly Tarreau #define WEXITSTATUS(status)   (((status) & 0xff00) >> 8)
22030ca2051SWilly Tarreau #define WIFEXITED(status)     (((status) & 0x7f) == 0)
22130ca2051SWilly Tarreau 
22230ca2051SWilly Tarreau /* Below comes the architecture-specific code. For each architecture, we have
22330ca2051SWilly Tarreau  * the syscall declarations and the _start code definition. This is the only
22430ca2051SWilly Tarreau  * global part. On all architectures the kernel puts everything in the stack
22530ca2051SWilly Tarreau  * before jumping to _start just above us, without any return address (_start
22630ca2051SWilly Tarreau  * is not a function but an entry pint). So at the stack pointer we find argc.
22730ca2051SWilly Tarreau  * Then argv[] begins, and ends at the first NULL. Then we have envp which
22830ca2051SWilly Tarreau  * starts and ends with a NULL as well. So envp=argv+argc+1.
22930ca2051SWilly Tarreau  */
23030ca2051SWilly Tarreau 
23130ca2051SWilly Tarreau #if defined(__x86_64__)
23230ca2051SWilly Tarreau /* Syscalls for x86_64 :
23330ca2051SWilly Tarreau  *   - registers are 64-bit
23430ca2051SWilly Tarreau  *   - syscall number is passed in rax
23530ca2051SWilly Tarreau  *   - arguments are in rdi, rsi, rdx, r10, r8, r9 respectively
23630ca2051SWilly Tarreau  *   - the system call is performed by calling the syscall instruction
23730ca2051SWilly Tarreau  *   - syscall return comes in rax
238bf916669SAmmar Faizi  *   - rcx and r11 are clobbered, others are preserved.
23930ca2051SWilly Tarreau  *   - the arguments are cast to long and assigned into the target registers
24030ca2051SWilly Tarreau  *     which are then simply passed as registers to the asm code, so that we
24130ca2051SWilly Tarreau  *     don't have to experience issues with register constraints.
24230ca2051SWilly Tarreau  *   - the syscall number is always specified last in order to allow to force
24330ca2051SWilly Tarreau  *     some registers before (gcc refuses a %-register at the last position).
244bf916669SAmmar Faizi  *   - see also x86-64 ABI section A.2 AMD64 Linux Kernel Conventions, A.2.1
245bf916669SAmmar Faizi  *     Calling Conventions.
246bf916669SAmmar Faizi  *
247bf916669SAmmar Faizi  * Link x86-64 ABI: https://gitlab.com/x86-psABIs/x86-64-ABI/-/wikis/x86-64-psABI
248bf916669SAmmar Faizi  *
24930ca2051SWilly Tarreau  */
25030ca2051SWilly Tarreau 
25130ca2051SWilly Tarreau #define my_syscall0(num)                                                      \
25230ca2051SWilly Tarreau ({                                                                            \
25330ca2051SWilly Tarreau 	long _ret;                                                            \
25430ca2051SWilly Tarreau 	register long _num  asm("rax") = (num);                               \
25530ca2051SWilly Tarreau 									      \
25630ca2051SWilly Tarreau 	asm volatile (                                                        \
25730ca2051SWilly Tarreau 		"syscall\n"                                                   \
25830ca2051SWilly Tarreau 		: "=a"(_ret)                                                  \
25930ca2051SWilly Tarreau 		: "0"(_num)                                                   \
260bf916669SAmmar Faizi 		: "rcx", "r11", "memory", "cc"                                \
26130ca2051SWilly Tarreau 	);                                                                    \
26230ca2051SWilly Tarreau 	_ret;                                                                 \
26330ca2051SWilly Tarreau })
26430ca2051SWilly Tarreau 
26530ca2051SWilly Tarreau #define my_syscall1(num, arg1)                                                \
26630ca2051SWilly Tarreau ({                                                                            \
26730ca2051SWilly Tarreau 	long _ret;                                                            \
26830ca2051SWilly Tarreau 	register long _num  asm("rax") = (num);                               \
26930ca2051SWilly Tarreau 	register long _arg1 asm("rdi") = (long)(arg1);                        \
27030ca2051SWilly Tarreau 									      \
27130ca2051SWilly Tarreau 	asm volatile (                                                        \
27230ca2051SWilly Tarreau 		"syscall\n"                                                   \
27330ca2051SWilly Tarreau 		: "=a"(_ret)                                                  \
27430ca2051SWilly Tarreau 		: "r"(_arg1),                                                 \
27530ca2051SWilly Tarreau 		  "0"(_num)                                                   \
276bf916669SAmmar Faizi 		: "rcx", "r11", "memory", "cc"                                \
27730ca2051SWilly Tarreau 	);                                                                    \
27830ca2051SWilly Tarreau 	_ret;                                                                 \
27930ca2051SWilly Tarreau })
28030ca2051SWilly Tarreau 
28130ca2051SWilly Tarreau #define my_syscall2(num, arg1, arg2)                                          \
28230ca2051SWilly Tarreau ({                                                                            \
28330ca2051SWilly Tarreau 	long _ret;                                                            \
28430ca2051SWilly Tarreau 	register long _num  asm("rax") = (num);                               \
28530ca2051SWilly Tarreau 	register long _arg1 asm("rdi") = (long)(arg1);                        \
28630ca2051SWilly Tarreau 	register long _arg2 asm("rsi") = (long)(arg2);                        \
28730ca2051SWilly Tarreau 									      \
28830ca2051SWilly Tarreau 	asm volatile (                                                        \
28930ca2051SWilly Tarreau 		"syscall\n"                                                   \
29030ca2051SWilly Tarreau 		: "=a"(_ret)                                                  \
29130ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2),                                     \
29230ca2051SWilly Tarreau 		  "0"(_num)                                                   \
293bf916669SAmmar Faizi 		: "rcx", "r11", "memory", "cc"                                \
29430ca2051SWilly Tarreau 	);                                                                    \
29530ca2051SWilly Tarreau 	_ret;                                                                 \
29630ca2051SWilly Tarreau })
29730ca2051SWilly Tarreau 
29830ca2051SWilly Tarreau #define my_syscall3(num, arg1, arg2, arg3)                                    \
29930ca2051SWilly Tarreau ({                                                                            \
30030ca2051SWilly Tarreau 	long _ret;                                                            \
30130ca2051SWilly Tarreau 	register long _num  asm("rax") = (num);                               \
30230ca2051SWilly Tarreau 	register long _arg1 asm("rdi") = (long)(arg1);                        \
30330ca2051SWilly Tarreau 	register long _arg2 asm("rsi") = (long)(arg2);                        \
30430ca2051SWilly Tarreau 	register long _arg3 asm("rdx") = (long)(arg3);                        \
30530ca2051SWilly Tarreau 									      \
30630ca2051SWilly Tarreau 	asm volatile (                                                        \
30730ca2051SWilly Tarreau 		"syscall\n"                                                   \
30830ca2051SWilly Tarreau 		: "=a"(_ret)                                                  \
30930ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
31030ca2051SWilly Tarreau 		  "0"(_num)                                                   \
311bf916669SAmmar Faizi 		: "rcx", "r11", "memory", "cc"                                \
31230ca2051SWilly Tarreau 	);                                                                    \
31330ca2051SWilly Tarreau 	_ret;                                                                 \
31430ca2051SWilly Tarreau })
31530ca2051SWilly Tarreau 
31630ca2051SWilly Tarreau #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
31730ca2051SWilly Tarreau ({                                                                            \
31830ca2051SWilly Tarreau 	long _ret;                                                            \
31930ca2051SWilly Tarreau 	register long _num  asm("rax") = (num);                               \
32030ca2051SWilly Tarreau 	register long _arg1 asm("rdi") = (long)(arg1);                        \
32130ca2051SWilly Tarreau 	register long _arg2 asm("rsi") = (long)(arg2);                        \
32230ca2051SWilly Tarreau 	register long _arg3 asm("rdx") = (long)(arg3);                        \
32330ca2051SWilly Tarreau 	register long _arg4 asm("r10") = (long)(arg4);                        \
32430ca2051SWilly Tarreau 									      \
32530ca2051SWilly Tarreau 	asm volatile (                                                        \
32630ca2051SWilly Tarreau 		"syscall\n"                                                   \
327bf916669SAmmar Faizi 		: "=a"(_ret)                                                  \
32830ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
32930ca2051SWilly Tarreau 		  "0"(_num)                                                   \
330bf916669SAmmar Faizi 		: "rcx", "r11", "memory", "cc"                                \
33130ca2051SWilly Tarreau 	);                                                                    \
33230ca2051SWilly Tarreau 	_ret;                                                                 \
33330ca2051SWilly Tarreau })
33430ca2051SWilly Tarreau 
33530ca2051SWilly Tarreau #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
33630ca2051SWilly Tarreau ({                                                                            \
33730ca2051SWilly Tarreau 	long _ret;                                                            \
33830ca2051SWilly Tarreau 	register long _num  asm("rax") = (num);                               \
33930ca2051SWilly Tarreau 	register long _arg1 asm("rdi") = (long)(arg1);                        \
34030ca2051SWilly Tarreau 	register long _arg2 asm("rsi") = (long)(arg2);                        \
34130ca2051SWilly Tarreau 	register long _arg3 asm("rdx") = (long)(arg3);                        \
34230ca2051SWilly Tarreau 	register long _arg4 asm("r10") = (long)(arg4);                        \
34330ca2051SWilly Tarreau 	register long _arg5 asm("r8")  = (long)(arg5);                        \
34430ca2051SWilly Tarreau 									      \
34530ca2051SWilly Tarreau 	asm volatile (                                                        \
34630ca2051SWilly Tarreau 		"syscall\n"                                                   \
347bf916669SAmmar Faizi 		: "=a"(_ret)                                                  \
34830ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
34930ca2051SWilly Tarreau 		  "0"(_num)                                                   \
350bf916669SAmmar Faizi 		: "rcx", "r11", "memory", "cc"                                \
35130ca2051SWilly Tarreau 	);                                                                    \
35230ca2051SWilly Tarreau 	_ret;                                                                 \
35330ca2051SWilly Tarreau })
35430ca2051SWilly Tarreau 
35530ca2051SWilly Tarreau #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
35630ca2051SWilly Tarreau ({                                                                            \
35730ca2051SWilly Tarreau 	long _ret;                                                            \
35830ca2051SWilly Tarreau 	register long _num  asm("rax") = (num);                               \
35930ca2051SWilly Tarreau 	register long _arg1 asm("rdi") = (long)(arg1);                        \
36030ca2051SWilly Tarreau 	register long _arg2 asm("rsi") = (long)(arg2);                        \
36130ca2051SWilly Tarreau 	register long _arg3 asm("rdx") = (long)(arg3);                        \
36230ca2051SWilly Tarreau 	register long _arg4 asm("r10") = (long)(arg4);                        \
36330ca2051SWilly Tarreau 	register long _arg5 asm("r8")  = (long)(arg5);                        \
36430ca2051SWilly Tarreau 	register long _arg6 asm("r9")  = (long)(arg6);                        \
36530ca2051SWilly Tarreau 									      \
36630ca2051SWilly Tarreau 	asm volatile (                                                        \
36730ca2051SWilly Tarreau 		"syscall\n"                                                   \
368bf916669SAmmar Faizi 		: "=a"(_ret)                                                  \
36930ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
37030ca2051SWilly Tarreau 		  "r"(_arg6), "0"(_num)                                       \
37130ca2051SWilly Tarreau 		: "rcx", "r11", "memory", "cc"                                \
37230ca2051SWilly Tarreau 	);                                                                    \
37330ca2051SWilly Tarreau 	_ret;                                                                 \
37430ca2051SWilly Tarreau })
37530ca2051SWilly Tarreau 
37630ca2051SWilly Tarreau /* startup code */
377937ed91cSAmmar Faizi /*
378937ed91cSAmmar Faizi  * x86-64 System V ABI mandates:
379937ed91cSAmmar Faizi  * 1) %rsp must be 16-byte aligned right before the function call.
380937ed91cSAmmar Faizi  * 2) The deepest stack frame should be zero (the %rbp).
381937ed91cSAmmar Faizi  *
382937ed91cSAmmar Faizi  */
38330ca2051SWilly Tarreau asm(".section .text\n"
38430ca2051SWilly Tarreau     ".global _start\n"
38530ca2051SWilly Tarreau     "_start:\n"
38630ca2051SWilly Tarreau     "pop %rdi\n"                // argc   (first arg, %rdi)
38730ca2051SWilly Tarreau     "mov %rsp, %rsi\n"          // argv[] (second arg, %rsi)
38830ca2051SWilly Tarreau     "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx)
389937ed91cSAmmar Faizi     "xor %ebp, %ebp\n"          // zero the stack frame
390937ed91cSAmmar Faizi     "and $-16, %rsp\n"          // x86 ABI : esp must be 16-byte aligned before call
39130ca2051SWilly Tarreau     "call main\n"               // main() returns the status code, we'll exit with it.
392de0244aeSWilly Tarreau     "mov %eax, %edi\n"          // retrieve exit code (32 bit)
3937bdc0e7aSAmmar Faizi     "mov $60, %eax\n"           // NR_exit == 60
39430ca2051SWilly Tarreau     "syscall\n"                 // really exit
39530ca2051SWilly Tarreau     "hlt\n"                     // ensure it does not return
39630ca2051SWilly Tarreau     "");
39730ca2051SWilly Tarreau 
39830ca2051SWilly Tarreau /* fcntl / open */
39930ca2051SWilly Tarreau #define O_RDONLY            0
40030ca2051SWilly Tarreau #define O_WRONLY            1
40130ca2051SWilly Tarreau #define O_RDWR              2
40230ca2051SWilly Tarreau #define O_CREAT          0x40
40330ca2051SWilly Tarreau #define O_EXCL           0x80
40430ca2051SWilly Tarreau #define O_NOCTTY        0x100
40530ca2051SWilly Tarreau #define O_TRUNC         0x200
40630ca2051SWilly Tarreau #define O_APPEND        0x400
40730ca2051SWilly Tarreau #define O_NONBLOCK      0x800
40830ca2051SWilly Tarreau #define O_DIRECTORY   0x10000
40930ca2051SWilly Tarreau 
41030ca2051SWilly Tarreau /* The struct returned by the stat() syscall, equivalent to stat64(). The
41130ca2051SWilly Tarreau  * syscall returns 116 bytes and stops in the middle of __unused.
41230ca2051SWilly Tarreau  */
41330ca2051SWilly Tarreau struct sys_stat_struct {
41430ca2051SWilly Tarreau 	unsigned long st_dev;
41530ca2051SWilly Tarreau 	unsigned long st_ino;
41630ca2051SWilly Tarreau 	unsigned long st_nlink;
41730ca2051SWilly Tarreau 	unsigned int  st_mode;
41830ca2051SWilly Tarreau 	unsigned int  st_uid;
41930ca2051SWilly Tarreau 
42030ca2051SWilly Tarreau 	unsigned int  st_gid;
42130ca2051SWilly Tarreau 	unsigned int  __pad0;
42230ca2051SWilly Tarreau 	unsigned long st_rdev;
42330ca2051SWilly Tarreau 	long          st_size;
42430ca2051SWilly Tarreau 	long          st_blksize;
42530ca2051SWilly Tarreau 
42630ca2051SWilly Tarreau 	long          st_blocks;
42730ca2051SWilly Tarreau 	unsigned long st_atime;
42830ca2051SWilly Tarreau 	unsigned long st_atime_nsec;
42930ca2051SWilly Tarreau 	unsigned long st_mtime;
43030ca2051SWilly Tarreau 
43130ca2051SWilly Tarreau 	unsigned long st_mtime_nsec;
43230ca2051SWilly Tarreau 	unsigned long st_ctime;
43330ca2051SWilly Tarreau 	unsigned long st_ctime_nsec;
43430ca2051SWilly Tarreau 	long          __unused[3];
43530ca2051SWilly Tarreau };
43630ca2051SWilly Tarreau 
43730ca2051SWilly Tarreau #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
43830ca2051SWilly Tarreau /* Syscalls for i386 :
43930ca2051SWilly Tarreau  *   - mostly similar to x86_64
44030ca2051SWilly Tarreau  *   - registers are 32-bit
44130ca2051SWilly Tarreau  *   - syscall number is passed in eax
44230ca2051SWilly Tarreau  *   - arguments are in ebx, ecx, edx, esi, edi, ebp respectively
44330ca2051SWilly Tarreau  *   - all registers are preserved (except eax of course)
44430ca2051SWilly Tarreau  *   - the system call is performed by calling int $0x80
44530ca2051SWilly Tarreau  *   - syscall return comes in eax
44630ca2051SWilly Tarreau  *   - the arguments are cast to long and assigned into the target registers
44730ca2051SWilly Tarreau  *     which are then simply passed as registers to the asm code, so that we
44830ca2051SWilly Tarreau  *     don't have to experience issues with register constraints.
44930ca2051SWilly Tarreau  *   - the syscall number is always specified last in order to allow to force
45030ca2051SWilly Tarreau  *     some registers before (gcc refuses a %-register at the last position).
45130ca2051SWilly Tarreau  *
45230ca2051SWilly Tarreau  * Also, i386 supports the old_select syscall if newselect is not available
45330ca2051SWilly Tarreau  */
45430ca2051SWilly Tarreau #define __ARCH_WANT_SYS_OLD_SELECT
45530ca2051SWilly Tarreau 
45630ca2051SWilly Tarreau #define my_syscall0(num)                                                      \
45730ca2051SWilly Tarreau ({                                                                            \
45830ca2051SWilly Tarreau 	long _ret;                                                            \
45930ca2051SWilly Tarreau 	register long _num asm("eax") = (num);                                \
46030ca2051SWilly Tarreau 									      \
46130ca2051SWilly Tarreau 	asm volatile (                                                        \
46230ca2051SWilly Tarreau 		"int $0x80\n"                                                 \
46330ca2051SWilly Tarreau 		: "=a" (_ret)                                                 \
46430ca2051SWilly Tarreau 		: "0"(_num)                                                   \
46530ca2051SWilly Tarreau 		: "memory", "cc"                                              \
46630ca2051SWilly Tarreau 	);                                                                    \
46730ca2051SWilly Tarreau 	_ret;                                                                 \
46830ca2051SWilly Tarreau })
46930ca2051SWilly Tarreau 
47030ca2051SWilly Tarreau #define my_syscall1(num, arg1)                                                \
47130ca2051SWilly Tarreau ({                                                                            \
47230ca2051SWilly Tarreau 	long _ret;                                                            \
47330ca2051SWilly Tarreau 	register long _num asm("eax") = (num);                                \
47430ca2051SWilly Tarreau 	register long _arg1 asm("ebx") = (long)(arg1);                        \
47530ca2051SWilly Tarreau 									      \
47630ca2051SWilly Tarreau 	asm volatile (                                                        \
47730ca2051SWilly Tarreau 		"int $0x80\n"                                                 \
47830ca2051SWilly Tarreau 		: "=a" (_ret)                                                 \
47930ca2051SWilly Tarreau 		: "r"(_arg1),                                                 \
48030ca2051SWilly Tarreau 		  "0"(_num)                                                   \
48130ca2051SWilly Tarreau 		: "memory", "cc"                                              \
48230ca2051SWilly Tarreau 	);                                                                    \
48330ca2051SWilly Tarreau 	_ret;                                                                 \
48430ca2051SWilly Tarreau })
48530ca2051SWilly Tarreau 
48630ca2051SWilly Tarreau #define my_syscall2(num, arg1, arg2)                                          \
48730ca2051SWilly Tarreau ({                                                                            \
48830ca2051SWilly Tarreau 	long _ret;                                                            \
48930ca2051SWilly Tarreau 	register long _num asm("eax") = (num);                                \
49030ca2051SWilly Tarreau 	register long _arg1 asm("ebx") = (long)(arg1);                        \
49130ca2051SWilly Tarreau 	register long _arg2 asm("ecx") = (long)(arg2);                        \
49230ca2051SWilly Tarreau 									      \
49330ca2051SWilly Tarreau 	asm volatile (                                                        \
49430ca2051SWilly Tarreau 		"int $0x80\n"                                                 \
49530ca2051SWilly Tarreau 		: "=a" (_ret)                                                 \
49630ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2),                                     \
49730ca2051SWilly Tarreau 		  "0"(_num)                                                   \
49830ca2051SWilly Tarreau 		: "memory", "cc"                                              \
49930ca2051SWilly Tarreau 	);                                                                    \
50030ca2051SWilly Tarreau 	_ret;                                                                 \
50130ca2051SWilly Tarreau })
50230ca2051SWilly Tarreau 
50330ca2051SWilly Tarreau #define my_syscall3(num, arg1, arg2, arg3)                                    \
50430ca2051SWilly Tarreau ({                                                                            \
50530ca2051SWilly Tarreau 	long _ret;                                                            \
50630ca2051SWilly Tarreau 	register long _num asm("eax") = (num);                                \
50730ca2051SWilly Tarreau 	register long _arg1 asm("ebx") = (long)(arg1);                        \
50830ca2051SWilly Tarreau 	register long _arg2 asm("ecx") = (long)(arg2);                        \
50930ca2051SWilly Tarreau 	register long _arg3 asm("edx") = (long)(arg3);                        \
51030ca2051SWilly Tarreau 									      \
51130ca2051SWilly Tarreau 	asm volatile (                                                        \
51230ca2051SWilly Tarreau 		"int $0x80\n"                                                 \
51330ca2051SWilly Tarreau 		: "=a" (_ret)                                                 \
51430ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
51530ca2051SWilly Tarreau 		  "0"(_num)                                                   \
51630ca2051SWilly Tarreau 		: "memory", "cc"                                              \
51730ca2051SWilly Tarreau 	);                                                                    \
51830ca2051SWilly Tarreau 	_ret;                                                                 \
51930ca2051SWilly Tarreau })
52030ca2051SWilly Tarreau 
52130ca2051SWilly Tarreau #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
52230ca2051SWilly Tarreau ({                                                                            \
52330ca2051SWilly Tarreau 	long _ret;                                                            \
52430ca2051SWilly Tarreau 	register long _num asm("eax") = (num);                                \
52530ca2051SWilly Tarreau 	register long _arg1 asm("ebx") = (long)(arg1);                        \
52630ca2051SWilly Tarreau 	register long _arg2 asm("ecx") = (long)(arg2);                        \
52730ca2051SWilly Tarreau 	register long _arg3 asm("edx") = (long)(arg3);                        \
52830ca2051SWilly Tarreau 	register long _arg4 asm("esi") = (long)(arg4);                        \
52930ca2051SWilly Tarreau 									      \
53030ca2051SWilly Tarreau 	asm volatile (                                                        \
53130ca2051SWilly Tarreau 		"int $0x80\n"                                                 \
53230ca2051SWilly Tarreau 		: "=a" (_ret)                                                 \
53330ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
53430ca2051SWilly Tarreau 		  "0"(_num)                                                   \
53530ca2051SWilly Tarreau 		: "memory", "cc"                                              \
53630ca2051SWilly Tarreau 	);                                                                    \
53730ca2051SWilly Tarreau 	_ret;                                                                 \
53830ca2051SWilly Tarreau })
53930ca2051SWilly Tarreau 
54030ca2051SWilly Tarreau #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
54130ca2051SWilly Tarreau ({                                                                            \
54230ca2051SWilly Tarreau 	long _ret;                                                            \
54330ca2051SWilly Tarreau 	register long _num asm("eax") = (num);                                \
54430ca2051SWilly Tarreau 	register long _arg1 asm("ebx") = (long)(arg1);                        \
54530ca2051SWilly Tarreau 	register long _arg2 asm("ecx") = (long)(arg2);                        \
54630ca2051SWilly Tarreau 	register long _arg3 asm("edx") = (long)(arg3);                        \
54730ca2051SWilly Tarreau 	register long _arg4 asm("esi") = (long)(arg4);                        \
54830ca2051SWilly Tarreau 	register long _arg5 asm("edi") = (long)(arg5);                        \
54930ca2051SWilly Tarreau 									      \
55030ca2051SWilly Tarreau 	asm volatile (                                                        \
55130ca2051SWilly Tarreau 		"int $0x80\n"                                                 \
55230ca2051SWilly Tarreau 		: "=a" (_ret)                                                 \
55330ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
55430ca2051SWilly Tarreau 		  "0"(_num)                                                   \
55530ca2051SWilly Tarreau 		: "memory", "cc"                                              \
55630ca2051SWilly Tarreau 	);                                                                    \
55730ca2051SWilly Tarreau 	_ret;                                                                 \
55830ca2051SWilly Tarreau })
55930ca2051SWilly Tarreau 
56030ca2051SWilly Tarreau /* startup code */
561ebbe0d8aSWilly Tarreau /*
562ebbe0d8aSWilly Tarreau  * i386 System V ABI mandates:
563ebbe0d8aSWilly Tarreau  * 1) last pushed argument must be 16-byte aligned.
564ebbe0d8aSWilly Tarreau  * 2) The deepest stack frame should be set to zero
565ebbe0d8aSWilly Tarreau  *
566ebbe0d8aSWilly Tarreau  */
56730ca2051SWilly Tarreau asm(".section .text\n"
56830ca2051SWilly Tarreau     ".global _start\n"
56930ca2051SWilly Tarreau     "_start:\n"
57030ca2051SWilly Tarreau     "pop %eax\n"                // argc   (first arg, %eax)
57130ca2051SWilly Tarreau     "mov %esp, %ebx\n"          // argv[] (second arg, %ebx)
57230ca2051SWilly Tarreau     "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx)
573ebbe0d8aSWilly Tarreau     "xor %ebp, %ebp\n"          // zero the stack frame
574ebbe0d8aSWilly Tarreau     "and $-16, %esp\n"          // x86 ABI : esp must be 16-byte aligned before
575ebbe0d8aSWilly Tarreau     "sub $4, %esp\n"            // the call instruction (args are aligned)
57630ca2051SWilly Tarreau     "push %ecx\n"               // push all registers on the stack so that we
57730ca2051SWilly Tarreau     "push %ebx\n"               // support both regparm and plain stack modes
57830ca2051SWilly Tarreau     "push %eax\n"
57930ca2051SWilly Tarreau     "call main\n"               // main() returns the status code in %eax
580de0244aeSWilly Tarreau     "mov %eax, %ebx\n"          // retrieve exit code (32-bit int)
58130ca2051SWilly Tarreau     "movl $1, %eax\n"           // NR_exit == 1
58230ca2051SWilly Tarreau     "int $0x80\n"               // exit now
58330ca2051SWilly Tarreau     "hlt\n"                     // ensure it does not
58430ca2051SWilly Tarreau     "");
58530ca2051SWilly Tarreau 
58630ca2051SWilly Tarreau /* fcntl / open */
58730ca2051SWilly Tarreau #define O_RDONLY            0
58830ca2051SWilly Tarreau #define O_WRONLY            1
58930ca2051SWilly Tarreau #define O_RDWR              2
59030ca2051SWilly Tarreau #define O_CREAT          0x40
59130ca2051SWilly Tarreau #define O_EXCL           0x80
59230ca2051SWilly Tarreau #define O_NOCTTY        0x100
59330ca2051SWilly Tarreau #define O_TRUNC         0x200
59430ca2051SWilly Tarreau #define O_APPEND        0x400
59530ca2051SWilly Tarreau #define O_NONBLOCK      0x800
59630ca2051SWilly Tarreau #define O_DIRECTORY   0x10000
59730ca2051SWilly Tarreau 
59830ca2051SWilly Tarreau /* The struct returned by the stat() syscall, 32-bit only, the syscall returns
59930ca2051SWilly Tarreau  * exactly 56 bytes (stops before the unused array).
60030ca2051SWilly Tarreau  */
60130ca2051SWilly Tarreau struct sys_stat_struct {
60230ca2051SWilly Tarreau 	unsigned long  st_dev;
60330ca2051SWilly Tarreau 	unsigned long  st_ino;
60430ca2051SWilly Tarreau 	unsigned short st_mode;
60530ca2051SWilly Tarreau 	unsigned short st_nlink;
60630ca2051SWilly Tarreau 	unsigned short st_uid;
60730ca2051SWilly Tarreau 	unsigned short st_gid;
60830ca2051SWilly Tarreau 
60930ca2051SWilly Tarreau 	unsigned long  st_rdev;
61030ca2051SWilly Tarreau 	unsigned long  st_size;
61130ca2051SWilly Tarreau 	unsigned long  st_blksize;
61230ca2051SWilly Tarreau 	unsigned long  st_blocks;
61330ca2051SWilly Tarreau 
61430ca2051SWilly Tarreau 	unsigned long  st_atime;
61530ca2051SWilly Tarreau 	unsigned long  st_atime_nsec;
61630ca2051SWilly Tarreau 	unsigned long  st_mtime;
61730ca2051SWilly Tarreau 	unsigned long  st_mtime_nsec;
61830ca2051SWilly Tarreau 
61930ca2051SWilly Tarreau 	unsigned long  st_ctime;
62030ca2051SWilly Tarreau 	unsigned long  st_ctime_nsec;
62130ca2051SWilly Tarreau 	unsigned long  __unused[2];
62230ca2051SWilly Tarreau };
62330ca2051SWilly Tarreau 
62430ca2051SWilly Tarreau #elif defined(__ARM_EABI__)
62530ca2051SWilly Tarreau /* Syscalls for ARM in ARM or Thumb modes :
62630ca2051SWilly Tarreau  *   - registers are 32-bit
62730ca2051SWilly Tarreau  *   - stack is 8-byte aligned
62830ca2051SWilly Tarreau  *     ( http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html)
62930ca2051SWilly Tarreau  *   - syscall number is passed in r7
63030ca2051SWilly Tarreau  *   - arguments are in r0, r1, r2, r3, r4, r5
63130ca2051SWilly Tarreau  *   - the system call is performed by calling svc #0
63230ca2051SWilly Tarreau  *   - syscall return comes in r0.
63330ca2051SWilly Tarreau  *   - only lr is clobbered.
63430ca2051SWilly Tarreau  *   - the arguments are cast to long and assigned into the target registers
63530ca2051SWilly Tarreau  *     which are then simply passed as registers to the asm code, so that we
63630ca2051SWilly Tarreau  *     don't have to experience issues with register constraints.
63730ca2051SWilly Tarreau  *   - the syscall number is always specified last in order to allow to force
63830ca2051SWilly Tarreau  *     some registers before (gcc refuses a %-register at the last position).
63930ca2051SWilly Tarreau  *
64030ca2051SWilly Tarreau  * Also, ARM supports the old_select syscall if newselect is not available
64130ca2051SWilly Tarreau  */
64230ca2051SWilly Tarreau #define __ARCH_WANT_SYS_OLD_SELECT
64330ca2051SWilly Tarreau 
64430ca2051SWilly Tarreau #define my_syscall0(num)                                                      \
64530ca2051SWilly Tarreau ({                                                                            \
64630ca2051SWilly Tarreau 	register long _num asm("r7") = (num);                                 \
64730ca2051SWilly Tarreau 	register long _arg1 asm("r0");                                        \
64830ca2051SWilly Tarreau 									      \
64930ca2051SWilly Tarreau 	asm volatile (                                                        \
65030ca2051SWilly Tarreau 		"svc #0\n"                                                    \
65130ca2051SWilly Tarreau 		: "=r"(_arg1)                                                 \
65230ca2051SWilly Tarreau 		: "r"(_num)                                                   \
65330ca2051SWilly Tarreau 		: "memory", "cc", "lr"                                        \
65430ca2051SWilly Tarreau 	);                                                                    \
65530ca2051SWilly Tarreau 	_arg1;                                                                \
65630ca2051SWilly Tarreau })
65730ca2051SWilly Tarreau 
65830ca2051SWilly Tarreau #define my_syscall1(num, arg1)                                                \
65930ca2051SWilly Tarreau ({                                                                            \
66030ca2051SWilly Tarreau 	register long _num asm("r7") = (num);                                 \
66130ca2051SWilly Tarreau 	register long _arg1 asm("r0") = (long)(arg1);                         \
66230ca2051SWilly Tarreau 									      \
66330ca2051SWilly Tarreau 	asm volatile (                                                        \
66430ca2051SWilly Tarreau 		"svc #0\n"                                                    \
66530ca2051SWilly Tarreau 		: "=r"(_arg1)                                                 \
66630ca2051SWilly Tarreau 		: "r"(_arg1),                                                 \
66730ca2051SWilly Tarreau 		  "r"(_num)                                                   \
66830ca2051SWilly Tarreau 		: "memory", "cc", "lr"                                        \
66930ca2051SWilly Tarreau 	);                                                                    \
67030ca2051SWilly Tarreau 	_arg1;                                                                \
67130ca2051SWilly Tarreau })
67230ca2051SWilly Tarreau 
67330ca2051SWilly Tarreau #define my_syscall2(num, arg1, arg2)                                          \
67430ca2051SWilly Tarreau ({                                                                            \
67530ca2051SWilly Tarreau 	register long _num asm("r7") = (num);                                 \
67630ca2051SWilly Tarreau 	register long _arg1 asm("r0") = (long)(arg1);                         \
67730ca2051SWilly Tarreau 	register long _arg2 asm("r1") = (long)(arg2);                         \
67830ca2051SWilly Tarreau 									      \
67930ca2051SWilly Tarreau 	asm volatile (                                                        \
68030ca2051SWilly Tarreau 		"svc #0\n"                                                    \
68130ca2051SWilly Tarreau 		: "=r"(_arg1)                                                 \
68230ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2),                                     \
68330ca2051SWilly Tarreau 		  "r"(_num)                                                   \
68430ca2051SWilly Tarreau 		: "memory", "cc", "lr"                                        \
68530ca2051SWilly Tarreau 	);                                                                    \
68630ca2051SWilly Tarreau 	_arg1;                                                                \
68730ca2051SWilly Tarreau })
68830ca2051SWilly Tarreau 
68930ca2051SWilly Tarreau #define my_syscall3(num, arg1, arg2, arg3)                                    \
69030ca2051SWilly Tarreau ({                                                                            \
69130ca2051SWilly Tarreau 	register long _num asm("r7") = (num);                                 \
69230ca2051SWilly Tarreau 	register long _arg1 asm("r0") = (long)(arg1);                         \
69330ca2051SWilly Tarreau 	register long _arg2 asm("r1") = (long)(arg2);                         \
69430ca2051SWilly Tarreau 	register long _arg3 asm("r2") = (long)(arg3);                         \
69530ca2051SWilly Tarreau 									      \
69630ca2051SWilly Tarreau 	asm volatile (                                                        \
69730ca2051SWilly Tarreau 		"svc #0\n"                                                    \
69830ca2051SWilly Tarreau 		: "=r"(_arg1)                                                 \
69930ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
70030ca2051SWilly Tarreau 		  "r"(_num)                                                   \
70130ca2051SWilly Tarreau 		: "memory", "cc", "lr"                                        \
70230ca2051SWilly Tarreau 	);                                                                    \
70330ca2051SWilly Tarreau 	_arg1;                                                                \
70430ca2051SWilly Tarreau })
70530ca2051SWilly Tarreau 
70630ca2051SWilly Tarreau #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
70730ca2051SWilly Tarreau ({                                                                            \
70830ca2051SWilly Tarreau 	register long _num asm("r7") = (num);                                 \
70930ca2051SWilly Tarreau 	register long _arg1 asm("r0") = (long)(arg1);                         \
71030ca2051SWilly Tarreau 	register long _arg2 asm("r1") = (long)(arg2);                         \
71130ca2051SWilly Tarreau 	register long _arg3 asm("r2") = (long)(arg3);                         \
71230ca2051SWilly Tarreau 	register long _arg4 asm("r3") = (long)(arg4);                         \
71330ca2051SWilly Tarreau 									      \
71430ca2051SWilly Tarreau 	asm volatile (                                                        \
71530ca2051SWilly Tarreau 		"svc #0\n"                                                    \
71630ca2051SWilly Tarreau 		: "=r"(_arg1)                                                 \
71730ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
71830ca2051SWilly Tarreau 		  "r"(_num)                                                   \
71930ca2051SWilly Tarreau 		: "memory", "cc", "lr"                                        \
72030ca2051SWilly Tarreau 	);                                                                    \
72130ca2051SWilly Tarreau 	_arg1;                                                                \
72230ca2051SWilly Tarreau })
72330ca2051SWilly Tarreau 
72430ca2051SWilly Tarreau #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
72530ca2051SWilly Tarreau ({                                                                            \
72630ca2051SWilly Tarreau 	register long _num asm("r7") = (num);                                 \
72730ca2051SWilly Tarreau 	register long _arg1 asm("r0") = (long)(arg1);                         \
72830ca2051SWilly Tarreau 	register long _arg2 asm("r1") = (long)(arg2);                         \
72930ca2051SWilly Tarreau 	register long _arg3 asm("r2") = (long)(arg3);                         \
73030ca2051SWilly Tarreau 	register long _arg4 asm("r3") = (long)(arg4);                         \
73130ca2051SWilly Tarreau 	register long _arg5 asm("r4") = (long)(arg5);                         \
73230ca2051SWilly Tarreau 									      \
73330ca2051SWilly Tarreau 	asm volatile (                                                        \
73430ca2051SWilly Tarreau 		"svc #0\n"                                                    \
73530ca2051SWilly Tarreau 		: "=r" (_arg1)                                                \
73630ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
73730ca2051SWilly Tarreau 		  "r"(_num)                                                   \
73830ca2051SWilly Tarreau 		: "memory", "cc", "lr"                                        \
73930ca2051SWilly Tarreau 	);                                                                    \
74030ca2051SWilly Tarreau 	_arg1;                                                                \
74130ca2051SWilly Tarreau })
74230ca2051SWilly Tarreau 
74330ca2051SWilly Tarreau /* startup code */
74430ca2051SWilly Tarreau asm(".section .text\n"
74530ca2051SWilly Tarreau     ".global _start\n"
74630ca2051SWilly Tarreau     "_start:\n"
74730ca2051SWilly Tarreau #if defined(__THUMBEB__) || defined(__THUMBEL__)
74830ca2051SWilly Tarreau     /* We enter here in 32-bit mode but if some previous functions were in
74930ca2051SWilly Tarreau      * 16-bit mode, the assembler cannot know, so we need to tell it we're in
75030ca2051SWilly Tarreau      * 32-bit now, then switch to 16-bit (is there a better way to do it than
75130ca2051SWilly Tarreau      * adding 1 by hand ?) and tell the asm we're now in 16-bit mode so that
75230ca2051SWilly Tarreau      * it generates correct instructions. Note that we do not support thumb1.
75330ca2051SWilly Tarreau      */
75430ca2051SWilly Tarreau     ".code 32\n"
75530ca2051SWilly Tarreau     "add     r0, pc, #1\n"
75630ca2051SWilly Tarreau     "bx      r0\n"
75730ca2051SWilly Tarreau     ".code 16\n"
75830ca2051SWilly Tarreau #endif
75930ca2051SWilly Tarreau     "pop {%r0}\n"                 // argc was in the stack
76030ca2051SWilly Tarreau     "mov %r1, %sp\n"              // argv = sp
76130ca2051SWilly Tarreau     "add %r2, %r1, %r0, lsl #2\n" // envp = argv + 4*argc ...
76230ca2051SWilly Tarreau     "add %r2, %r2, $4\n"          //        ... + 4
76330ca2051SWilly Tarreau     "and %r3, %r1, $-8\n"         // AAPCS : sp must be 8-byte aligned in the
76430ca2051SWilly Tarreau     "mov %sp, %r3\n"              //         callee, an bl doesn't push (lr=pc)
76530ca2051SWilly Tarreau     "bl main\n"                   // main() returns the status code, we'll exit with it.
76630ca2051SWilly Tarreau     "movs r7, $1\n"               // NR_exit == 1
76730ca2051SWilly Tarreau     "svc $0x00\n"
76830ca2051SWilly Tarreau     "");
76930ca2051SWilly Tarreau 
77030ca2051SWilly Tarreau /* fcntl / open */
77130ca2051SWilly Tarreau #define O_RDONLY            0
77230ca2051SWilly Tarreau #define O_WRONLY            1
77330ca2051SWilly Tarreau #define O_RDWR              2
77430ca2051SWilly Tarreau #define O_CREAT          0x40
77530ca2051SWilly Tarreau #define O_EXCL           0x80
77630ca2051SWilly Tarreau #define O_NOCTTY        0x100
77730ca2051SWilly Tarreau #define O_TRUNC         0x200
77830ca2051SWilly Tarreau #define O_APPEND        0x400
77930ca2051SWilly Tarreau #define O_NONBLOCK      0x800
78030ca2051SWilly Tarreau #define O_DIRECTORY    0x4000
78130ca2051SWilly Tarreau 
78230ca2051SWilly Tarreau /* The struct returned by the stat() syscall, 32-bit only, the syscall returns
78330ca2051SWilly Tarreau  * exactly 56 bytes (stops before the unused array). In big endian, the format
78430ca2051SWilly Tarreau  * differs as devices are returned as short only.
78530ca2051SWilly Tarreau  */
78630ca2051SWilly Tarreau struct sys_stat_struct {
78730ca2051SWilly Tarreau #if defined(__ARMEB__)
78830ca2051SWilly Tarreau 	unsigned short st_dev;
78930ca2051SWilly Tarreau 	unsigned short __pad1;
79030ca2051SWilly Tarreau #else
79130ca2051SWilly Tarreau 	unsigned long  st_dev;
79230ca2051SWilly Tarreau #endif
79330ca2051SWilly Tarreau 	unsigned long  st_ino;
79430ca2051SWilly Tarreau 	unsigned short st_mode;
79530ca2051SWilly Tarreau 	unsigned short st_nlink;
79630ca2051SWilly Tarreau 	unsigned short st_uid;
79730ca2051SWilly Tarreau 	unsigned short st_gid;
79830ca2051SWilly Tarreau #if defined(__ARMEB__)
79930ca2051SWilly Tarreau 	unsigned short st_rdev;
80030ca2051SWilly Tarreau 	unsigned short __pad2;
80130ca2051SWilly Tarreau #else
80230ca2051SWilly Tarreau 	unsigned long  st_rdev;
80330ca2051SWilly Tarreau #endif
80430ca2051SWilly Tarreau 	unsigned long  st_size;
80530ca2051SWilly Tarreau 	unsigned long  st_blksize;
80630ca2051SWilly Tarreau 	unsigned long  st_blocks;
80730ca2051SWilly Tarreau 	unsigned long  st_atime;
80830ca2051SWilly Tarreau 	unsigned long  st_atime_nsec;
80930ca2051SWilly Tarreau 	unsigned long  st_mtime;
81030ca2051SWilly Tarreau 	unsigned long  st_mtime_nsec;
81130ca2051SWilly Tarreau 	unsigned long  st_ctime;
81230ca2051SWilly Tarreau 	unsigned long  st_ctime_nsec;
81330ca2051SWilly Tarreau 	unsigned long  __unused[2];
81430ca2051SWilly Tarreau };
81530ca2051SWilly Tarreau 
81630ca2051SWilly Tarreau #elif defined(__aarch64__)
81730ca2051SWilly Tarreau /* Syscalls for AARCH64 :
81830ca2051SWilly Tarreau  *   - registers are 64-bit
81930ca2051SWilly Tarreau  *   - stack is 16-byte aligned
82030ca2051SWilly Tarreau  *   - syscall number is passed in x8
82130ca2051SWilly Tarreau  *   - arguments are in x0, x1, x2, x3, x4, x5
82230ca2051SWilly Tarreau  *   - the system call is performed by calling svc 0
82330ca2051SWilly Tarreau  *   - syscall return comes in x0.
82430ca2051SWilly Tarreau  *   - the arguments are cast to long and assigned into the target registers
82530ca2051SWilly Tarreau  *     which are then simply passed as registers to the asm code, so that we
82630ca2051SWilly Tarreau  *     don't have to experience issues with register constraints.
82730ca2051SWilly Tarreau  *
82830ca2051SWilly Tarreau  * On aarch64, select() is not implemented so we have to use pselect6().
82930ca2051SWilly Tarreau  */
83030ca2051SWilly Tarreau #define __ARCH_WANT_SYS_PSELECT6
83130ca2051SWilly Tarreau 
83230ca2051SWilly Tarreau #define my_syscall0(num)                                                      \
83330ca2051SWilly Tarreau ({                                                                            \
83430ca2051SWilly Tarreau 	register long _num  asm("x8") = (num);                                \
83530ca2051SWilly Tarreau 	register long _arg1 asm("x0");                                        \
83630ca2051SWilly Tarreau 									      \
83730ca2051SWilly Tarreau 	asm volatile (                                                        \
83830ca2051SWilly Tarreau 		"svc #0\n"                                                    \
83930ca2051SWilly Tarreau 		: "=r"(_arg1)                                                 \
84030ca2051SWilly Tarreau 		: "r"(_num)                                                   \
84130ca2051SWilly Tarreau 		: "memory", "cc"                                              \
84230ca2051SWilly Tarreau 	);                                                                    \
84330ca2051SWilly Tarreau 	_arg1;                                                                \
84430ca2051SWilly Tarreau })
84530ca2051SWilly Tarreau 
84630ca2051SWilly Tarreau #define my_syscall1(num, arg1)                                                \
84730ca2051SWilly Tarreau ({                                                                            \
84830ca2051SWilly Tarreau 	register long _num  asm("x8") = (num);                                \
84930ca2051SWilly Tarreau 	register long _arg1 asm("x0") = (long)(arg1);                         \
85030ca2051SWilly Tarreau 									      \
85130ca2051SWilly Tarreau 	asm volatile (                                                        \
85230ca2051SWilly Tarreau 		"svc #0\n"                                                    \
85330ca2051SWilly Tarreau 		: "=r"(_arg1)                                                 \
85430ca2051SWilly Tarreau 		: "r"(_arg1),                                                 \
85530ca2051SWilly Tarreau 		  "r"(_num)                                                   \
85630ca2051SWilly Tarreau 		: "memory", "cc"                                              \
85730ca2051SWilly Tarreau 	);                                                                    \
85830ca2051SWilly Tarreau 	_arg1;                                                                \
85930ca2051SWilly Tarreau })
86030ca2051SWilly Tarreau 
86130ca2051SWilly Tarreau #define my_syscall2(num, arg1, arg2)                                          \
86230ca2051SWilly Tarreau ({                                                                            \
86330ca2051SWilly Tarreau 	register long _num  asm("x8") = (num);                                \
86430ca2051SWilly Tarreau 	register long _arg1 asm("x0") = (long)(arg1);                         \
86530ca2051SWilly Tarreau 	register long _arg2 asm("x1") = (long)(arg2);                         \
86630ca2051SWilly Tarreau 									      \
86730ca2051SWilly Tarreau 	asm volatile (                                                        \
86830ca2051SWilly Tarreau 		"svc #0\n"                                                    \
86930ca2051SWilly Tarreau 		: "=r"(_arg1)                                                 \
87030ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2),                                     \
87130ca2051SWilly Tarreau 		  "r"(_num)                                                   \
87230ca2051SWilly Tarreau 		: "memory", "cc"                                              \
87330ca2051SWilly Tarreau 	);                                                                    \
87430ca2051SWilly Tarreau 	_arg1;                                                                \
87530ca2051SWilly Tarreau })
87630ca2051SWilly Tarreau 
87730ca2051SWilly Tarreau #define my_syscall3(num, arg1, arg2, arg3)                                    \
87830ca2051SWilly Tarreau ({                                                                            \
87930ca2051SWilly Tarreau 	register long _num  asm("x8") = (num);                                \
88030ca2051SWilly Tarreau 	register long _arg1 asm("x0") = (long)(arg1);                         \
88130ca2051SWilly Tarreau 	register long _arg2 asm("x1") = (long)(arg2);                         \
88230ca2051SWilly Tarreau 	register long _arg3 asm("x2") = (long)(arg3);                         \
88330ca2051SWilly Tarreau 									      \
88430ca2051SWilly Tarreau 	asm volatile (                                                        \
88530ca2051SWilly Tarreau 		"svc #0\n"                                                    \
88630ca2051SWilly Tarreau 		: "=r"(_arg1)                                                 \
88730ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
88830ca2051SWilly Tarreau 		  "r"(_num)                                                   \
88930ca2051SWilly Tarreau 		: "memory", "cc"                                              \
89030ca2051SWilly Tarreau 	);                                                                    \
89130ca2051SWilly Tarreau 	_arg1;                                                                \
89230ca2051SWilly Tarreau })
89330ca2051SWilly Tarreau 
89430ca2051SWilly Tarreau #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
89530ca2051SWilly Tarreau ({                                                                            \
89630ca2051SWilly Tarreau 	register long _num  asm("x8") = (num);                                \
89730ca2051SWilly Tarreau 	register long _arg1 asm("x0") = (long)(arg1);                         \
89830ca2051SWilly Tarreau 	register long _arg2 asm("x1") = (long)(arg2);                         \
89930ca2051SWilly Tarreau 	register long _arg3 asm("x2") = (long)(arg3);                         \
90030ca2051SWilly Tarreau 	register long _arg4 asm("x3") = (long)(arg4);                         \
90130ca2051SWilly Tarreau 									      \
90230ca2051SWilly Tarreau 	asm volatile (                                                        \
90330ca2051SWilly Tarreau 		"svc #0\n"                                                    \
90430ca2051SWilly Tarreau 		: "=r"(_arg1)                                                 \
90530ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
90630ca2051SWilly Tarreau 		  "r"(_num)                                                   \
90730ca2051SWilly Tarreau 		: "memory", "cc"                                              \
90830ca2051SWilly Tarreau 	);                                                                    \
90930ca2051SWilly Tarreau 	_arg1;                                                                \
91030ca2051SWilly Tarreau })
91130ca2051SWilly Tarreau 
91230ca2051SWilly Tarreau #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
91330ca2051SWilly Tarreau ({                                                                            \
91430ca2051SWilly Tarreau 	register long _num  asm("x8") = (num);                                \
91530ca2051SWilly Tarreau 	register long _arg1 asm("x0") = (long)(arg1);                         \
91630ca2051SWilly Tarreau 	register long _arg2 asm("x1") = (long)(arg2);                         \
91730ca2051SWilly Tarreau 	register long _arg3 asm("x2") = (long)(arg3);                         \
91830ca2051SWilly Tarreau 	register long _arg4 asm("x3") = (long)(arg4);                         \
91930ca2051SWilly Tarreau 	register long _arg5 asm("x4") = (long)(arg5);                         \
92030ca2051SWilly Tarreau 									      \
92130ca2051SWilly Tarreau 	asm volatile (                                                        \
92230ca2051SWilly Tarreau 		"svc #0\n"                                                    \
92330ca2051SWilly Tarreau 		: "=r" (_arg1)                                                \
92430ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
92530ca2051SWilly Tarreau 		  "r"(_num)                                                   \
92630ca2051SWilly Tarreau 		: "memory", "cc"                                              \
92730ca2051SWilly Tarreau 	);                                                                    \
92830ca2051SWilly Tarreau 	_arg1;                                                                \
92930ca2051SWilly Tarreau })
93030ca2051SWilly Tarreau 
93130ca2051SWilly Tarreau #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
93230ca2051SWilly Tarreau ({                                                                            \
93330ca2051SWilly Tarreau 	register long _num  asm("x8") = (num);                                \
93430ca2051SWilly Tarreau 	register long _arg1 asm("x0") = (long)(arg1);                         \
93530ca2051SWilly Tarreau 	register long _arg2 asm("x1") = (long)(arg2);                         \
93630ca2051SWilly Tarreau 	register long _arg3 asm("x2") = (long)(arg3);                         \
93730ca2051SWilly Tarreau 	register long _arg4 asm("x3") = (long)(arg4);                         \
93830ca2051SWilly Tarreau 	register long _arg5 asm("x4") = (long)(arg5);                         \
93930ca2051SWilly Tarreau 	register long _arg6 asm("x5") = (long)(arg6);                         \
94030ca2051SWilly Tarreau 									      \
94130ca2051SWilly Tarreau 	asm volatile (                                                        \
94230ca2051SWilly Tarreau 		"svc #0\n"                                                    \
94330ca2051SWilly Tarreau 		: "=r" (_arg1)                                                \
94430ca2051SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
94530ca2051SWilly Tarreau 		  "r"(_arg6), "r"(_num)                                       \
94630ca2051SWilly Tarreau 		: "memory", "cc"                                              \
94730ca2051SWilly Tarreau 	);                                                                    \
94830ca2051SWilly Tarreau 	_arg1;                                                                \
94930ca2051SWilly Tarreau })
95030ca2051SWilly Tarreau 
95130ca2051SWilly Tarreau /* startup code */
95230ca2051SWilly Tarreau asm(".section .text\n"
95330ca2051SWilly Tarreau     ".global _start\n"
95430ca2051SWilly Tarreau     "_start:\n"
95530ca2051SWilly Tarreau     "ldr x0, [sp]\n"              // argc (x0) was in the stack
95630ca2051SWilly Tarreau     "add x1, sp, 8\n"             // argv (x1) = sp
95730ca2051SWilly Tarreau     "lsl x2, x0, 3\n"             // envp (x2) = 8*argc ...
95830ca2051SWilly Tarreau     "add x2, x2, 8\n"             //           + 8 (skip null)
95930ca2051SWilly Tarreau     "add x2, x2, x1\n"            //           + argv
96030ca2051SWilly Tarreau     "and sp, x1, -16\n"           // sp must be 16-byte aligned in the callee
96130ca2051SWilly Tarreau     "bl main\n"                   // main() returns the status code, we'll exit with it.
96230ca2051SWilly Tarreau     "mov x8, 93\n"                // NR_exit == 93
96330ca2051SWilly Tarreau     "svc #0\n"
96430ca2051SWilly Tarreau     "");
96530ca2051SWilly Tarreau 
96630ca2051SWilly Tarreau /* fcntl / open */
96730ca2051SWilly Tarreau #define O_RDONLY            0
96830ca2051SWilly Tarreau #define O_WRONLY            1
96930ca2051SWilly Tarreau #define O_RDWR              2
97030ca2051SWilly Tarreau #define O_CREAT          0x40
97130ca2051SWilly Tarreau #define O_EXCL           0x80
97230ca2051SWilly Tarreau #define O_NOCTTY        0x100
97330ca2051SWilly Tarreau #define O_TRUNC         0x200
97430ca2051SWilly Tarreau #define O_APPEND        0x400
97530ca2051SWilly Tarreau #define O_NONBLOCK      0x800
97630ca2051SWilly Tarreau #define O_DIRECTORY    0x4000
97730ca2051SWilly Tarreau 
97830ca2051SWilly Tarreau /* The struct returned by the newfstatat() syscall. Differs slightly from the
97930ca2051SWilly Tarreau  * x86_64's stat one by field ordering, so be careful.
98030ca2051SWilly Tarreau  */
98130ca2051SWilly Tarreau struct sys_stat_struct {
98230ca2051SWilly Tarreau 	unsigned long   st_dev;
98330ca2051SWilly Tarreau 	unsigned long   st_ino;
98430ca2051SWilly Tarreau 	unsigned int    st_mode;
98530ca2051SWilly Tarreau 	unsigned int    st_nlink;
98630ca2051SWilly Tarreau 	unsigned int    st_uid;
98730ca2051SWilly Tarreau 	unsigned int    st_gid;
98830ca2051SWilly Tarreau 
98930ca2051SWilly Tarreau 	unsigned long   st_rdev;
99030ca2051SWilly Tarreau 	unsigned long   __pad1;
99130ca2051SWilly Tarreau 	long            st_size;
99230ca2051SWilly Tarreau 	int             st_blksize;
99330ca2051SWilly Tarreau 	int             __pad2;
99430ca2051SWilly Tarreau 
99530ca2051SWilly Tarreau 	long            st_blocks;
99630ca2051SWilly Tarreau 	long            st_atime;
99730ca2051SWilly Tarreau 	unsigned long   st_atime_nsec;
99830ca2051SWilly Tarreau 	long            st_mtime;
99930ca2051SWilly Tarreau 
100030ca2051SWilly Tarreau 	unsigned long   st_mtime_nsec;
100130ca2051SWilly Tarreau 	long            st_ctime;
100230ca2051SWilly Tarreau 	unsigned long   st_ctime_nsec;
100330ca2051SWilly Tarreau 	unsigned int    __unused[2];
100430ca2051SWilly Tarreau };
100530ca2051SWilly Tarreau 
100630ca2051SWilly Tarreau #elif defined(__mips__) && defined(_ABIO32)
100730ca2051SWilly Tarreau /* Syscalls for MIPS ABI O32 :
100830ca2051SWilly Tarreau  *   - WARNING! there's always a delayed slot!
100930ca2051SWilly Tarreau  *   - WARNING again, the syntax is different, registers take a '$' and numbers
101030ca2051SWilly Tarreau  *     do not.
101130ca2051SWilly Tarreau  *   - registers are 32-bit
101230ca2051SWilly Tarreau  *   - stack is 8-byte aligned
101330ca2051SWilly Tarreau  *   - syscall number is passed in v0 (starts at 0xfa0).
101430ca2051SWilly Tarreau  *   - arguments are in a0, a1, a2, a3, then the stack. The caller needs to
101530ca2051SWilly Tarreau  *     leave some room in the stack for the callee to save a0..a3 if needed.
101630ca2051SWilly Tarreau  *   - Many registers are clobbered, in fact only a0..a2 and s0..s8 are
101730ca2051SWilly Tarreau  *     preserved. See: https://www.linux-mips.org/wiki/Syscall as well as
101830ca2051SWilly Tarreau  *     scall32-o32.S in the kernel sources.
101930ca2051SWilly Tarreau  *   - the system call is performed by calling "syscall"
102030ca2051SWilly Tarreau  *   - syscall return comes in v0, and register a3 needs to be checked to know
10219a83f9aeSBhaskar Chowdhury  *     if an error occurred, in which case errno is in v0.
102230ca2051SWilly Tarreau  *   - the arguments are cast to long and assigned into the target registers
102330ca2051SWilly Tarreau  *     which are then simply passed as registers to the asm code, so that we
102430ca2051SWilly Tarreau  *     don't have to experience issues with register constraints.
102530ca2051SWilly Tarreau  */
102630ca2051SWilly Tarreau 
102730ca2051SWilly Tarreau #define my_syscall0(num)                                                      \
102830ca2051SWilly Tarreau ({                                                                            \
102930ca2051SWilly Tarreau 	register long _num asm("v0") = (num);                                 \
103030ca2051SWilly Tarreau 	register long _arg4 asm("a3");                                        \
103130ca2051SWilly Tarreau 									      \
103230ca2051SWilly Tarreau 	asm volatile (                                                        \
103330ca2051SWilly Tarreau 		"addiu $sp, $sp, -32\n"                                       \
103430ca2051SWilly Tarreau 		"syscall\n"                                                   \
103530ca2051SWilly Tarreau 		"addiu $sp, $sp, 32\n"                                        \
103630ca2051SWilly Tarreau 		: "=r"(_num), "=r"(_arg4)                                     \
103730ca2051SWilly Tarreau 		: "r"(_num)                                                   \
103830ca2051SWilly Tarreau 		: "memory", "cc", "at", "v1", "hi", "lo",                     \
103930ca2051SWilly Tarreau 		  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
104030ca2051SWilly Tarreau 	);                                                                    \
104130ca2051SWilly Tarreau 	_arg4 ? -_num : _num;                                                 \
104230ca2051SWilly Tarreau })
104330ca2051SWilly Tarreau 
104430ca2051SWilly Tarreau #define my_syscall1(num, arg1)                                                \
104530ca2051SWilly Tarreau ({                                                                            \
104630ca2051SWilly Tarreau 	register long _num asm("v0") = (num);                                 \
104730ca2051SWilly Tarreau 	register long _arg1 asm("a0") = (long)(arg1);                         \
104830ca2051SWilly Tarreau 	register long _arg4 asm("a3");                                        \
104930ca2051SWilly Tarreau 									      \
105030ca2051SWilly Tarreau 	asm volatile (                                                        \
105130ca2051SWilly Tarreau 		"addiu $sp, $sp, -32\n"                                       \
105230ca2051SWilly Tarreau 		"syscall\n"                                                   \
105330ca2051SWilly Tarreau 		"addiu $sp, $sp, 32\n"                                        \
105430ca2051SWilly Tarreau 		: "=r"(_num), "=r"(_arg4)                                     \
105530ca2051SWilly Tarreau 		: "0"(_num),                                                  \
105630ca2051SWilly Tarreau 		  "r"(_arg1)                                                  \
105730ca2051SWilly Tarreau 		: "memory", "cc", "at", "v1", "hi", "lo",                     \
105830ca2051SWilly Tarreau 		  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
105930ca2051SWilly Tarreau 	);                                                                    \
106030ca2051SWilly Tarreau 	_arg4 ? -_num : _num;                                                 \
106130ca2051SWilly Tarreau })
106230ca2051SWilly Tarreau 
106330ca2051SWilly Tarreau #define my_syscall2(num, arg1, arg2)                                          \
106430ca2051SWilly Tarreau ({                                                                            \
106530ca2051SWilly Tarreau 	register long _num asm("v0") = (num);                                 \
106630ca2051SWilly Tarreau 	register long _arg1 asm("a0") = (long)(arg1);                         \
106730ca2051SWilly Tarreau 	register long _arg2 asm("a1") = (long)(arg2);                         \
106830ca2051SWilly Tarreau 	register long _arg4 asm("a3");                                        \
106930ca2051SWilly Tarreau 									      \
107030ca2051SWilly Tarreau 	asm volatile (                                                        \
107130ca2051SWilly Tarreau 		"addiu $sp, $sp, -32\n"                                       \
107230ca2051SWilly Tarreau 		"syscall\n"                                                   \
107330ca2051SWilly Tarreau 		"addiu $sp, $sp, 32\n"                                        \
107430ca2051SWilly Tarreau 		: "=r"(_num), "=r"(_arg4)                                     \
107530ca2051SWilly Tarreau 		: "0"(_num),                                                  \
107630ca2051SWilly Tarreau 		  "r"(_arg1), "r"(_arg2)                                      \
107730ca2051SWilly Tarreau 		: "memory", "cc", "at", "v1", "hi", "lo",                     \
107830ca2051SWilly Tarreau 		  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
107930ca2051SWilly Tarreau 	);                                                                    \
108030ca2051SWilly Tarreau 	_arg4 ? -_num : _num;                                                 \
108130ca2051SWilly Tarreau })
108230ca2051SWilly Tarreau 
108330ca2051SWilly Tarreau #define my_syscall3(num, arg1, arg2, arg3)                                    \
108430ca2051SWilly Tarreau ({                                                                            \
108530ca2051SWilly Tarreau 	register long _num asm("v0")  = (num);                                \
108630ca2051SWilly Tarreau 	register long _arg1 asm("a0") = (long)(arg1);                         \
108730ca2051SWilly Tarreau 	register long _arg2 asm("a1") = (long)(arg2);                         \
108830ca2051SWilly Tarreau 	register long _arg3 asm("a2") = (long)(arg3);                         \
108930ca2051SWilly Tarreau 	register long _arg4 asm("a3");                                        \
109030ca2051SWilly Tarreau 									      \
109130ca2051SWilly Tarreau 	asm volatile (                                                        \
109230ca2051SWilly Tarreau 		"addiu $sp, $sp, -32\n"                                       \
109330ca2051SWilly Tarreau 		"syscall\n"                                                   \
109430ca2051SWilly Tarreau 		"addiu $sp, $sp, 32\n"                                        \
109530ca2051SWilly Tarreau 		: "=r"(_num), "=r"(_arg4)                                     \
109630ca2051SWilly Tarreau 		: "0"(_num),                                                  \
109730ca2051SWilly Tarreau 		  "r"(_arg1), "r"(_arg2), "r"(_arg3)                          \
109830ca2051SWilly Tarreau 		: "memory", "cc", "at", "v1", "hi", "lo",                     \
109930ca2051SWilly Tarreau 		  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
110030ca2051SWilly Tarreau 	);                                                                    \
110130ca2051SWilly Tarreau 	_arg4 ? -_num : _num;                                                 \
110230ca2051SWilly Tarreau })
110330ca2051SWilly Tarreau 
110430ca2051SWilly Tarreau #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
110530ca2051SWilly Tarreau ({                                                                            \
110630ca2051SWilly Tarreau 	register long _num asm("v0") = (num);                                 \
110730ca2051SWilly Tarreau 	register long _arg1 asm("a0") = (long)(arg1);                         \
110830ca2051SWilly Tarreau 	register long _arg2 asm("a1") = (long)(arg2);                         \
110930ca2051SWilly Tarreau 	register long _arg3 asm("a2") = (long)(arg3);                         \
111030ca2051SWilly Tarreau 	register long _arg4 asm("a3") = (long)(arg4);                         \
111130ca2051SWilly Tarreau 									      \
111230ca2051SWilly Tarreau 	asm volatile (                                                        \
111330ca2051SWilly Tarreau 		"addiu $sp, $sp, -32\n"                                       \
111430ca2051SWilly Tarreau 		"syscall\n"                                                   \
111530ca2051SWilly Tarreau 		"addiu $sp, $sp, 32\n"                                        \
111630ca2051SWilly Tarreau 		: "=r" (_num), "=r"(_arg4)                                    \
111730ca2051SWilly Tarreau 		: "0"(_num),                                                  \
111830ca2051SWilly Tarreau 		  "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4)              \
111930ca2051SWilly Tarreau 		: "memory", "cc", "at", "v1", "hi", "lo",                     \
112030ca2051SWilly Tarreau 		  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
112130ca2051SWilly Tarreau 	);                                                                    \
112230ca2051SWilly Tarreau 	_arg4 ? -_num : _num;                                                 \
112330ca2051SWilly Tarreau })
112430ca2051SWilly Tarreau 
112530ca2051SWilly Tarreau #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
112630ca2051SWilly Tarreau ({                                                                            \
112730ca2051SWilly Tarreau 	register long _num asm("v0") = (num);                                 \
112830ca2051SWilly Tarreau 	register long _arg1 asm("a0") = (long)(arg1);                         \
112930ca2051SWilly Tarreau 	register long _arg2 asm("a1") = (long)(arg2);                         \
113030ca2051SWilly Tarreau 	register long _arg3 asm("a2") = (long)(arg3);                         \
113130ca2051SWilly Tarreau 	register long _arg4 asm("a3") = (long)(arg4);                         \
113230ca2051SWilly Tarreau 	register long _arg5 = (long)(arg5);				      \
113330ca2051SWilly Tarreau 									      \
113430ca2051SWilly Tarreau 	asm volatile (                                                        \
113530ca2051SWilly Tarreau 		"addiu $sp, $sp, -32\n"                                       \
113630ca2051SWilly Tarreau 		"sw %7, 16($sp)\n"                                            \
113730ca2051SWilly Tarreau 		"syscall\n  "                                                 \
113830ca2051SWilly Tarreau 		"addiu $sp, $sp, 32\n"                                        \
113930ca2051SWilly Tarreau 		: "=r" (_num), "=r"(_arg4)                                    \
114030ca2051SWilly Tarreau 		: "0"(_num),                                                  \
114130ca2051SWilly Tarreau 		  "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5)  \
114230ca2051SWilly Tarreau 		: "memory", "cc", "at", "v1", "hi", "lo",                     \
114330ca2051SWilly Tarreau 		  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"  \
114430ca2051SWilly Tarreau 	);                                                                    \
114530ca2051SWilly Tarreau 	_arg4 ? -_num : _num;                                                 \
114630ca2051SWilly Tarreau })
114730ca2051SWilly Tarreau 
114830ca2051SWilly Tarreau /* startup code, note that it's called __start on MIPS */
114930ca2051SWilly Tarreau asm(".section .text\n"
115030ca2051SWilly Tarreau     ".set nomips16\n"
115130ca2051SWilly Tarreau     ".global __start\n"
115230ca2051SWilly Tarreau     ".set    noreorder\n"
115330ca2051SWilly Tarreau     ".option pic0\n"
115430ca2051SWilly Tarreau     ".ent __start\n"
115530ca2051SWilly Tarreau     "__start:\n"
115630ca2051SWilly Tarreau     "lw $a0,($sp)\n"              // argc was in the stack
115730ca2051SWilly Tarreau     "addiu  $a1, $sp, 4\n"        // argv = sp + 4
115830ca2051SWilly Tarreau     "sll $a2, $a0, 2\n"           // a2 = argc * 4
115930ca2051SWilly Tarreau     "add   $a2, $a2, $a1\n"       // envp = argv + 4*argc ...
116030ca2051SWilly Tarreau     "addiu $a2, $a2, 4\n"         //        ... + 4
116130ca2051SWilly Tarreau     "li $t0, -8\n"
116230ca2051SWilly Tarreau     "and $sp, $sp, $t0\n"         // sp must be 8-byte aligned
116330ca2051SWilly Tarreau     "addiu $sp,$sp,-16\n"         // the callee expects to save a0..a3 there!
116430ca2051SWilly Tarreau     "jal main\n"                  // main() returns the status code, we'll exit with it.
116530ca2051SWilly Tarreau     "nop\n"                       // delayed slot
1166de0244aeSWilly Tarreau     "move $a0, $v0\n"             // retrieve 32-bit exit code from v0
116730ca2051SWilly Tarreau     "li $v0, 4001\n"              // NR_exit == 4001
116830ca2051SWilly Tarreau     "syscall\n"
116930ca2051SWilly Tarreau     ".end __start\n"
117030ca2051SWilly Tarreau     "");
117130ca2051SWilly Tarreau 
117230ca2051SWilly Tarreau /* fcntl / open */
117330ca2051SWilly Tarreau #define O_RDONLY            0
117430ca2051SWilly Tarreau #define O_WRONLY            1
117530ca2051SWilly Tarreau #define O_RDWR              2
117630ca2051SWilly Tarreau #define O_APPEND       0x0008
117730ca2051SWilly Tarreau #define O_NONBLOCK     0x0080
117830ca2051SWilly Tarreau #define O_CREAT        0x0100
117930ca2051SWilly Tarreau #define O_TRUNC        0x0200
118030ca2051SWilly Tarreau #define O_EXCL         0x0400
118130ca2051SWilly Tarreau #define O_NOCTTY       0x0800
118230ca2051SWilly Tarreau #define O_DIRECTORY   0x10000
118330ca2051SWilly Tarreau 
118430ca2051SWilly Tarreau /* The struct returned by the stat() syscall. 88 bytes are returned by the
118530ca2051SWilly Tarreau  * syscall.
118630ca2051SWilly Tarreau  */
118730ca2051SWilly Tarreau struct sys_stat_struct {
118830ca2051SWilly Tarreau 	unsigned int  st_dev;
118930ca2051SWilly Tarreau 	long          st_pad1[3];
119030ca2051SWilly Tarreau 	unsigned long st_ino;
119130ca2051SWilly Tarreau 	unsigned int  st_mode;
119230ca2051SWilly Tarreau 	unsigned int  st_nlink;
119330ca2051SWilly Tarreau 	unsigned int  st_uid;
119430ca2051SWilly Tarreau 	unsigned int  st_gid;
119530ca2051SWilly Tarreau 	unsigned int  st_rdev;
119630ca2051SWilly Tarreau 	long          st_pad2[2];
119730ca2051SWilly Tarreau 	long          st_size;
119830ca2051SWilly Tarreau 	long          st_pad3;
119930ca2051SWilly Tarreau 	long          st_atime;
120030ca2051SWilly Tarreau 	long          st_atime_nsec;
120130ca2051SWilly Tarreau 	long          st_mtime;
120230ca2051SWilly Tarreau 	long          st_mtime_nsec;
120330ca2051SWilly Tarreau 	long          st_ctime;
120430ca2051SWilly Tarreau 	long          st_ctime_nsec;
120530ca2051SWilly Tarreau 	long          st_blksize;
120630ca2051SWilly Tarreau 	long          st_blocks;
120730ca2051SWilly Tarreau 	long          st_pad4[14];
120830ca2051SWilly Tarreau };
120930ca2051SWilly Tarreau 
1210582e84f7SPranith Kumar #elif defined(__riscv)
1211582e84f7SPranith Kumar 
1212582e84f7SPranith Kumar #if   __riscv_xlen == 64
1213582e84f7SPranith Kumar #define PTRLOG "3"
1214582e84f7SPranith Kumar #define SZREG  "8"
1215582e84f7SPranith Kumar #elif __riscv_xlen == 32
1216582e84f7SPranith Kumar #define PTRLOG "2"
1217582e84f7SPranith Kumar #define SZREG  "4"
1218582e84f7SPranith Kumar #endif
1219582e84f7SPranith Kumar 
1220582e84f7SPranith Kumar /* Syscalls for RISCV :
1221582e84f7SPranith Kumar  *   - stack is 16-byte aligned
1222582e84f7SPranith Kumar  *   - syscall number is passed in a7
1223582e84f7SPranith Kumar  *   - arguments are in a0, a1, a2, a3, a4, a5
1224582e84f7SPranith Kumar  *   - the system call is performed by calling ecall
1225582e84f7SPranith Kumar  *   - syscall return comes in a0
1226582e84f7SPranith Kumar  *   - the arguments are cast to long and assigned into the target
1227582e84f7SPranith Kumar  *     registers which are then simply passed as registers to the asm code,
1228582e84f7SPranith Kumar  *     so that we don't have to experience issues with register constraints.
12299c2970fbSWilly Tarreau  *
12309c2970fbSWilly Tarreau  * On riscv, select() is not implemented so we have to use pselect6().
1231582e84f7SPranith Kumar  */
12329c2970fbSWilly Tarreau #define __ARCH_WANT_SYS_PSELECT6
1233582e84f7SPranith Kumar 
1234582e84f7SPranith Kumar #define my_syscall0(num)                                                      \
1235582e84f7SPranith Kumar ({                                                                            \
1236582e84f7SPranith Kumar 	register long _num  asm("a7") = (num);                                \
1237582e84f7SPranith Kumar 	register long _arg1 asm("a0");                                        \
1238582e84f7SPranith Kumar 									      \
1239582e84f7SPranith Kumar 	asm volatile (                                                        \
1240582e84f7SPranith Kumar 		"ecall\n\t"                                                   \
1241582e84f7SPranith Kumar 		: "=r"(_arg1)                                                 \
1242582e84f7SPranith Kumar 		: "r"(_num)                                                   \
1243582e84f7SPranith Kumar 		: "memory", "cc"                                              \
1244582e84f7SPranith Kumar 	);                                                                    \
1245582e84f7SPranith Kumar 	_arg1;                                                                \
1246582e84f7SPranith Kumar })
1247582e84f7SPranith Kumar 
1248582e84f7SPranith Kumar #define my_syscall1(num, arg1)                                                \
1249582e84f7SPranith Kumar ({                                                                            \
1250582e84f7SPranith Kumar 	register long _num  asm("a7") = (num);                                \
1251582e84f7SPranith Kumar 	register long _arg1 asm("a0") = (long)(arg1);		              \
1252582e84f7SPranith Kumar 									      \
1253582e84f7SPranith Kumar 	asm volatile (                                                        \
1254582e84f7SPranith Kumar 		"ecall\n"                                                     \
1255582e84f7SPranith Kumar 		: "+r"(_arg1)                                                 \
1256582e84f7SPranith Kumar 		: "r"(_num)                                                   \
1257582e84f7SPranith Kumar 		: "memory", "cc"                                              \
1258582e84f7SPranith Kumar 	);                                                                    \
1259582e84f7SPranith Kumar 	_arg1;                                                                \
1260582e84f7SPranith Kumar })
1261582e84f7SPranith Kumar 
1262582e84f7SPranith Kumar #define my_syscall2(num, arg1, arg2)                                          \
1263582e84f7SPranith Kumar ({                                                                            \
1264582e84f7SPranith Kumar 	register long _num  asm("a7") = (num);                                \
1265582e84f7SPranith Kumar 	register long _arg1 asm("a0") = (long)(arg1);                         \
1266582e84f7SPranith Kumar 	register long _arg2 asm("a1") = (long)(arg2);                         \
1267582e84f7SPranith Kumar 									      \
1268582e84f7SPranith Kumar 	asm volatile (                                                        \
1269582e84f7SPranith Kumar 		"ecall\n"                                                     \
1270582e84f7SPranith Kumar 		: "+r"(_arg1)                                                 \
1271582e84f7SPranith Kumar 		: "r"(_arg2),                                                 \
1272582e84f7SPranith Kumar 		  "r"(_num)                                                   \
1273582e84f7SPranith Kumar 		: "memory", "cc"                                              \
1274582e84f7SPranith Kumar 	);                                                                    \
1275582e84f7SPranith Kumar 	_arg1;                                                                \
1276582e84f7SPranith Kumar })
1277582e84f7SPranith Kumar 
1278582e84f7SPranith Kumar #define my_syscall3(num, arg1, arg2, arg3)                                    \
1279582e84f7SPranith Kumar ({                                                                            \
1280582e84f7SPranith Kumar 	register long _num  asm("a7") = (num);                                \
1281582e84f7SPranith Kumar 	register long _arg1 asm("a0") = (long)(arg1);                         \
1282582e84f7SPranith Kumar 	register long _arg2 asm("a1") = (long)(arg2);                         \
1283582e84f7SPranith Kumar 	register long _arg3 asm("a2") = (long)(arg3);                         \
1284582e84f7SPranith Kumar 									      \
1285582e84f7SPranith Kumar 	asm volatile (                                                        \
1286582e84f7SPranith Kumar 		"ecall\n\t"                                                   \
1287582e84f7SPranith Kumar 		: "+r"(_arg1)                                                 \
1288582e84f7SPranith Kumar 		: "r"(_arg2), "r"(_arg3),                                     \
1289582e84f7SPranith Kumar 		  "r"(_num)                                                   \
1290582e84f7SPranith Kumar 		: "memory", "cc"                                              \
1291582e84f7SPranith Kumar 	);                                                                    \
1292582e84f7SPranith Kumar 	_arg1;                                                                \
1293582e84f7SPranith Kumar })
1294582e84f7SPranith Kumar 
1295582e84f7SPranith Kumar #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
1296582e84f7SPranith Kumar ({                                                                            \
1297582e84f7SPranith Kumar 	register long _num  asm("a7") = (num);                                \
1298582e84f7SPranith Kumar 	register long _arg1 asm("a0") = (long)(arg1);                         \
1299582e84f7SPranith Kumar 	register long _arg2 asm("a1") = (long)(arg2);                         \
1300582e84f7SPranith Kumar 	register long _arg3 asm("a2") = (long)(arg3);                         \
1301582e84f7SPranith Kumar 	register long _arg4 asm("a3") = (long)(arg4);                         \
1302582e84f7SPranith Kumar 									      \
1303582e84f7SPranith Kumar 	asm volatile (                                                        \
1304582e84f7SPranith Kumar 		"ecall\n"                                                     \
1305582e84f7SPranith Kumar 		: "+r"(_arg1)                                                 \
1306582e84f7SPranith Kumar 		: "r"(_arg2), "r"(_arg3), "r"(_arg4),                         \
1307582e84f7SPranith Kumar 		  "r"(_num)                                                   \
1308582e84f7SPranith Kumar 		: "memory", "cc"                                              \
1309582e84f7SPranith Kumar 	);                                                                    \
1310582e84f7SPranith Kumar 	_arg1;                                                                \
1311582e84f7SPranith Kumar })
1312582e84f7SPranith Kumar 
1313582e84f7SPranith Kumar #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
1314582e84f7SPranith Kumar ({                                                                            \
1315582e84f7SPranith Kumar 	register long _num  asm("a7") = (num);                                \
1316582e84f7SPranith Kumar 	register long _arg1 asm("a0") = (long)(arg1);                         \
1317582e84f7SPranith Kumar 	register long _arg2 asm("a1") = (long)(arg2);                         \
1318582e84f7SPranith Kumar 	register long _arg3 asm("a2") = (long)(arg3);                         \
1319582e84f7SPranith Kumar 	register long _arg4 asm("a3") = (long)(arg4);                         \
1320582e84f7SPranith Kumar 	register long _arg5 asm("a4") = (long)(arg5);                         \
1321582e84f7SPranith Kumar 									      \
1322582e84f7SPranith Kumar 	asm volatile (                                                        \
1323582e84f7SPranith Kumar 		"ecall\n"                                                     \
1324582e84f7SPranith Kumar 		: "+r"(_arg1)                                                 \
1325582e84f7SPranith Kumar 		: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5),             \
1326582e84f7SPranith Kumar 		  "r"(_num)                                                   \
1327582e84f7SPranith Kumar 		: "memory", "cc"                                              \
1328582e84f7SPranith Kumar 	);                                                                    \
1329582e84f7SPranith Kumar 	_arg1;                                                                \
1330582e84f7SPranith Kumar })
1331582e84f7SPranith Kumar 
1332582e84f7SPranith Kumar #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
1333582e84f7SPranith Kumar ({                                                                            \
1334582e84f7SPranith Kumar 	register long _num  asm("a7") = (num);                                \
1335582e84f7SPranith Kumar 	register long _arg1 asm("a0") = (long)(arg1);                         \
1336582e84f7SPranith Kumar 	register long _arg2 asm("a1") = (long)(arg2);                         \
1337582e84f7SPranith Kumar 	register long _arg3 asm("a2") = (long)(arg3);                         \
1338582e84f7SPranith Kumar 	register long _arg4 asm("a3") = (long)(arg4);                         \
1339582e84f7SPranith Kumar 	register long _arg5 asm("a4") = (long)(arg5);                         \
1340582e84f7SPranith Kumar 	register long _arg6 asm("a5") = (long)(arg6);                         \
1341582e84f7SPranith Kumar 									      \
1342582e84f7SPranith Kumar 	asm volatile (                                                        \
1343582e84f7SPranith Kumar 		"ecall\n"                                                     \
1344582e84f7SPranith Kumar 		: "+r"(_arg1)                                                 \
1345582e84f7SPranith Kumar 		: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
1346582e84f7SPranith Kumar 		  "r"(_num)                                                   \
1347582e84f7SPranith Kumar 		: "memory", "cc"                                              \
1348582e84f7SPranith Kumar 	);                                                                    \
1349582e84f7SPranith Kumar 	_arg1;                                                                \
1350582e84f7SPranith Kumar })
1351582e84f7SPranith Kumar 
1352582e84f7SPranith Kumar /* startup code */
1353582e84f7SPranith Kumar asm(".section .text\n"
1354582e84f7SPranith Kumar     ".global _start\n"
1355582e84f7SPranith Kumar     "_start:\n"
1356582e84f7SPranith Kumar     ".option push\n"
1357582e84f7SPranith Kumar     ".option norelax\n"
1358582e84f7SPranith Kumar     "lla   gp, __global_pointer$\n"
1359582e84f7SPranith Kumar     ".option pop\n"
1360582e84f7SPranith Kumar     "ld    a0, 0(sp)\n"          // argc (a0) was in the stack
1361582e84f7SPranith Kumar     "add   a1, sp, "SZREG"\n"    // argv (a1) = sp
1362582e84f7SPranith Kumar     "slli  a2, a0, "PTRLOG"\n"   // envp (a2) = SZREG*argc ...
1363582e84f7SPranith Kumar     "add   a2, a2, "SZREG"\n"    //             + SZREG (skip null)
1364582e84f7SPranith Kumar     "add   a2,a2,a1\n"           //             + argv
1365582e84f7SPranith Kumar     "andi  sp,a1,-16\n"          // sp must be 16-byte aligned
1366582e84f7SPranith Kumar     "call  main\n"               // main() returns the status code, we'll exit with it.
1367582e84f7SPranith Kumar     "li a7, 93\n"                // NR_exit == 93
1368582e84f7SPranith Kumar     "ecall\n"
1369582e84f7SPranith Kumar     "");
1370582e84f7SPranith Kumar 
1371582e84f7SPranith Kumar /* fcntl / open */
1372582e84f7SPranith Kumar #define O_RDONLY            0
1373582e84f7SPranith Kumar #define O_WRONLY            1
1374582e84f7SPranith Kumar #define O_RDWR              2
1375582e84f7SPranith Kumar #define O_CREAT         0x100
1376582e84f7SPranith Kumar #define O_EXCL          0x200
1377582e84f7SPranith Kumar #define O_NOCTTY        0x400
1378582e84f7SPranith Kumar #define O_TRUNC        0x1000
1379582e84f7SPranith Kumar #define O_APPEND       0x2000
1380582e84f7SPranith Kumar #define O_NONBLOCK     0x4000
1381582e84f7SPranith Kumar #define O_DIRECTORY  0x200000
1382582e84f7SPranith Kumar 
1383582e84f7SPranith Kumar struct sys_stat_struct {
1384582e84f7SPranith Kumar 	unsigned long	st_dev;		/* Device.  */
1385582e84f7SPranith Kumar 	unsigned long	st_ino;		/* File serial number.  */
1386582e84f7SPranith Kumar 	unsigned int	st_mode;	/* File mode.  */
1387582e84f7SPranith Kumar 	unsigned int	st_nlink;	/* Link count.  */
1388582e84f7SPranith Kumar 	unsigned int	st_uid;		/* User ID of the file's owner.  */
1389582e84f7SPranith Kumar 	unsigned int	st_gid;		/* Group ID of the file's group. */
1390582e84f7SPranith Kumar 	unsigned long	st_rdev;	/* Device number, if device.  */
1391582e84f7SPranith Kumar 	unsigned long	__pad1;
1392582e84f7SPranith Kumar 	long		st_size;	/* Size of file, in bytes.  */
1393582e84f7SPranith Kumar 	int		st_blksize;	/* Optimal block size for I/O.  */
1394582e84f7SPranith Kumar 	int		__pad2;
1395582e84f7SPranith Kumar 	long		st_blocks;	/* Number 512-byte blocks allocated. */
1396582e84f7SPranith Kumar 	long		st_atime;	/* Time of last access.  */
1397582e84f7SPranith Kumar 	unsigned long	st_atime_nsec;
1398582e84f7SPranith Kumar 	long		st_mtime;	/* Time of last modification.  */
1399582e84f7SPranith Kumar 	unsigned long	st_mtime_nsec;
1400582e84f7SPranith Kumar 	long		st_ctime;	/* Time of last status change.  */
1401582e84f7SPranith Kumar 	unsigned long	st_ctime_nsec;
1402582e84f7SPranith Kumar 	unsigned int	__unused4;
1403582e84f7SPranith Kumar 	unsigned int	__unused5;
1404582e84f7SPranith Kumar };
1405582e84f7SPranith Kumar 
140630ca2051SWilly Tarreau #endif
140730ca2051SWilly Tarreau 
140830ca2051SWilly Tarreau 
140930ca2051SWilly Tarreau /* Below are the C functions used to declare the raw syscalls. They try to be
141030ca2051SWilly Tarreau  * architecture-agnostic, and return either a success or -errno. Declaring them
141130ca2051SWilly Tarreau  * static will lead to them being inlined in most cases, but it's still possible
141230ca2051SWilly Tarreau  * to reference them by a pointer if needed.
141330ca2051SWilly Tarreau  */
141430ca2051SWilly Tarreau static __attribute__((unused))
141530ca2051SWilly Tarreau void *sys_brk(void *addr)
141630ca2051SWilly Tarreau {
141730ca2051SWilly Tarreau 	return (void *)my_syscall1(__NR_brk, addr);
141830ca2051SWilly Tarreau }
141930ca2051SWilly Tarreau 
142030ca2051SWilly Tarreau static __attribute__((noreturn,unused))
142130ca2051SWilly Tarreau void sys_exit(int status)
142230ca2051SWilly Tarreau {
142330ca2051SWilly Tarreau 	my_syscall1(__NR_exit, status & 255);
142430ca2051SWilly Tarreau 	while(1); // shut the "noreturn" warnings.
142530ca2051SWilly Tarreau }
142630ca2051SWilly Tarreau 
142730ca2051SWilly Tarreau static __attribute__((unused))
142830ca2051SWilly Tarreau int sys_chdir(const char *path)
142930ca2051SWilly Tarreau {
143030ca2051SWilly Tarreau 	return my_syscall1(__NR_chdir, path);
143130ca2051SWilly Tarreau }
143230ca2051SWilly Tarreau 
143330ca2051SWilly Tarreau static __attribute__((unused))
143430ca2051SWilly Tarreau int sys_chmod(const char *path, mode_t mode)
143530ca2051SWilly Tarreau {
143630ca2051SWilly Tarreau #ifdef __NR_fchmodat
143730ca2051SWilly Tarreau 	return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0);
143835635d7fSWilly Tarreau #elif defined(__NR_chmod)
143930ca2051SWilly Tarreau 	return my_syscall2(__NR_chmod, path, mode);
144035635d7fSWilly Tarreau #else
144135635d7fSWilly Tarreau #error Neither __NR_fchmodat nor __NR_chmod defined, cannot implement sys_chmod()
144230ca2051SWilly Tarreau #endif
144330ca2051SWilly Tarreau }
144430ca2051SWilly Tarreau 
144530ca2051SWilly Tarreau static __attribute__((unused))
144630ca2051SWilly Tarreau int sys_chown(const char *path, uid_t owner, gid_t group)
144730ca2051SWilly Tarreau {
144830ca2051SWilly Tarreau #ifdef __NR_fchownat
144930ca2051SWilly Tarreau 	return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0);
145035635d7fSWilly Tarreau #elif defined(__NR_chown)
145130ca2051SWilly Tarreau 	return my_syscall3(__NR_chown, path, owner, group);
145235635d7fSWilly Tarreau #else
145335635d7fSWilly Tarreau #error Neither __NR_fchownat nor __NR_chown defined, cannot implement sys_chown()
145430ca2051SWilly Tarreau #endif
145530ca2051SWilly Tarreau }
145630ca2051SWilly Tarreau 
145730ca2051SWilly Tarreau static __attribute__((unused))
145830ca2051SWilly Tarreau int sys_chroot(const char *path)
145930ca2051SWilly Tarreau {
146030ca2051SWilly Tarreau 	return my_syscall1(__NR_chroot, path);
146130ca2051SWilly Tarreau }
146230ca2051SWilly Tarreau 
146330ca2051SWilly Tarreau static __attribute__((unused))
146430ca2051SWilly Tarreau int sys_close(int fd)
146530ca2051SWilly Tarreau {
146630ca2051SWilly Tarreau 	return my_syscall1(__NR_close, fd);
146730ca2051SWilly Tarreau }
146830ca2051SWilly Tarreau 
146930ca2051SWilly Tarreau static __attribute__((unused))
147030ca2051SWilly Tarreau int sys_dup(int fd)
147130ca2051SWilly Tarreau {
147230ca2051SWilly Tarreau 	return my_syscall1(__NR_dup, fd);
147330ca2051SWilly Tarreau }
147430ca2051SWilly Tarreau 
147579f220e5SWilly Tarreau #ifdef __NR_dup3
147679f220e5SWilly Tarreau static __attribute__((unused))
147779f220e5SWilly Tarreau int sys_dup3(int old, int new, int flags)
147879f220e5SWilly Tarreau {
147979f220e5SWilly Tarreau 	return my_syscall3(__NR_dup3, old, new, flags);
148079f220e5SWilly Tarreau }
148179f220e5SWilly Tarreau #endif
148279f220e5SWilly Tarreau 
148330ca2051SWilly Tarreau static __attribute__((unused))
148430ca2051SWilly Tarreau int sys_dup2(int old, int new)
148530ca2051SWilly Tarreau {
148679f220e5SWilly Tarreau #ifdef __NR_dup3
148779f220e5SWilly Tarreau 	return my_syscall3(__NR_dup3, old, new, 0);
148835635d7fSWilly Tarreau #elif defined(__NR_dup2)
148930ca2051SWilly Tarreau 	return my_syscall2(__NR_dup2, old, new);
149035635d7fSWilly Tarreau #else
149135635d7fSWilly Tarreau #error Neither __NR_dup3 nor __NR_dup2 defined, cannot implement sys_dup2()
149279f220e5SWilly Tarreau #endif
149330ca2051SWilly Tarreau }
149430ca2051SWilly Tarreau 
149530ca2051SWilly Tarreau static __attribute__((unused))
149630ca2051SWilly Tarreau int sys_execve(const char *filename, char *const argv[], char *const envp[])
149730ca2051SWilly Tarreau {
149830ca2051SWilly Tarreau 	return my_syscall3(__NR_execve, filename, argv, envp);
149930ca2051SWilly Tarreau }
150030ca2051SWilly Tarreau 
150130ca2051SWilly Tarreau static __attribute__((unused))
150230ca2051SWilly Tarreau pid_t sys_fork(void)
150330ca2051SWilly Tarreau {
1504be60ca41SWilly Tarreau #ifdef __NR_clone
1505be60ca41SWilly Tarreau 	/* note: some archs only have clone() and not fork(). Different archs
1506be60ca41SWilly Tarreau 	 * have a different API, but most archs have the flags on first arg and
1507be60ca41SWilly Tarreau 	 * will not use the rest with no other flag.
1508be60ca41SWilly Tarreau 	 */
1509be60ca41SWilly Tarreau 	return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0);
151035635d7fSWilly Tarreau #elif defined(__NR_fork)
151130ca2051SWilly Tarreau 	return my_syscall0(__NR_fork);
151235635d7fSWilly Tarreau #else
151335635d7fSWilly Tarreau #error Neither __NR_clone nor __NR_fork defined, cannot implement sys_fork()
1514be60ca41SWilly Tarreau #endif
151530ca2051SWilly Tarreau }
151630ca2051SWilly Tarreau 
151730ca2051SWilly Tarreau static __attribute__((unused))
151830ca2051SWilly Tarreau int sys_fsync(int fd)
151930ca2051SWilly Tarreau {
152030ca2051SWilly Tarreau 	return my_syscall1(__NR_fsync, fd);
152130ca2051SWilly Tarreau }
152230ca2051SWilly Tarreau 
152330ca2051SWilly Tarreau static __attribute__((unused))
152430ca2051SWilly Tarreau int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count)
152530ca2051SWilly Tarreau {
152630ca2051SWilly Tarreau 	return my_syscall3(__NR_getdents64, fd, dirp, count);
152730ca2051SWilly Tarreau }
152830ca2051SWilly Tarreau 
152930ca2051SWilly Tarreau static __attribute__((unused))
1530c0c7c103SWilly Tarreau pid_t sys_getpgid(pid_t pid)
1531c0c7c103SWilly Tarreau {
1532c0c7c103SWilly Tarreau 	return my_syscall1(__NR_getpgid, pid);
1533c0c7c103SWilly Tarreau }
1534c0c7c103SWilly Tarreau 
1535c0c7c103SWilly Tarreau static __attribute__((unused))
153630ca2051SWilly Tarreau pid_t sys_getpgrp(void)
153730ca2051SWilly Tarreau {
1538c0c7c103SWilly Tarreau 	return sys_getpgid(0);
153930ca2051SWilly Tarreau }
154030ca2051SWilly Tarreau 
154130ca2051SWilly Tarreau static __attribute__((unused))
154230ca2051SWilly Tarreau pid_t sys_getpid(void)
154330ca2051SWilly Tarreau {
154430ca2051SWilly Tarreau 	return my_syscall0(__NR_getpid);
154530ca2051SWilly Tarreau }
154630ca2051SWilly Tarreau 
154730ca2051SWilly Tarreau static __attribute__((unused))
1548b0fe9decSMark Brown pid_t sys_gettid(void)
1549b0fe9decSMark Brown {
1550b0fe9decSMark Brown 	return my_syscall0(__NR_gettid);
1551b0fe9decSMark Brown }
1552b0fe9decSMark Brown 
1553b0fe9decSMark Brown static __attribute__((unused))
155430ca2051SWilly Tarreau int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
155530ca2051SWilly Tarreau {
155630ca2051SWilly Tarreau 	return my_syscall2(__NR_gettimeofday, tv, tz);
155730ca2051SWilly Tarreau }
155830ca2051SWilly Tarreau 
155930ca2051SWilly Tarreau static __attribute__((unused))
156030ca2051SWilly Tarreau int sys_ioctl(int fd, unsigned long req, void *value)
156130ca2051SWilly Tarreau {
156230ca2051SWilly Tarreau 	return my_syscall3(__NR_ioctl, fd, req, value);
156330ca2051SWilly Tarreau }
156430ca2051SWilly Tarreau 
156530ca2051SWilly Tarreau static __attribute__((unused))
156630ca2051SWilly Tarreau int sys_kill(pid_t pid, int signal)
156730ca2051SWilly Tarreau {
156830ca2051SWilly Tarreau 	return my_syscall2(__NR_kill, pid, signal);
156930ca2051SWilly Tarreau }
157030ca2051SWilly Tarreau 
157130ca2051SWilly Tarreau static __attribute__((unused))
157230ca2051SWilly Tarreau int sys_link(const char *old, const char *new)
157330ca2051SWilly Tarreau {
157430ca2051SWilly Tarreau #ifdef __NR_linkat
157530ca2051SWilly Tarreau 	return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0);
157635635d7fSWilly Tarreau #elif defined(__NR_link)
157730ca2051SWilly Tarreau 	return my_syscall2(__NR_link, old, new);
157835635d7fSWilly Tarreau #else
157935635d7fSWilly Tarreau #error Neither __NR_linkat nor __NR_link defined, cannot implement sys_link()
158030ca2051SWilly Tarreau #endif
158130ca2051SWilly Tarreau }
158230ca2051SWilly Tarreau 
158330ca2051SWilly Tarreau static __attribute__((unused))
158430ca2051SWilly Tarreau off_t sys_lseek(int fd, off_t offset, int whence)
158530ca2051SWilly Tarreau {
158630ca2051SWilly Tarreau 	return my_syscall3(__NR_lseek, fd, offset, whence);
158730ca2051SWilly Tarreau }
158830ca2051SWilly Tarreau 
158930ca2051SWilly Tarreau static __attribute__((unused))
159030ca2051SWilly Tarreau int sys_mkdir(const char *path, mode_t mode)
159130ca2051SWilly Tarreau {
159230ca2051SWilly Tarreau #ifdef __NR_mkdirat
159330ca2051SWilly Tarreau 	return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode);
159435635d7fSWilly Tarreau #elif defined(__NR_mkdir)
159530ca2051SWilly Tarreau 	return my_syscall2(__NR_mkdir, path, mode);
159635635d7fSWilly Tarreau #else
159735635d7fSWilly Tarreau #error Neither __NR_mkdirat nor __NR_mkdir defined, cannot implement sys_mkdir()
159830ca2051SWilly Tarreau #endif
159930ca2051SWilly Tarreau }
160030ca2051SWilly Tarreau 
160130ca2051SWilly Tarreau static __attribute__((unused))
160230ca2051SWilly Tarreau long sys_mknod(const char *path, mode_t mode, dev_t dev)
160330ca2051SWilly Tarreau {
160430ca2051SWilly Tarreau #ifdef __NR_mknodat
160530ca2051SWilly Tarreau 	return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev);
160635635d7fSWilly Tarreau #elif defined(__NR_mknod)
160730ca2051SWilly Tarreau 	return my_syscall3(__NR_mknod, path, mode, dev);
160835635d7fSWilly Tarreau #else
160935635d7fSWilly Tarreau #error Neither __NR_mknodat nor __NR_mknod defined, cannot implement sys_mknod()
161030ca2051SWilly Tarreau #endif
161130ca2051SWilly Tarreau }
161230ca2051SWilly Tarreau 
161330ca2051SWilly Tarreau static __attribute__((unused))
161430ca2051SWilly Tarreau int sys_mount(const char *src, const char *tgt, const char *fst,
161530ca2051SWilly Tarreau 	      unsigned long flags, const void *data)
161630ca2051SWilly Tarreau {
161730ca2051SWilly Tarreau 	return my_syscall5(__NR_mount, src, tgt, fst, flags, data);
161830ca2051SWilly Tarreau }
161930ca2051SWilly Tarreau 
162030ca2051SWilly Tarreau static __attribute__((unused))
162130ca2051SWilly Tarreau int sys_open(const char *path, int flags, mode_t mode)
162230ca2051SWilly Tarreau {
162330ca2051SWilly Tarreau #ifdef __NR_openat
162430ca2051SWilly Tarreau 	return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode);
162535635d7fSWilly Tarreau #elif defined(__NR_open)
162630ca2051SWilly Tarreau 	return my_syscall3(__NR_open, path, flags, mode);
162735635d7fSWilly Tarreau #else
162835635d7fSWilly Tarreau #error Neither __NR_openat nor __NR_open defined, cannot implement sys_open()
162930ca2051SWilly Tarreau #endif
163030ca2051SWilly Tarreau }
163130ca2051SWilly Tarreau 
163230ca2051SWilly Tarreau static __attribute__((unused))
163330ca2051SWilly Tarreau int sys_pivot_root(const char *new, const char *old)
163430ca2051SWilly Tarreau {
163530ca2051SWilly Tarreau 	return my_syscall2(__NR_pivot_root, new, old);
163630ca2051SWilly Tarreau }
163730ca2051SWilly Tarreau 
163830ca2051SWilly Tarreau static __attribute__((unused))
163930ca2051SWilly Tarreau int sys_poll(struct pollfd *fds, int nfds, int timeout)
164030ca2051SWilly Tarreau {
16415b1c827cSWilly Tarreau #if defined(__NR_ppoll)
16425b1c827cSWilly Tarreau 	struct timespec t;
16435b1c827cSWilly Tarreau 
16445b1c827cSWilly Tarreau 	if (timeout >= 0) {
16455b1c827cSWilly Tarreau 		t.tv_sec  = timeout / 1000;
16465b1c827cSWilly Tarreau 		t.tv_nsec = (timeout % 1000) * 1000000;
16475b1c827cSWilly Tarreau 	}
16485b1c827cSWilly Tarreau 	return my_syscall4(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL);
164935635d7fSWilly Tarreau #elif defined(__NR_poll)
165030ca2051SWilly Tarreau 	return my_syscall3(__NR_poll, fds, nfds, timeout);
165135635d7fSWilly Tarreau #else
165235635d7fSWilly Tarreau #error Neither __NR_ppoll nor __NR_poll defined, cannot implement sys_poll()
16535b1c827cSWilly Tarreau #endif
165430ca2051SWilly Tarreau }
165530ca2051SWilly Tarreau 
165630ca2051SWilly Tarreau static __attribute__((unused))
165730ca2051SWilly Tarreau ssize_t sys_read(int fd, void *buf, size_t count)
165830ca2051SWilly Tarreau {
165930ca2051SWilly Tarreau 	return my_syscall3(__NR_read, fd, buf, count);
166030ca2051SWilly Tarreau }
166130ca2051SWilly Tarreau 
166230ca2051SWilly Tarreau static __attribute__((unused))
166330ca2051SWilly Tarreau ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg)
166430ca2051SWilly Tarreau {
166530ca2051SWilly Tarreau 	return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg);
166630ca2051SWilly Tarreau }
166730ca2051SWilly Tarreau 
166830ca2051SWilly Tarreau static __attribute__((unused))
166930ca2051SWilly Tarreau int sys_sched_yield(void)
167030ca2051SWilly Tarreau {
167130ca2051SWilly Tarreau 	return my_syscall0(__NR_sched_yield);
167230ca2051SWilly Tarreau }
167330ca2051SWilly Tarreau 
167430ca2051SWilly Tarreau static __attribute__((unused))
167530ca2051SWilly Tarreau int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
167630ca2051SWilly Tarreau {
167730ca2051SWilly Tarreau #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect)
167830ca2051SWilly Tarreau 	struct sel_arg_struct {
167930ca2051SWilly Tarreau 		unsigned long n;
168030ca2051SWilly Tarreau 		fd_set *r, *w, *e;
168130ca2051SWilly Tarreau 		struct timeval *t;
168230ca2051SWilly Tarreau 	} arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout };
168330ca2051SWilly Tarreau 	return my_syscall1(__NR_select, &arg);
168430ca2051SWilly Tarreau #elif defined(__ARCH_WANT_SYS_PSELECT6) && defined(__NR_pselect6)
168530ca2051SWilly Tarreau 	struct timespec t;
168630ca2051SWilly Tarreau 
168730ca2051SWilly Tarreau 	if (timeout) {
168830ca2051SWilly Tarreau 		t.tv_sec  = timeout->tv_sec;
168930ca2051SWilly Tarreau 		t.tv_nsec = timeout->tv_usec * 1000;
169030ca2051SWilly Tarreau 	}
169130ca2051SWilly Tarreau 	return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
169235635d7fSWilly Tarreau #elif defined(__NR__newselect) || defined(__NR_select)
169330ca2051SWilly Tarreau #ifndef __NR__newselect
169430ca2051SWilly Tarreau #define __NR__newselect __NR_select
169530ca2051SWilly Tarreau #endif
169630ca2051SWilly Tarreau 	return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout);
169735635d7fSWilly Tarreau #else
169835635d7fSWilly Tarreau #error None of __NR_select, __NR_pselect6, nor __NR__newselect defined, cannot implement sys_select()
169930ca2051SWilly Tarreau #endif
170030ca2051SWilly Tarreau }
170130ca2051SWilly Tarreau 
170230ca2051SWilly Tarreau static __attribute__((unused))
170330ca2051SWilly Tarreau int sys_setpgid(pid_t pid, pid_t pgid)
170430ca2051SWilly Tarreau {
170530ca2051SWilly Tarreau 	return my_syscall2(__NR_setpgid, pid, pgid);
170630ca2051SWilly Tarreau }
170730ca2051SWilly Tarreau 
170830ca2051SWilly Tarreau static __attribute__((unused))
170930ca2051SWilly Tarreau pid_t sys_setsid(void)
171030ca2051SWilly Tarreau {
171130ca2051SWilly Tarreau 	return my_syscall0(__NR_setsid);
171230ca2051SWilly Tarreau }
171330ca2051SWilly Tarreau 
171430ca2051SWilly Tarreau static __attribute__((unused))
171530ca2051SWilly Tarreau int sys_stat(const char *path, struct stat *buf)
171630ca2051SWilly Tarreau {
171730ca2051SWilly Tarreau 	struct sys_stat_struct stat;
171830ca2051SWilly Tarreau 	long ret;
171930ca2051SWilly Tarreau 
172030ca2051SWilly Tarreau #ifdef __NR_newfstatat
172130ca2051SWilly Tarreau 	/* only solution for arm64 */
172230ca2051SWilly Tarreau 	ret = my_syscall4(__NR_newfstatat, AT_FDCWD, path, &stat, 0);
172335635d7fSWilly Tarreau #elif defined(__NR_stat)
172430ca2051SWilly Tarreau 	ret = my_syscall2(__NR_stat, path, &stat);
172535635d7fSWilly Tarreau #else
172635635d7fSWilly Tarreau #error Neither __NR_newfstatat nor __NR_stat defined, cannot implement sys_stat()
172730ca2051SWilly Tarreau #endif
172830ca2051SWilly Tarreau 	buf->st_dev     = stat.st_dev;
172930ca2051SWilly Tarreau 	buf->st_ino     = stat.st_ino;
173030ca2051SWilly Tarreau 	buf->st_mode    = stat.st_mode;
173130ca2051SWilly Tarreau 	buf->st_nlink   = stat.st_nlink;
173230ca2051SWilly Tarreau 	buf->st_uid     = stat.st_uid;
173330ca2051SWilly Tarreau 	buf->st_gid     = stat.st_gid;
173430ca2051SWilly Tarreau 	buf->st_rdev    = stat.st_rdev;
173530ca2051SWilly Tarreau 	buf->st_size    = stat.st_size;
173630ca2051SWilly Tarreau 	buf->st_blksize = stat.st_blksize;
173730ca2051SWilly Tarreau 	buf->st_blocks  = stat.st_blocks;
173830ca2051SWilly Tarreau 	buf->st_atime   = stat.st_atime;
173930ca2051SWilly Tarreau 	buf->st_mtime   = stat.st_mtime;
174030ca2051SWilly Tarreau 	buf->st_ctime   = stat.st_ctime;
174130ca2051SWilly Tarreau 	return ret;
174230ca2051SWilly Tarreau }
174330ca2051SWilly Tarreau 
174430ca2051SWilly Tarreau 
174530ca2051SWilly Tarreau static __attribute__((unused))
174630ca2051SWilly Tarreau int sys_symlink(const char *old, const char *new)
174730ca2051SWilly Tarreau {
174830ca2051SWilly Tarreau #ifdef __NR_symlinkat
174930ca2051SWilly Tarreau 	return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new);
175035635d7fSWilly Tarreau #elif defined(__NR_symlink)
175130ca2051SWilly Tarreau 	return my_syscall2(__NR_symlink, old, new);
175235635d7fSWilly Tarreau #else
175335635d7fSWilly Tarreau #error Neither __NR_symlinkat nor __NR_symlink defined, cannot implement sys_symlink()
175430ca2051SWilly Tarreau #endif
175530ca2051SWilly Tarreau }
175630ca2051SWilly Tarreau 
175730ca2051SWilly Tarreau static __attribute__((unused))
175830ca2051SWilly Tarreau mode_t sys_umask(mode_t mode)
175930ca2051SWilly Tarreau {
176030ca2051SWilly Tarreau 	return my_syscall1(__NR_umask, mode);
176130ca2051SWilly Tarreau }
176230ca2051SWilly Tarreau 
176330ca2051SWilly Tarreau static __attribute__((unused))
176430ca2051SWilly Tarreau int sys_umount2(const char *path, int flags)
176530ca2051SWilly Tarreau {
176630ca2051SWilly Tarreau 	return my_syscall2(__NR_umount2, path, flags);
176730ca2051SWilly Tarreau }
176830ca2051SWilly Tarreau 
176930ca2051SWilly Tarreau static __attribute__((unused))
177030ca2051SWilly Tarreau int sys_unlink(const char *path)
177130ca2051SWilly Tarreau {
177230ca2051SWilly Tarreau #ifdef __NR_unlinkat
177330ca2051SWilly Tarreau 	return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0);
177435635d7fSWilly Tarreau #elif defined(__NR_unlink)
177530ca2051SWilly Tarreau 	return my_syscall1(__NR_unlink, path);
177635635d7fSWilly Tarreau #else
177735635d7fSWilly Tarreau #error Neither __NR_unlinkat nor __NR_unlink defined, cannot implement sys_unlink()
177830ca2051SWilly Tarreau #endif
177930ca2051SWilly Tarreau }
178030ca2051SWilly Tarreau 
178130ca2051SWilly Tarreau static __attribute__((unused))
178230ca2051SWilly Tarreau pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
178330ca2051SWilly Tarreau {
178430ca2051SWilly Tarreau 	return my_syscall4(__NR_wait4, pid, status, options, rusage);
178530ca2051SWilly Tarreau }
178630ca2051SWilly Tarreau 
178730ca2051SWilly Tarreau static __attribute__((unused))
178830ca2051SWilly Tarreau pid_t sys_waitpid(pid_t pid, int *status, int options)
178930ca2051SWilly Tarreau {
179030ca2051SWilly Tarreau 	return sys_wait4(pid, status, options, 0);
179130ca2051SWilly Tarreau }
179230ca2051SWilly Tarreau 
179330ca2051SWilly Tarreau static __attribute__((unused))
179430ca2051SWilly Tarreau pid_t sys_wait(int *status)
179530ca2051SWilly Tarreau {
179630ca2051SWilly Tarreau 	return sys_waitpid(-1, status, 0);
179730ca2051SWilly Tarreau }
179830ca2051SWilly Tarreau 
179930ca2051SWilly Tarreau static __attribute__((unused))
180030ca2051SWilly Tarreau ssize_t sys_write(int fd, const void *buf, size_t count)
180130ca2051SWilly Tarreau {
180230ca2051SWilly Tarreau 	return my_syscall3(__NR_write, fd, buf, count);
180330ca2051SWilly Tarreau }
180430ca2051SWilly Tarreau 
180530ca2051SWilly Tarreau 
180630ca2051SWilly Tarreau /* Below are the libc-compatible syscalls which return x or -1 and set errno.
180730ca2051SWilly Tarreau  * They rely on the functions above. Similarly they're marked static so that it
180830ca2051SWilly Tarreau  * is possible to assign pointers to them if needed.
180930ca2051SWilly Tarreau  */
181030ca2051SWilly Tarreau 
181130ca2051SWilly Tarreau static __attribute__((unused))
181230ca2051SWilly Tarreau int brk(void *addr)
181330ca2051SWilly Tarreau {
181430ca2051SWilly Tarreau 	void *ret = sys_brk(addr);
181530ca2051SWilly Tarreau 
181630ca2051SWilly Tarreau 	if (!ret) {
181730ca2051SWilly Tarreau 		SET_ERRNO(ENOMEM);
181830ca2051SWilly Tarreau 		return -1;
181930ca2051SWilly Tarreau 	}
182030ca2051SWilly Tarreau 	return 0;
182130ca2051SWilly Tarreau }
182230ca2051SWilly Tarreau 
182330ca2051SWilly Tarreau static __attribute__((noreturn,unused))
182430ca2051SWilly Tarreau void exit(int status)
182530ca2051SWilly Tarreau {
182630ca2051SWilly Tarreau 	sys_exit(status);
182730ca2051SWilly Tarreau }
182830ca2051SWilly Tarreau 
182930ca2051SWilly Tarreau static __attribute__((unused))
183030ca2051SWilly Tarreau int chdir(const char *path)
183130ca2051SWilly Tarreau {
183230ca2051SWilly Tarreau 	int ret = sys_chdir(path);
183330ca2051SWilly Tarreau 
183430ca2051SWilly Tarreau 	if (ret < 0) {
183530ca2051SWilly Tarreau 		SET_ERRNO(-ret);
183630ca2051SWilly Tarreau 		ret = -1;
183730ca2051SWilly Tarreau 	}
183830ca2051SWilly Tarreau 	return ret;
183930ca2051SWilly Tarreau }
184030ca2051SWilly Tarreau 
184130ca2051SWilly Tarreau static __attribute__((unused))
184230ca2051SWilly Tarreau int chmod(const char *path, mode_t mode)
184330ca2051SWilly Tarreau {
184430ca2051SWilly Tarreau 	int ret = sys_chmod(path, mode);
184530ca2051SWilly Tarreau 
184630ca2051SWilly Tarreau 	if (ret < 0) {
184730ca2051SWilly Tarreau 		SET_ERRNO(-ret);
184830ca2051SWilly Tarreau 		ret = -1;
184930ca2051SWilly Tarreau 	}
185030ca2051SWilly Tarreau 	return ret;
185130ca2051SWilly Tarreau }
185230ca2051SWilly Tarreau 
185330ca2051SWilly Tarreau static __attribute__((unused))
185430ca2051SWilly Tarreau int chown(const char *path, uid_t owner, gid_t group)
185530ca2051SWilly Tarreau {
185630ca2051SWilly Tarreau 	int ret = sys_chown(path, owner, group);
185730ca2051SWilly Tarreau 
185830ca2051SWilly Tarreau 	if (ret < 0) {
185930ca2051SWilly Tarreau 		SET_ERRNO(-ret);
186030ca2051SWilly Tarreau 		ret = -1;
186130ca2051SWilly Tarreau 	}
186230ca2051SWilly Tarreau 	return ret;
186330ca2051SWilly Tarreau }
186430ca2051SWilly Tarreau 
186530ca2051SWilly Tarreau static __attribute__((unused))
186630ca2051SWilly Tarreau int chroot(const char *path)
186730ca2051SWilly Tarreau {
186830ca2051SWilly Tarreau 	int ret = sys_chroot(path);
186930ca2051SWilly Tarreau 
187030ca2051SWilly Tarreau 	if (ret < 0) {
187130ca2051SWilly Tarreau 		SET_ERRNO(-ret);
187230ca2051SWilly Tarreau 		ret = -1;
187330ca2051SWilly Tarreau 	}
187430ca2051SWilly Tarreau 	return ret;
187530ca2051SWilly Tarreau }
187630ca2051SWilly Tarreau 
187730ca2051SWilly Tarreau static __attribute__((unused))
187830ca2051SWilly Tarreau int close(int fd)
187930ca2051SWilly Tarreau {
188030ca2051SWilly Tarreau 	int ret = sys_close(fd);
188130ca2051SWilly Tarreau 
188230ca2051SWilly Tarreau 	if (ret < 0) {
188330ca2051SWilly Tarreau 		SET_ERRNO(-ret);
188430ca2051SWilly Tarreau 		ret = -1;
188530ca2051SWilly Tarreau 	}
188630ca2051SWilly Tarreau 	return ret;
188730ca2051SWilly Tarreau }
188830ca2051SWilly Tarreau 
188930ca2051SWilly Tarreau static __attribute__((unused))
1890c261145aSWilly Tarreau int dup(int fd)
1891c261145aSWilly Tarreau {
1892c261145aSWilly Tarreau 	int ret = sys_dup(fd);
1893c261145aSWilly Tarreau 
1894c261145aSWilly Tarreau 	if (ret < 0) {
1895c261145aSWilly Tarreau 		SET_ERRNO(-ret);
1896c261145aSWilly Tarreau 		ret = -1;
1897c261145aSWilly Tarreau 	}
1898c261145aSWilly Tarreau 	return ret;
1899c261145aSWilly Tarreau }
1900c261145aSWilly Tarreau 
1901c261145aSWilly Tarreau static __attribute__((unused))
190230ca2051SWilly Tarreau int dup2(int old, int new)
190330ca2051SWilly Tarreau {
190430ca2051SWilly Tarreau 	int ret = sys_dup2(old, new);
190530ca2051SWilly Tarreau 
190630ca2051SWilly Tarreau 	if (ret < 0) {
190730ca2051SWilly Tarreau 		SET_ERRNO(-ret);
190830ca2051SWilly Tarreau 		ret = -1;
190930ca2051SWilly Tarreau 	}
191030ca2051SWilly Tarreau 	return ret;
191130ca2051SWilly Tarreau }
191230ca2051SWilly Tarreau 
191379f220e5SWilly Tarreau #ifdef __NR_dup3
191479f220e5SWilly Tarreau static __attribute__((unused))
191579f220e5SWilly Tarreau int dup3(int old, int new, int flags)
191679f220e5SWilly Tarreau {
191779f220e5SWilly Tarreau 	int ret = sys_dup3(old, new, flags);
191879f220e5SWilly Tarreau 
191979f220e5SWilly Tarreau 	if (ret < 0) {
192079f220e5SWilly Tarreau 		SET_ERRNO(-ret);
192179f220e5SWilly Tarreau 		ret = -1;
192279f220e5SWilly Tarreau 	}
192379f220e5SWilly Tarreau 	return ret;
192479f220e5SWilly Tarreau }
192579f220e5SWilly Tarreau #endif
192679f220e5SWilly Tarreau 
192730ca2051SWilly Tarreau static __attribute__((unused))
192830ca2051SWilly Tarreau int execve(const char *filename, char *const argv[], char *const envp[])
192930ca2051SWilly Tarreau {
193030ca2051SWilly Tarreau 	int ret = sys_execve(filename, argv, envp);
193130ca2051SWilly Tarreau 
193230ca2051SWilly Tarreau 	if (ret < 0) {
193330ca2051SWilly Tarreau 		SET_ERRNO(-ret);
193430ca2051SWilly Tarreau 		ret = -1;
193530ca2051SWilly Tarreau 	}
193630ca2051SWilly Tarreau 	return ret;
193730ca2051SWilly Tarreau }
193830ca2051SWilly Tarreau 
193930ca2051SWilly Tarreau static __attribute__((unused))
194030ca2051SWilly Tarreau pid_t fork(void)
194130ca2051SWilly Tarreau {
194230ca2051SWilly Tarreau 	pid_t ret = sys_fork();
194330ca2051SWilly Tarreau 
194430ca2051SWilly Tarreau 	if (ret < 0) {
194530ca2051SWilly Tarreau 		SET_ERRNO(-ret);
194630ca2051SWilly Tarreau 		ret = -1;
194730ca2051SWilly Tarreau 	}
194830ca2051SWilly Tarreau 	return ret;
194930ca2051SWilly Tarreau }
195030ca2051SWilly Tarreau 
195130ca2051SWilly Tarreau static __attribute__((unused))
195230ca2051SWilly Tarreau int fsync(int fd)
195330ca2051SWilly Tarreau {
195430ca2051SWilly Tarreau 	int ret = sys_fsync(fd);
195530ca2051SWilly Tarreau 
195630ca2051SWilly Tarreau 	if (ret < 0) {
195730ca2051SWilly Tarreau 		SET_ERRNO(-ret);
195830ca2051SWilly Tarreau 		ret = -1;
195930ca2051SWilly Tarreau 	}
196030ca2051SWilly Tarreau 	return ret;
196130ca2051SWilly Tarreau }
196230ca2051SWilly Tarreau 
196330ca2051SWilly Tarreau static __attribute__((unused))
196430ca2051SWilly Tarreau int getdents64(int fd, struct linux_dirent64 *dirp, int count)
196530ca2051SWilly Tarreau {
196630ca2051SWilly Tarreau 	int ret = sys_getdents64(fd, dirp, count);
196730ca2051SWilly Tarreau 
196830ca2051SWilly Tarreau 	if (ret < 0) {
196930ca2051SWilly Tarreau 		SET_ERRNO(-ret);
197030ca2051SWilly Tarreau 		ret = -1;
197130ca2051SWilly Tarreau 	}
197230ca2051SWilly Tarreau 	return ret;
197330ca2051SWilly Tarreau }
197430ca2051SWilly Tarreau 
197530ca2051SWilly Tarreau static __attribute__((unused))
1976c0c7c103SWilly Tarreau pid_t getpgid(pid_t pid)
1977c0c7c103SWilly Tarreau {
1978c0c7c103SWilly Tarreau 	pid_t ret = sys_getpgid(pid);
1979c0c7c103SWilly Tarreau 
1980c0c7c103SWilly Tarreau 	if (ret < 0) {
1981c0c7c103SWilly Tarreau 		SET_ERRNO(-ret);
1982c0c7c103SWilly Tarreau 		ret = -1;
1983c0c7c103SWilly Tarreau 	}
1984c0c7c103SWilly Tarreau 	return ret;
1985c0c7c103SWilly Tarreau }
1986c0c7c103SWilly Tarreau 
1987c0c7c103SWilly Tarreau static __attribute__((unused))
198830ca2051SWilly Tarreau pid_t getpgrp(void)
198930ca2051SWilly Tarreau {
199030ca2051SWilly Tarreau 	pid_t ret = sys_getpgrp();
199130ca2051SWilly Tarreau 
199230ca2051SWilly Tarreau 	if (ret < 0) {
199330ca2051SWilly Tarreau 		SET_ERRNO(-ret);
199430ca2051SWilly Tarreau 		ret = -1;
199530ca2051SWilly Tarreau 	}
199630ca2051SWilly Tarreau 	return ret;
199730ca2051SWilly Tarreau }
199830ca2051SWilly Tarreau 
199930ca2051SWilly Tarreau static __attribute__((unused))
200030ca2051SWilly Tarreau pid_t getpid(void)
200130ca2051SWilly Tarreau {
200230ca2051SWilly Tarreau 	pid_t ret = sys_getpid();
200330ca2051SWilly Tarreau 
200430ca2051SWilly Tarreau 	if (ret < 0) {
200530ca2051SWilly Tarreau 		SET_ERRNO(-ret);
200630ca2051SWilly Tarreau 		ret = -1;
200730ca2051SWilly Tarreau 	}
200830ca2051SWilly Tarreau 	return ret;
200930ca2051SWilly Tarreau }
201030ca2051SWilly Tarreau 
201130ca2051SWilly Tarreau static __attribute__((unused))
2012b0fe9decSMark Brown pid_t gettid(void)
2013b0fe9decSMark Brown {
2014b0fe9decSMark Brown 	pid_t ret = sys_gettid();
2015b0fe9decSMark Brown 
2016b0fe9decSMark Brown 	if (ret < 0) {
2017b0fe9decSMark Brown 		SET_ERRNO(-ret);
2018b0fe9decSMark Brown 		ret = -1;
2019b0fe9decSMark Brown 	}
2020b0fe9decSMark Brown 	return ret;
2021b0fe9decSMark Brown }
2022b0fe9decSMark Brown 
2023b0fe9decSMark Brown static __attribute__((unused))
202430ca2051SWilly Tarreau int gettimeofday(struct timeval *tv, struct timezone *tz)
202530ca2051SWilly Tarreau {
202630ca2051SWilly Tarreau 	int ret = sys_gettimeofday(tv, tz);
202730ca2051SWilly Tarreau 
202830ca2051SWilly Tarreau 	if (ret < 0) {
202930ca2051SWilly Tarreau 		SET_ERRNO(-ret);
203030ca2051SWilly Tarreau 		ret = -1;
203130ca2051SWilly Tarreau 	}
203230ca2051SWilly Tarreau 	return ret;
203330ca2051SWilly Tarreau }
203430ca2051SWilly Tarreau 
203530ca2051SWilly Tarreau static __attribute__((unused))
203630ca2051SWilly Tarreau int ioctl(int fd, unsigned long req, void *value)
203730ca2051SWilly Tarreau {
203830ca2051SWilly Tarreau 	int ret = sys_ioctl(fd, req, value);
203930ca2051SWilly Tarreau 
204030ca2051SWilly Tarreau 	if (ret < 0) {
204130ca2051SWilly Tarreau 		SET_ERRNO(-ret);
204230ca2051SWilly Tarreau 		ret = -1;
204330ca2051SWilly Tarreau 	}
204430ca2051SWilly Tarreau 	return ret;
204530ca2051SWilly Tarreau }
204630ca2051SWilly Tarreau 
204730ca2051SWilly Tarreau static __attribute__((unused))
204830ca2051SWilly Tarreau int kill(pid_t pid, int signal)
204930ca2051SWilly Tarreau {
205030ca2051SWilly Tarreau 	int ret = sys_kill(pid, signal);
205130ca2051SWilly Tarreau 
205230ca2051SWilly Tarreau 	if (ret < 0) {
205330ca2051SWilly Tarreau 		SET_ERRNO(-ret);
205430ca2051SWilly Tarreau 		ret = -1;
205530ca2051SWilly Tarreau 	}
205630ca2051SWilly Tarreau 	return ret;
205730ca2051SWilly Tarreau }
205830ca2051SWilly Tarreau 
205930ca2051SWilly Tarreau static __attribute__((unused))
206030ca2051SWilly Tarreau int link(const char *old, const char *new)
206130ca2051SWilly Tarreau {
206230ca2051SWilly Tarreau 	int ret = sys_link(old, new);
206330ca2051SWilly Tarreau 
206430ca2051SWilly Tarreau 	if (ret < 0) {
206530ca2051SWilly Tarreau 		SET_ERRNO(-ret);
206630ca2051SWilly Tarreau 		ret = -1;
206730ca2051SWilly Tarreau 	}
206830ca2051SWilly Tarreau 	return ret;
206930ca2051SWilly Tarreau }
207030ca2051SWilly Tarreau 
207130ca2051SWilly Tarreau static __attribute__((unused))
207230ca2051SWilly Tarreau off_t lseek(int fd, off_t offset, int whence)
207330ca2051SWilly Tarreau {
207430ca2051SWilly Tarreau 	off_t ret = sys_lseek(fd, offset, whence);
207530ca2051SWilly Tarreau 
207630ca2051SWilly Tarreau 	if (ret < 0) {
207730ca2051SWilly Tarreau 		SET_ERRNO(-ret);
207830ca2051SWilly Tarreau 		ret = -1;
207930ca2051SWilly Tarreau 	}
208030ca2051SWilly Tarreau 	return ret;
208130ca2051SWilly Tarreau }
208230ca2051SWilly Tarreau 
208330ca2051SWilly Tarreau static __attribute__((unused))
208430ca2051SWilly Tarreau int mkdir(const char *path, mode_t mode)
208530ca2051SWilly Tarreau {
208630ca2051SWilly Tarreau 	int ret = sys_mkdir(path, mode);
208730ca2051SWilly Tarreau 
208830ca2051SWilly Tarreau 	if (ret < 0) {
208930ca2051SWilly Tarreau 		SET_ERRNO(-ret);
209030ca2051SWilly Tarreau 		ret = -1;
209130ca2051SWilly Tarreau 	}
209230ca2051SWilly Tarreau 	return ret;
209330ca2051SWilly Tarreau }
209430ca2051SWilly Tarreau 
209530ca2051SWilly Tarreau static __attribute__((unused))
209630ca2051SWilly Tarreau int mknod(const char *path, mode_t mode, dev_t dev)
209730ca2051SWilly Tarreau {
209830ca2051SWilly Tarreau 	int ret = sys_mknod(path, mode, dev);
209930ca2051SWilly Tarreau 
210030ca2051SWilly Tarreau 	if (ret < 0) {
210130ca2051SWilly Tarreau 		SET_ERRNO(-ret);
210230ca2051SWilly Tarreau 		ret = -1;
210330ca2051SWilly Tarreau 	}
210430ca2051SWilly Tarreau 	return ret;
210530ca2051SWilly Tarreau }
210630ca2051SWilly Tarreau 
210730ca2051SWilly Tarreau static __attribute__((unused))
210830ca2051SWilly Tarreau int mount(const char *src, const char *tgt,
210930ca2051SWilly Tarreau 	  const char *fst, unsigned long flags,
211030ca2051SWilly Tarreau 	  const void *data)
211130ca2051SWilly Tarreau {
211230ca2051SWilly Tarreau 	int ret = sys_mount(src, tgt, fst, flags, data);
211330ca2051SWilly Tarreau 
211430ca2051SWilly Tarreau 	if (ret < 0) {
211530ca2051SWilly Tarreau 		SET_ERRNO(-ret);
211630ca2051SWilly Tarreau 		ret = -1;
211730ca2051SWilly Tarreau 	}
211830ca2051SWilly Tarreau 	return ret;
211930ca2051SWilly Tarreau }
212030ca2051SWilly Tarreau 
212130ca2051SWilly Tarreau static __attribute__((unused))
212230ca2051SWilly Tarreau int open(const char *path, int flags, mode_t mode)
212330ca2051SWilly Tarreau {
212430ca2051SWilly Tarreau 	int ret = sys_open(path, flags, mode);
212530ca2051SWilly Tarreau 
212630ca2051SWilly Tarreau 	if (ret < 0) {
212730ca2051SWilly Tarreau 		SET_ERRNO(-ret);
212830ca2051SWilly Tarreau 		ret = -1;
212930ca2051SWilly Tarreau 	}
213030ca2051SWilly Tarreau 	return ret;
213130ca2051SWilly Tarreau }
213230ca2051SWilly Tarreau 
213330ca2051SWilly Tarreau static __attribute__((unused))
213430ca2051SWilly Tarreau int pivot_root(const char *new, const char *old)
213530ca2051SWilly Tarreau {
213630ca2051SWilly Tarreau 	int ret = sys_pivot_root(new, old);
213730ca2051SWilly Tarreau 
213830ca2051SWilly Tarreau 	if (ret < 0) {
213930ca2051SWilly Tarreau 		SET_ERRNO(-ret);
214030ca2051SWilly Tarreau 		ret = -1;
214130ca2051SWilly Tarreau 	}
214230ca2051SWilly Tarreau 	return ret;
214330ca2051SWilly Tarreau }
214430ca2051SWilly Tarreau 
214530ca2051SWilly Tarreau static __attribute__((unused))
214630ca2051SWilly Tarreau int poll(struct pollfd *fds, int nfds, int timeout)
214730ca2051SWilly Tarreau {
214830ca2051SWilly Tarreau 	int ret = sys_poll(fds, nfds, timeout);
214930ca2051SWilly Tarreau 
215030ca2051SWilly Tarreau 	if (ret < 0) {
215130ca2051SWilly Tarreau 		SET_ERRNO(-ret);
215230ca2051SWilly Tarreau 		ret = -1;
215330ca2051SWilly Tarreau 	}
215430ca2051SWilly Tarreau 	return ret;
215530ca2051SWilly Tarreau }
215630ca2051SWilly Tarreau 
215730ca2051SWilly Tarreau static __attribute__((unused))
215830ca2051SWilly Tarreau ssize_t read(int fd, void *buf, size_t count)
215930ca2051SWilly Tarreau {
216030ca2051SWilly Tarreau 	ssize_t ret = sys_read(fd, buf, count);
216130ca2051SWilly Tarreau 
216230ca2051SWilly Tarreau 	if (ret < 0) {
216330ca2051SWilly Tarreau 		SET_ERRNO(-ret);
216430ca2051SWilly Tarreau 		ret = -1;
216530ca2051SWilly Tarreau 	}
216630ca2051SWilly Tarreau 	return ret;
216730ca2051SWilly Tarreau }
216830ca2051SWilly Tarreau 
216930ca2051SWilly Tarreau static __attribute__((unused))
217030ca2051SWilly Tarreau int reboot(int cmd)
217130ca2051SWilly Tarreau {
217230ca2051SWilly Tarreau 	int ret = sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0);
217330ca2051SWilly Tarreau 
217430ca2051SWilly Tarreau 	if (ret < 0) {
217530ca2051SWilly Tarreau 		SET_ERRNO(-ret);
217630ca2051SWilly Tarreau 		ret = -1;
217730ca2051SWilly Tarreau 	}
217830ca2051SWilly Tarreau 	return ret;
217930ca2051SWilly Tarreau }
218030ca2051SWilly Tarreau 
218130ca2051SWilly Tarreau static __attribute__((unused))
218230ca2051SWilly Tarreau void *sbrk(intptr_t inc)
218330ca2051SWilly Tarreau {
218430ca2051SWilly Tarreau 	void *ret;
218530ca2051SWilly Tarreau 
218630ca2051SWilly Tarreau 	/* first call to find current end */
218730ca2051SWilly Tarreau 	if ((ret = sys_brk(0)) && (sys_brk(ret + inc) == ret + inc))
218830ca2051SWilly Tarreau 		return ret + inc;
218930ca2051SWilly Tarreau 
219030ca2051SWilly Tarreau 	SET_ERRNO(ENOMEM);
219130ca2051SWilly Tarreau 	return (void *)-1;
219230ca2051SWilly Tarreau }
219330ca2051SWilly Tarreau 
219430ca2051SWilly Tarreau static __attribute__((unused))
219530ca2051SWilly Tarreau int sched_yield(void)
219630ca2051SWilly Tarreau {
219730ca2051SWilly Tarreau 	int ret = sys_sched_yield();
219830ca2051SWilly Tarreau 
219930ca2051SWilly Tarreau 	if (ret < 0) {
220030ca2051SWilly Tarreau 		SET_ERRNO(-ret);
220130ca2051SWilly Tarreau 		ret = -1;
220230ca2051SWilly Tarreau 	}
220330ca2051SWilly Tarreau 	return ret;
220430ca2051SWilly Tarreau }
220530ca2051SWilly Tarreau 
220630ca2051SWilly Tarreau static __attribute__((unused))
220730ca2051SWilly Tarreau int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
220830ca2051SWilly Tarreau {
220930ca2051SWilly Tarreau 	int ret = sys_select(nfds, rfds, wfds, efds, timeout);
221030ca2051SWilly Tarreau 
221130ca2051SWilly Tarreau 	if (ret < 0) {
221230ca2051SWilly Tarreau 		SET_ERRNO(-ret);
221330ca2051SWilly Tarreau 		ret = -1;
221430ca2051SWilly Tarreau 	}
221530ca2051SWilly Tarreau 	return ret;
221630ca2051SWilly Tarreau }
221730ca2051SWilly Tarreau 
221830ca2051SWilly Tarreau static __attribute__((unused))
221930ca2051SWilly Tarreau int setpgid(pid_t pid, pid_t pgid)
222030ca2051SWilly Tarreau {
222130ca2051SWilly Tarreau 	int ret = sys_setpgid(pid, pgid);
222230ca2051SWilly Tarreau 
222330ca2051SWilly Tarreau 	if (ret < 0) {
222430ca2051SWilly Tarreau 		SET_ERRNO(-ret);
222530ca2051SWilly Tarreau 		ret = -1;
222630ca2051SWilly Tarreau 	}
222730ca2051SWilly Tarreau 	return ret;
222830ca2051SWilly Tarreau }
222930ca2051SWilly Tarreau 
223030ca2051SWilly Tarreau static __attribute__((unused))
223130ca2051SWilly Tarreau pid_t setsid(void)
223230ca2051SWilly Tarreau {
223330ca2051SWilly Tarreau 	pid_t ret = sys_setsid();
223430ca2051SWilly Tarreau 
223530ca2051SWilly Tarreau 	if (ret < 0) {
223630ca2051SWilly Tarreau 		SET_ERRNO(-ret);
223730ca2051SWilly Tarreau 		ret = -1;
223830ca2051SWilly Tarreau 	}
223930ca2051SWilly Tarreau 	return ret;
224030ca2051SWilly Tarreau }
224130ca2051SWilly Tarreau 
224230ca2051SWilly Tarreau static __attribute__((unused))
224330ca2051SWilly Tarreau unsigned int sleep(unsigned int seconds)
224430ca2051SWilly Tarreau {
224530ca2051SWilly Tarreau 	struct timeval my_timeval = { seconds, 0 };
224630ca2051SWilly Tarreau 
224730ca2051SWilly Tarreau 	if (sys_select(0, 0, 0, 0, &my_timeval) < 0)
224830ca2051SWilly Tarreau 		return my_timeval.tv_sec + !!my_timeval.tv_usec;
224930ca2051SWilly Tarreau 	else
225030ca2051SWilly Tarreau 		return 0;
225130ca2051SWilly Tarreau }
225230ca2051SWilly Tarreau 
225330ca2051SWilly Tarreau static __attribute__((unused))
2254f916d77eSMark Brown int msleep(unsigned int msecs)
2255f916d77eSMark Brown {
2256f916d77eSMark Brown 	struct timeval my_timeval = { msecs / 1000, (msecs % 1000) * 1000 };
2257f916d77eSMark Brown 
2258f916d77eSMark Brown 	if (sys_select(0, 0, 0, 0, &my_timeval) < 0)
2259f916d77eSMark Brown 		return (my_timeval.tv_sec * 1000) +
2260f916d77eSMark Brown 			(my_timeval.tv_usec / 1000) +
2261f916d77eSMark Brown 			!!(my_timeval.tv_usec % 1000);
2262f916d77eSMark Brown 	else
2263f916d77eSMark Brown 		return 0;
2264f916d77eSMark Brown }
2265f916d77eSMark Brown 
2266f916d77eSMark Brown static __attribute__((unused))
226730ca2051SWilly Tarreau int stat(const char *path, struct stat *buf)
226830ca2051SWilly Tarreau {
226930ca2051SWilly Tarreau 	int ret = sys_stat(path, buf);
227030ca2051SWilly Tarreau 
227130ca2051SWilly Tarreau 	if (ret < 0) {
227230ca2051SWilly Tarreau 		SET_ERRNO(-ret);
227330ca2051SWilly Tarreau 		ret = -1;
227430ca2051SWilly Tarreau 	}
227530ca2051SWilly Tarreau 	return ret;
227630ca2051SWilly Tarreau }
227730ca2051SWilly Tarreau 
227830ca2051SWilly Tarreau static __attribute__((unused))
227930ca2051SWilly Tarreau int symlink(const char *old, const char *new)
228030ca2051SWilly Tarreau {
228130ca2051SWilly Tarreau 	int ret = sys_symlink(old, new);
228230ca2051SWilly Tarreau 
228330ca2051SWilly Tarreau 	if (ret < 0) {
228430ca2051SWilly Tarreau 		SET_ERRNO(-ret);
228530ca2051SWilly Tarreau 		ret = -1;
228630ca2051SWilly Tarreau 	}
228730ca2051SWilly Tarreau 	return ret;
228830ca2051SWilly Tarreau }
228930ca2051SWilly Tarreau 
229030ca2051SWilly Tarreau static __attribute__((unused))
229130ca2051SWilly Tarreau int tcsetpgrp(int fd, pid_t pid)
229230ca2051SWilly Tarreau {
229330ca2051SWilly Tarreau 	return ioctl(fd, TIOCSPGRP, &pid);
229430ca2051SWilly Tarreau }
229530ca2051SWilly Tarreau 
229630ca2051SWilly Tarreau static __attribute__((unused))
229730ca2051SWilly Tarreau mode_t umask(mode_t mode)
229830ca2051SWilly Tarreau {
229930ca2051SWilly Tarreau 	return sys_umask(mode);
230030ca2051SWilly Tarreau }
230130ca2051SWilly Tarreau 
230230ca2051SWilly Tarreau static __attribute__((unused))
230330ca2051SWilly Tarreau int umount2(const char *path, int flags)
230430ca2051SWilly Tarreau {
230530ca2051SWilly Tarreau 	int ret = sys_umount2(path, flags);
230630ca2051SWilly Tarreau 
230730ca2051SWilly Tarreau 	if (ret < 0) {
230830ca2051SWilly Tarreau 		SET_ERRNO(-ret);
230930ca2051SWilly Tarreau 		ret = -1;
231030ca2051SWilly Tarreau 	}
231130ca2051SWilly Tarreau 	return ret;
231230ca2051SWilly Tarreau }
231330ca2051SWilly Tarreau 
231430ca2051SWilly Tarreau static __attribute__((unused))
231530ca2051SWilly Tarreau int unlink(const char *path)
231630ca2051SWilly Tarreau {
231730ca2051SWilly Tarreau 	int ret = sys_unlink(path);
231830ca2051SWilly Tarreau 
231930ca2051SWilly Tarreau 	if (ret < 0) {
232030ca2051SWilly Tarreau 		SET_ERRNO(-ret);
232130ca2051SWilly Tarreau 		ret = -1;
232230ca2051SWilly Tarreau 	}
232330ca2051SWilly Tarreau 	return ret;
232430ca2051SWilly Tarreau }
232530ca2051SWilly Tarreau 
232630ca2051SWilly Tarreau static __attribute__((unused))
232730ca2051SWilly Tarreau pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage)
232830ca2051SWilly Tarreau {
232930ca2051SWilly Tarreau 	pid_t ret = sys_wait4(pid, status, options, rusage);
233030ca2051SWilly Tarreau 
233130ca2051SWilly Tarreau 	if (ret < 0) {
233230ca2051SWilly Tarreau 		SET_ERRNO(-ret);
233330ca2051SWilly Tarreau 		ret = -1;
233430ca2051SWilly Tarreau 	}
233530ca2051SWilly Tarreau 	return ret;
233630ca2051SWilly Tarreau }
233730ca2051SWilly Tarreau 
233830ca2051SWilly Tarreau static __attribute__((unused))
233930ca2051SWilly Tarreau pid_t waitpid(pid_t pid, int *status, int options)
234030ca2051SWilly Tarreau {
234130ca2051SWilly Tarreau 	pid_t ret = sys_waitpid(pid, status, options);
234230ca2051SWilly Tarreau 
234330ca2051SWilly Tarreau 	if (ret < 0) {
234430ca2051SWilly Tarreau 		SET_ERRNO(-ret);
234530ca2051SWilly Tarreau 		ret = -1;
234630ca2051SWilly Tarreau 	}
234730ca2051SWilly Tarreau 	return ret;
234830ca2051SWilly Tarreau }
234930ca2051SWilly Tarreau 
235030ca2051SWilly Tarreau static __attribute__((unused))
235130ca2051SWilly Tarreau pid_t wait(int *status)
235230ca2051SWilly Tarreau {
235330ca2051SWilly Tarreau 	pid_t ret = sys_wait(status);
235430ca2051SWilly Tarreau 
235530ca2051SWilly Tarreau 	if (ret < 0) {
235630ca2051SWilly Tarreau 		SET_ERRNO(-ret);
235730ca2051SWilly Tarreau 		ret = -1;
235830ca2051SWilly Tarreau 	}
235930ca2051SWilly Tarreau 	return ret;
236030ca2051SWilly Tarreau }
236130ca2051SWilly Tarreau 
236230ca2051SWilly Tarreau static __attribute__((unused))
236330ca2051SWilly Tarreau ssize_t write(int fd, const void *buf, size_t count)
236430ca2051SWilly Tarreau {
236530ca2051SWilly Tarreau 	ssize_t ret = sys_write(fd, buf, count);
236630ca2051SWilly Tarreau 
236730ca2051SWilly Tarreau 	if (ret < 0) {
236830ca2051SWilly Tarreau 		SET_ERRNO(-ret);
236930ca2051SWilly Tarreau 		ret = -1;
237030ca2051SWilly Tarreau 	}
237130ca2051SWilly Tarreau 	return ret;
237230ca2051SWilly Tarreau }
237330ca2051SWilly Tarreau 
237430ca2051SWilly Tarreau /* some size-optimized reimplementations of a few common str* and mem*
237530ca2051SWilly Tarreau  * functions. They're marked static, except memcpy() and raise() which are used
237630ca2051SWilly Tarreau  * by libgcc on ARM, so they are marked weak instead in order not to cause an
237730ca2051SWilly Tarreau  * error when building a program made of multiple files (not recommended).
237830ca2051SWilly Tarreau  */
237930ca2051SWilly Tarreau 
238030ca2051SWilly Tarreau static __attribute__((unused))
238130ca2051SWilly Tarreau void *memmove(void *dst, const void *src, size_t len)
238230ca2051SWilly Tarreau {
238330ca2051SWilly Tarreau 	ssize_t pos = (dst <= src) ? -1 : (long)len;
238430ca2051SWilly Tarreau 	void *ret = dst;
238530ca2051SWilly Tarreau 
238630ca2051SWilly Tarreau 	while (len--) {
238730ca2051SWilly Tarreau 		pos += (dst <= src) ? 1 : -1;
238830ca2051SWilly Tarreau 		((char *)dst)[pos] = ((char *)src)[pos];
238930ca2051SWilly Tarreau 	}
239030ca2051SWilly Tarreau 	return ret;
239130ca2051SWilly Tarreau }
239230ca2051SWilly Tarreau 
239330ca2051SWilly Tarreau static __attribute__((unused))
239430ca2051SWilly Tarreau void *memset(void *dst, int b, size_t len)
239530ca2051SWilly Tarreau {
239630ca2051SWilly Tarreau 	char *p = dst;
239730ca2051SWilly Tarreau 
239830ca2051SWilly Tarreau 	while (len--)
239930ca2051SWilly Tarreau 		*(p++) = b;
240030ca2051SWilly Tarreau 	return dst;
240130ca2051SWilly Tarreau }
240230ca2051SWilly Tarreau 
240330ca2051SWilly Tarreau static __attribute__((unused))
240430ca2051SWilly Tarreau int memcmp(const void *s1, const void *s2, size_t n)
240530ca2051SWilly Tarreau {
240630ca2051SWilly Tarreau 	size_t ofs = 0;
240730ca2051SWilly Tarreau 	char c1 = 0;
240830ca2051SWilly Tarreau 
240930ca2051SWilly Tarreau 	while (ofs < n && !(c1 = ((char *)s1)[ofs] - ((char *)s2)[ofs])) {
241030ca2051SWilly Tarreau 		ofs++;
241130ca2051SWilly Tarreau 	}
241230ca2051SWilly Tarreau 	return c1;
241330ca2051SWilly Tarreau }
241430ca2051SWilly Tarreau 
241530ca2051SWilly Tarreau static __attribute__((unused))
241630ca2051SWilly Tarreau char *strcpy(char *dst, const char *src)
241730ca2051SWilly Tarreau {
241830ca2051SWilly Tarreau 	char *ret = dst;
241930ca2051SWilly Tarreau 
242030ca2051SWilly Tarreau 	while ((*dst++ = *src++));
242130ca2051SWilly Tarreau 	return ret;
242230ca2051SWilly Tarreau }
242330ca2051SWilly Tarreau 
242430ca2051SWilly Tarreau static __attribute__((unused))
242530ca2051SWilly Tarreau char *strchr(const char *s, int c)
242630ca2051SWilly Tarreau {
242730ca2051SWilly Tarreau 	while (*s) {
242830ca2051SWilly Tarreau 		if (*s == (char)c)
242930ca2051SWilly Tarreau 			return (char *)s;
243030ca2051SWilly Tarreau 		s++;
243130ca2051SWilly Tarreau 	}
243230ca2051SWilly Tarreau 	return NULL;
243330ca2051SWilly Tarreau }
243430ca2051SWilly Tarreau 
243530ca2051SWilly Tarreau static __attribute__((unused))
243630ca2051SWilly Tarreau char *strrchr(const char *s, int c)
243730ca2051SWilly Tarreau {
243830ca2051SWilly Tarreau 	const char *ret = NULL;
243930ca2051SWilly Tarreau 
244030ca2051SWilly Tarreau 	while (*s) {
244130ca2051SWilly Tarreau 		if (*s == (char)c)
244230ca2051SWilly Tarreau 			ret = s;
244330ca2051SWilly Tarreau 		s++;
244430ca2051SWilly Tarreau 	}
244530ca2051SWilly Tarreau 	return (char *)ret;
244630ca2051SWilly Tarreau }
244730ca2051SWilly Tarreau 
244830ca2051SWilly Tarreau static __attribute__((unused))
244930ca2051SWilly Tarreau size_t nolibc_strlen(const char *str)
245030ca2051SWilly Tarreau {
245130ca2051SWilly Tarreau 	size_t len;
245230ca2051SWilly Tarreau 
245330ca2051SWilly Tarreau 	for (len = 0; str[len]; len++);
245430ca2051SWilly Tarreau 	return len;
245530ca2051SWilly Tarreau }
245630ca2051SWilly Tarreau 
245730ca2051SWilly Tarreau #define strlen(str) ({                          \
245830ca2051SWilly Tarreau 	__builtin_constant_p((str)) ?           \
245930ca2051SWilly Tarreau 		__builtin_strlen((str)) :       \
246030ca2051SWilly Tarreau 		nolibc_strlen((str));           \
246130ca2051SWilly Tarreau })
246230ca2051SWilly Tarreau 
246330ca2051SWilly Tarreau static __attribute__((unused))
246430ca2051SWilly Tarreau int isdigit(int c)
246530ca2051SWilly Tarreau {
246630ca2051SWilly Tarreau 	return (unsigned int)(c - '0') <= 9;
246730ca2051SWilly Tarreau }
246830ca2051SWilly Tarreau 
246930ca2051SWilly Tarreau static __attribute__((unused))
247030ca2051SWilly Tarreau long atol(const char *s)
247130ca2051SWilly Tarreau {
247230ca2051SWilly Tarreau 	unsigned long ret = 0;
247330ca2051SWilly Tarreau 	unsigned long d;
247430ca2051SWilly Tarreau 	int neg = 0;
247530ca2051SWilly Tarreau 
247630ca2051SWilly Tarreau 	if (*s == '-') {
247730ca2051SWilly Tarreau 		neg = 1;
247830ca2051SWilly Tarreau 		s++;
247930ca2051SWilly Tarreau 	}
248030ca2051SWilly Tarreau 
248130ca2051SWilly Tarreau 	while (1) {
248230ca2051SWilly Tarreau 		d = (*s++) - '0';
248330ca2051SWilly Tarreau 		if (d > 9)
248430ca2051SWilly Tarreau 			break;
248530ca2051SWilly Tarreau 		ret *= 10;
248630ca2051SWilly Tarreau 		ret += d;
248730ca2051SWilly Tarreau 	}
248830ca2051SWilly Tarreau 
248930ca2051SWilly Tarreau 	return neg ? -ret : ret;
249030ca2051SWilly Tarreau }
249130ca2051SWilly Tarreau 
249230ca2051SWilly Tarreau static __attribute__((unused))
249330ca2051SWilly Tarreau int atoi(const char *s)
249430ca2051SWilly Tarreau {
249530ca2051SWilly Tarreau 	return atol(s);
249630ca2051SWilly Tarreau }
249730ca2051SWilly Tarreau 
249830ca2051SWilly Tarreau static __attribute__((unused))
249930ca2051SWilly Tarreau const char *ltoa(long in)
250030ca2051SWilly Tarreau {
250130ca2051SWilly Tarreau 	/* large enough for -9223372036854775808 */
250230ca2051SWilly Tarreau 	static char buffer[21];
250330ca2051SWilly Tarreau 	char       *pos = buffer + sizeof(buffer) - 1;
250430ca2051SWilly Tarreau 	int         neg = in < 0;
250530ca2051SWilly Tarreau 	unsigned long n = neg ? -in : in;
250630ca2051SWilly Tarreau 
250730ca2051SWilly Tarreau 	*pos-- = '\0';
250830ca2051SWilly Tarreau 	do {
250930ca2051SWilly Tarreau 		*pos-- = '0' + n % 10;
251030ca2051SWilly Tarreau 		n /= 10;
251130ca2051SWilly Tarreau 		if (pos < buffer)
251230ca2051SWilly Tarreau 			return pos + 1;
251330ca2051SWilly Tarreau 	} while (n);
251430ca2051SWilly Tarreau 
251530ca2051SWilly Tarreau 	if (neg)
251630ca2051SWilly Tarreau 		*pos-- = '-';
251730ca2051SWilly Tarreau 	return pos + 1;
251830ca2051SWilly Tarreau }
251930ca2051SWilly Tarreau 
252030ca2051SWilly Tarreau __attribute__((weak,unused))
252130ca2051SWilly Tarreau void *memcpy(void *dst, const void *src, size_t len)
252230ca2051SWilly Tarreau {
252330ca2051SWilly Tarreau 	return memmove(dst, src, len);
252430ca2051SWilly Tarreau }
252530ca2051SWilly Tarreau 
252630ca2051SWilly Tarreau /* needed by libgcc for divide by zero */
252730ca2051SWilly Tarreau __attribute__((weak,unused))
252830ca2051SWilly Tarreau int raise(int signal)
252930ca2051SWilly Tarreau {
253030ca2051SWilly Tarreau 	return kill(getpid(), signal);
253130ca2051SWilly Tarreau }
253230ca2051SWilly Tarreau 
253330ca2051SWilly Tarreau /* Here come a few helper functions */
253430ca2051SWilly Tarreau 
253530ca2051SWilly Tarreau static __attribute__((unused))
253630ca2051SWilly Tarreau void FD_ZERO(fd_set *set)
253730ca2051SWilly Tarreau {
253830ca2051SWilly Tarreau 	memset(set, 0, sizeof(*set));
253930ca2051SWilly Tarreau }
254030ca2051SWilly Tarreau 
254130ca2051SWilly Tarreau static __attribute__((unused))
254230ca2051SWilly Tarreau void FD_SET(int fd, fd_set *set)
254330ca2051SWilly Tarreau {
254430ca2051SWilly Tarreau 	if (fd < 0 || fd >= FD_SETSIZE)
254530ca2051SWilly Tarreau 		return;
254630ca2051SWilly Tarreau 	set->fd32[fd / 32] |= 1 << (fd & 31);
254730ca2051SWilly Tarreau }
254830ca2051SWilly Tarreau 
254930ca2051SWilly Tarreau /* WARNING, it only deals with the 4096 first majors and 256 first minors */
255030ca2051SWilly Tarreau static __attribute__((unused))
255130ca2051SWilly Tarreau dev_t makedev(unsigned int major, unsigned int minor)
255230ca2051SWilly Tarreau {
255330ca2051SWilly Tarreau 	return ((major & 0xfff) << 8) | (minor & 0xff);
255430ca2051SWilly Tarreau }
2555930c4accSWilly Tarreau 
2556930c4accSWilly Tarreau #endif /* _NOLIBC_H */
2557