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 */ 83*930c4accSWilly Tarreau #ifndef _NOLIBC_H 84*930c4accSWilly Tarreau #define _NOLIBC_H 8530ca2051SWilly Tarreau 8630ca2051SWilly Tarreau #include <asm/unistd.h> 8730ca2051SWilly Tarreau #include <asm/ioctls.h> 8830ca2051SWilly Tarreau #include <asm/errno.h> 8930ca2051SWilly Tarreau #include <linux/fs.h> 9030ca2051SWilly Tarreau #include <linux/loop.h> 9170ca7aeaSWilly Tarreau #include <linux/time.h> 9230ca2051SWilly Tarreau 9330ca2051SWilly Tarreau #define NOLIBC 9430ca2051SWilly Tarreau 9530ca2051SWilly Tarreau /* this way it will be removed if unused */ 9630ca2051SWilly Tarreau static int errno; 9730ca2051SWilly Tarreau 9830ca2051SWilly Tarreau #ifndef NOLIBC_IGNORE_ERRNO 9930ca2051SWilly Tarreau #define SET_ERRNO(v) do { errno = (v); } while (0) 10030ca2051SWilly Tarreau #else 10130ca2051SWilly Tarreau #define SET_ERRNO(v) do { } while (0) 10230ca2051SWilly Tarreau #endif 10330ca2051SWilly Tarreau 10430ca2051SWilly Tarreau /* errno codes all ensure that they will not conflict with a valid pointer 10506dc8d45SBhaskar Chowdhury * because they all correspond to the highest addressable memory page. 10630ca2051SWilly Tarreau */ 10730ca2051SWilly Tarreau #define MAX_ERRNO 4095 10830ca2051SWilly Tarreau 10930ca2051SWilly Tarreau /* Declare a few quite common macros and types that usually are in stdlib.h, 11030ca2051SWilly Tarreau * stdint.h, ctype.h, unistd.h and a few other common locations. 11130ca2051SWilly Tarreau */ 11230ca2051SWilly Tarreau 11330ca2051SWilly Tarreau #define NULL ((void *)0) 11430ca2051SWilly Tarreau 11530ca2051SWilly Tarreau /* stdint types */ 11630ca2051SWilly Tarreau typedef unsigned char uint8_t; 11730ca2051SWilly Tarreau typedef signed char int8_t; 11830ca2051SWilly Tarreau typedef unsigned short uint16_t; 11930ca2051SWilly Tarreau typedef signed short int16_t; 12030ca2051SWilly Tarreau typedef unsigned int uint32_t; 12130ca2051SWilly Tarreau typedef signed int int32_t; 12230ca2051SWilly Tarreau typedef unsigned long long uint64_t; 12330ca2051SWilly Tarreau typedef signed long long int64_t; 12430ca2051SWilly Tarreau typedef unsigned long size_t; 12530ca2051SWilly Tarreau typedef signed long ssize_t; 12630ca2051SWilly Tarreau typedef unsigned long uintptr_t; 12730ca2051SWilly Tarreau typedef signed long intptr_t; 12830ca2051SWilly Tarreau typedef signed long ptrdiff_t; 12930ca2051SWilly Tarreau 13030ca2051SWilly Tarreau /* for stat() */ 13130ca2051SWilly Tarreau typedef unsigned int dev_t; 13230ca2051SWilly Tarreau typedef unsigned long ino_t; 13330ca2051SWilly Tarreau typedef unsigned int mode_t; 13430ca2051SWilly Tarreau typedef signed int pid_t; 13530ca2051SWilly Tarreau typedef unsigned int uid_t; 13630ca2051SWilly Tarreau typedef unsigned int gid_t; 13730ca2051SWilly Tarreau typedef unsigned long nlink_t; 13830ca2051SWilly Tarreau typedef signed long off_t; 13930ca2051SWilly Tarreau typedef signed long blksize_t; 14030ca2051SWilly Tarreau typedef signed long blkcnt_t; 14130ca2051SWilly Tarreau typedef signed long time_t; 14230ca2051SWilly Tarreau 14330ca2051SWilly Tarreau /* for poll() */ 14430ca2051SWilly Tarreau struct pollfd { 14530ca2051SWilly Tarreau int fd; 14630ca2051SWilly Tarreau short int events; 14730ca2051SWilly Tarreau short int revents; 14830ca2051SWilly Tarreau }; 14930ca2051SWilly Tarreau 15030ca2051SWilly Tarreau /* for getdents64() */ 15130ca2051SWilly Tarreau struct linux_dirent64 { 15230ca2051SWilly Tarreau uint64_t d_ino; 15330ca2051SWilly Tarreau int64_t d_off; 15430ca2051SWilly Tarreau unsigned short d_reclen; 15530ca2051SWilly Tarreau unsigned char d_type; 15630ca2051SWilly Tarreau char d_name[]; 15730ca2051SWilly Tarreau }; 15830ca2051SWilly Tarreau 15930ca2051SWilly Tarreau /* commonly an fd_set represents 256 FDs */ 16030ca2051SWilly Tarreau #define FD_SETSIZE 256 16130ca2051SWilly Tarreau typedef struct { uint32_t fd32[FD_SETSIZE/32]; } fd_set; 16230ca2051SWilly Tarreau 16330ca2051SWilly Tarreau /* needed by wait4() */ 16430ca2051SWilly Tarreau struct rusage { 16530ca2051SWilly Tarreau struct timeval ru_utime; 16630ca2051SWilly Tarreau struct timeval ru_stime; 16730ca2051SWilly Tarreau long ru_maxrss; 16830ca2051SWilly Tarreau long ru_ixrss; 16930ca2051SWilly Tarreau long ru_idrss; 17030ca2051SWilly Tarreau long ru_isrss; 17130ca2051SWilly Tarreau long ru_minflt; 17230ca2051SWilly Tarreau long ru_majflt; 17330ca2051SWilly Tarreau long ru_nswap; 17430ca2051SWilly Tarreau long ru_inblock; 17530ca2051SWilly Tarreau long ru_oublock; 17630ca2051SWilly Tarreau long ru_msgsnd; 17730ca2051SWilly Tarreau long ru_msgrcv; 17830ca2051SWilly Tarreau long ru_nsignals; 17930ca2051SWilly Tarreau long ru_nvcsw; 18030ca2051SWilly Tarreau long ru_nivcsw; 18130ca2051SWilly Tarreau }; 18230ca2051SWilly Tarreau 18330ca2051SWilly Tarreau /* stat flags (WARNING, octal here) */ 18430ca2051SWilly Tarreau #define S_IFDIR 0040000 18530ca2051SWilly Tarreau #define S_IFCHR 0020000 18630ca2051SWilly Tarreau #define S_IFBLK 0060000 18730ca2051SWilly Tarreau #define S_IFREG 0100000 18830ca2051SWilly Tarreau #define S_IFIFO 0010000 18930ca2051SWilly Tarreau #define S_IFLNK 0120000 19030ca2051SWilly Tarreau #define S_IFSOCK 0140000 19130ca2051SWilly Tarreau #define S_IFMT 0170000 19230ca2051SWilly Tarreau 19330ca2051SWilly Tarreau #define S_ISDIR(mode) (((mode) & S_IFDIR) == S_IFDIR) 19430ca2051SWilly Tarreau #define S_ISCHR(mode) (((mode) & S_IFCHR) == S_IFCHR) 19530ca2051SWilly Tarreau #define S_ISBLK(mode) (((mode) & S_IFBLK) == S_IFBLK) 19630ca2051SWilly Tarreau #define S_ISREG(mode) (((mode) & S_IFREG) == S_IFREG) 19730ca2051SWilly Tarreau #define S_ISFIFO(mode) (((mode) & S_IFIFO) == S_IFIFO) 19830ca2051SWilly Tarreau #define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK) 19930ca2051SWilly Tarreau #define S_ISSOCK(mode) (((mode) & S_IFSOCK) == S_IFSOCK) 20030ca2051SWilly Tarreau 20130ca2051SWilly Tarreau #define DT_UNKNOWN 0 20230ca2051SWilly Tarreau #define DT_FIFO 1 20330ca2051SWilly Tarreau #define DT_CHR 2 20430ca2051SWilly Tarreau #define DT_DIR 4 20530ca2051SWilly Tarreau #define DT_BLK 6 20630ca2051SWilly Tarreau #define DT_REG 8 20730ca2051SWilly Tarreau #define DT_LNK 10 20830ca2051SWilly Tarreau #define DT_SOCK 12 20930ca2051SWilly Tarreau 21030ca2051SWilly Tarreau /* all the *at functions */ 2116c5b9de2SSamuel Hernandez #ifndef AT_FDCWD 21230ca2051SWilly Tarreau #define AT_FDCWD -100 21330ca2051SWilly Tarreau #endif 21430ca2051SWilly Tarreau 21530ca2051SWilly Tarreau /* lseek */ 21630ca2051SWilly Tarreau #define SEEK_SET 0 21730ca2051SWilly Tarreau #define SEEK_CUR 1 21830ca2051SWilly Tarreau #define SEEK_END 2 21930ca2051SWilly Tarreau 22030ca2051SWilly Tarreau /* reboot */ 22130ca2051SWilly Tarreau #define LINUX_REBOOT_MAGIC1 0xfee1dead 22230ca2051SWilly Tarreau #define LINUX_REBOOT_MAGIC2 0x28121969 22330ca2051SWilly Tarreau #define LINUX_REBOOT_CMD_HALT 0xcdef0123 22430ca2051SWilly Tarreau #define LINUX_REBOOT_CMD_POWER_OFF 0x4321fedc 22530ca2051SWilly Tarreau #define LINUX_REBOOT_CMD_RESTART 0x01234567 22630ca2051SWilly Tarreau #define LINUX_REBOOT_CMD_SW_SUSPEND 0xd000fce2 22730ca2051SWilly Tarreau 22830ca2051SWilly Tarreau 22930ca2051SWilly Tarreau /* The format of the struct as returned by the libc to the application, which 23030ca2051SWilly Tarreau * significantly differs from the format returned by the stat() syscall flavours. 23130ca2051SWilly Tarreau */ 23230ca2051SWilly Tarreau struct stat { 23330ca2051SWilly Tarreau dev_t st_dev; /* ID of device containing file */ 23430ca2051SWilly Tarreau ino_t st_ino; /* inode number */ 23530ca2051SWilly Tarreau mode_t st_mode; /* protection */ 23630ca2051SWilly Tarreau nlink_t st_nlink; /* number of hard links */ 23730ca2051SWilly Tarreau uid_t st_uid; /* user ID of owner */ 23830ca2051SWilly Tarreau gid_t st_gid; /* group ID of owner */ 23930ca2051SWilly Tarreau dev_t st_rdev; /* device ID (if special file) */ 24030ca2051SWilly Tarreau off_t st_size; /* total size, in bytes */ 24130ca2051SWilly Tarreau blksize_t st_blksize; /* blocksize for file system I/O */ 24230ca2051SWilly Tarreau blkcnt_t st_blocks; /* number of 512B blocks allocated */ 24330ca2051SWilly Tarreau time_t st_atime; /* time of last access */ 24430ca2051SWilly Tarreau time_t st_mtime; /* time of last modification */ 24530ca2051SWilly Tarreau time_t st_ctime; /* time of last status change */ 24630ca2051SWilly Tarreau }; 24730ca2051SWilly Tarreau 24830ca2051SWilly Tarreau #define WEXITSTATUS(status) (((status) & 0xff00) >> 8) 24930ca2051SWilly Tarreau #define WIFEXITED(status) (((status) & 0x7f) == 0) 25030ca2051SWilly Tarreau 251be60ca41SWilly Tarreau /* for SIGCHLD */ 252be60ca41SWilly Tarreau #include <asm/signal.h> 25330ca2051SWilly Tarreau 25430ca2051SWilly Tarreau /* Below comes the architecture-specific code. For each architecture, we have 25530ca2051SWilly Tarreau * the syscall declarations and the _start code definition. This is the only 25630ca2051SWilly Tarreau * global part. On all architectures the kernel puts everything in the stack 25730ca2051SWilly Tarreau * before jumping to _start just above us, without any return address (_start 25830ca2051SWilly Tarreau * is not a function but an entry pint). So at the stack pointer we find argc. 25930ca2051SWilly Tarreau * Then argv[] begins, and ends at the first NULL. Then we have envp which 26030ca2051SWilly Tarreau * starts and ends with a NULL as well. So envp=argv+argc+1. 26130ca2051SWilly Tarreau */ 26230ca2051SWilly Tarreau 26330ca2051SWilly Tarreau #if defined(__x86_64__) 26430ca2051SWilly Tarreau /* Syscalls for x86_64 : 26530ca2051SWilly Tarreau * - registers are 64-bit 26630ca2051SWilly Tarreau * - syscall number is passed in rax 26730ca2051SWilly Tarreau * - arguments are in rdi, rsi, rdx, r10, r8, r9 respectively 26830ca2051SWilly Tarreau * - the system call is performed by calling the syscall instruction 26930ca2051SWilly Tarreau * - syscall return comes in rax 270bf916669SAmmar Faizi * - rcx and r11 are clobbered, others are preserved. 27130ca2051SWilly Tarreau * - the arguments are cast to long and assigned into the target registers 27230ca2051SWilly Tarreau * which are then simply passed as registers to the asm code, so that we 27330ca2051SWilly Tarreau * don't have to experience issues with register constraints. 27430ca2051SWilly Tarreau * - the syscall number is always specified last in order to allow to force 27530ca2051SWilly Tarreau * some registers before (gcc refuses a %-register at the last position). 276bf916669SAmmar Faizi * - see also x86-64 ABI section A.2 AMD64 Linux Kernel Conventions, A.2.1 277bf916669SAmmar Faizi * Calling Conventions. 278bf916669SAmmar Faizi * 279bf916669SAmmar Faizi * Link x86-64 ABI: https://gitlab.com/x86-psABIs/x86-64-ABI/-/wikis/x86-64-psABI 280bf916669SAmmar Faizi * 28130ca2051SWilly Tarreau */ 28230ca2051SWilly Tarreau 28330ca2051SWilly Tarreau #define my_syscall0(num) \ 28430ca2051SWilly Tarreau ({ \ 28530ca2051SWilly Tarreau long _ret; \ 28630ca2051SWilly Tarreau register long _num asm("rax") = (num); \ 28730ca2051SWilly Tarreau \ 28830ca2051SWilly Tarreau asm volatile ( \ 28930ca2051SWilly Tarreau "syscall\n" \ 29030ca2051SWilly Tarreau : "=a"(_ret) \ 29130ca2051SWilly Tarreau : "0"(_num) \ 292bf916669SAmmar Faizi : "rcx", "r11", "memory", "cc" \ 29330ca2051SWilly Tarreau ); \ 29430ca2051SWilly Tarreau _ret; \ 29530ca2051SWilly Tarreau }) 29630ca2051SWilly Tarreau 29730ca2051SWilly Tarreau #define my_syscall1(num, arg1) \ 29830ca2051SWilly Tarreau ({ \ 29930ca2051SWilly Tarreau long _ret; \ 30030ca2051SWilly Tarreau register long _num asm("rax") = (num); \ 30130ca2051SWilly Tarreau register long _arg1 asm("rdi") = (long)(arg1); \ 30230ca2051SWilly Tarreau \ 30330ca2051SWilly Tarreau asm volatile ( \ 30430ca2051SWilly Tarreau "syscall\n" \ 30530ca2051SWilly Tarreau : "=a"(_ret) \ 30630ca2051SWilly Tarreau : "r"(_arg1), \ 30730ca2051SWilly Tarreau "0"(_num) \ 308bf916669SAmmar Faizi : "rcx", "r11", "memory", "cc" \ 30930ca2051SWilly Tarreau ); \ 31030ca2051SWilly Tarreau _ret; \ 31130ca2051SWilly Tarreau }) 31230ca2051SWilly Tarreau 31330ca2051SWilly Tarreau #define my_syscall2(num, arg1, arg2) \ 31430ca2051SWilly Tarreau ({ \ 31530ca2051SWilly Tarreau long _ret; \ 31630ca2051SWilly Tarreau register long _num asm("rax") = (num); \ 31730ca2051SWilly Tarreau register long _arg1 asm("rdi") = (long)(arg1); \ 31830ca2051SWilly Tarreau register long _arg2 asm("rsi") = (long)(arg2); \ 31930ca2051SWilly Tarreau \ 32030ca2051SWilly Tarreau asm volatile ( \ 32130ca2051SWilly Tarreau "syscall\n" \ 32230ca2051SWilly Tarreau : "=a"(_ret) \ 32330ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), \ 32430ca2051SWilly Tarreau "0"(_num) \ 325bf916669SAmmar Faizi : "rcx", "r11", "memory", "cc" \ 32630ca2051SWilly Tarreau ); \ 32730ca2051SWilly Tarreau _ret; \ 32830ca2051SWilly Tarreau }) 32930ca2051SWilly Tarreau 33030ca2051SWilly Tarreau #define my_syscall3(num, arg1, arg2, arg3) \ 33130ca2051SWilly Tarreau ({ \ 33230ca2051SWilly Tarreau long _ret; \ 33330ca2051SWilly Tarreau register long _num asm("rax") = (num); \ 33430ca2051SWilly Tarreau register long _arg1 asm("rdi") = (long)(arg1); \ 33530ca2051SWilly Tarreau register long _arg2 asm("rsi") = (long)(arg2); \ 33630ca2051SWilly Tarreau register long _arg3 asm("rdx") = (long)(arg3); \ 33730ca2051SWilly Tarreau \ 33830ca2051SWilly Tarreau asm volatile ( \ 33930ca2051SWilly Tarreau "syscall\n" \ 34030ca2051SWilly Tarreau : "=a"(_ret) \ 34130ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ 34230ca2051SWilly Tarreau "0"(_num) \ 343bf916669SAmmar Faizi : "rcx", "r11", "memory", "cc" \ 34430ca2051SWilly Tarreau ); \ 34530ca2051SWilly Tarreau _ret; \ 34630ca2051SWilly Tarreau }) 34730ca2051SWilly Tarreau 34830ca2051SWilly Tarreau #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 34930ca2051SWilly Tarreau ({ \ 35030ca2051SWilly Tarreau long _ret; \ 35130ca2051SWilly Tarreau register long _num asm("rax") = (num); \ 35230ca2051SWilly Tarreau register long _arg1 asm("rdi") = (long)(arg1); \ 35330ca2051SWilly Tarreau register long _arg2 asm("rsi") = (long)(arg2); \ 35430ca2051SWilly Tarreau register long _arg3 asm("rdx") = (long)(arg3); \ 35530ca2051SWilly Tarreau register long _arg4 asm("r10") = (long)(arg4); \ 35630ca2051SWilly Tarreau \ 35730ca2051SWilly Tarreau asm volatile ( \ 35830ca2051SWilly Tarreau "syscall\n" \ 359bf916669SAmmar Faizi : "=a"(_ret) \ 36030ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 36130ca2051SWilly Tarreau "0"(_num) \ 362bf916669SAmmar Faizi : "rcx", "r11", "memory", "cc" \ 36330ca2051SWilly Tarreau ); \ 36430ca2051SWilly Tarreau _ret; \ 36530ca2051SWilly Tarreau }) 36630ca2051SWilly Tarreau 36730ca2051SWilly Tarreau #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 36830ca2051SWilly Tarreau ({ \ 36930ca2051SWilly Tarreau long _ret; \ 37030ca2051SWilly Tarreau register long _num asm("rax") = (num); \ 37130ca2051SWilly Tarreau register long _arg1 asm("rdi") = (long)(arg1); \ 37230ca2051SWilly Tarreau register long _arg2 asm("rsi") = (long)(arg2); \ 37330ca2051SWilly Tarreau register long _arg3 asm("rdx") = (long)(arg3); \ 37430ca2051SWilly Tarreau register long _arg4 asm("r10") = (long)(arg4); \ 37530ca2051SWilly Tarreau register long _arg5 asm("r8") = (long)(arg5); \ 37630ca2051SWilly Tarreau \ 37730ca2051SWilly Tarreau asm volatile ( \ 37830ca2051SWilly Tarreau "syscall\n" \ 379bf916669SAmmar Faizi : "=a"(_ret) \ 38030ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 38130ca2051SWilly Tarreau "0"(_num) \ 382bf916669SAmmar Faizi : "rcx", "r11", "memory", "cc" \ 38330ca2051SWilly Tarreau ); \ 38430ca2051SWilly Tarreau _ret; \ 38530ca2051SWilly Tarreau }) 38630ca2051SWilly Tarreau 38730ca2051SWilly Tarreau #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 38830ca2051SWilly Tarreau ({ \ 38930ca2051SWilly Tarreau long _ret; \ 39030ca2051SWilly Tarreau register long _num asm("rax") = (num); \ 39130ca2051SWilly Tarreau register long _arg1 asm("rdi") = (long)(arg1); \ 39230ca2051SWilly Tarreau register long _arg2 asm("rsi") = (long)(arg2); \ 39330ca2051SWilly Tarreau register long _arg3 asm("rdx") = (long)(arg3); \ 39430ca2051SWilly Tarreau register long _arg4 asm("r10") = (long)(arg4); \ 39530ca2051SWilly Tarreau register long _arg5 asm("r8") = (long)(arg5); \ 39630ca2051SWilly Tarreau register long _arg6 asm("r9") = (long)(arg6); \ 39730ca2051SWilly Tarreau \ 39830ca2051SWilly Tarreau asm volatile ( \ 39930ca2051SWilly Tarreau "syscall\n" \ 400bf916669SAmmar Faizi : "=a"(_ret) \ 40130ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 40230ca2051SWilly Tarreau "r"(_arg6), "0"(_num) \ 40330ca2051SWilly Tarreau : "rcx", "r11", "memory", "cc" \ 40430ca2051SWilly Tarreau ); \ 40530ca2051SWilly Tarreau _ret; \ 40630ca2051SWilly Tarreau }) 40730ca2051SWilly Tarreau 40830ca2051SWilly Tarreau /* startup code */ 409937ed91cSAmmar Faizi /* 410937ed91cSAmmar Faizi * x86-64 System V ABI mandates: 411937ed91cSAmmar Faizi * 1) %rsp must be 16-byte aligned right before the function call. 412937ed91cSAmmar Faizi * 2) The deepest stack frame should be zero (the %rbp). 413937ed91cSAmmar Faizi * 414937ed91cSAmmar Faizi */ 41530ca2051SWilly Tarreau asm(".section .text\n" 41630ca2051SWilly Tarreau ".global _start\n" 41730ca2051SWilly Tarreau "_start:\n" 41830ca2051SWilly Tarreau "pop %rdi\n" // argc (first arg, %rdi) 41930ca2051SWilly Tarreau "mov %rsp, %rsi\n" // argv[] (second arg, %rsi) 42030ca2051SWilly Tarreau "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx) 421937ed91cSAmmar Faizi "xor %ebp, %ebp\n" // zero the stack frame 422937ed91cSAmmar Faizi "and $-16, %rsp\n" // x86 ABI : esp must be 16-byte aligned before call 42330ca2051SWilly Tarreau "call main\n" // main() returns the status code, we'll exit with it. 424de0244aeSWilly Tarreau "mov %eax, %edi\n" // retrieve exit code (32 bit) 4257bdc0e7aSAmmar Faizi "mov $60, %eax\n" // NR_exit == 60 42630ca2051SWilly Tarreau "syscall\n" // really exit 42730ca2051SWilly Tarreau "hlt\n" // ensure it does not return 42830ca2051SWilly Tarreau ""); 42930ca2051SWilly Tarreau 43030ca2051SWilly Tarreau /* fcntl / open */ 43130ca2051SWilly Tarreau #define O_RDONLY 0 43230ca2051SWilly Tarreau #define O_WRONLY 1 43330ca2051SWilly Tarreau #define O_RDWR 2 43430ca2051SWilly Tarreau #define O_CREAT 0x40 43530ca2051SWilly Tarreau #define O_EXCL 0x80 43630ca2051SWilly Tarreau #define O_NOCTTY 0x100 43730ca2051SWilly Tarreau #define O_TRUNC 0x200 43830ca2051SWilly Tarreau #define O_APPEND 0x400 43930ca2051SWilly Tarreau #define O_NONBLOCK 0x800 44030ca2051SWilly Tarreau #define O_DIRECTORY 0x10000 44130ca2051SWilly Tarreau 44230ca2051SWilly Tarreau /* The struct returned by the stat() syscall, equivalent to stat64(). The 44330ca2051SWilly Tarreau * syscall returns 116 bytes and stops in the middle of __unused. 44430ca2051SWilly Tarreau */ 44530ca2051SWilly Tarreau struct sys_stat_struct { 44630ca2051SWilly Tarreau unsigned long st_dev; 44730ca2051SWilly Tarreau unsigned long st_ino; 44830ca2051SWilly Tarreau unsigned long st_nlink; 44930ca2051SWilly Tarreau unsigned int st_mode; 45030ca2051SWilly Tarreau unsigned int st_uid; 45130ca2051SWilly Tarreau 45230ca2051SWilly Tarreau unsigned int st_gid; 45330ca2051SWilly Tarreau unsigned int __pad0; 45430ca2051SWilly Tarreau unsigned long st_rdev; 45530ca2051SWilly Tarreau long st_size; 45630ca2051SWilly Tarreau long st_blksize; 45730ca2051SWilly Tarreau 45830ca2051SWilly Tarreau long st_blocks; 45930ca2051SWilly Tarreau unsigned long st_atime; 46030ca2051SWilly Tarreau unsigned long st_atime_nsec; 46130ca2051SWilly Tarreau unsigned long st_mtime; 46230ca2051SWilly Tarreau 46330ca2051SWilly Tarreau unsigned long st_mtime_nsec; 46430ca2051SWilly Tarreau unsigned long st_ctime; 46530ca2051SWilly Tarreau unsigned long st_ctime_nsec; 46630ca2051SWilly Tarreau long __unused[3]; 46730ca2051SWilly Tarreau }; 46830ca2051SWilly Tarreau 46930ca2051SWilly Tarreau #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) 47030ca2051SWilly Tarreau /* Syscalls for i386 : 47130ca2051SWilly Tarreau * - mostly similar to x86_64 47230ca2051SWilly Tarreau * - registers are 32-bit 47330ca2051SWilly Tarreau * - syscall number is passed in eax 47430ca2051SWilly Tarreau * - arguments are in ebx, ecx, edx, esi, edi, ebp respectively 47530ca2051SWilly Tarreau * - all registers are preserved (except eax of course) 47630ca2051SWilly Tarreau * - the system call is performed by calling int $0x80 47730ca2051SWilly Tarreau * - syscall return comes in eax 47830ca2051SWilly Tarreau * - the arguments are cast to long and assigned into the target registers 47930ca2051SWilly Tarreau * which are then simply passed as registers to the asm code, so that we 48030ca2051SWilly Tarreau * don't have to experience issues with register constraints. 48130ca2051SWilly Tarreau * - the syscall number is always specified last in order to allow to force 48230ca2051SWilly Tarreau * some registers before (gcc refuses a %-register at the last position). 48330ca2051SWilly Tarreau * 48430ca2051SWilly Tarreau * Also, i386 supports the old_select syscall if newselect is not available 48530ca2051SWilly Tarreau */ 48630ca2051SWilly Tarreau #define __ARCH_WANT_SYS_OLD_SELECT 48730ca2051SWilly Tarreau 48830ca2051SWilly Tarreau #define my_syscall0(num) \ 48930ca2051SWilly Tarreau ({ \ 49030ca2051SWilly Tarreau long _ret; \ 49130ca2051SWilly Tarreau register long _num asm("eax") = (num); \ 49230ca2051SWilly Tarreau \ 49330ca2051SWilly Tarreau asm volatile ( \ 49430ca2051SWilly Tarreau "int $0x80\n" \ 49530ca2051SWilly Tarreau : "=a" (_ret) \ 49630ca2051SWilly Tarreau : "0"(_num) \ 49730ca2051SWilly Tarreau : "memory", "cc" \ 49830ca2051SWilly Tarreau ); \ 49930ca2051SWilly Tarreau _ret; \ 50030ca2051SWilly Tarreau }) 50130ca2051SWilly Tarreau 50230ca2051SWilly Tarreau #define my_syscall1(num, arg1) \ 50330ca2051SWilly Tarreau ({ \ 50430ca2051SWilly Tarreau long _ret; \ 50530ca2051SWilly Tarreau register long _num asm("eax") = (num); \ 50630ca2051SWilly Tarreau register long _arg1 asm("ebx") = (long)(arg1); \ 50730ca2051SWilly Tarreau \ 50830ca2051SWilly Tarreau asm volatile ( \ 50930ca2051SWilly Tarreau "int $0x80\n" \ 51030ca2051SWilly Tarreau : "=a" (_ret) \ 51130ca2051SWilly Tarreau : "r"(_arg1), \ 51230ca2051SWilly Tarreau "0"(_num) \ 51330ca2051SWilly Tarreau : "memory", "cc" \ 51430ca2051SWilly Tarreau ); \ 51530ca2051SWilly Tarreau _ret; \ 51630ca2051SWilly Tarreau }) 51730ca2051SWilly Tarreau 51830ca2051SWilly Tarreau #define my_syscall2(num, arg1, arg2) \ 51930ca2051SWilly Tarreau ({ \ 52030ca2051SWilly Tarreau long _ret; \ 52130ca2051SWilly Tarreau register long _num asm("eax") = (num); \ 52230ca2051SWilly Tarreau register long _arg1 asm("ebx") = (long)(arg1); \ 52330ca2051SWilly Tarreau register long _arg2 asm("ecx") = (long)(arg2); \ 52430ca2051SWilly Tarreau \ 52530ca2051SWilly Tarreau asm volatile ( \ 52630ca2051SWilly Tarreau "int $0x80\n" \ 52730ca2051SWilly Tarreau : "=a" (_ret) \ 52830ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), \ 52930ca2051SWilly Tarreau "0"(_num) \ 53030ca2051SWilly Tarreau : "memory", "cc" \ 53130ca2051SWilly Tarreau ); \ 53230ca2051SWilly Tarreau _ret; \ 53330ca2051SWilly Tarreau }) 53430ca2051SWilly Tarreau 53530ca2051SWilly Tarreau #define my_syscall3(num, arg1, arg2, arg3) \ 53630ca2051SWilly Tarreau ({ \ 53730ca2051SWilly Tarreau long _ret; \ 53830ca2051SWilly Tarreau register long _num asm("eax") = (num); \ 53930ca2051SWilly Tarreau register long _arg1 asm("ebx") = (long)(arg1); \ 54030ca2051SWilly Tarreau register long _arg2 asm("ecx") = (long)(arg2); \ 54130ca2051SWilly Tarreau register long _arg3 asm("edx") = (long)(arg3); \ 54230ca2051SWilly Tarreau \ 54330ca2051SWilly Tarreau asm volatile ( \ 54430ca2051SWilly Tarreau "int $0x80\n" \ 54530ca2051SWilly Tarreau : "=a" (_ret) \ 54630ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ 54730ca2051SWilly Tarreau "0"(_num) \ 54830ca2051SWilly Tarreau : "memory", "cc" \ 54930ca2051SWilly Tarreau ); \ 55030ca2051SWilly Tarreau _ret; \ 55130ca2051SWilly Tarreau }) 55230ca2051SWilly Tarreau 55330ca2051SWilly Tarreau #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 55430ca2051SWilly Tarreau ({ \ 55530ca2051SWilly Tarreau long _ret; \ 55630ca2051SWilly Tarreau register long _num asm("eax") = (num); \ 55730ca2051SWilly Tarreau register long _arg1 asm("ebx") = (long)(arg1); \ 55830ca2051SWilly Tarreau register long _arg2 asm("ecx") = (long)(arg2); \ 55930ca2051SWilly Tarreau register long _arg3 asm("edx") = (long)(arg3); \ 56030ca2051SWilly Tarreau register long _arg4 asm("esi") = (long)(arg4); \ 56130ca2051SWilly Tarreau \ 56230ca2051SWilly Tarreau asm volatile ( \ 56330ca2051SWilly Tarreau "int $0x80\n" \ 56430ca2051SWilly Tarreau : "=a" (_ret) \ 56530ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 56630ca2051SWilly Tarreau "0"(_num) \ 56730ca2051SWilly Tarreau : "memory", "cc" \ 56830ca2051SWilly Tarreau ); \ 56930ca2051SWilly Tarreau _ret; \ 57030ca2051SWilly Tarreau }) 57130ca2051SWilly Tarreau 57230ca2051SWilly Tarreau #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 57330ca2051SWilly Tarreau ({ \ 57430ca2051SWilly Tarreau long _ret; \ 57530ca2051SWilly Tarreau register long _num asm("eax") = (num); \ 57630ca2051SWilly Tarreau register long _arg1 asm("ebx") = (long)(arg1); \ 57730ca2051SWilly Tarreau register long _arg2 asm("ecx") = (long)(arg2); \ 57830ca2051SWilly Tarreau register long _arg3 asm("edx") = (long)(arg3); \ 57930ca2051SWilly Tarreau register long _arg4 asm("esi") = (long)(arg4); \ 58030ca2051SWilly Tarreau register long _arg5 asm("edi") = (long)(arg5); \ 58130ca2051SWilly Tarreau \ 58230ca2051SWilly Tarreau asm volatile ( \ 58330ca2051SWilly Tarreau "int $0x80\n" \ 58430ca2051SWilly Tarreau : "=a" (_ret) \ 58530ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 58630ca2051SWilly Tarreau "0"(_num) \ 58730ca2051SWilly Tarreau : "memory", "cc" \ 58830ca2051SWilly Tarreau ); \ 58930ca2051SWilly Tarreau _ret; \ 59030ca2051SWilly Tarreau }) 59130ca2051SWilly Tarreau 59230ca2051SWilly Tarreau /* startup code */ 593ebbe0d8aSWilly Tarreau /* 594ebbe0d8aSWilly Tarreau * i386 System V ABI mandates: 595ebbe0d8aSWilly Tarreau * 1) last pushed argument must be 16-byte aligned. 596ebbe0d8aSWilly Tarreau * 2) The deepest stack frame should be set to zero 597ebbe0d8aSWilly Tarreau * 598ebbe0d8aSWilly Tarreau */ 59930ca2051SWilly Tarreau asm(".section .text\n" 60030ca2051SWilly Tarreau ".global _start\n" 60130ca2051SWilly Tarreau "_start:\n" 60230ca2051SWilly Tarreau "pop %eax\n" // argc (first arg, %eax) 60330ca2051SWilly Tarreau "mov %esp, %ebx\n" // argv[] (second arg, %ebx) 60430ca2051SWilly Tarreau "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx) 605ebbe0d8aSWilly Tarreau "xor %ebp, %ebp\n" // zero the stack frame 606ebbe0d8aSWilly Tarreau "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned before 607ebbe0d8aSWilly Tarreau "sub $4, %esp\n" // the call instruction (args are aligned) 60830ca2051SWilly Tarreau "push %ecx\n" // push all registers on the stack so that we 60930ca2051SWilly Tarreau "push %ebx\n" // support both regparm and plain stack modes 61030ca2051SWilly Tarreau "push %eax\n" 61130ca2051SWilly Tarreau "call main\n" // main() returns the status code in %eax 612de0244aeSWilly Tarreau "mov %eax, %ebx\n" // retrieve exit code (32-bit int) 61330ca2051SWilly Tarreau "movl $1, %eax\n" // NR_exit == 1 61430ca2051SWilly Tarreau "int $0x80\n" // exit now 61530ca2051SWilly Tarreau "hlt\n" // ensure it does not 61630ca2051SWilly Tarreau ""); 61730ca2051SWilly Tarreau 61830ca2051SWilly Tarreau /* fcntl / open */ 61930ca2051SWilly Tarreau #define O_RDONLY 0 62030ca2051SWilly Tarreau #define O_WRONLY 1 62130ca2051SWilly Tarreau #define O_RDWR 2 62230ca2051SWilly Tarreau #define O_CREAT 0x40 62330ca2051SWilly Tarreau #define O_EXCL 0x80 62430ca2051SWilly Tarreau #define O_NOCTTY 0x100 62530ca2051SWilly Tarreau #define O_TRUNC 0x200 62630ca2051SWilly Tarreau #define O_APPEND 0x400 62730ca2051SWilly Tarreau #define O_NONBLOCK 0x800 62830ca2051SWilly Tarreau #define O_DIRECTORY 0x10000 62930ca2051SWilly Tarreau 63030ca2051SWilly Tarreau /* The struct returned by the stat() syscall, 32-bit only, the syscall returns 63130ca2051SWilly Tarreau * exactly 56 bytes (stops before the unused array). 63230ca2051SWilly Tarreau */ 63330ca2051SWilly Tarreau struct sys_stat_struct { 63430ca2051SWilly Tarreau unsigned long st_dev; 63530ca2051SWilly Tarreau unsigned long st_ino; 63630ca2051SWilly Tarreau unsigned short st_mode; 63730ca2051SWilly Tarreau unsigned short st_nlink; 63830ca2051SWilly Tarreau unsigned short st_uid; 63930ca2051SWilly Tarreau unsigned short st_gid; 64030ca2051SWilly Tarreau 64130ca2051SWilly Tarreau unsigned long st_rdev; 64230ca2051SWilly Tarreau unsigned long st_size; 64330ca2051SWilly Tarreau unsigned long st_blksize; 64430ca2051SWilly Tarreau unsigned long st_blocks; 64530ca2051SWilly Tarreau 64630ca2051SWilly Tarreau unsigned long st_atime; 64730ca2051SWilly Tarreau unsigned long st_atime_nsec; 64830ca2051SWilly Tarreau unsigned long st_mtime; 64930ca2051SWilly Tarreau unsigned long st_mtime_nsec; 65030ca2051SWilly Tarreau 65130ca2051SWilly Tarreau unsigned long st_ctime; 65230ca2051SWilly Tarreau unsigned long st_ctime_nsec; 65330ca2051SWilly Tarreau unsigned long __unused[2]; 65430ca2051SWilly Tarreau }; 65530ca2051SWilly Tarreau 65630ca2051SWilly Tarreau #elif defined(__ARM_EABI__) 65730ca2051SWilly Tarreau /* Syscalls for ARM in ARM or Thumb modes : 65830ca2051SWilly Tarreau * - registers are 32-bit 65930ca2051SWilly Tarreau * - stack is 8-byte aligned 66030ca2051SWilly Tarreau * ( http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html) 66130ca2051SWilly Tarreau * - syscall number is passed in r7 66230ca2051SWilly Tarreau * - arguments are in r0, r1, r2, r3, r4, r5 66330ca2051SWilly Tarreau * - the system call is performed by calling svc #0 66430ca2051SWilly Tarreau * - syscall return comes in r0. 66530ca2051SWilly Tarreau * - only lr is clobbered. 66630ca2051SWilly Tarreau * - the arguments are cast to long and assigned into the target registers 66730ca2051SWilly Tarreau * which are then simply passed as registers to the asm code, so that we 66830ca2051SWilly Tarreau * don't have to experience issues with register constraints. 66930ca2051SWilly Tarreau * - the syscall number is always specified last in order to allow to force 67030ca2051SWilly Tarreau * some registers before (gcc refuses a %-register at the last position). 67130ca2051SWilly Tarreau * 67230ca2051SWilly Tarreau * Also, ARM supports the old_select syscall if newselect is not available 67330ca2051SWilly Tarreau */ 67430ca2051SWilly Tarreau #define __ARCH_WANT_SYS_OLD_SELECT 67530ca2051SWilly Tarreau 67630ca2051SWilly Tarreau #define my_syscall0(num) \ 67730ca2051SWilly Tarreau ({ \ 67830ca2051SWilly Tarreau register long _num asm("r7") = (num); \ 67930ca2051SWilly Tarreau register long _arg1 asm("r0"); \ 68030ca2051SWilly Tarreau \ 68130ca2051SWilly Tarreau asm volatile ( \ 68230ca2051SWilly Tarreau "svc #0\n" \ 68330ca2051SWilly Tarreau : "=r"(_arg1) \ 68430ca2051SWilly Tarreau : "r"(_num) \ 68530ca2051SWilly Tarreau : "memory", "cc", "lr" \ 68630ca2051SWilly Tarreau ); \ 68730ca2051SWilly Tarreau _arg1; \ 68830ca2051SWilly Tarreau }) 68930ca2051SWilly Tarreau 69030ca2051SWilly Tarreau #define my_syscall1(num, arg1) \ 69130ca2051SWilly Tarreau ({ \ 69230ca2051SWilly Tarreau register long _num asm("r7") = (num); \ 69330ca2051SWilly Tarreau register long _arg1 asm("r0") = (long)(arg1); \ 69430ca2051SWilly Tarreau \ 69530ca2051SWilly Tarreau asm volatile ( \ 69630ca2051SWilly Tarreau "svc #0\n" \ 69730ca2051SWilly Tarreau : "=r"(_arg1) \ 69830ca2051SWilly Tarreau : "r"(_arg1), \ 69930ca2051SWilly Tarreau "r"(_num) \ 70030ca2051SWilly Tarreau : "memory", "cc", "lr" \ 70130ca2051SWilly Tarreau ); \ 70230ca2051SWilly Tarreau _arg1; \ 70330ca2051SWilly Tarreau }) 70430ca2051SWilly Tarreau 70530ca2051SWilly Tarreau #define my_syscall2(num, arg1, arg2) \ 70630ca2051SWilly Tarreau ({ \ 70730ca2051SWilly Tarreau register long _num asm("r7") = (num); \ 70830ca2051SWilly Tarreau register long _arg1 asm("r0") = (long)(arg1); \ 70930ca2051SWilly Tarreau register long _arg2 asm("r1") = (long)(arg2); \ 71030ca2051SWilly Tarreau \ 71130ca2051SWilly Tarreau asm volatile ( \ 71230ca2051SWilly Tarreau "svc #0\n" \ 71330ca2051SWilly Tarreau : "=r"(_arg1) \ 71430ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), \ 71530ca2051SWilly Tarreau "r"(_num) \ 71630ca2051SWilly Tarreau : "memory", "cc", "lr" \ 71730ca2051SWilly Tarreau ); \ 71830ca2051SWilly Tarreau _arg1; \ 71930ca2051SWilly Tarreau }) 72030ca2051SWilly Tarreau 72130ca2051SWilly Tarreau #define my_syscall3(num, arg1, arg2, arg3) \ 72230ca2051SWilly Tarreau ({ \ 72330ca2051SWilly Tarreau register long _num asm("r7") = (num); \ 72430ca2051SWilly Tarreau register long _arg1 asm("r0") = (long)(arg1); \ 72530ca2051SWilly Tarreau register long _arg2 asm("r1") = (long)(arg2); \ 72630ca2051SWilly Tarreau register long _arg3 asm("r2") = (long)(arg3); \ 72730ca2051SWilly Tarreau \ 72830ca2051SWilly Tarreau asm volatile ( \ 72930ca2051SWilly Tarreau "svc #0\n" \ 73030ca2051SWilly Tarreau : "=r"(_arg1) \ 73130ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ 73230ca2051SWilly Tarreau "r"(_num) \ 73330ca2051SWilly Tarreau : "memory", "cc", "lr" \ 73430ca2051SWilly Tarreau ); \ 73530ca2051SWilly Tarreau _arg1; \ 73630ca2051SWilly Tarreau }) 73730ca2051SWilly Tarreau 73830ca2051SWilly Tarreau #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 73930ca2051SWilly Tarreau ({ \ 74030ca2051SWilly Tarreau register long _num asm("r7") = (num); \ 74130ca2051SWilly Tarreau register long _arg1 asm("r0") = (long)(arg1); \ 74230ca2051SWilly Tarreau register long _arg2 asm("r1") = (long)(arg2); \ 74330ca2051SWilly Tarreau register long _arg3 asm("r2") = (long)(arg3); \ 74430ca2051SWilly Tarreau register long _arg4 asm("r3") = (long)(arg4); \ 74530ca2051SWilly Tarreau \ 74630ca2051SWilly Tarreau asm volatile ( \ 74730ca2051SWilly Tarreau "svc #0\n" \ 74830ca2051SWilly Tarreau : "=r"(_arg1) \ 74930ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 75030ca2051SWilly Tarreau "r"(_num) \ 75130ca2051SWilly Tarreau : "memory", "cc", "lr" \ 75230ca2051SWilly Tarreau ); \ 75330ca2051SWilly Tarreau _arg1; \ 75430ca2051SWilly Tarreau }) 75530ca2051SWilly Tarreau 75630ca2051SWilly Tarreau #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 75730ca2051SWilly Tarreau ({ \ 75830ca2051SWilly Tarreau register long _num asm("r7") = (num); \ 75930ca2051SWilly Tarreau register long _arg1 asm("r0") = (long)(arg1); \ 76030ca2051SWilly Tarreau register long _arg2 asm("r1") = (long)(arg2); \ 76130ca2051SWilly Tarreau register long _arg3 asm("r2") = (long)(arg3); \ 76230ca2051SWilly Tarreau register long _arg4 asm("r3") = (long)(arg4); \ 76330ca2051SWilly Tarreau register long _arg5 asm("r4") = (long)(arg5); \ 76430ca2051SWilly Tarreau \ 76530ca2051SWilly Tarreau asm volatile ( \ 76630ca2051SWilly Tarreau "svc #0\n" \ 76730ca2051SWilly Tarreau : "=r" (_arg1) \ 76830ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 76930ca2051SWilly Tarreau "r"(_num) \ 77030ca2051SWilly Tarreau : "memory", "cc", "lr" \ 77130ca2051SWilly Tarreau ); \ 77230ca2051SWilly Tarreau _arg1; \ 77330ca2051SWilly Tarreau }) 77430ca2051SWilly Tarreau 77530ca2051SWilly Tarreau /* startup code */ 77630ca2051SWilly Tarreau asm(".section .text\n" 77730ca2051SWilly Tarreau ".global _start\n" 77830ca2051SWilly Tarreau "_start:\n" 77930ca2051SWilly Tarreau #if defined(__THUMBEB__) || defined(__THUMBEL__) 78030ca2051SWilly Tarreau /* We enter here in 32-bit mode but if some previous functions were in 78130ca2051SWilly Tarreau * 16-bit mode, the assembler cannot know, so we need to tell it we're in 78230ca2051SWilly Tarreau * 32-bit now, then switch to 16-bit (is there a better way to do it than 78330ca2051SWilly Tarreau * adding 1 by hand ?) and tell the asm we're now in 16-bit mode so that 78430ca2051SWilly Tarreau * it generates correct instructions. Note that we do not support thumb1. 78530ca2051SWilly Tarreau */ 78630ca2051SWilly Tarreau ".code 32\n" 78730ca2051SWilly Tarreau "add r0, pc, #1\n" 78830ca2051SWilly Tarreau "bx r0\n" 78930ca2051SWilly Tarreau ".code 16\n" 79030ca2051SWilly Tarreau #endif 79130ca2051SWilly Tarreau "pop {%r0}\n" // argc was in the stack 79230ca2051SWilly Tarreau "mov %r1, %sp\n" // argv = sp 79330ca2051SWilly Tarreau "add %r2, %r1, %r0, lsl #2\n" // envp = argv + 4*argc ... 79430ca2051SWilly Tarreau "add %r2, %r2, $4\n" // ... + 4 79530ca2051SWilly Tarreau "and %r3, %r1, $-8\n" // AAPCS : sp must be 8-byte aligned in the 79630ca2051SWilly Tarreau "mov %sp, %r3\n" // callee, an bl doesn't push (lr=pc) 79730ca2051SWilly Tarreau "bl main\n" // main() returns the status code, we'll exit with it. 79830ca2051SWilly Tarreau "movs r7, $1\n" // NR_exit == 1 79930ca2051SWilly Tarreau "svc $0x00\n" 80030ca2051SWilly Tarreau ""); 80130ca2051SWilly Tarreau 80230ca2051SWilly Tarreau /* fcntl / open */ 80330ca2051SWilly Tarreau #define O_RDONLY 0 80430ca2051SWilly Tarreau #define O_WRONLY 1 80530ca2051SWilly Tarreau #define O_RDWR 2 80630ca2051SWilly Tarreau #define O_CREAT 0x40 80730ca2051SWilly Tarreau #define O_EXCL 0x80 80830ca2051SWilly Tarreau #define O_NOCTTY 0x100 80930ca2051SWilly Tarreau #define O_TRUNC 0x200 81030ca2051SWilly Tarreau #define O_APPEND 0x400 81130ca2051SWilly Tarreau #define O_NONBLOCK 0x800 81230ca2051SWilly Tarreau #define O_DIRECTORY 0x4000 81330ca2051SWilly Tarreau 81430ca2051SWilly Tarreau /* The struct returned by the stat() syscall, 32-bit only, the syscall returns 81530ca2051SWilly Tarreau * exactly 56 bytes (stops before the unused array). In big endian, the format 81630ca2051SWilly Tarreau * differs as devices are returned as short only. 81730ca2051SWilly Tarreau */ 81830ca2051SWilly Tarreau struct sys_stat_struct { 81930ca2051SWilly Tarreau #if defined(__ARMEB__) 82030ca2051SWilly Tarreau unsigned short st_dev; 82130ca2051SWilly Tarreau unsigned short __pad1; 82230ca2051SWilly Tarreau #else 82330ca2051SWilly Tarreau unsigned long st_dev; 82430ca2051SWilly Tarreau #endif 82530ca2051SWilly Tarreau unsigned long st_ino; 82630ca2051SWilly Tarreau unsigned short st_mode; 82730ca2051SWilly Tarreau unsigned short st_nlink; 82830ca2051SWilly Tarreau unsigned short st_uid; 82930ca2051SWilly Tarreau unsigned short st_gid; 83030ca2051SWilly Tarreau #if defined(__ARMEB__) 83130ca2051SWilly Tarreau unsigned short st_rdev; 83230ca2051SWilly Tarreau unsigned short __pad2; 83330ca2051SWilly Tarreau #else 83430ca2051SWilly Tarreau unsigned long st_rdev; 83530ca2051SWilly Tarreau #endif 83630ca2051SWilly Tarreau unsigned long st_size; 83730ca2051SWilly Tarreau unsigned long st_blksize; 83830ca2051SWilly Tarreau unsigned long st_blocks; 83930ca2051SWilly Tarreau unsigned long st_atime; 84030ca2051SWilly Tarreau unsigned long st_atime_nsec; 84130ca2051SWilly Tarreau unsigned long st_mtime; 84230ca2051SWilly Tarreau unsigned long st_mtime_nsec; 84330ca2051SWilly Tarreau unsigned long st_ctime; 84430ca2051SWilly Tarreau unsigned long st_ctime_nsec; 84530ca2051SWilly Tarreau unsigned long __unused[2]; 84630ca2051SWilly Tarreau }; 84730ca2051SWilly Tarreau 84830ca2051SWilly Tarreau #elif defined(__aarch64__) 84930ca2051SWilly Tarreau /* Syscalls for AARCH64 : 85030ca2051SWilly Tarreau * - registers are 64-bit 85130ca2051SWilly Tarreau * - stack is 16-byte aligned 85230ca2051SWilly Tarreau * - syscall number is passed in x8 85330ca2051SWilly Tarreau * - arguments are in x0, x1, x2, x3, x4, x5 85430ca2051SWilly Tarreau * - the system call is performed by calling svc 0 85530ca2051SWilly Tarreau * - syscall return comes in x0. 85630ca2051SWilly Tarreau * - the arguments are cast to long and assigned into the target registers 85730ca2051SWilly Tarreau * which are then simply passed as registers to the asm code, so that we 85830ca2051SWilly Tarreau * don't have to experience issues with register constraints. 85930ca2051SWilly Tarreau * 86030ca2051SWilly Tarreau * On aarch64, select() is not implemented so we have to use pselect6(). 86130ca2051SWilly Tarreau */ 86230ca2051SWilly Tarreau #define __ARCH_WANT_SYS_PSELECT6 86330ca2051SWilly Tarreau 86430ca2051SWilly Tarreau #define my_syscall0(num) \ 86530ca2051SWilly Tarreau ({ \ 86630ca2051SWilly Tarreau register long _num asm("x8") = (num); \ 86730ca2051SWilly Tarreau register long _arg1 asm("x0"); \ 86830ca2051SWilly Tarreau \ 86930ca2051SWilly Tarreau asm volatile ( \ 87030ca2051SWilly Tarreau "svc #0\n" \ 87130ca2051SWilly Tarreau : "=r"(_arg1) \ 87230ca2051SWilly Tarreau : "r"(_num) \ 87330ca2051SWilly Tarreau : "memory", "cc" \ 87430ca2051SWilly Tarreau ); \ 87530ca2051SWilly Tarreau _arg1; \ 87630ca2051SWilly Tarreau }) 87730ca2051SWilly Tarreau 87830ca2051SWilly Tarreau #define my_syscall1(num, arg1) \ 87930ca2051SWilly Tarreau ({ \ 88030ca2051SWilly Tarreau register long _num asm("x8") = (num); \ 88130ca2051SWilly Tarreau register long _arg1 asm("x0") = (long)(arg1); \ 88230ca2051SWilly Tarreau \ 88330ca2051SWilly Tarreau asm volatile ( \ 88430ca2051SWilly Tarreau "svc #0\n" \ 88530ca2051SWilly Tarreau : "=r"(_arg1) \ 88630ca2051SWilly Tarreau : "r"(_arg1), \ 88730ca2051SWilly Tarreau "r"(_num) \ 88830ca2051SWilly Tarreau : "memory", "cc" \ 88930ca2051SWilly Tarreau ); \ 89030ca2051SWilly Tarreau _arg1; \ 89130ca2051SWilly Tarreau }) 89230ca2051SWilly Tarreau 89330ca2051SWilly Tarreau #define my_syscall2(num, arg1, arg2) \ 89430ca2051SWilly Tarreau ({ \ 89530ca2051SWilly Tarreau register long _num asm("x8") = (num); \ 89630ca2051SWilly Tarreau register long _arg1 asm("x0") = (long)(arg1); \ 89730ca2051SWilly Tarreau register long _arg2 asm("x1") = (long)(arg2); \ 89830ca2051SWilly Tarreau \ 89930ca2051SWilly Tarreau asm volatile ( \ 90030ca2051SWilly Tarreau "svc #0\n" \ 90130ca2051SWilly Tarreau : "=r"(_arg1) \ 90230ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), \ 90330ca2051SWilly Tarreau "r"(_num) \ 90430ca2051SWilly Tarreau : "memory", "cc" \ 90530ca2051SWilly Tarreau ); \ 90630ca2051SWilly Tarreau _arg1; \ 90730ca2051SWilly Tarreau }) 90830ca2051SWilly Tarreau 90930ca2051SWilly Tarreau #define my_syscall3(num, arg1, arg2, arg3) \ 91030ca2051SWilly Tarreau ({ \ 91130ca2051SWilly Tarreau register long _num asm("x8") = (num); \ 91230ca2051SWilly Tarreau register long _arg1 asm("x0") = (long)(arg1); \ 91330ca2051SWilly Tarreau register long _arg2 asm("x1") = (long)(arg2); \ 91430ca2051SWilly Tarreau register long _arg3 asm("x2") = (long)(arg3); \ 91530ca2051SWilly Tarreau \ 91630ca2051SWilly Tarreau asm volatile ( \ 91730ca2051SWilly Tarreau "svc #0\n" \ 91830ca2051SWilly Tarreau : "=r"(_arg1) \ 91930ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ 92030ca2051SWilly Tarreau "r"(_num) \ 92130ca2051SWilly Tarreau : "memory", "cc" \ 92230ca2051SWilly Tarreau ); \ 92330ca2051SWilly Tarreau _arg1; \ 92430ca2051SWilly Tarreau }) 92530ca2051SWilly Tarreau 92630ca2051SWilly Tarreau #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 92730ca2051SWilly Tarreau ({ \ 92830ca2051SWilly Tarreau register long _num asm("x8") = (num); \ 92930ca2051SWilly Tarreau register long _arg1 asm("x0") = (long)(arg1); \ 93030ca2051SWilly Tarreau register long _arg2 asm("x1") = (long)(arg2); \ 93130ca2051SWilly Tarreau register long _arg3 asm("x2") = (long)(arg3); \ 93230ca2051SWilly Tarreau register long _arg4 asm("x3") = (long)(arg4); \ 93330ca2051SWilly Tarreau \ 93430ca2051SWilly Tarreau asm volatile ( \ 93530ca2051SWilly Tarreau "svc #0\n" \ 93630ca2051SWilly Tarreau : "=r"(_arg1) \ 93730ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 93830ca2051SWilly Tarreau "r"(_num) \ 93930ca2051SWilly Tarreau : "memory", "cc" \ 94030ca2051SWilly Tarreau ); \ 94130ca2051SWilly Tarreau _arg1; \ 94230ca2051SWilly Tarreau }) 94330ca2051SWilly Tarreau 94430ca2051SWilly Tarreau #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 94530ca2051SWilly Tarreau ({ \ 94630ca2051SWilly Tarreau register long _num asm("x8") = (num); \ 94730ca2051SWilly Tarreau register long _arg1 asm("x0") = (long)(arg1); \ 94830ca2051SWilly Tarreau register long _arg2 asm("x1") = (long)(arg2); \ 94930ca2051SWilly Tarreau register long _arg3 asm("x2") = (long)(arg3); \ 95030ca2051SWilly Tarreau register long _arg4 asm("x3") = (long)(arg4); \ 95130ca2051SWilly Tarreau register long _arg5 asm("x4") = (long)(arg5); \ 95230ca2051SWilly Tarreau \ 95330ca2051SWilly Tarreau asm volatile ( \ 95430ca2051SWilly Tarreau "svc #0\n" \ 95530ca2051SWilly Tarreau : "=r" (_arg1) \ 95630ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 95730ca2051SWilly Tarreau "r"(_num) \ 95830ca2051SWilly Tarreau : "memory", "cc" \ 95930ca2051SWilly Tarreau ); \ 96030ca2051SWilly Tarreau _arg1; \ 96130ca2051SWilly Tarreau }) 96230ca2051SWilly Tarreau 96330ca2051SWilly Tarreau #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 96430ca2051SWilly Tarreau ({ \ 96530ca2051SWilly Tarreau register long _num asm("x8") = (num); \ 96630ca2051SWilly Tarreau register long _arg1 asm("x0") = (long)(arg1); \ 96730ca2051SWilly Tarreau register long _arg2 asm("x1") = (long)(arg2); \ 96830ca2051SWilly Tarreau register long _arg3 asm("x2") = (long)(arg3); \ 96930ca2051SWilly Tarreau register long _arg4 asm("x3") = (long)(arg4); \ 97030ca2051SWilly Tarreau register long _arg5 asm("x4") = (long)(arg5); \ 97130ca2051SWilly Tarreau register long _arg6 asm("x5") = (long)(arg6); \ 97230ca2051SWilly Tarreau \ 97330ca2051SWilly Tarreau asm volatile ( \ 97430ca2051SWilly Tarreau "svc #0\n" \ 97530ca2051SWilly Tarreau : "=r" (_arg1) \ 97630ca2051SWilly Tarreau : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 97730ca2051SWilly Tarreau "r"(_arg6), "r"(_num) \ 97830ca2051SWilly Tarreau : "memory", "cc" \ 97930ca2051SWilly Tarreau ); \ 98030ca2051SWilly Tarreau _arg1; \ 98130ca2051SWilly Tarreau }) 98230ca2051SWilly Tarreau 98330ca2051SWilly Tarreau /* startup code */ 98430ca2051SWilly Tarreau asm(".section .text\n" 98530ca2051SWilly Tarreau ".global _start\n" 98630ca2051SWilly Tarreau "_start:\n" 98730ca2051SWilly Tarreau "ldr x0, [sp]\n" // argc (x0) was in the stack 98830ca2051SWilly Tarreau "add x1, sp, 8\n" // argv (x1) = sp 98930ca2051SWilly Tarreau "lsl x2, x0, 3\n" // envp (x2) = 8*argc ... 99030ca2051SWilly Tarreau "add x2, x2, 8\n" // + 8 (skip null) 99130ca2051SWilly Tarreau "add x2, x2, x1\n" // + argv 99230ca2051SWilly Tarreau "and sp, x1, -16\n" // sp must be 16-byte aligned in the callee 99330ca2051SWilly Tarreau "bl main\n" // main() returns the status code, we'll exit with it. 99430ca2051SWilly Tarreau "mov x8, 93\n" // NR_exit == 93 99530ca2051SWilly Tarreau "svc #0\n" 99630ca2051SWilly Tarreau ""); 99730ca2051SWilly Tarreau 99830ca2051SWilly Tarreau /* fcntl / open */ 99930ca2051SWilly Tarreau #define O_RDONLY 0 100030ca2051SWilly Tarreau #define O_WRONLY 1 100130ca2051SWilly Tarreau #define O_RDWR 2 100230ca2051SWilly Tarreau #define O_CREAT 0x40 100330ca2051SWilly Tarreau #define O_EXCL 0x80 100430ca2051SWilly Tarreau #define O_NOCTTY 0x100 100530ca2051SWilly Tarreau #define O_TRUNC 0x200 100630ca2051SWilly Tarreau #define O_APPEND 0x400 100730ca2051SWilly Tarreau #define O_NONBLOCK 0x800 100830ca2051SWilly Tarreau #define O_DIRECTORY 0x4000 100930ca2051SWilly Tarreau 101030ca2051SWilly Tarreau /* The struct returned by the newfstatat() syscall. Differs slightly from the 101130ca2051SWilly Tarreau * x86_64's stat one by field ordering, so be careful. 101230ca2051SWilly Tarreau */ 101330ca2051SWilly Tarreau struct sys_stat_struct { 101430ca2051SWilly Tarreau unsigned long st_dev; 101530ca2051SWilly Tarreau unsigned long st_ino; 101630ca2051SWilly Tarreau unsigned int st_mode; 101730ca2051SWilly Tarreau unsigned int st_nlink; 101830ca2051SWilly Tarreau unsigned int st_uid; 101930ca2051SWilly Tarreau unsigned int st_gid; 102030ca2051SWilly Tarreau 102130ca2051SWilly Tarreau unsigned long st_rdev; 102230ca2051SWilly Tarreau unsigned long __pad1; 102330ca2051SWilly Tarreau long st_size; 102430ca2051SWilly Tarreau int st_blksize; 102530ca2051SWilly Tarreau int __pad2; 102630ca2051SWilly Tarreau 102730ca2051SWilly Tarreau long st_blocks; 102830ca2051SWilly Tarreau long st_atime; 102930ca2051SWilly Tarreau unsigned long st_atime_nsec; 103030ca2051SWilly Tarreau long st_mtime; 103130ca2051SWilly Tarreau 103230ca2051SWilly Tarreau unsigned long st_mtime_nsec; 103330ca2051SWilly Tarreau long st_ctime; 103430ca2051SWilly Tarreau unsigned long st_ctime_nsec; 103530ca2051SWilly Tarreau unsigned int __unused[2]; 103630ca2051SWilly Tarreau }; 103730ca2051SWilly Tarreau 103830ca2051SWilly Tarreau #elif defined(__mips__) && defined(_ABIO32) 103930ca2051SWilly Tarreau /* Syscalls for MIPS ABI O32 : 104030ca2051SWilly Tarreau * - WARNING! there's always a delayed slot! 104130ca2051SWilly Tarreau * - WARNING again, the syntax is different, registers take a '$' and numbers 104230ca2051SWilly Tarreau * do not. 104330ca2051SWilly Tarreau * - registers are 32-bit 104430ca2051SWilly Tarreau * - stack is 8-byte aligned 104530ca2051SWilly Tarreau * - syscall number is passed in v0 (starts at 0xfa0). 104630ca2051SWilly Tarreau * - arguments are in a0, a1, a2, a3, then the stack. The caller needs to 104730ca2051SWilly Tarreau * leave some room in the stack for the callee to save a0..a3 if needed. 104830ca2051SWilly Tarreau * - Many registers are clobbered, in fact only a0..a2 and s0..s8 are 104930ca2051SWilly Tarreau * preserved. See: https://www.linux-mips.org/wiki/Syscall as well as 105030ca2051SWilly Tarreau * scall32-o32.S in the kernel sources. 105130ca2051SWilly Tarreau * - the system call is performed by calling "syscall" 105230ca2051SWilly Tarreau * - syscall return comes in v0, and register a3 needs to be checked to know 10539a83f9aeSBhaskar Chowdhury * if an error occurred, in which case errno is in v0. 105430ca2051SWilly Tarreau * - the arguments are cast to long and assigned into the target registers 105530ca2051SWilly Tarreau * which are then simply passed as registers to the asm code, so that we 105630ca2051SWilly Tarreau * don't have to experience issues with register constraints. 105730ca2051SWilly Tarreau */ 105830ca2051SWilly Tarreau 105930ca2051SWilly Tarreau #define my_syscall0(num) \ 106030ca2051SWilly Tarreau ({ \ 106130ca2051SWilly Tarreau register long _num asm("v0") = (num); \ 106230ca2051SWilly Tarreau register long _arg4 asm("a3"); \ 106330ca2051SWilly Tarreau \ 106430ca2051SWilly Tarreau asm volatile ( \ 106530ca2051SWilly Tarreau "addiu $sp, $sp, -32\n" \ 106630ca2051SWilly Tarreau "syscall\n" \ 106730ca2051SWilly Tarreau "addiu $sp, $sp, 32\n" \ 106830ca2051SWilly Tarreau : "=r"(_num), "=r"(_arg4) \ 106930ca2051SWilly Tarreau : "r"(_num) \ 107030ca2051SWilly Tarreau : "memory", "cc", "at", "v1", "hi", "lo", \ 107130ca2051SWilly Tarreau "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ 107230ca2051SWilly Tarreau ); \ 107330ca2051SWilly Tarreau _arg4 ? -_num : _num; \ 107430ca2051SWilly Tarreau }) 107530ca2051SWilly Tarreau 107630ca2051SWilly Tarreau #define my_syscall1(num, arg1) \ 107730ca2051SWilly Tarreau ({ \ 107830ca2051SWilly Tarreau register long _num asm("v0") = (num); \ 107930ca2051SWilly Tarreau register long _arg1 asm("a0") = (long)(arg1); \ 108030ca2051SWilly Tarreau register long _arg4 asm("a3"); \ 108130ca2051SWilly Tarreau \ 108230ca2051SWilly Tarreau asm volatile ( \ 108330ca2051SWilly Tarreau "addiu $sp, $sp, -32\n" \ 108430ca2051SWilly Tarreau "syscall\n" \ 108530ca2051SWilly Tarreau "addiu $sp, $sp, 32\n" \ 108630ca2051SWilly Tarreau : "=r"(_num), "=r"(_arg4) \ 108730ca2051SWilly Tarreau : "0"(_num), \ 108830ca2051SWilly Tarreau "r"(_arg1) \ 108930ca2051SWilly Tarreau : "memory", "cc", "at", "v1", "hi", "lo", \ 109030ca2051SWilly Tarreau "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ 109130ca2051SWilly Tarreau ); \ 109230ca2051SWilly Tarreau _arg4 ? -_num : _num; \ 109330ca2051SWilly Tarreau }) 109430ca2051SWilly Tarreau 109530ca2051SWilly Tarreau #define my_syscall2(num, arg1, arg2) \ 109630ca2051SWilly Tarreau ({ \ 109730ca2051SWilly Tarreau register long _num asm("v0") = (num); \ 109830ca2051SWilly Tarreau register long _arg1 asm("a0") = (long)(arg1); \ 109930ca2051SWilly Tarreau register long _arg2 asm("a1") = (long)(arg2); \ 110030ca2051SWilly Tarreau register long _arg4 asm("a3"); \ 110130ca2051SWilly Tarreau \ 110230ca2051SWilly Tarreau asm volatile ( \ 110330ca2051SWilly Tarreau "addiu $sp, $sp, -32\n" \ 110430ca2051SWilly Tarreau "syscall\n" \ 110530ca2051SWilly Tarreau "addiu $sp, $sp, 32\n" \ 110630ca2051SWilly Tarreau : "=r"(_num), "=r"(_arg4) \ 110730ca2051SWilly Tarreau : "0"(_num), \ 110830ca2051SWilly Tarreau "r"(_arg1), "r"(_arg2) \ 110930ca2051SWilly Tarreau : "memory", "cc", "at", "v1", "hi", "lo", \ 111030ca2051SWilly Tarreau "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ 111130ca2051SWilly Tarreau ); \ 111230ca2051SWilly Tarreau _arg4 ? -_num : _num; \ 111330ca2051SWilly Tarreau }) 111430ca2051SWilly Tarreau 111530ca2051SWilly Tarreau #define my_syscall3(num, arg1, arg2, arg3) \ 111630ca2051SWilly Tarreau ({ \ 111730ca2051SWilly Tarreau register long _num asm("v0") = (num); \ 111830ca2051SWilly Tarreau register long _arg1 asm("a0") = (long)(arg1); \ 111930ca2051SWilly Tarreau register long _arg2 asm("a1") = (long)(arg2); \ 112030ca2051SWilly Tarreau register long _arg3 asm("a2") = (long)(arg3); \ 112130ca2051SWilly Tarreau register long _arg4 asm("a3"); \ 112230ca2051SWilly Tarreau \ 112330ca2051SWilly Tarreau asm volatile ( \ 112430ca2051SWilly Tarreau "addiu $sp, $sp, -32\n" \ 112530ca2051SWilly Tarreau "syscall\n" \ 112630ca2051SWilly Tarreau "addiu $sp, $sp, 32\n" \ 112730ca2051SWilly Tarreau : "=r"(_num), "=r"(_arg4) \ 112830ca2051SWilly Tarreau : "0"(_num), \ 112930ca2051SWilly Tarreau "r"(_arg1), "r"(_arg2), "r"(_arg3) \ 113030ca2051SWilly Tarreau : "memory", "cc", "at", "v1", "hi", "lo", \ 113130ca2051SWilly Tarreau "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ 113230ca2051SWilly Tarreau ); \ 113330ca2051SWilly Tarreau _arg4 ? -_num : _num; \ 113430ca2051SWilly Tarreau }) 113530ca2051SWilly Tarreau 113630ca2051SWilly Tarreau #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 113730ca2051SWilly Tarreau ({ \ 113830ca2051SWilly Tarreau register long _num asm("v0") = (num); \ 113930ca2051SWilly Tarreau register long _arg1 asm("a0") = (long)(arg1); \ 114030ca2051SWilly Tarreau register long _arg2 asm("a1") = (long)(arg2); \ 114130ca2051SWilly Tarreau register long _arg3 asm("a2") = (long)(arg3); \ 114230ca2051SWilly Tarreau register long _arg4 asm("a3") = (long)(arg4); \ 114330ca2051SWilly Tarreau \ 114430ca2051SWilly Tarreau asm volatile ( \ 114530ca2051SWilly Tarreau "addiu $sp, $sp, -32\n" \ 114630ca2051SWilly Tarreau "syscall\n" \ 114730ca2051SWilly Tarreau "addiu $sp, $sp, 32\n" \ 114830ca2051SWilly Tarreau : "=r" (_num), "=r"(_arg4) \ 114930ca2051SWilly Tarreau : "0"(_num), \ 115030ca2051SWilly Tarreau "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \ 115130ca2051SWilly Tarreau : "memory", "cc", "at", "v1", "hi", "lo", \ 115230ca2051SWilly Tarreau "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ 115330ca2051SWilly Tarreau ); \ 115430ca2051SWilly Tarreau _arg4 ? -_num : _num; \ 115530ca2051SWilly Tarreau }) 115630ca2051SWilly Tarreau 115730ca2051SWilly Tarreau #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 115830ca2051SWilly Tarreau ({ \ 115930ca2051SWilly Tarreau register long _num asm("v0") = (num); \ 116030ca2051SWilly Tarreau register long _arg1 asm("a0") = (long)(arg1); \ 116130ca2051SWilly Tarreau register long _arg2 asm("a1") = (long)(arg2); \ 116230ca2051SWilly Tarreau register long _arg3 asm("a2") = (long)(arg3); \ 116330ca2051SWilly Tarreau register long _arg4 asm("a3") = (long)(arg4); \ 116430ca2051SWilly Tarreau register long _arg5 = (long)(arg5); \ 116530ca2051SWilly Tarreau \ 116630ca2051SWilly Tarreau asm volatile ( \ 116730ca2051SWilly Tarreau "addiu $sp, $sp, -32\n" \ 116830ca2051SWilly Tarreau "sw %7, 16($sp)\n" \ 116930ca2051SWilly Tarreau "syscall\n " \ 117030ca2051SWilly Tarreau "addiu $sp, $sp, 32\n" \ 117130ca2051SWilly Tarreau : "=r" (_num), "=r"(_arg4) \ 117230ca2051SWilly Tarreau : "0"(_num), \ 117330ca2051SWilly Tarreau "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \ 117430ca2051SWilly Tarreau : "memory", "cc", "at", "v1", "hi", "lo", \ 117530ca2051SWilly Tarreau "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ 117630ca2051SWilly Tarreau ); \ 117730ca2051SWilly Tarreau _arg4 ? -_num : _num; \ 117830ca2051SWilly Tarreau }) 117930ca2051SWilly Tarreau 118030ca2051SWilly Tarreau /* startup code, note that it's called __start on MIPS */ 118130ca2051SWilly Tarreau asm(".section .text\n" 118230ca2051SWilly Tarreau ".set nomips16\n" 118330ca2051SWilly Tarreau ".global __start\n" 118430ca2051SWilly Tarreau ".set noreorder\n" 118530ca2051SWilly Tarreau ".option pic0\n" 118630ca2051SWilly Tarreau ".ent __start\n" 118730ca2051SWilly Tarreau "__start:\n" 118830ca2051SWilly Tarreau "lw $a0,($sp)\n" // argc was in the stack 118930ca2051SWilly Tarreau "addiu $a1, $sp, 4\n" // argv = sp + 4 119030ca2051SWilly Tarreau "sll $a2, $a0, 2\n" // a2 = argc * 4 119130ca2051SWilly Tarreau "add $a2, $a2, $a1\n" // envp = argv + 4*argc ... 119230ca2051SWilly Tarreau "addiu $a2, $a2, 4\n" // ... + 4 119330ca2051SWilly Tarreau "li $t0, -8\n" 119430ca2051SWilly Tarreau "and $sp, $sp, $t0\n" // sp must be 8-byte aligned 119530ca2051SWilly Tarreau "addiu $sp,$sp,-16\n" // the callee expects to save a0..a3 there! 119630ca2051SWilly Tarreau "jal main\n" // main() returns the status code, we'll exit with it. 119730ca2051SWilly Tarreau "nop\n" // delayed slot 1198de0244aeSWilly Tarreau "move $a0, $v0\n" // retrieve 32-bit exit code from v0 119930ca2051SWilly Tarreau "li $v0, 4001\n" // NR_exit == 4001 120030ca2051SWilly Tarreau "syscall\n" 120130ca2051SWilly Tarreau ".end __start\n" 120230ca2051SWilly Tarreau ""); 120330ca2051SWilly Tarreau 120430ca2051SWilly Tarreau /* fcntl / open */ 120530ca2051SWilly Tarreau #define O_RDONLY 0 120630ca2051SWilly Tarreau #define O_WRONLY 1 120730ca2051SWilly Tarreau #define O_RDWR 2 120830ca2051SWilly Tarreau #define O_APPEND 0x0008 120930ca2051SWilly Tarreau #define O_NONBLOCK 0x0080 121030ca2051SWilly Tarreau #define O_CREAT 0x0100 121130ca2051SWilly Tarreau #define O_TRUNC 0x0200 121230ca2051SWilly Tarreau #define O_EXCL 0x0400 121330ca2051SWilly Tarreau #define O_NOCTTY 0x0800 121430ca2051SWilly Tarreau #define O_DIRECTORY 0x10000 121530ca2051SWilly Tarreau 121630ca2051SWilly Tarreau /* The struct returned by the stat() syscall. 88 bytes are returned by the 121730ca2051SWilly Tarreau * syscall. 121830ca2051SWilly Tarreau */ 121930ca2051SWilly Tarreau struct sys_stat_struct { 122030ca2051SWilly Tarreau unsigned int st_dev; 122130ca2051SWilly Tarreau long st_pad1[3]; 122230ca2051SWilly Tarreau unsigned long st_ino; 122330ca2051SWilly Tarreau unsigned int st_mode; 122430ca2051SWilly Tarreau unsigned int st_nlink; 122530ca2051SWilly Tarreau unsigned int st_uid; 122630ca2051SWilly Tarreau unsigned int st_gid; 122730ca2051SWilly Tarreau unsigned int st_rdev; 122830ca2051SWilly Tarreau long st_pad2[2]; 122930ca2051SWilly Tarreau long st_size; 123030ca2051SWilly Tarreau long st_pad3; 123130ca2051SWilly Tarreau long st_atime; 123230ca2051SWilly Tarreau long st_atime_nsec; 123330ca2051SWilly Tarreau long st_mtime; 123430ca2051SWilly Tarreau long st_mtime_nsec; 123530ca2051SWilly Tarreau long st_ctime; 123630ca2051SWilly Tarreau long st_ctime_nsec; 123730ca2051SWilly Tarreau long st_blksize; 123830ca2051SWilly Tarreau long st_blocks; 123930ca2051SWilly Tarreau long st_pad4[14]; 124030ca2051SWilly Tarreau }; 124130ca2051SWilly Tarreau 1242582e84f7SPranith Kumar #elif defined(__riscv) 1243582e84f7SPranith Kumar 1244582e84f7SPranith Kumar #if __riscv_xlen == 64 1245582e84f7SPranith Kumar #define PTRLOG "3" 1246582e84f7SPranith Kumar #define SZREG "8" 1247582e84f7SPranith Kumar #elif __riscv_xlen == 32 1248582e84f7SPranith Kumar #define PTRLOG "2" 1249582e84f7SPranith Kumar #define SZREG "4" 1250582e84f7SPranith Kumar #endif 1251582e84f7SPranith Kumar 1252582e84f7SPranith Kumar /* Syscalls for RISCV : 1253582e84f7SPranith Kumar * - stack is 16-byte aligned 1254582e84f7SPranith Kumar * - syscall number is passed in a7 1255582e84f7SPranith Kumar * - arguments are in a0, a1, a2, a3, a4, a5 1256582e84f7SPranith Kumar * - the system call is performed by calling ecall 1257582e84f7SPranith Kumar * - syscall return comes in a0 1258582e84f7SPranith Kumar * - the arguments are cast to long and assigned into the target 1259582e84f7SPranith Kumar * registers which are then simply passed as registers to the asm code, 1260582e84f7SPranith Kumar * so that we don't have to experience issues with register constraints. 12619c2970fbSWilly Tarreau * 12629c2970fbSWilly Tarreau * On riscv, select() is not implemented so we have to use pselect6(). 1263582e84f7SPranith Kumar */ 12649c2970fbSWilly Tarreau #define __ARCH_WANT_SYS_PSELECT6 1265582e84f7SPranith Kumar 1266582e84f7SPranith Kumar #define my_syscall0(num) \ 1267582e84f7SPranith Kumar ({ \ 1268582e84f7SPranith Kumar register long _num asm("a7") = (num); \ 1269582e84f7SPranith Kumar register long _arg1 asm("a0"); \ 1270582e84f7SPranith Kumar \ 1271582e84f7SPranith Kumar asm volatile ( \ 1272582e84f7SPranith Kumar "ecall\n\t" \ 1273582e84f7SPranith Kumar : "=r"(_arg1) \ 1274582e84f7SPranith Kumar : "r"(_num) \ 1275582e84f7SPranith Kumar : "memory", "cc" \ 1276582e84f7SPranith Kumar ); \ 1277582e84f7SPranith Kumar _arg1; \ 1278582e84f7SPranith Kumar }) 1279582e84f7SPranith Kumar 1280582e84f7SPranith Kumar #define my_syscall1(num, arg1) \ 1281582e84f7SPranith Kumar ({ \ 1282582e84f7SPranith Kumar register long _num asm("a7") = (num); \ 1283582e84f7SPranith Kumar register long _arg1 asm("a0") = (long)(arg1); \ 1284582e84f7SPranith Kumar \ 1285582e84f7SPranith Kumar asm volatile ( \ 1286582e84f7SPranith Kumar "ecall\n" \ 1287582e84f7SPranith Kumar : "+r"(_arg1) \ 1288582e84f7SPranith Kumar : "r"(_num) \ 1289582e84f7SPranith Kumar : "memory", "cc" \ 1290582e84f7SPranith Kumar ); \ 1291582e84f7SPranith Kumar _arg1; \ 1292582e84f7SPranith Kumar }) 1293582e84f7SPranith Kumar 1294582e84f7SPranith Kumar #define my_syscall2(num, arg1, arg2) \ 1295582e84f7SPranith Kumar ({ \ 1296582e84f7SPranith Kumar register long _num asm("a7") = (num); \ 1297582e84f7SPranith Kumar register long _arg1 asm("a0") = (long)(arg1); \ 1298582e84f7SPranith Kumar register long _arg2 asm("a1") = (long)(arg2); \ 1299582e84f7SPranith Kumar \ 1300582e84f7SPranith Kumar asm volatile ( \ 1301582e84f7SPranith Kumar "ecall\n" \ 1302582e84f7SPranith Kumar : "+r"(_arg1) \ 1303582e84f7SPranith Kumar : "r"(_arg2), \ 1304582e84f7SPranith Kumar "r"(_num) \ 1305582e84f7SPranith Kumar : "memory", "cc" \ 1306582e84f7SPranith Kumar ); \ 1307582e84f7SPranith Kumar _arg1; \ 1308582e84f7SPranith Kumar }) 1309582e84f7SPranith Kumar 1310582e84f7SPranith Kumar #define my_syscall3(num, arg1, arg2, arg3) \ 1311582e84f7SPranith Kumar ({ \ 1312582e84f7SPranith Kumar register long _num asm("a7") = (num); \ 1313582e84f7SPranith Kumar register long _arg1 asm("a0") = (long)(arg1); \ 1314582e84f7SPranith Kumar register long _arg2 asm("a1") = (long)(arg2); \ 1315582e84f7SPranith Kumar register long _arg3 asm("a2") = (long)(arg3); \ 1316582e84f7SPranith Kumar \ 1317582e84f7SPranith Kumar asm volatile ( \ 1318582e84f7SPranith Kumar "ecall\n\t" \ 1319582e84f7SPranith Kumar : "+r"(_arg1) \ 1320582e84f7SPranith Kumar : "r"(_arg2), "r"(_arg3), \ 1321582e84f7SPranith Kumar "r"(_num) \ 1322582e84f7SPranith Kumar : "memory", "cc" \ 1323582e84f7SPranith Kumar ); \ 1324582e84f7SPranith Kumar _arg1; \ 1325582e84f7SPranith Kumar }) 1326582e84f7SPranith Kumar 1327582e84f7SPranith Kumar #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 1328582e84f7SPranith Kumar ({ \ 1329582e84f7SPranith Kumar register long _num asm("a7") = (num); \ 1330582e84f7SPranith Kumar register long _arg1 asm("a0") = (long)(arg1); \ 1331582e84f7SPranith Kumar register long _arg2 asm("a1") = (long)(arg2); \ 1332582e84f7SPranith Kumar register long _arg3 asm("a2") = (long)(arg3); \ 1333582e84f7SPranith Kumar register long _arg4 asm("a3") = (long)(arg4); \ 1334582e84f7SPranith Kumar \ 1335582e84f7SPranith Kumar asm volatile ( \ 1336582e84f7SPranith Kumar "ecall\n" \ 1337582e84f7SPranith Kumar : "+r"(_arg1) \ 1338582e84f7SPranith Kumar : "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 1339582e84f7SPranith Kumar "r"(_num) \ 1340582e84f7SPranith Kumar : "memory", "cc" \ 1341582e84f7SPranith Kumar ); \ 1342582e84f7SPranith Kumar _arg1; \ 1343582e84f7SPranith Kumar }) 1344582e84f7SPranith Kumar 1345582e84f7SPranith Kumar #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 1346582e84f7SPranith Kumar ({ \ 1347582e84f7SPranith Kumar register long _num asm("a7") = (num); \ 1348582e84f7SPranith Kumar register long _arg1 asm("a0") = (long)(arg1); \ 1349582e84f7SPranith Kumar register long _arg2 asm("a1") = (long)(arg2); \ 1350582e84f7SPranith Kumar register long _arg3 asm("a2") = (long)(arg3); \ 1351582e84f7SPranith Kumar register long _arg4 asm("a3") = (long)(arg4); \ 1352582e84f7SPranith Kumar register long _arg5 asm("a4") = (long)(arg5); \ 1353582e84f7SPranith Kumar \ 1354582e84f7SPranith Kumar asm volatile ( \ 1355582e84f7SPranith Kumar "ecall\n" \ 1356582e84f7SPranith Kumar : "+r"(_arg1) \ 1357582e84f7SPranith Kumar : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 1358582e84f7SPranith Kumar "r"(_num) \ 1359582e84f7SPranith Kumar : "memory", "cc" \ 1360582e84f7SPranith Kumar ); \ 1361582e84f7SPranith Kumar _arg1; \ 1362582e84f7SPranith Kumar }) 1363582e84f7SPranith Kumar 1364582e84f7SPranith Kumar #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 1365582e84f7SPranith Kumar ({ \ 1366582e84f7SPranith Kumar register long _num asm("a7") = (num); \ 1367582e84f7SPranith Kumar register long _arg1 asm("a0") = (long)(arg1); \ 1368582e84f7SPranith Kumar register long _arg2 asm("a1") = (long)(arg2); \ 1369582e84f7SPranith Kumar register long _arg3 asm("a2") = (long)(arg3); \ 1370582e84f7SPranith Kumar register long _arg4 asm("a3") = (long)(arg4); \ 1371582e84f7SPranith Kumar register long _arg5 asm("a4") = (long)(arg5); \ 1372582e84f7SPranith Kumar register long _arg6 asm("a5") = (long)(arg6); \ 1373582e84f7SPranith Kumar \ 1374582e84f7SPranith Kumar asm volatile ( \ 1375582e84f7SPranith Kumar "ecall\n" \ 1376582e84f7SPranith Kumar : "+r"(_arg1) \ 1377582e84f7SPranith Kumar : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \ 1378582e84f7SPranith Kumar "r"(_num) \ 1379582e84f7SPranith Kumar : "memory", "cc" \ 1380582e84f7SPranith Kumar ); \ 1381582e84f7SPranith Kumar _arg1; \ 1382582e84f7SPranith Kumar }) 1383582e84f7SPranith Kumar 1384582e84f7SPranith Kumar /* startup code */ 1385582e84f7SPranith Kumar asm(".section .text\n" 1386582e84f7SPranith Kumar ".global _start\n" 1387582e84f7SPranith Kumar "_start:\n" 1388582e84f7SPranith Kumar ".option push\n" 1389582e84f7SPranith Kumar ".option norelax\n" 1390582e84f7SPranith Kumar "lla gp, __global_pointer$\n" 1391582e84f7SPranith Kumar ".option pop\n" 1392582e84f7SPranith Kumar "ld a0, 0(sp)\n" // argc (a0) was in the stack 1393582e84f7SPranith Kumar "add a1, sp, "SZREG"\n" // argv (a1) = sp 1394582e84f7SPranith Kumar "slli a2, a0, "PTRLOG"\n" // envp (a2) = SZREG*argc ... 1395582e84f7SPranith Kumar "add a2, a2, "SZREG"\n" // + SZREG (skip null) 1396582e84f7SPranith Kumar "add a2,a2,a1\n" // + argv 1397582e84f7SPranith Kumar "andi sp,a1,-16\n" // sp must be 16-byte aligned 1398582e84f7SPranith Kumar "call main\n" // main() returns the status code, we'll exit with it. 1399582e84f7SPranith Kumar "li a7, 93\n" // NR_exit == 93 1400582e84f7SPranith Kumar "ecall\n" 1401582e84f7SPranith Kumar ""); 1402582e84f7SPranith Kumar 1403582e84f7SPranith Kumar /* fcntl / open */ 1404582e84f7SPranith Kumar #define O_RDONLY 0 1405582e84f7SPranith Kumar #define O_WRONLY 1 1406582e84f7SPranith Kumar #define O_RDWR 2 1407582e84f7SPranith Kumar #define O_CREAT 0x100 1408582e84f7SPranith Kumar #define O_EXCL 0x200 1409582e84f7SPranith Kumar #define O_NOCTTY 0x400 1410582e84f7SPranith Kumar #define O_TRUNC 0x1000 1411582e84f7SPranith Kumar #define O_APPEND 0x2000 1412582e84f7SPranith Kumar #define O_NONBLOCK 0x4000 1413582e84f7SPranith Kumar #define O_DIRECTORY 0x200000 1414582e84f7SPranith Kumar 1415582e84f7SPranith Kumar struct sys_stat_struct { 1416582e84f7SPranith Kumar unsigned long st_dev; /* Device. */ 1417582e84f7SPranith Kumar unsigned long st_ino; /* File serial number. */ 1418582e84f7SPranith Kumar unsigned int st_mode; /* File mode. */ 1419582e84f7SPranith Kumar unsigned int st_nlink; /* Link count. */ 1420582e84f7SPranith Kumar unsigned int st_uid; /* User ID of the file's owner. */ 1421582e84f7SPranith Kumar unsigned int st_gid; /* Group ID of the file's group. */ 1422582e84f7SPranith Kumar unsigned long st_rdev; /* Device number, if device. */ 1423582e84f7SPranith Kumar unsigned long __pad1; 1424582e84f7SPranith Kumar long st_size; /* Size of file, in bytes. */ 1425582e84f7SPranith Kumar int st_blksize; /* Optimal block size for I/O. */ 1426582e84f7SPranith Kumar int __pad2; 1427582e84f7SPranith Kumar long st_blocks; /* Number 512-byte blocks allocated. */ 1428582e84f7SPranith Kumar long st_atime; /* Time of last access. */ 1429582e84f7SPranith Kumar unsigned long st_atime_nsec; 1430582e84f7SPranith Kumar long st_mtime; /* Time of last modification. */ 1431582e84f7SPranith Kumar unsigned long st_mtime_nsec; 1432582e84f7SPranith Kumar long st_ctime; /* Time of last status change. */ 1433582e84f7SPranith Kumar unsigned long st_ctime_nsec; 1434582e84f7SPranith Kumar unsigned int __unused4; 1435582e84f7SPranith Kumar unsigned int __unused5; 1436582e84f7SPranith Kumar }; 1437582e84f7SPranith Kumar 143830ca2051SWilly Tarreau #endif 143930ca2051SWilly Tarreau 144030ca2051SWilly Tarreau 144130ca2051SWilly Tarreau /* Below are the C functions used to declare the raw syscalls. They try to be 144230ca2051SWilly Tarreau * architecture-agnostic, and return either a success or -errno. Declaring them 144330ca2051SWilly Tarreau * static will lead to them being inlined in most cases, but it's still possible 144430ca2051SWilly Tarreau * to reference them by a pointer if needed. 144530ca2051SWilly Tarreau */ 144630ca2051SWilly Tarreau static __attribute__((unused)) 144730ca2051SWilly Tarreau void *sys_brk(void *addr) 144830ca2051SWilly Tarreau { 144930ca2051SWilly Tarreau return (void *)my_syscall1(__NR_brk, addr); 145030ca2051SWilly Tarreau } 145130ca2051SWilly Tarreau 145230ca2051SWilly Tarreau static __attribute__((noreturn,unused)) 145330ca2051SWilly Tarreau void sys_exit(int status) 145430ca2051SWilly Tarreau { 145530ca2051SWilly Tarreau my_syscall1(__NR_exit, status & 255); 145630ca2051SWilly Tarreau while(1); // shut the "noreturn" warnings. 145730ca2051SWilly Tarreau } 145830ca2051SWilly Tarreau 145930ca2051SWilly Tarreau static __attribute__((unused)) 146030ca2051SWilly Tarreau int sys_chdir(const char *path) 146130ca2051SWilly Tarreau { 146230ca2051SWilly Tarreau return my_syscall1(__NR_chdir, path); 146330ca2051SWilly Tarreau } 146430ca2051SWilly Tarreau 146530ca2051SWilly Tarreau static __attribute__((unused)) 146630ca2051SWilly Tarreau int sys_chmod(const char *path, mode_t mode) 146730ca2051SWilly Tarreau { 146830ca2051SWilly Tarreau #ifdef __NR_fchmodat 146930ca2051SWilly Tarreau return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0); 147035635d7fSWilly Tarreau #elif defined(__NR_chmod) 147130ca2051SWilly Tarreau return my_syscall2(__NR_chmod, path, mode); 147235635d7fSWilly Tarreau #else 147335635d7fSWilly Tarreau #error Neither __NR_fchmodat nor __NR_chmod defined, cannot implement sys_chmod() 147430ca2051SWilly Tarreau #endif 147530ca2051SWilly Tarreau } 147630ca2051SWilly Tarreau 147730ca2051SWilly Tarreau static __attribute__((unused)) 147830ca2051SWilly Tarreau int sys_chown(const char *path, uid_t owner, gid_t group) 147930ca2051SWilly Tarreau { 148030ca2051SWilly Tarreau #ifdef __NR_fchownat 148130ca2051SWilly Tarreau return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0); 148235635d7fSWilly Tarreau #elif defined(__NR_chown) 148330ca2051SWilly Tarreau return my_syscall3(__NR_chown, path, owner, group); 148435635d7fSWilly Tarreau #else 148535635d7fSWilly Tarreau #error Neither __NR_fchownat nor __NR_chown defined, cannot implement sys_chown() 148630ca2051SWilly Tarreau #endif 148730ca2051SWilly Tarreau } 148830ca2051SWilly Tarreau 148930ca2051SWilly Tarreau static __attribute__((unused)) 149030ca2051SWilly Tarreau int sys_chroot(const char *path) 149130ca2051SWilly Tarreau { 149230ca2051SWilly Tarreau return my_syscall1(__NR_chroot, path); 149330ca2051SWilly Tarreau } 149430ca2051SWilly Tarreau 149530ca2051SWilly Tarreau static __attribute__((unused)) 149630ca2051SWilly Tarreau int sys_close(int fd) 149730ca2051SWilly Tarreau { 149830ca2051SWilly Tarreau return my_syscall1(__NR_close, fd); 149930ca2051SWilly Tarreau } 150030ca2051SWilly Tarreau 150130ca2051SWilly Tarreau static __attribute__((unused)) 150230ca2051SWilly Tarreau int sys_dup(int fd) 150330ca2051SWilly Tarreau { 150430ca2051SWilly Tarreau return my_syscall1(__NR_dup, fd); 150530ca2051SWilly Tarreau } 150630ca2051SWilly Tarreau 150779f220e5SWilly Tarreau #ifdef __NR_dup3 150879f220e5SWilly Tarreau static __attribute__((unused)) 150979f220e5SWilly Tarreau int sys_dup3(int old, int new, int flags) 151079f220e5SWilly Tarreau { 151179f220e5SWilly Tarreau return my_syscall3(__NR_dup3, old, new, flags); 151279f220e5SWilly Tarreau } 151379f220e5SWilly Tarreau #endif 151479f220e5SWilly Tarreau 151530ca2051SWilly Tarreau static __attribute__((unused)) 151630ca2051SWilly Tarreau int sys_dup2(int old, int new) 151730ca2051SWilly Tarreau { 151879f220e5SWilly Tarreau #ifdef __NR_dup3 151979f220e5SWilly Tarreau return my_syscall3(__NR_dup3, old, new, 0); 152035635d7fSWilly Tarreau #elif defined(__NR_dup2) 152130ca2051SWilly Tarreau return my_syscall2(__NR_dup2, old, new); 152235635d7fSWilly Tarreau #else 152335635d7fSWilly Tarreau #error Neither __NR_dup3 nor __NR_dup2 defined, cannot implement sys_dup2() 152479f220e5SWilly Tarreau #endif 152530ca2051SWilly Tarreau } 152630ca2051SWilly Tarreau 152730ca2051SWilly Tarreau static __attribute__((unused)) 152830ca2051SWilly Tarreau int sys_execve(const char *filename, char *const argv[], char *const envp[]) 152930ca2051SWilly Tarreau { 153030ca2051SWilly Tarreau return my_syscall3(__NR_execve, filename, argv, envp); 153130ca2051SWilly Tarreau } 153230ca2051SWilly Tarreau 153330ca2051SWilly Tarreau static __attribute__((unused)) 153430ca2051SWilly Tarreau pid_t sys_fork(void) 153530ca2051SWilly Tarreau { 1536be60ca41SWilly Tarreau #ifdef __NR_clone 1537be60ca41SWilly Tarreau /* note: some archs only have clone() and not fork(). Different archs 1538be60ca41SWilly Tarreau * have a different API, but most archs have the flags on first arg and 1539be60ca41SWilly Tarreau * will not use the rest with no other flag. 1540be60ca41SWilly Tarreau */ 1541be60ca41SWilly Tarreau return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0); 154235635d7fSWilly Tarreau #elif defined(__NR_fork) 154330ca2051SWilly Tarreau return my_syscall0(__NR_fork); 154435635d7fSWilly Tarreau #else 154535635d7fSWilly Tarreau #error Neither __NR_clone nor __NR_fork defined, cannot implement sys_fork() 1546be60ca41SWilly Tarreau #endif 154730ca2051SWilly Tarreau } 154830ca2051SWilly Tarreau 154930ca2051SWilly Tarreau static __attribute__((unused)) 155030ca2051SWilly Tarreau int sys_fsync(int fd) 155130ca2051SWilly Tarreau { 155230ca2051SWilly Tarreau return my_syscall1(__NR_fsync, fd); 155330ca2051SWilly Tarreau } 155430ca2051SWilly Tarreau 155530ca2051SWilly Tarreau static __attribute__((unused)) 155630ca2051SWilly Tarreau int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count) 155730ca2051SWilly Tarreau { 155830ca2051SWilly Tarreau return my_syscall3(__NR_getdents64, fd, dirp, count); 155930ca2051SWilly Tarreau } 156030ca2051SWilly Tarreau 156130ca2051SWilly Tarreau static __attribute__((unused)) 1562c0c7c103SWilly Tarreau pid_t sys_getpgid(pid_t pid) 1563c0c7c103SWilly Tarreau { 1564c0c7c103SWilly Tarreau return my_syscall1(__NR_getpgid, pid); 1565c0c7c103SWilly Tarreau } 1566c0c7c103SWilly Tarreau 1567c0c7c103SWilly Tarreau static __attribute__((unused)) 156830ca2051SWilly Tarreau pid_t sys_getpgrp(void) 156930ca2051SWilly Tarreau { 1570c0c7c103SWilly Tarreau return sys_getpgid(0); 157130ca2051SWilly Tarreau } 157230ca2051SWilly Tarreau 157330ca2051SWilly Tarreau static __attribute__((unused)) 157430ca2051SWilly Tarreau pid_t sys_getpid(void) 157530ca2051SWilly Tarreau { 157630ca2051SWilly Tarreau return my_syscall0(__NR_getpid); 157730ca2051SWilly Tarreau } 157830ca2051SWilly Tarreau 157930ca2051SWilly Tarreau static __attribute__((unused)) 1580b0fe9decSMark Brown pid_t sys_gettid(void) 1581b0fe9decSMark Brown { 1582b0fe9decSMark Brown return my_syscall0(__NR_gettid); 1583b0fe9decSMark Brown } 1584b0fe9decSMark Brown 1585b0fe9decSMark Brown static __attribute__((unused)) 158630ca2051SWilly Tarreau int sys_gettimeofday(struct timeval *tv, struct timezone *tz) 158730ca2051SWilly Tarreau { 158830ca2051SWilly Tarreau return my_syscall2(__NR_gettimeofday, tv, tz); 158930ca2051SWilly Tarreau } 159030ca2051SWilly Tarreau 159130ca2051SWilly Tarreau static __attribute__((unused)) 159230ca2051SWilly Tarreau int sys_ioctl(int fd, unsigned long req, void *value) 159330ca2051SWilly Tarreau { 159430ca2051SWilly Tarreau return my_syscall3(__NR_ioctl, fd, req, value); 159530ca2051SWilly Tarreau } 159630ca2051SWilly Tarreau 159730ca2051SWilly Tarreau static __attribute__((unused)) 159830ca2051SWilly Tarreau int sys_kill(pid_t pid, int signal) 159930ca2051SWilly Tarreau { 160030ca2051SWilly Tarreau return my_syscall2(__NR_kill, pid, signal); 160130ca2051SWilly Tarreau } 160230ca2051SWilly Tarreau 160330ca2051SWilly Tarreau static __attribute__((unused)) 160430ca2051SWilly Tarreau int sys_link(const char *old, const char *new) 160530ca2051SWilly Tarreau { 160630ca2051SWilly Tarreau #ifdef __NR_linkat 160730ca2051SWilly Tarreau return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); 160835635d7fSWilly Tarreau #elif defined(__NR_link) 160930ca2051SWilly Tarreau return my_syscall2(__NR_link, old, new); 161035635d7fSWilly Tarreau #else 161135635d7fSWilly Tarreau #error Neither __NR_linkat nor __NR_link defined, cannot implement sys_link() 161230ca2051SWilly Tarreau #endif 161330ca2051SWilly Tarreau } 161430ca2051SWilly Tarreau 161530ca2051SWilly Tarreau static __attribute__((unused)) 161630ca2051SWilly Tarreau off_t sys_lseek(int fd, off_t offset, int whence) 161730ca2051SWilly Tarreau { 161830ca2051SWilly Tarreau return my_syscall3(__NR_lseek, fd, offset, whence); 161930ca2051SWilly Tarreau } 162030ca2051SWilly Tarreau 162130ca2051SWilly Tarreau static __attribute__((unused)) 162230ca2051SWilly Tarreau int sys_mkdir(const char *path, mode_t mode) 162330ca2051SWilly Tarreau { 162430ca2051SWilly Tarreau #ifdef __NR_mkdirat 162530ca2051SWilly Tarreau return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); 162635635d7fSWilly Tarreau #elif defined(__NR_mkdir) 162730ca2051SWilly Tarreau return my_syscall2(__NR_mkdir, path, mode); 162835635d7fSWilly Tarreau #else 162935635d7fSWilly Tarreau #error Neither __NR_mkdirat nor __NR_mkdir defined, cannot implement sys_mkdir() 163030ca2051SWilly Tarreau #endif 163130ca2051SWilly Tarreau } 163230ca2051SWilly Tarreau 163330ca2051SWilly Tarreau static __attribute__((unused)) 163430ca2051SWilly Tarreau long sys_mknod(const char *path, mode_t mode, dev_t dev) 163530ca2051SWilly Tarreau { 163630ca2051SWilly Tarreau #ifdef __NR_mknodat 163730ca2051SWilly Tarreau return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); 163835635d7fSWilly Tarreau #elif defined(__NR_mknod) 163930ca2051SWilly Tarreau return my_syscall3(__NR_mknod, path, mode, dev); 164035635d7fSWilly Tarreau #else 164135635d7fSWilly Tarreau #error Neither __NR_mknodat nor __NR_mknod defined, cannot implement sys_mknod() 164230ca2051SWilly Tarreau #endif 164330ca2051SWilly Tarreau } 164430ca2051SWilly Tarreau 164530ca2051SWilly Tarreau static __attribute__((unused)) 164630ca2051SWilly Tarreau int sys_mount(const char *src, const char *tgt, const char *fst, 164730ca2051SWilly Tarreau unsigned long flags, const void *data) 164830ca2051SWilly Tarreau { 164930ca2051SWilly Tarreau return my_syscall5(__NR_mount, src, tgt, fst, flags, data); 165030ca2051SWilly Tarreau } 165130ca2051SWilly Tarreau 165230ca2051SWilly Tarreau static __attribute__((unused)) 165330ca2051SWilly Tarreau int sys_open(const char *path, int flags, mode_t mode) 165430ca2051SWilly Tarreau { 165530ca2051SWilly Tarreau #ifdef __NR_openat 165630ca2051SWilly Tarreau return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode); 165735635d7fSWilly Tarreau #elif defined(__NR_open) 165830ca2051SWilly Tarreau return my_syscall3(__NR_open, path, flags, mode); 165935635d7fSWilly Tarreau #else 166035635d7fSWilly Tarreau #error Neither __NR_openat nor __NR_open defined, cannot implement sys_open() 166130ca2051SWilly Tarreau #endif 166230ca2051SWilly Tarreau } 166330ca2051SWilly Tarreau 166430ca2051SWilly Tarreau static __attribute__((unused)) 166530ca2051SWilly Tarreau int sys_pivot_root(const char *new, const char *old) 166630ca2051SWilly Tarreau { 166730ca2051SWilly Tarreau return my_syscall2(__NR_pivot_root, new, old); 166830ca2051SWilly Tarreau } 166930ca2051SWilly Tarreau 167030ca2051SWilly Tarreau static __attribute__((unused)) 167130ca2051SWilly Tarreau int sys_poll(struct pollfd *fds, int nfds, int timeout) 167230ca2051SWilly Tarreau { 16735b1c827cSWilly Tarreau #if defined(__NR_ppoll) 16745b1c827cSWilly Tarreau struct timespec t; 16755b1c827cSWilly Tarreau 16765b1c827cSWilly Tarreau if (timeout >= 0) { 16775b1c827cSWilly Tarreau t.tv_sec = timeout / 1000; 16785b1c827cSWilly Tarreau t.tv_nsec = (timeout % 1000) * 1000000; 16795b1c827cSWilly Tarreau } 16805b1c827cSWilly Tarreau return my_syscall4(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL); 168135635d7fSWilly Tarreau #elif defined(__NR_poll) 168230ca2051SWilly Tarreau return my_syscall3(__NR_poll, fds, nfds, timeout); 168335635d7fSWilly Tarreau #else 168435635d7fSWilly Tarreau #error Neither __NR_ppoll nor __NR_poll defined, cannot implement sys_poll() 16855b1c827cSWilly Tarreau #endif 168630ca2051SWilly Tarreau } 168730ca2051SWilly Tarreau 168830ca2051SWilly Tarreau static __attribute__((unused)) 168930ca2051SWilly Tarreau ssize_t sys_read(int fd, void *buf, size_t count) 169030ca2051SWilly Tarreau { 169130ca2051SWilly Tarreau return my_syscall3(__NR_read, fd, buf, count); 169230ca2051SWilly Tarreau } 169330ca2051SWilly Tarreau 169430ca2051SWilly Tarreau static __attribute__((unused)) 169530ca2051SWilly Tarreau ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg) 169630ca2051SWilly Tarreau { 169730ca2051SWilly Tarreau return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg); 169830ca2051SWilly Tarreau } 169930ca2051SWilly Tarreau 170030ca2051SWilly Tarreau static __attribute__((unused)) 170130ca2051SWilly Tarreau int sys_sched_yield(void) 170230ca2051SWilly Tarreau { 170330ca2051SWilly Tarreau return my_syscall0(__NR_sched_yield); 170430ca2051SWilly Tarreau } 170530ca2051SWilly Tarreau 170630ca2051SWilly Tarreau static __attribute__((unused)) 170730ca2051SWilly Tarreau int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 170830ca2051SWilly Tarreau { 170930ca2051SWilly Tarreau #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect) 171030ca2051SWilly Tarreau struct sel_arg_struct { 171130ca2051SWilly Tarreau unsigned long n; 171230ca2051SWilly Tarreau fd_set *r, *w, *e; 171330ca2051SWilly Tarreau struct timeval *t; 171430ca2051SWilly Tarreau } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout }; 171530ca2051SWilly Tarreau return my_syscall1(__NR_select, &arg); 171630ca2051SWilly Tarreau #elif defined(__ARCH_WANT_SYS_PSELECT6) && defined(__NR_pselect6) 171730ca2051SWilly Tarreau struct timespec t; 171830ca2051SWilly Tarreau 171930ca2051SWilly Tarreau if (timeout) { 172030ca2051SWilly Tarreau t.tv_sec = timeout->tv_sec; 172130ca2051SWilly Tarreau t.tv_nsec = timeout->tv_usec * 1000; 172230ca2051SWilly Tarreau } 172330ca2051SWilly Tarreau return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 172435635d7fSWilly Tarreau #elif defined(__NR__newselect) || defined(__NR_select) 172530ca2051SWilly Tarreau #ifndef __NR__newselect 172630ca2051SWilly Tarreau #define __NR__newselect __NR_select 172730ca2051SWilly Tarreau #endif 172830ca2051SWilly Tarreau return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); 172935635d7fSWilly Tarreau #else 173035635d7fSWilly Tarreau #error None of __NR_select, __NR_pselect6, nor __NR__newselect defined, cannot implement sys_select() 173130ca2051SWilly Tarreau #endif 173230ca2051SWilly Tarreau } 173330ca2051SWilly Tarreau 173430ca2051SWilly Tarreau static __attribute__((unused)) 173530ca2051SWilly Tarreau int sys_setpgid(pid_t pid, pid_t pgid) 173630ca2051SWilly Tarreau { 173730ca2051SWilly Tarreau return my_syscall2(__NR_setpgid, pid, pgid); 173830ca2051SWilly Tarreau } 173930ca2051SWilly Tarreau 174030ca2051SWilly Tarreau static __attribute__((unused)) 174130ca2051SWilly Tarreau pid_t sys_setsid(void) 174230ca2051SWilly Tarreau { 174330ca2051SWilly Tarreau return my_syscall0(__NR_setsid); 174430ca2051SWilly Tarreau } 174530ca2051SWilly Tarreau 174630ca2051SWilly Tarreau static __attribute__((unused)) 174730ca2051SWilly Tarreau int sys_stat(const char *path, struct stat *buf) 174830ca2051SWilly Tarreau { 174930ca2051SWilly Tarreau struct sys_stat_struct stat; 175030ca2051SWilly Tarreau long ret; 175130ca2051SWilly Tarreau 175230ca2051SWilly Tarreau #ifdef __NR_newfstatat 175330ca2051SWilly Tarreau /* only solution for arm64 */ 175430ca2051SWilly Tarreau ret = my_syscall4(__NR_newfstatat, AT_FDCWD, path, &stat, 0); 175535635d7fSWilly Tarreau #elif defined(__NR_stat) 175630ca2051SWilly Tarreau ret = my_syscall2(__NR_stat, path, &stat); 175735635d7fSWilly Tarreau #else 175835635d7fSWilly Tarreau #error Neither __NR_newfstatat nor __NR_stat defined, cannot implement sys_stat() 175930ca2051SWilly Tarreau #endif 176030ca2051SWilly Tarreau buf->st_dev = stat.st_dev; 176130ca2051SWilly Tarreau buf->st_ino = stat.st_ino; 176230ca2051SWilly Tarreau buf->st_mode = stat.st_mode; 176330ca2051SWilly Tarreau buf->st_nlink = stat.st_nlink; 176430ca2051SWilly Tarreau buf->st_uid = stat.st_uid; 176530ca2051SWilly Tarreau buf->st_gid = stat.st_gid; 176630ca2051SWilly Tarreau buf->st_rdev = stat.st_rdev; 176730ca2051SWilly Tarreau buf->st_size = stat.st_size; 176830ca2051SWilly Tarreau buf->st_blksize = stat.st_blksize; 176930ca2051SWilly Tarreau buf->st_blocks = stat.st_blocks; 177030ca2051SWilly Tarreau buf->st_atime = stat.st_atime; 177130ca2051SWilly Tarreau buf->st_mtime = stat.st_mtime; 177230ca2051SWilly Tarreau buf->st_ctime = stat.st_ctime; 177330ca2051SWilly Tarreau return ret; 177430ca2051SWilly Tarreau } 177530ca2051SWilly Tarreau 177630ca2051SWilly Tarreau 177730ca2051SWilly Tarreau static __attribute__((unused)) 177830ca2051SWilly Tarreau int sys_symlink(const char *old, const char *new) 177930ca2051SWilly Tarreau { 178030ca2051SWilly Tarreau #ifdef __NR_symlinkat 178130ca2051SWilly Tarreau return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); 178235635d7fSWilly Tarreau #elif defined(__NR_symlink) 178330ca2051SWilly Tarreau return my_syscall2(__NR_symlink, old, new); 178435635d7fSWilly Tarreau #else 178535635d7fSWilly Tarreau #error Neither __NR_symlinkat nor __NR_symlink defined, cannot implement sys_symlink() 178630ca2051SWilly Tarreau #endif 178730ca2051SWilly Tarreau } 178830ca2051SWilly Tarreau 178930ca2051SWilly Tarreau static __attribute__((unused)) 179030ca2051SWilly Tarreau mode_t sys_umask(mode_t mode) 179130ca2051SWilly Tarreau { 179230ca2051SWilly Tarreau return my_syscall1(__NR_umask, mode); 179330ca2051SWilly Tarreau } 179430ca2051SWilly Tarreau 179530ca2051SWilly Tarreau static __attribute__((unused)) 179630ca2051SWilly Tarreau int sys_umount2(const char *path, int flags) 179730ca2051SWilly Tarreau { 179830ca2051SWilly Tarreau return my_syscall2(__NR_umount2, path, flags); 179930ca2051SWilly Tarreau } 180030ca2051SWilly Tarreau 180130ca2051SWilly Tarreau static __attribute__((unused)) 180230ca2051SWilly Tarreau int sys_unlink(const char *path) 180330ca2051SWilly Tarreau { 180430ca2051SWilly Tarreau #ifdef __NR_unlinkat 180530ca2051SWilly Tarreau return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); 180635635d7fSWilly Tarreau #elif defined(__NR_unlink) 180730ca2051SWilly Tarreau return my_syscall1(__NR_unlink, path); 180835635d7fSWilly Tarreau #else 180935635d7fSWilly Tarreau #error Neither __NR_unlinkat nor __NR_unlink defined, cannot implement sys_unlink() 181030ca2051SWilly Tarreau #endif 181130ca2051SWilly Tarreau } 181230ca2051SWilly Tarreau 181330ca2051SWilly Tarreau static __attribute__((unused)) 181430ca2051SWilly Tarreau pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage) 181530ca2051SWilly Tarreau { 181630ca2051SWilly Tarreau return my_syscall4(__NR_wait4, pid, status, options, rusage); 181730ca2051SWilly Tarreau } 181830ca2051SWilly Tarreau 181930ca2051SWilly Tarreau static __attribute__((unused)) 182030ca2051SWilly Tarreau pid_t sys_waitpid(pid_t pid, int *status, int options) 182130ca2051SWilly Tarreau { 182230ca2051SWilly Tarreau return sys_wait4(pid, status, options, 0); 182330ca2051SWilly Tarreau } 182430ca2051SWilly Tarreau 182530ca2051SWilly Tarreau static __attribute__((unused)) 182630ca2051SWilly Tarreau pid_t sys_wait(int *status) 182730ca2051SWilly Tarreau { 182830ca2051SWilly Tarreau return sys_waitpid(-1, status, 0); 182930ca2051SWilly Tarreau } 183030ca2051SWilly Tarreau 183130ca2051SWilly Tarreau static __attribute__((unused)) 183230ca2051SWilly Tarreau ssize_t sys_write(int fd, const void *buf, size_t count) 183330ca2051SWilly Tarreau { 183430ca2051SWilly Tarreau return my_syscall3(__NR_write, fd, buf, count); 183530ca2051SWilly Tarreau } 183630ca2051SWilly Tarreau 183730ca2051SWilly Tarreau 183830ca2051SWilly Tarreau /* Below are the libc-compatible syscalls which return x or -1 and set errno. 183930ca2051SWilly Tarreau * They rely on the functions above. Similarly they're marked static so that it 184030ca2051SWilly Tarreau * is possible to assign pointers to them if needed. 184130ca2051SWilly Tarreau */ 184230ca2051SWilly Tarreau 184330ca2051SWilly Tarreau static __attribute__((unused)) 184430ca2051SWilly Tarreau int brk(void *addr) 184530ca2051SWilly Tarreau { 184630ca2051SWilly Tarreau void *ret = sys_brk(addr); 184730ca2051SWilly Tarreau 184830ca2051SWilly Tarreau if (!ret) { 184930ca2051SWilly Tarreau SET_ERRNO(ENOMEM); 185030ca2051SWilly Tarreau return -1; 185130ca2051SWilly Tarreau } 185230ca2051SWilly Tarreau return 0; 185330ca2051SWilly Tarreau } 185430ca2051SWilly Tarreau 185530ca2051SWilly Tarreau static __attribute__((noreturn,unused)) 185630ca2051SWilly Tarreau void exit(int status) 185730ca2051SWilly Tarreau { 185830ca2051SWilly Tarreau sys_exit(status); 185930ca2051SWilly Tarreau } 186030ca2051SWilly Tarreau 186130ca2051SWilly Tarreau static __attribute__((unused)) 186230ca2051SWilly Tarreau int chdir(const char *path) 186330ca2051SWilly Tarreau { 186430ca2051SWilly Tarreau int ret = sys_chdir(path); 186530ca2051SWilly Tarreau 186630ca2051SWilly Tarreau if (ret < 0) { 186730ca2051SWilly Tarreau SET_ERRNO(-ret); 186830ca2051SWilly Tarreau ret = -1; 186930ca2051SWilly Tarreau } 187030ca2051SWilly Tarreau return ret; 187130ca2051SWilly Tarreau } 187230ca2051SWilly Tarreau 187330ca2051SWilly Tarreau static __attribute__((unused)) 187430ca2051SWilly Tarreau int chmod(const char *path, mode_t mode) 187530ca2051SWilly Tarreau { 187630ca2051SWilly Tarreau int ret = sys_chmod(path, mode); 187730ca2051SWilly Tarreau 187830ca2051SWilly Tarreau if (ret < 0) { 187930ca2051SWilly Tarreau SET_ERRNO(-ret); 188030ca2051SWilly Tarreau ret = -1; 188130ca2051SWilly Tarreau } 188230ca2051SWilly Tarreau return ret; 188330ca2051SWilly Tarreau } 188430ca2051SWilly Tarreau 188530ca2051SWilly Tarreau static __attribute__((unused)) 188630ca2051SWilly Tarreau int chown(const char *path, uid_t owner, gid_t group) 188730ca2051SWilly Tarreau { 188830ca2051SWilly Tarreau int ret = sys_chown(path, owner, group); 188930ca2051SWilly Tarreau 189030ca2051SWilly Tarreau if (ret < 0) { 189130ca2051SWilly Tarreau SET_ERRNO(-ret); 189230ca2051SWilly Tarreau ret = -1; 189330ca2051SWilly Tarreau } 189430ca2051SWilly Tarreau return ret; 189530ca2051SWilly Tarreau } 189630ca2051SWilly Tarreau 189730ca2051SWilly Tarreau static __attribute__((unused)) 189830ca2051SWilly Tarreau int chroot(const char *path) 189930ca2051SWilly Tarreau { 190030ca2051SWilly Tarreau int ret = sys_chroot(path); 190130ca2051SWilly Tarreau 190230ca2051SWilly Tarreau if (ret < 0) { 190330ca2051SWilly Tarreau SET_ERRNO(-ret); 190430ca2051SWilly Tarreau ret = -1; 190530ca2051SWilly Tarreau } 190630ca2051SWilly Tarreau return ret; 190730ca2051SWilly Tarreau } 190830ca2051SWilly Tarreau 190930ca2051SWilly Tarreau static __attribute__((unused)) 191030ca2051SWilly Tarreau int close(int fd) 191130ca2051SWilly Tarreau { 191230ca2051SWilly Tarreau int ret = sys_close(fd); 191330ca2051SWilly Tarreau 191430ca2051SWilly Tarreau if (ret < 0) { 191530ca2051SWilly Tarreau SET_ERRNO(-ret); 191630ca2051SWilly Tarreau ret = -1; 191730ca2051SWilly Tarreau } 191830ca2051SWilly Tarreau return ret; 191930ca2051SWilly Tarreau } 192030ca2051SWilly Tarreau 192130ca2051SWilly Tarreau static __attribute__((unused)) 1922c261145aSWilly Tarreau int dup(int fd) 1923c261145aSWilly Tarreau { 1924c261145aSWilly Tarreau int ret = sys_dup(fd); 1925c261145aSWilly Tarreau 1926c261145aSWilly Tarreau if (ret < 0) { 1927c261145aSWilly Tarreau SET_ERRNO(-ret); 1928c261145aSWilly Tarreau ret = -1; 1929c261145aSWilly Tarreau } 1930c261145aSWilly Tarreau return ret; 1931c261145aSWilly Tarreau } 1932c261145aSWilly Tarreau 1933c261145aSWilly Tarreau static __attribute__((unused)) 193430ca2051SWilly Tarreau int dup2(int old, int new) 193530ca2051SWilly Tarreau { 193630ca2051SWilly Tarreau int ret = sys_dup2(old, new); 193730ca2051SWilly Tarreau 193830ca2051SWilly Tarreau if (ret < 0) { 193930ca2051SWilly Tarreau SET_ERRNO(-ret); 194030ca2051SWilly Tarreau ret = -1; 194130ca2051SWilly Tarreau } 194230ca2051SWilly Tarreau return ret; 194330ca2051SWilly Tarreau } 194430ca2051SWilly Tarreau 194579f220e5SWilly Tarreau #ifdef __NR_dup3 194679f220e5SWilly Tarreau static __attribute__((unused)) 194779f220e5SWilly Tarreau int dup3(int old, int new, int flags) 194879f220e5SWilly Tarreau { 194979f220e5SWilly Tarreau int ret = sys_dup3(old, new, flags); 195079f220e5SWilly Tarreau 195179f220e5SWilly Tarreau if (ret < 0) { 195279f220e5SWilly Tarreau SET_ERRNO(-ret); 195379f220e5SWilly Tarreau ret = -1; 195479f220e5SWilly Tarreau } 195579f220e5SWilly Tarreau return ret; 195679f220e5SWilly Tarreau } 195779f220e5SWilly Tarreau #endif 195879f220e5SWilly Tarreau 195930ca2051SWilly Tarreau static __attribute__((unused)) 196030ca2051SWilly Tarreau int execve(const char *filename, char *const argv[], char *const envp[]) 196130ca2051SWilly Tarreau { 196230ca2051SWilly Tarreau int ret = sys_execve(filename, argv, envp); 196330ca2051SWilly Tarreau 196430ca2051SWilly Tarreau if (ret < 0) { 196530ca2051SWilly Tarreau SET_ERRNO(-ret); 196630ca2051SWilly Tarreau ret = -1; 196730ca2051SWilly Tarreau } 196830ca2051SWilly Tarreau return ret; 196930ca2051SWilly Tarreau } 197030ca2051SWilly Tarreau 197130ca2051SWilly Tarreau static __attribute__((unused)) 197230ca2051SWilly Tarreau pid_t fork(void) 197330ca2051SWilly Tarreau { 197430ca2051SWilly Tarreau pid_t ret = sys_fork(); 197530ca2051SWilly Tarreau 197630ca2051SWilly Tarreau if (ret < 0) { 197730ca2051SWilly Tarreau SET_ERRNO(-ret); 197830ca2051SWilly Tarreau ret = -1; 197930ca2051SWilly Tarreau } 198030ca2051SWilly Tarreau return ret; 198130ca2051SWilly Tarreau } 198230ca2051SWilly Tarreau 198330ca2051SWilly Tarreau static __attribute__((unused)) 198430ca2051SWilly Tarreau int fsync(int fd) 198530ca2051SWilly Tarreau { 198630ca2051SWilly Tarreau int ret = sys_fsync(fd); 198730ca2051SWilly Tarreau 198830ca2051SWilly Tarreau if (ret < 0) { 198930ca2051SWilly Tarreau SET_ERRNO(-ret); 199030ca2051SWilly Tarreau ret = -1; 199130ca2051SWilly Tarreau } 199230ca2051SWilly Tarreau return ret; 199330ca2051SWilly Tarreau } 199430ca2051SWilly Tarreau 199530ca2051SWilly Tarreau static __attribute__((unused)) 199630ca2051SWilly Tarreau int getdents64(int fd, struct linux_dirent64 *dirp, int count) 199730ca2051SWilly Tarreau { 199830ca2051SWilly Tarreau int ret = sys_getdents64(fd, dirp, count); 199930ca2051SWilly Tarreau 200030ca2051SWilly Tarreau if (ret < 0) { 200130ca2051SWilly Tarreau SET_ERRNO(-ret); 200230ca2051SWilly Tarreau ret = -1; 200330ca2051SWilly Tarreau } 200430ca2051SWilly Tarreau return ret; 200530ca2051SWilly Tarreau } 200630ca2051SWilly Tarreau 200730ca2051SWilly Tarreau static __attribute__((unused)) 2008c0c7c103SWilly Tarreau pid_t getpgid(pid_t pid) 2009c0c7c103SWilly Tarreau { 2010c0c7c103SWilly Tarreau pid_t ret = sys_getpgid(pid); 2011c0c7c103SWilly Tarreau 2012c0c7c103SWilly Tarreau if (ret < 0) { 2013c0c7c103SWilly Tarreau SET_ERRNO(-ret); 2014c0c7c103SWilly Tarreau ret = -1; 2015c0c7c103SWilly Tarreau } 2016c0c7c103SWilly Tarreau return ret; 2017c0c7c103SWilly Tarreau } 2018c0c7c103SWilly Tarreau 2019c0c7c103SWilly Tarreau static __attribute__((unused)) 202030ca2051SWilly Tarreau pid_t getpgrp(void) 202130ca2051SWilly Tarreau { 202230ca2051SWilly Tarreau pid_t ret = sys_getpgrp(); 202330ca2051SWilly Tarreau 202430ca2051SWilly Tarreau if (ret < 0) { 202530ca2051SWilly Tarreau SET_ERRNO(-ret); 202630ca2051SWilly Tarreau ret = -1; 202730ca2051SWilly Tarreau } 202830ca2051SWilly Tarreau return ret; 202930ca2051SWilly Tarreau } 203030ca2051SWilly Tarreau 203130ca2051SWilly Tarreau static __attribute__((unused)) 203230ca2051SWilly Tarreau pid_t getpid(void) 203330ca2051SWilly Tarreau { 203430ca2051SWilly Tarreau pid_t ret = sys_getpid(); 203530ca2051SWilly Tarreau 203630ca2051SWilly Tarreau if (ret < 0) { 203730ca2051SWilly Tarreau SET_ERRNO(-ret); 203830ca2051SWilly Tarreau ret = -1; 203930ca2051SWilly Tarreau } 204030ca2051SWilly Tarreau return ret; 204130ca2051SWilly Tarreau } 204230ca2051SWilly Tarreau 204330ca2051SWilly Tarreau static __attribute__((unused)) 2044b0fe9decSMark Brown pid_t gettid(void) 2045b0fe9decSMark Brown { 2046b0fe9decSMark Brown pid_t ret = sys_gettid(); 2047b0fe9decSMark Brown 2048b0fe9decSMark Brown if (ret < 0) { 2049b0fe9decSMark Brown SET_ERRNO(-ret); 2050b0fe9decSMark Brown ret = -1; 2051b0fe9decSMark Brown } 2052b0fe9decSMark Brown return ret; 2053b0fe9decSMark Brown } 2054b0fe9decSMark Brown 2055b0fe9decSMark Brown static __attribute__((unused)) 205630ca2051SWilly Tarreau int gettimeofday(struct timeval *tv, struct timezone *tz) 205730ca2051SWilly Tarreau { 205830ca2051SWilly Tarreau int ret = sys_gettimeofday(tv, tz); 205930ca2051SWilly Tarreau 206030ca2051SWilly Tarreau if (ret < 0) { 206130ca2051SWilly Tarreau SET_ERRNO(-ret); 206230ca2051SWilly Tarreau ret = -1; 206330ca2051SWilly Tarreau } 206430ca2051SWilly Tarreau return ret; 206530ca2051SWilly Tarreau } 206630ca2051SWilly Tarreau 206730ca2051SWilly Tarreau static __attribute__((unused)) 206830ca2051SWilly Tarreau int ioctl(int fd, unsigned long req, void *value) 206930ca2051SWilly Tarreau { 207030ca2051SWilly Tarreau int ret = sys_ioctl(fd, req, value); 207130ca2051SWilly Tarreau 207230ca2051SWilly Tarreau if (ret < 0) { 207330ca2051SWilly Tarreau SET_ERRNO(-ret); 207430ca2051SWilly Tarreau ret = -1; 207530ca2051SWilly Tarreau } 207630ca2051SWilly Tarreau return ret; 207730ca2051SWilly Tarreau } 207830ca2051SWilly Tarreau 207930ca2051SWilly Tarreau static __attribute__((unused)) 208030ca2051SWilly Tarreau int kill(pid_t pid, int signal) 208130ca2051SWilly Tarreau { 208230ca2051SWilly Tarreau int ret = sys_kill(pid, signal); 208330ca2051SWilly Tarreau 208430ca2051SWilly Tarreau if (ret < 0) { 208530ca2051SWilly Tarreau SET_ERRNO(-ret); 208630ca2051SWilly Tarreau ret = -1; 208730ca2051SWilly Tarreau } 208830ca2051SWilly Tarreau return ret; 208930ca2051SWilly Tarreau } 209030ca2051SWilly Tarreau 209130ca2051SWilly Tarreau static __attribute__((unused)) 209230ca2051SWilly Tarreau int link(const char *old, const char *new) 209330ca2051SWilly Tarreau { 209430ca2051SWilly Tarreau int ret = sys_link(old, new); 209530ca2051SWilly Tarreau 209630ca2051SWilly Tarreau if (ret < 0) { 209730ca2051SWilly Tarreau SET_ERRNO(-ret); 209830ca2051SWilly Tarreau ret = -1; 209930ca2051SWilly Tarreau } 210030ca2051SWilly Tarreau return ret; 210130ca2051SWilly Tarreau } 210230ca2051SWilly Tarreau 210330ca2051SWilly Tarreau static __attribute__((unused)) 210430ca2051SWilly Tarreau off_t lseek(int fd, off_t offset, int whence) 210530ca2051SWilly Tarreau { 210630ca2051SWilly Tarreau off_t ret = sys_lseek(fd, offset, whence); 210730ca2051SWilly Tarreau 210830ca2051SWilly Tarreau if (ret < 0) { 210930ca2051SWilly Tarreau SET_ERRNO(-ret); 211030ca2051SWilly Tarreau ret = -1; 211130ca2051SWilly Tarreau } 211230ca2051SWilly Tarreau return ret; 211330ca2051SWilly Tarreau } 211430ca2051SWilly Tarreau 211530ca2051SWilly Tarreau static __attribute__((unused)) 211630ca2051SWilly Tarreau int mkdir(const char *path, mode_t mode) 211730ca2051SWilly Tarreau { 211830ca2051SWilly Tarreau int ret = sys_mkdir(path, mode); 211930ca2051SWilly Tarreau 212030ca2051SWilly Tarreau if (ret < 0) { 212130ca2051SWilly Tarreau SET_ERRNO(-ret); 212230ca2051SWilly Tarreau ret = -1; 212330ca2051SWilly Tarreau } 212430ca2051SWilly Tarreau return ret; 212530ca2051SWilly Tarreau } 212630ca2051SWilly Tarreau 212730ca2051SWilly Tarreau static __attribute__((unused)) 212830ca2051SWilly Tarreau int mknod(const char *path, mode_t mode, dev_t dev) 212930ca2051SWilly Tarreau { 213030ca2051SWilly Tarreau int ret = sys_mknod(path, mode, dev); 213130ca2051SWilly Tarreau 213230ca2051SWilly Tarreau if (ret < 0) { 213330ca2051SWilly Tarreau SET_ERRNO(-ret); 213430ca2051SWilly Tarreau ret = -1; 213530ca2051SWilly Tarreau } 213630ca2051SWilly Tarreau return ret; 213730ca2051SWilly Tarreau } 213830ca2051SWilly Tarreau 213930ca2051SWilly Tarreau static __attribute__((unused)) 214030ca2051SWilly Tarreau int mount(const char *src, const char *tgt, 214130ca2051SWilly Tarreau const char *fst, unsigned long flags, 214230ca2051SWilly Tarreau const void *data) 214330ca2051SWilly Tarreau { 214430ca2051SWilly Tarreau int ret = sys_mount(src, tgt, fst, flags, data); 214530ca2051SWilly Tarreau 214630ca2051SWilly Tarreau if (ret < 0) { 214730ca2051SWilly Tarreau SET_ERRNO(-ret); 214830ca2051SWilly Tarreau ret = -1; 214930ca2051SWilly Tarreau } 215030ca2051SWilly Tarreau return ret; 215130ca2051SWilly Tarreau } 215230ca2051SWilly Tarreau 215330ca2051SWilly Tarreau static __attribute__((unused)) 215430ca2051SWilly Tarreau int open(const char *path, int flags, mode_t mode) 215530ca2051SWilly Tarreau { 215630ca2051SWilly Tarreau int ret = sys_open(path, flags, mode); 215730ca2051SWilly Tarreau 215830ca2051SWilly Tarreau if (ret < 0) { 215930ca2051SWilly Tarreau SET_ERRNO(-ret); 216030ca2051SWilly Tarreau ret = -1; 216130ca2051SWilly Tarreau } 216230ca2051SWilly Tarreau return ret; 216330ca2051SWilly Tarreau } 216430ca2051SWilly Tarreau 216530ca2051SWilly Tarreau static __attribute__((unused)) 216630ca2051SWilly Tarreau int pivot_root(const char *new, const char *old) 216730ca2051SWilly Tarreau { 216830ca2051SWilly Tarreau int ret = sys_pivot_root(new, old); 216930ca2051SWilly Tarreau 217030ca2051SWilly Tarreau if (ret < 0) { 217130ca2051SWilly Tarreau SET_ERRNO(-ret); 217230ca2051SWilly Tarreau ret = -1; 217330ca2051SWilly Tarreau } 217430ca2051SWilly Tarreau return ret; 217530ca2051SWilly Tarreau } 217630ca2051SWilly Tarreau 217730ca2051SWilly Tarreau static __attribute__((unused)) 217830ca2051SWilly Tarreau int poll(struct pollfd *fds, int nfds, int timeout) 217930ca2051SWilly Tarreau { 218030ca2051SWilly Tarreau int ret = sys_poll(fds, nfds, timeout); 218130ca2051SWilly Tarreau 218230ca2051SWilly Tarreau if (ret < 0) { 218330ca2051SWilly Tarreau SET_ERRNO(-ret); 218430ca2051SWilly Tarreau ret = -1; 218530ca2051SWilly Tarreau } 218630ca2051SWilly Tarreau return ret; 218730ca2051SWilly Tarreau } 218830ca2051SWilly Tarreau 218930ca2051SWilly Tarreau static __attribute__((unused)) 219030ca2051SWilly Tarreau ssize_t read(int fd, void *buf, size_t count) 219130ca2051SWilly Tarreau { 219230ca2051SWilly Tarreau ssize_t ret = sys_read(fd, buf, count); 219330ca2051SWilly Tarreau 219430ca2051SWilly Tarreau if (ret < 0) { 219530ca2051SWilly Tarreau SET_ERRNO(-ret); 219630ca2051SWilly Tarreau ret = -1; 219730ca2051SWilly Tarreau } 219830ca2051SWilly Tarreau return ret; 219930ca2051SWilly Tarreau } 220030ca2051SWilly Tarreau 220130ca2051SWilly Tarreau static __attribute__((unused)) 220230ca2051SWilly Tarreau int reboot(int cmd) 220330ca2051SWilly Tarreau { 220430ca2051SWilly Tarreau int ret = sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0); 220530ca2051SWilly Tarreau 220630ca2051SWilly Tarreau if (ret < 0) { 220730ca2051SWilly Tarreau SET_ERRNO(-ret); 220830ca2051SWilly Tarreau ret = -1; 220930ca2051SWilly Tarreau } 221030ca2051SWilly Tarreau return ret; 221130ca2051SWilly Tarreau } 221230ca2051SWilly Tarreau 221330ca2051SWilly Tarreau static __attribute__((unused)) 221430ca2051SWilly Tarreau void *sbrk(intptr_t inc) 221530ca2051SWilly Tarreau { 221630ca2051SWilly Tarreau void *ret; 221730ca2051SWilly Tarreau 221830ca2051SWilly Tarreau /* first call to find current end */ 221930ca2051SWilly Tarreau if ((ret = sys_brk(0)) && (sys_brk(ret + inc) == ret + inc)) 222030ca2051SWilly Tarreau return ret + inc; 222130ca2051SWilly Tarreau 222230ca2051SWilly Tarreau SET_ERRNO(ENOMEM); 222330ca2051SWilly Tarreau return (void *)-1; 222430ca2051SWilly Tarreau } 222530ca2051SWilly Tarreau 222630ca2051SWilly Tarreau static __attribute__((unused)) 222730ca2051SWilly Tarreau int sched_yield(void) 222830ca2051SWilly Tarreau { 222930ca2051SWilly Tarreau int ret = sys_sched_yield(); 223030ca2051SWilly Tarreau 223130ca2051SWilly Tarreau if (ret < 0) { 223230ca2051SWilly Tarreau SET_ERRNO(-ret); 223330ca2051SWilly Tarreau ret = -1; 223430ca2051SWilly Tarreau } 223530ca2051SWilly Tarreau return ret; 223630ca2051SWilly Tarreau } 223730ca2051SWilly Tarreau 223830ca2051SWilly Tarreau static __attribute__((unused)) 223930ca2051SWilly Tarreau int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 224030ca2051SWilly Tarreau { 224130ca2051SWilly Tarreau int ret = sys_select(nfds, rfds, wfds, efds, timeout); 224230ca2051SWilly Tarreau 224330ca2051SWilly Tarreau if (ret < 0) { 224430ca2051SWilly Tarreau SET_ERRNO(-ret); 224530ca2051SWilly Tarreau ret = -1; 224630ca2051SWilly Tarreau } 224730ca2051SWilly Tarreau return ret; 224830ca2051SWilly Tarreau } 224930ca2051SWilly Tarreau 225030ca2051SWilly Tarreau static __attribute__((unused)) 225130ca2051SWilly Tarreau int setpgid(pid_t pid, pid_t pgid) 225230ca2051SWilly Tarreau { 225330ca2051SWilly Tarreau int ret = sys_setpgid(pid, pgid); 225430ca2051SWilly Tarreau 225530ca2051SWilly Tarreau if (ret < 0) { 225630ca2051SWilly Tarreau SET_ERRNO(-ret); 225730ca2051SWilly Tarreau ret = -1; 225830ca2051SWilly Tarreau } 225930ca2051SWilly Tarreau return ret; 226030ca2051SWilly Tarreau } 226130ca2051SWilly Tarreau 226230ca2051SWilly Tarreau static __attribute__((unused)) 226330ca2051SWilly Tarreau pid_t setsid(void) 226430ca2051SWilly Tarreau { 226530ca2051SWilly Tarreau pid_t ret = sys_setsid(); 226630ca2051SWilly Tarreau 226730ca2051SWilly Tarreau if (ret < 0) { 226830ca2051SWilly Tarreau SET_ERRNO(-ret); 226930ca2051SWilly Tarreau ret = -1; 227030ca2051SWilly Tarreau } 227130ca2051SWilly Tarreau return ret; 227230ca2051SWilly Tarreau } 227330ca2051SWilly Tarreau 227430ca2051SWilly Tarreau static __attribute__((unused)) 227530ca2051SWilly Tarreau unsigned int sleep(unsigned int seconds) 227630ca2051SWilly Tarreau { 227730ca2051SWilly Tarreau struct timeval my_timeval = { seconds, 0 }; 227830ca2051SWilly Tarreau 227930ca2051SWilly Tarreau if (sys_select(0, 0, 0, 0, &my_timeval) < 0) 228030ca2051SWilly Tarreau return my_timeval.tv_sec + !!my_timeval.tv_usec; 228130ca2051SWilly Tarreau else 228230ca2051SWilly Tarreau return 0; 228330ca2051SWilly Tarreau } 228430ca2051SWilly Tarreau 228530ca2051SWilly Tarreau static __attribute__((unused)) 2286f916d77eSMark Brown int msleep(unsigned int msecs) 2287f916d77eSMark Brown { 2288f916d77eSMark Brown struct timeval my_timeval = { msecs / 1000, (msecs % 1000) * 1000 }; 2289f916d77eSMark Brown 2290f916d77eSMark Brown if (sys_select(0, 0, 0, 0, &my_timeval) < 0) 2291f916d77eSMark Brown return (my_timeval.tv_sec * 1000) + 2292f916d77eSMark Brown (my_timeval.tv_usec / 1000) + 2293f916d77eSMark Brown !!(my_timeval.tv_usec % 1000); 2294f916d77eSMark Brown else 2295f916d77eSMark Brown return 0; 2296f916d77eSMark Brown } 2297f916d77eSMark Brown 2298f916d77eSMark Brown static __attribute__((unused)) 229930ca2051SWilly Tarreau int stat(const char *path, struct stat *buf) 230030ca2051SWilly Tarreau { 230130ca2051SWilly Tarreau int ret = sys_stat(path, buf); 230230ca2051SWilly Tarreau 230330ca2051SWilly Tarreau if (ret < 0) { 230430ca2051SWilly Tarreau SET_ERRNO(-ret); 230530ca2051SWilly Tarreau ret = -1; 230630ca2051SWilly Tarreau } 230730ca2051SWilly Tarreau return ret; 230830ca2051SWilly Tarreau } 230930ca2051SWilly Tarreau 231030ca2051SWilly Tarreau static __attribute__((unused)) 231130ca2051SWilly Tarreau int symlink(const char *old, const char *new) 231230ca2051SWilly Tarreau { 231330ca2051SWilly Tarreau int ret = sys_symlink(old, new); 231430ca2051SWilly Tarreau 231530ca2051SWilly Tarreau if (ret < 0) { 231630ca2051SWilly Tarreau SET_ERRNO(-ret); 231730ca2051SWilly Tarreau ret = -1; 231830ca2051SWilly Tarreau } 231930ca2051SWilly Tarreau return ret; 232030ca2051SWilly Tarreau } 232130ca2051SWilly Tarreau 232230ca2051SWilly Tarreau static __attribute__((unused)) 232330ca2051SWilly Tarreau int tcsetpgrp(int fd, pid_t pid) 232430ca2051SWilly Tarreau { 232530ca2051SWilly Tarreau return ioctl(fd, TIOCSPGRP, &pid); 232630ca2051SWilly Tarreau } 232730ca2051SWilly Tarreau 232830ca2051SWilly Tarreau static __attribute__((unused)) 232930ca2051SWilly Tarreau mode_t umask(mode_t mode) 233030ca2051SWilly Tarreau { 233130ca2051SWilly Tarreau return sys_umask(mode); 233230ca2051SWilly Tarreau } 233330ca2051SWilly Tarreau 233430ca2051SWilly Tarreau static __attribute__((unused)) 233530ca2051SWilly Tarreau int umount2(const char *path, int flags) 233630ca2051SWilly Tarreau { 233730ca2051SWilly Tarreau int ret = sys_umount2(path, flags); 233830ca2051SWilly Tarreau 233930ca2051SWilly Tarreau if (ret < 0) { 234030ca2051SWilly Tarreau SET_ERRNO(-ret); 234130ca2051SWilly Tarreau ret = -1; 234230ca2051SWilly Tarreau } 234330ca2051SWilly Tarreau return ret; 234430ca2051SWilly Tarreau } 234530ca2051SWilly Tarreau 234630ca2051SWilly Tarreau static __attribute__((unused)) 234730ca2051SWilly Tarreau int unlink(const char *path) 234830ca2051SWilly Tarreau { 234930ca2051SWilly Tarreau int ret = sys_unlink(path); 235030ca2051SWilly Tarreau 235130ca2051SWilly Tarreau if (ret < 0) { 235230ca2051SWilly Tarreau SET_ERRNO(-ret); 235330ca2051SWilly Tarreau ret = -1; 235430ca2051SWilly Tarreau } 235530ca2051SWilly Tarreau return ret; 235630ca2051SWilly Tarreau } 235730ca2051SWilly Tarreau 235830ca2051SWilly Tarreau static __attribute__((unused)) 235930ca2051SWilly Tarreau pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage) 236030ca2051SWilly Tarreau { 236130ca2051SWilly Tarreau pid_t ret = sys_wait4(pid, status, options, rusage); 236230ca2051SWilly Tarreau 236330ca2051SWilly Tarreau if (ret < 0) { 236430ca2051SWilly Tarreau SET_ERRNO(-ret); 236530ca2051SWilly Tarreau ret = -1; 236630ca2051SWilly Tarreau } 236730ca2051SWilly Tarreau return ret; 236830ca2051SWilly Tarreau } 236930ca2051SWilly Tarreau 237030ca2051SWilly Tarreau static __attribute__((unused)) 237130ca2051SWilly Tarreau pid_t waitpid(pid_t pid, int *status, int options) 237230ca2051SWilly Tarreau { 237330ca2051SWilly Tarreau pid_t ret = sys_waitpid(pid, status, options); 237430ca2051SWilly Tarreau 237530ca2051SWilly Tarreau if (ret < 0) { 237630ca2051SWilly Tarreau SET_ERRNO(-ret); 237730ca2051SWilly Tarreau ret = -1; 237830ca2051SWilly Tarreau } 237930ca2051SWilly Tarreau return ret; 238030ca2051SWilly Tarreau } 238130ca2051SWilly Tarreau 238230ca2051SWilly Tarreau static __attribute__((unused)) 238330ca2051SWilly Tarreau pid_t wait(int *status) 238430ca2051SWilly Tarreau { 238530ca2051SWilly Tarreau pid_t ret = sys_wait(status); 238630ca2051SWilly Tarreau 238730ca2051SWilly Tarreau if (ret < 0) { 238830ca2051SWilly Tarreau SET_ERRNO(-ret); 238930ca2051SWilly Tarreau ret = -1; 239030ca2051SWilly Tarreau } 239130ca2051SWilly Tarreau return ret; 239230ca2051SWilly Tarreau } 239330ca2051SWilly Tarreau 239430ca2051SWilly Tarreau static __attribute__((unused)) 239530ca2051SWilly Tarreau ssize_t write(int fd, const void *buf, size_t count) 239630ca2051SWilly Tarreau { 239730ca2051SWilly Tarreau ssize_t ret = sys_write(fd, buf, count); 239830ca2051SWilly Tarreau 239930ca2051SWilly Tarreau if (ret < 0) { 240030ca2051SWilly Tarreau SET_ERRNO(-ret); 240130ca2051SWilly Tarreau ret = -1; 240230ca2051SWilly Tarreau } 240330ca2051SWilly Tarreau return ret; 240430ca2051SWilly Tarreau } 240530ca2051SWilly Tarreau 240630ca2051SWilly Tarreau /* some size-optimized reimplementations of a few common str* and mem* 240730ca2051SWilly Tarreau * functions. They're marked static, except memcpy() and raise() which are used 240830ca2051SWilly Tarreau * by libgcc on ARM, so they are marked weak instead in order not to cause an 240930ca2051SWilly Tarreau * error when building a program made of multiple files (not recommended). 241030ca2051SWilly Tarreau */ 241130ca2051SWilly Tarreau 241230ca2051SWilly Tarreau static __attribute__((unused)) 241330ca2051SWilly Tarreau void *memmove(void *dst, const void *src, size_t len) 241430ca2051SWilly Tarreau { 241530ca2051SWilly Tarreau ssize_t pos = (dst <= src) ? -1 : (long)len; 241630ca2051SWilly Tarreau void *ret = dst; 241730ca2051SWilly Tarreau 241830ca2051SWilly Tarreau while (len--) { 241930ca2051SWilly Tarreau pos += (dst <= src) ? 1 : -1; 242030ca2051SWilly Tarreau ((char *)dst)[pos] = ((char *)src)[pos]; 242130ca2051SWilly Tarreau } 242230ca2051SWilly Tarreau return ret; 242330ca2051SWilly Tarreau } 242430ca2051SWilly Tarreau 242530ca2051SWilly Tarreau static __attribute__((unused)) 242630ca2051SWilly Tarreau void *memset(void *dst, int b, size_t len) 242730ca2051SWilly Tarreau { 242830ca2051SWilly Tarreau char *p = dst; 242930ca2051SWilly Tarreau 243030ca2051SWilly Tarreau while (len--) 243130ca2051SWilly Tarreau *(p++) = b; 243230ca2051SWilly Tarreau return dst; 243330ca2051SWilly Tarreau } 243430ca2051SWilly Tarreau 243530ca2051SWilly Tarreau static __attribute__((unused)) 243630ca2051SWilly Tarreau int memcmp(const void *s1, const void *s2, size_t n) 243730ca2051SWilly Tarreau { 243830ca2051SWilly Tarreau size_t ofs = 0; 243930ca2051SWilly Tarreau char c1 = 0; 244030ca2051SWilly Tarreau 244130ca2051SWilly Tarreau while (ofs < n && !(c1 = ((char *)s1)[ofs] - ((char *)s2)[ofs])) { 244230ca2051SWilly Tarreau ofs++; 244330ca2051SWilly Tarreau } 244430ca2051SWilly Tarreau return c1; 244530ca2051SWilly Tarreau } 244630ca2051SWilly Tarreau 244730ca2051SWilly Tarreau static __attribute__((unused)) 244830ca2051SWilly Tarreau char *strcpy(char *dst, const char *src) 244930ca2051SWilly Tarreau { 245030ca2051SWilly Tarreau char *ret = dst; 245130ca2051SWilly Tarreau 245230ca2051SWilly Tarreau while ((*dst++ = *src++)); 245330ca2051SWilly Tarreau return ret; 245430ca2051SWilly Tarreau } 245530ca2051SWilly Tarreau 245630ca2051SWilly Tarreau static __attribute__((unused)) 245730ca2051SWilly Tarreau char *strchr(const char *s, int c) 245830ca2051SWilly Tarreau { 245930ca2051SWilly Tarreau while (*s) { 246030ca2051SWilly Tarreau if (*s == (char)c) 246130ca2051SWilly Tarreau return (char *)s; 246230ca2051SWilly Tarreau s++; 246330ca2051SWilly Tarreau } 246430ca2051SWilly Tarreau return NULL; 246530ca2051SWilly Tarreau } 246630ca2051SWilly Tarreau 246730ca2051SWilly Tarreau static __attribute__((unused)) 246830ca2051SWilly Tarreau char *strrchr(const char *s, int c) 246930ca2051SWilly Tarreau { 247030ca2051SWilly Tarreau const char *ret = NULL; 247130ca2051SWilly Tarreau 247230ca2051SWilly Tarreau while (*s) { 247330ca2051SWilly Tarreau if (*s == (char)c) 247430ca2051SWilly Tarreau ret = s; 247530ca2051SWilly Tarreau s++; 247630ca2051SWilly Tarreau } 247730ca2051SWilly Tarreau return (char *)ret; 247830ca2051SWilly Tarreau } 247930ca2051SWilly Tarreau 248030ca2051SWilly Tarreau static __attribute__((unused)) 248130ca2051SWilly Tarreau size_t nolibc_strlen(const char *str) 248230ca2051SWilly Tarreau { 248330ca2051SWilly Tarreau size_t len; 248430ca2051SWilly Tarreau 248530ca2051SWilly Tarreau for (len = 0; str[len]; len++); 248630ca2051SWilly Tarreau return len; 248730ca2051SWilly Tarreau } 248830ca2051SWilly Tarreau 248930ca2051SWilly Tarreau #define strlen(str) ({ \ 249030ca2051SWilly Tarreau __builtin_constant_p((str)) ? \ 249130ca2051SWilly Tarreau __builtin_strlen((str)) : \ 249230ca2051SWilly Tarreau nolibc_strlen((str)); \ 249330ca2051SWilly Tarreau }) 249430ca2051SWilly Tarreau 249530ca2051SWilly Tarreau static __attribute__((unused)) 249630ca2051SWilly Tarreau int isdigit(int c) 249730ca2051SWilly Tarreau { 249830ca2051SWilly Tarreau return (unsigned int)(c - '0') <= 9; 249930ca2051SWilly Tarreau } 250030ca2051SWilly Tarreau 250130ca2051SWilly Tarreau static __attribute__((unused)) 250230ca2051SWilly Tarreau long atol(const char *s) 250330ca2051SWilly Tarreau { 250430ca2051SWilly Tarreau unsigned long ret = 0; 250530ca2051SWilly Tarreau unsigned long d; 250630ca2051SWilly Tarreau int neg = 0; 250730ca2051SWilly Tarreau 250830ca2051SWilly Tarreau if (*s == '-') { 250930ca2051SWilly Tarreau neg = 1; 251030ca2051SWilly Tarreau s++; 251130ca2051SWilly Tarreau } 251230ca2051SWilly Tarreau 251330ca2051SWilly Tarreau while (1) { 251430ca2051SWilly Tarreau d = (*s++) - '0'; 251530ca2051SWilly Tarreau if (d > 9) 251630ca2051SWilly Tarreau break; 251730ca2051SWilly Tarreau ret *= 10; 251830ca2051SWilly Tarreau ret += d; 251930ca2051SWilly Tarreau } 252030ca2051SWilly Tarreau 252130ca2051SWilly Tarreau return neg ? -ret : ret; 252230ca2051SWilly Tarreau } 252330ca2051SWilly Tarreau 252430ca2051SWilly Tarreau static __attribute__((unused)) 252530ca2051SWilly Tarreau int atoi(const char *s) 252630ca2051SWilly Tarreau { 252730ca2051SWilly Tarreau return atol(s); 252830ca2051SWilly Tarreau } 252930ca2051SWilly Tarreau 253030ca2051SWilly Tarreau static __attribute__((unused)) 253130ca2051SWilly Tarreau const char *ltoa(long in) 253230ca2051SWilly Tarreau { 253330ca2051SWilly Tarreau /* large enough for -9223372036854775808 */ 253430ca2051SWilly Tarreau static char buffer[21]; 253530ca2051SWilly Tarreau char *pos = buffer + sizeof(buffer) - 1; 253630ca2051SWilly Tarreau int neg = in < 0; 253730ca2051SWilly Tarreau unsigned long n = neg ? -in : in; 253830ca2051SWilly Tarreau 253930ca2051SWilly Tarreau *pos-- = '\0'; 254030ca2051SWilly Tarreau do { 254130ca2051SWilly Tarreau *pos-- = '0' + n % 10; 254230ca2051SWilly Tarreau n /= 10; 254330ca2051SWilly Tarreau if (pos < buffer) 254430ca2051SWilly Tarreau return pos + 1; 254530ca2051SWilly Tarreau } while (n); 254630ca2051SWilly Tarreau 254730ca2051SWilly Tarreau if (neg) 254830ca2051SWilly Tarreau *pos-- = '-'; 254930ca2051SWilly Tarreau return pos + 1; 255030ca2051SWilly Tarreau } 255130ca2051SWilly Tarreau 255230ca2051SWilly Tarreau __attribute__((weak,unused)) 255330ca2051SWilly Tarreau void *memcpy(void *dst, const void *src, size_t len) 255430ca2051SWilly Tarreau { 255530ca2051SWilly Tarreau return memmove(dst, src, len); 255630ca2051SWilly Tarreau } 255730ca2051SWilly Tarreau 255830ca2051SWilly Tarreau /* needed by libgcc for divide by zero */ 255930ca2051SWilly Tarreau __attribute__((weak,unused)) 256030ca2051SWilly Tarreau int raise(int signal) 256130ca2051SWilly Tarreau { 256230ca2051SWilly Tarreau return kill(getpid(), signal); 256330ca2051SWilly Tarreau } 256430ca2051SWilly Tarreau 256530ca2051SWilly Tarreau /* Here come a few helper functions */ 256630ca2051SWilly Tarreau 256730ca2051SWilly Tarreau static __attribute__((unused)) 256830ca2051SWilly Tarreau void FD_ZERO(fd_set *set) 256930ca2051SWilly Tarreau { 257030ca2051SWilly Tarreau memset(set, 0, sizeof(*set)); 257130ca2051SWilly Tarreau } 257230ca2051SWilly Tarreau 257330ca2051SWilly Tarreau static __attribute__((unused)) 257430ca2051SWilly Tarreau void FD_SET(int fd, fd_set *set) 257530ca2051SWilly Tarreau { 257630ca2051SWilly Tarreau if (fd < 0 || fd >= FD_SETSIZE) 257730ca2051SWilly Tarreau return; 257830ca2051SWilly Tarreau set->fd32[fd / 32] |= 1 << (fd & 31); 257930ca2051SWilly Tarreau } 258030ca2051SWilly Tarreau 258130ca2051SWilly Tarreau /* WARNING, it only deals with the 4096 first majors and 256 first minors */ 258230ca2051SWilly Tarreau static __attribute__((unused)) 258330ca2051SWilly Tarreau dev_t makedev(unsigned int major, unsigned int minor) 258430ca2051SWilly Tarreau { 258530ca2051SWilly Tarreau return ((major & 0xfff) << 8) | (minor & 0xff); 258630ca2051SWilly Tarreau } 2587*930c4accSWilly Tarreau 2588*930c4accSWilly Tarreau #endif /* _NOLIBC_H */ 2589