From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BA32EC47084 for ; Mon, 7 Feb 2022 16:45:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1384475AbiBGQoZ (ORCPT ); Mon, 7 Feb 2022 11:44:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40766 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390530AbiBGQfA (ORCPT ); Mon, 7 Feb 2022 11:35:00 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2BBC9C0401D6 for ; Mon, 7 Feb 2022 08:34:56 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOaHK014384; Mon, 7 Feb 2022 17:24:36 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 01/42] tools/nolibc: use pselect6 on RISCV Date: Mon, 7 Feb 2022 17:23:13 +0100 Message-Id: <20220207162354.14293-2-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This arch doesn't provide the old-style select() syscall, we have to use pselect6(). Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index c1c285fe494a..ad23712f9cb5 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -1256,7 +1256,10 @@ struct sys_stat_struct { * - the arguments are cast to long and assigned into the target * registers which are then simply passed as registers to the asm code, * so that we don't have to experience issues with register constraint= s. + * + * On riscv, select() is not implemented so we have to use pselect6(). */ +#define __ARCH_WANT_SYS_PSELECT6 =20 #define my_syscall0(num) = \ ({ = \ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 561DBC433F5 for ; Mon, 7 Feb 2022 16:45:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1383479AbiBGQoO (ORCPT ); Mon, 7 Feb 2022 11:44:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40414 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390492AbiBGQeu (ORCPT ); Mon, 7 Feb 2022 11:34:50 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id A865DC0401D8 for ; Mon, 7 Feb 2022 08:34:48 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOaeF014385; Mon, 7 Feb 2022 17:24:36 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 02/42] tools/nolibc: guard the main file against multiple inclusion Date: Mon, 7 Feb 2022 17:23:14 +0100 Message-Id: <20220207162354.14293-3-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Including nolibc.h multiple times results in build errors due to multiple definitions. Let's add a guard against multiple inclusions. Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index ad23712f9cb5..4660637d9b17 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -80,6 +80,8 @@ * https://w3challs.com/syscalls/ * */ +#ifndef _NOLIBC_H +#define _NOLIBC_H =20 #include #include @@ -2582,3 +2584,5 @@ dev_t makedev(unsigned int major, unsigned int minor) { return ((major & 0xfff) << 8) | (minor & 0xff); } + +#endif /* _NOLIBC_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 78F56C4332F for ; Mon, 7 Feb 2022 16:45:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355432AbiBGQnc (ORCPT ); Mon, 7 Feb 2022 11:43:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41588 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390674AbiBGQf0 (ORCPT ); Mon, 7 Feb 2022 11:35:26 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id D7CCCC0401CC for ; Mon, 7 Feb 2022 08:35:24 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOb6q014386; Mon, 7 Feb 2022 17:24:37 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 03/42] tools/nolibc/std: move the standard type definitions to std.h Date: Mon, 7 Feb 2022 17:23:15 +0100 Message-Id: <20220207162354.14293-4-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The ordering of includes and definitions for now is a bit of a mess, as for example asm/signal.h is included after int defintions, but plenty of structures are defined later as they rely on other includes. Let's move the standard type definitions to a dedicated file that is included first. We also move NULL there. This way all other includes are aware of it, and we can bring asm/signal.h back to the top of the file. Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 42 ++++-------------------------- tools/include/nolibc/std.h | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 37 deletions(-) create mode 100644 tools/include/nolibc/std.h diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index 4660637d9b17..186a78c25326 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -83,7 +83,12 @@ #ifndef _NOLIBC_H #define _NOLIBC_H =20 +/* standard type definitions */ +#include "std.h" + +/* system includes */ #include +#include // for SIGCHLD #include #include #include @@ -106,40 +111,6 @@ static int errno; */ #define MAX_ERRNO 4095 =20 -/* Declare a few quite common macros and types that usually are in stdlib.= h, - * stdint.h, ctype.h, unistd.h and a few other common locations. - */ - -#define NULL ((void *)0) - -/* stdint types */ -typedef unsigned char uint8_t; -typedef signed char int8_t; -typedef unsigned short uint16_t; -typedef signed short int16_t; -typedef unsigned int uint32_t; -typedef signed int int32_t; -typedef unsigned long long uint64_t; -typedef signed long long int64_t; -typedef unsigned long size_t; -typedef signed long ssize_t; -typedef unsigned long uintptr_t; -typedef signed long intptr_t; -typedef signed long ptrdiff_t; - -/* for stat() */ -typedef unsigned int dev_t; -typedef unsigned long ino_t; -typedef unsigned int mode_t; -typedef signed int pid_t; -typedef unsigned int uid_t; -typedef unsigned int gid_t; -typedef unsigned long nlink_t; -typedef signed long off_t; -typedef signed long blksize_t; -typedef signed long blkcnt_t; -typedef signed long time_t; - /* for poll() */ struct pollfd { int fd; @@ -248,9 +219,6 @@ struct stat { #define WEXITSTATUS(status) (((status) & 0xff00) >> 8) #define WIFEXITED(status) (((status) & 0x7f) =3D=3D 0) =20 -/* for SIGCHLD */ -#include - /* Below comes the architecture-specific code. For each architecture, we h= ave * the syscall declarations and the _start code definition. This is the on= ly * global part. On all architectures the kernel puts everything in the sta= ck diff --git a/tools/include/nolibc/std.h b/tools/include/nolibc/std.h new file mode 100644 index 000000000000..1747ae125392 --- /dev/null +++ b/tools/include/nolibc/std.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * Standard definitions and types for NOLIBC + * Copyright (C) 2017-2021 Willy Tarreau + */ + +#ifndef _NOLIBC_STD_H +#define _NOLIBC_STD_H + +/* Declare a few quite common macros and types that usually are in stdlib.= h, + * stdint.h, ctype.h, unistd.h and a few other common locations. Please pl= ace + * integer type definitions and generic macros here, but avoid OS-specific= and + * syscall-specific stuff, as this file is expected to be included very ea= rly. + */ + +/* note: may already be defined */ +#ifndef NULL +#define NULL ((void *)0) +#endif + +/* stdint types */ +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned int uint32_t; +typedef signed int int32_t; +typedef unsigned long long uint64_t; +typedef signed long long int64_t; +typedef unsigned long size_t; +typedef signed long ssize_t; +typedef unsigned long uintptr_t; +typedef signed long intptr_t; +typedef signed long ptrdiff_t; + +/* those are commonly provided by sys/types.h */ +typedef unsigned int dev_t; +typedef unsigned long ino_t; +typedef unsigned int mode_t; +typedef signed int pid_t; +typedef unsigned int uid_t; +typedef unsigned int gid_t; +typedef unsigned long nlink_t; +typedef signed long off_t; +typedef signed long blksize_t; +typedef signed long blkcnt_t; +typedef signed long time_t; + +#endif /* _NOLIBC_STD_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0AB7BC47081 for ; Mon, 7 Feb 2022 16:45:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1382942AbiBGQoK (ORCPT ); Mon, 7 Feb 2022 11:44:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41684 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390693AbiBGQfc (ORCPT ); Mon, 7 Feb 2022 11:35:32 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E0D12C0401CC for ; Mon, 7 Feb 2022 08:35:30 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GObV1014387; Mon, 7 Feb 2022 17:24:37 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 04/42] tools/nolibc/types: split syscall-specific definitions into their own files Date: Mon, 7 Feb 2022 17:23:16 +0100 Message-Id: <20220207162354.14293-5-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The macros and type definitions used by a number of syscalls were moved to types.h where they will be easier to maintain. A few of them are arch-specific and must not be moved there (e.g. O_*, sys_stat_struct). A warning about them was placed at the top of the file. Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 110 +--------------------------- tools/include/nolibc/types.h | 133 ++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 108 deletions(-) create mode 100644 tools/include/nolibc/types.h diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index 186a78c25326..3719959e6f57 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -94,7 +94,9 @@ #include #include #include +#include "types.h" =20 +/* Used by programs to avoid std includes */ #define NOLIBC =20 /* this way it will be removed if unused */ @@ -111,114 +113,6 @@ static int errno; */ #define MAX_ERRNO 4095 =20 -/* for poll() */ -struct pollfd { - int fd; - short int events; - short int revents; -}; - -/* for getdents64() */ -struct linux_dirent64 { - uint64_t d_ino; - int64_t d_off; - unsigned short d_reclen; - unsigned char d_type; - char d_name[]; -}; - -/* commonly an fd_set represents 256 FDs */ -#define FD_SETSIZE 256 -typedef struct { uint32_t fd32[FD_SETSIZE/32]; } fd_set; - -/* needed by wait4() */ -struct rusage { - struct timeval ru_utime; - struct timeval ru_stime; - long ru_maxrss; - long ru_ixrss; - long ru_idrss; - long ru_isrss; - long ru_minflt; - long ru_majflt; - long ru_nswap; - long ru_inblock; - long ru_oublock; - long ru_msgsnd; - long ru_msgrcv; - long ru_nsignals; - long ru_nvcsw; - long ru_nivcsw; -}; - -/* stat flags (WARNING, octal here) */ -#define S_IFDIR 0040000 -#define S_IFCHR 0020000 -#define S_IFBLK 0060000 -#define S_IFREG 0100000 -#define S_IFIFO 0010000 -#define S_IFLNK 0120000 -#define S_IFSOCK 0140000 -#define S_IFMT 0170000 - -#define S_ISDIR(mode) (((mode) & S_IFDIR) =3D=3D S_IFDIR) -#define S_ISCHR(mode) (((mode) & S_IFCHR) =3D=3D S_IFCHR) -#define S_ISBLK(mode) (((mode) & S_IFBLK) =3D=3D S_IFBLK) -#define S_ISREG(mode) (((mode) & S_IFREG) =3D=3D S_IFREG) -#define S_ISFIFO(mode) (((mode) & S_IFIFO) =3D=3D S_IFIFO) -#define S_ISLNK(mode) (((mode) & S_IFLNK) =3D=3D S_IFLNK) -#define S_ISSOCK(mode) (((mode) & S_IFSOCK) =3D=3D S_IFSOCK) - -#define DT_UNKNOWN 0 -#define DT_FIFO 1 -#define DT_CHR 2 -#define DT_DIR 4 -#define DT_BLK 6 -#define DT_REG 8 -#define DT_LNK 10 -#define DT_SOCK 12 - -/* all the *at functions */ -#ifndef AT_FDCWD -#define AT_FDCWD -100 -#endif - -/* lseek */ -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 - -/* reboot */ -#define LINUX_REBOOT_MAGIC1 0xfee1dead -#define LINUX_REBOOT_MAGIC2 0x28121969 -#define LINUX_REBOOT_CMD_HALT 0xcdef0123 -#define LINUX_REBOOT_CMD_POWER_OFF 0x4321fedc -#define LINUX_REBOOT_CMD_RESTART 0x01234567 -#define LINUX_REBOOT_CMD_SW_SUSPEND 0xd000fce2 - - -/* The format of the struct as returned by the libc to the application, wh= ich - * significantly differs from the format returned by the stat() syscall fl= avours. - */ -struct stat { - dev_t st_dev; /* ID of device containing file */ - ino_t st_ino; /* inode number */ - mode_t st_mode; /* protection */ - nlink_t st_nlink; /* number of hard links */ - uid_t st_uid; /* user ID of owner */ - gid_t st_gid; /* group ID of owner */ - dev_t st_rdev; /* device ID (if special file) */ - off_t st_size; /* total size, in bytes */ - blksize_t st_blksize; /* blocksize for file system I/O */ - blkcnt_t st_blocks; /* number of 512B blocks allocated */ - time_t st_atime; /* time of last access */ - time_t st_mtime; /* time of last modification */ - time_t st_ctime; /* time of last status change */ -}; - -#define WEXITSTATUS(status) (((status) & 0xff00) >> 8) -#define WIFEXITED(status) (((status) & 0x7f) =3D=3D 0) - /* Below comes the architecture-specific code. For each architecture, we h= ave * the syscall declarations and the _start code definition. This is the on= ly * global part. On all architectures the kernel puts everything in the sta= ck diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h new file mode 100644 index 000000000000..2f09abaf95f1 --- /dev/null +++ b/tools/include/nolibc/types.h @@ -0,0 +1,133 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * Special types used by various syscalls for NOLIBC + * Copyright (C) 2017-2021 Willy Tarreau + */ + +#ifndef _NOLIBC_TYPES_H +#define _NOLIBC_TYPES_H + +#include "std.h" +#include + + +/* Only the generic macros and types may be defined here. The arch-specific + * ones such as the O_RDONLY and related macros used by fcntl() and open()= , or + * the layout of sys_stat_struct must not be defined here. + */ + +/* stat flags (WARNING, octal here) */ +#define S_IFDIR 0040000 +#define S_IFCHR 0020000 +#define S_IFBLK 0060000 +#define S_IFREG 0100000 +#define S_IFIFO 0010000 +#define S_IFLNK 0120000 +#define S_IFSOCK 0140000 +#define S_IFMT 0170000 + +#define S_ISDIR(mode) (((mode) & S_IFDIR) =3D=3D S_IFDIR) +#define S_ISCHR(mode) (((mode) & S_IFCHR) =3D=3D S_IFCHR) +#define S_ISBLK(mode) (((mode) & S_IFBLK) =3D=3D S_IFBLK) +#define S_ISREG(mode) (((mode) & S_IFREG) =3D=3D S_IFREG) +#define S_ISFIFO(mode) (((mode) & S_IFIFO) =3D=3D S_IFIFO) +#define S_ISLNK(mode) (((mode) & S_IFLNK) =3D=3D S_IFLNK) +#define S_ISSOCK(mode) (((mode) & S_IFSOCK) =3D=3D S_IFSOCK) + +/* dirent types */ +#define DT_UNKNOWN 0x0 +#define DT_FIFO 0x1 +#define DT_CHR 0x2 +#define DT_DIR 0x4 +#define DT_BLK 0x6 +#define DT_REG 0x8 +#define DT_LNK 0xa +#define DT_SOCK 0xc + +/* commonly an fd_set represents 256 FDs */ +#define FD_SETSIZE 256 + +/* Special FD used by all the *at functions */ +#ifndef AT_FDCWD +#define AT_FDCWD (-100) +#endif + +/* whence values for lseek() */ +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +/* cmd for reboot() */ +#define LINUX_REBOOT_MAGIC1 0xfee1dead +#define LINUX_REBOOT_MAGIC2 0x28121969 +#define LINUX_REBOOT_CMD_HALT 0xcdef0123 +#define LINUX_REBOOT_CMD_POWER_OFF 0x4321fedc +#define LINUX_REBOOT_CMD_RESTART 0x01234567 +#define LINUX_REBOOT_CMD_SW_SUSPEND 0xd000fce2 + +/* Macros used on waitpid()'s return status */ +#define WEXITSTATUS(status) (((status) & 0xff00) >> 8) +#define WIFEXITED(status) (((status) & 0x7f) =3D=3D 0) + + +/* for select() */ +typedef struct { + uint32_t fd32[FD_SETSIZE / 32]; +} fd_set; + +/* for poll() */ +struct pollfd { + int fd; + short int events; + short int revents; +}; + +/* for getdents64() */ +struct linux_dirent64 { + uint64_t d_ino; + int64_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[]; +}; + +/* needed by wait4() */ +struct rusage { + struct timeval ru_utime; + struct timeval ru_stime; + long ru_maxrss; + long ru_ixrss; + long ru_idrss; + long ru_isrss; + long ru_minflt; + long ru_majflt; + long ru_nswap; + long ru_inblock; + long ru_oublock; + long ru_msgsnd; + long ru_msgrcv; + long ru_nsignals; + long ru_nvcsw; + long ru_nivcsw; +}; + +/* The format of the struct as returned by the libc to the application, wh= ich + * significantly differs from the format returned by the stat() syscall fl= avours. + */ +struct stat { + dev_t st_dev; /* ID of device containing file */ + ino_t st_ino; /* inode number */ + mode_t st_mode; /* protection */ + nlink_t st_nlink; /* number of hard links */ + uid_t st_uid; /* user ID of owner */ + gid_t st_gid; /* group ID of owner */ + dev_t st_rdev; /* device ID (if special file) */ + off_t st_size; /* total size, in bytes */ + blksize_t st_blksize; /* blocksize for file system I/O */ + blkcnt_t st_blocks; /* number of 512B blocks allocated */ + time_t st_atime; /* time of last access */ + time_t st_mtime; /* time of last modification */ + time_t st_ctime; /* time of last status change */ +}; + +#endif /* _NOLIBC_TYPES_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 831CAC3527C for ; Mon, 7 Feb 2022 16:45:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1383868AbiBGQoU (ORCPT ); Mon, 7 Feb 2022 11:44:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41864 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390762AbiBGQfr (ORCPT ); Mon, 7 Feb 2022 11:35:47 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 79288C0401DB for ; Mon, 7 Feb 2022 08:35:40 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GObvb014388; Mon, 7 Feb 2022 17:24:37 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 05/42] tools/nolibc/arch: split arch-specific code into individual files Date: Mon, 7 Feb 2022 17:23:17 +0100 Message-Id: <20220207162354.14293-6-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" In order to ease maintenance, this splits the arch-specific code into one file per architecture. A common file "arch.h" is used to include the right file among arch-* based on the detected architecture. Projects which are already split per architecture could simply rename these files to $arch/arch.h and get rid of the common arch.h. For this reason, include guards were placed into each arch-specific file. Signed-off-by: Willy Tarreau --- tools/include/nolibc/arch-aarch64.h | 199 +++++ tools/include/nolibc/arch-arm.h | 204 +++++ tools/include/nolibc/arch-i386.h | 196 +++++ tools/include/nolibc/arch-mips.h | 215 +++++ tools/include/nolibc/arch-riscv.h | 204 +++++ tools/include/nolibc/arch-x86_64.h | 215 +++++ tools/include/nolibc/arch.h | 32 + tools/include/nolibc/nolibc.h | 1187 +-------------------------- 8 files changed, 1266 insertions(+), 1186 deletions(-) create mode 100644 tools/include/nolibc/arch-aarch64.h create mode 100644 tools/include/nolibc/arch-arm.h create mode 100644 tools/include/nolibc/arch-i386.h create mode 100644 tools/include/nolibc/arch-mips.h create mode 100644 tools/include/nolibc/arch-riscv.h create mode 100644 tools/include/nolibc/arch-x86_64.h create mode 100644 tools/include/nolibc/arch.h diff --git a/tools/include/nolibc/arch-aarch64.h b/tools/include/nolibc/arc= h-aarch64.h new file mode 100644 index 000000000000..443de5fb7f54 --- /dev/null +++ b/tools/include/nolibc/arch-aarch64.h @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * AARCH64 specific definitions for NOLIBC + * Copyright (C) 2017-2022 Willy Tarreau + */ + +#ifndef _NOLIBC_ARCH_AARCH64_H +#define _NOLIBC_ARCH_AARCH64_H + +/* O_* macros for fcntl/open are architecture-specific */ +#define O_RDONLY 0 +#define O_WRONLY 1 +#define O_RDWR 2 +#define O_CREAT 0x40 +#define O_EXCL 0x80 +#define O_NOCTTY 0x100 +#define O_TRUNC 0x200 +#define O_APPEND 0x400 +#define O_NONBLOCK 0x800 +#define O_DIRECTORY 0x4000 + +/* The struct returned by the newfstatat() syscall. Differs slightly from = the + * x86_64's stat one by field ordering, so be careful. + */ +struct sys_stat_struct { + unsigned long st_dev; + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + + unsigned long st_rdev; + unsigned long __pad1; + long st_size; + int st_blksize; + int __pad2; + + long st_blocks; + long st_atime; + unsigned long st_atime_nsec; + long st_mtime; + + unsigned long st_mtime_nsec; + long st_ctime; + unsigned long st_ctime_nsec; + unsigned int __unused[2]; +}; + +/* Syscalls for AARCH64 : + * - registers are 64-bit + * - stack is 16-byte aligned + * - syscall number is passed in x8 + * - arguments are in x0, x1, x2, x3, x4, x5 + * - the system call is performed by calling svc 0 + * - syscall return comes in x0. + * - the arguments are cast to long and assigned into the target registe= rs + * which are then simply passed as registers to the asm code, so that = we + * don't have to experience issues with register constraints. + * + * On aarch64, select() is not implemented so we have to use pselect6(). + */ +#define __ARCH_WANT_SYS_PSELECT6 + +#define my_syscall0(num) = \ +({ = \ + register long _num asm("x8") =3D (num); \ + register long _arg1 asm("x0"); \ + \ + asm volatile ( \ + "svc #0\n" \ + : "=3Dr"(_arg1) \ + : "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall1(num, arg1) = \ +({ = \ + register long _num asm("x8") =3D (num); \ + register long _arg1 asm("x0") =3D (long)(arg1); \ + \ + asm volatile ( \ + "svc #0\n" \ + : "=3Dr"(_arg1) \ + : "r"(_arg1), \ + "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall2(num, arg1, arg2) = \ +({ = \ + register long _num asm("x8") =3D (num); \ + register long _arg1 asm("x0") =3D (long)(arg1); \ + register long _arg2 asm("x1") =3D (long)(arg2); \ + \ + asm volatile ( \ + "svc #0\n" \ + : "=3Dr"(_arg1) \ + : "r"(_arg1), "r"(_arg2), \ + "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall3(num, arg1, arg2, arg3) = \ +({ = \ + register long _num asm("x8") =3D (num); \ + register long _arg1 asm("x0") =3D (long)(arg1); \ + register long _arg2 asm("x1") =3D (long)(arg2); \ + register long _arg3 asm("x2") =3D (long)(arg3); \ + \ + asm volatile ( \ + "svc #0\n" \ + : "=3Dr"(_arg1) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ + "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall4(num, arg1, arg2, arg3, arg4) = \ +({ = \ + register long _num asm("x8") =3D (num); \ + register long _arg1 asm("x0") =3D (long)(arg1); \ + register long _arg2 asm("x1") =3D (long)(arg2); \ + register long _arg3 asm("x2") =3D (long)(arg3); \ + register long _arg4 asm("x3") =3D (long)(arg4); \ + \ + asm volatile ( \ + "svc #0\n" \ + : "=3Dr"(_arg1) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ + "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) = \ +({ = \ + register long _num asm("x8") =3D (num); \ + register long _arg1 asm("x0") =3D (long)(arg1); \ + register long _arg2 asm("x1") =3D (long)(arg2); \ + register long _arg3 asm("x2") =3D (long)(arg3); \ + register long _arg4 asm("x3") =3D (long)(arg4); \ + register long _arg5 asm("x4") =3D (long)(arg5); \ + \ + asm volatile ( \ + "svc #0\n" \ + : "=3Dr" (_arg1) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ + "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) = \ +({ = \ + register long _num asm("x8") =3D (num); \ + register long _arg1 asm("x0") =3D (long)(arg1); \ + register long _arg2 asm("x1") =3D (long)(arg2); \ + register long _arg3 asm("x2") =3D (long)(arg3); \ + register long _arg4 asm("x3") =3D (long)(arg4); \ + register long _arg5 asm("x4") =3D (long)(arg5); \ + register long _arg6 asm("x5") =3D (long)(arg6); \ + \ + asm volatile ( \ + "svc #0\n" \ + : "=3Dr" (_arg1) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ + "r"(_arg6), "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +/* startup code */ +asm(".section .text\n" + ".global _start\n" + "_start:\n" + "ldr x0, [sp]\n" // argc (x0) was in the stack + "add x1, sp, 8\n" // argv (x1) =3D sp + "lsl x2, x0, 3\n" // envp (x2) =3D 8*argc ... + "add x2, x2, 8\n" // + 8 (skip null) + "add x2, x2, x1\n" // + argv + "and sp, x1, -16\n" // sp must be 16-byte aligned in the cal= lee + "bl main\n" // main() returns the status code, we'll= exit with it. + "mov x8, 93\n" // NR_exit =3D=3D 93 + "svc #0\n" + ""); + +#endif // _NOLIBC_ARCH_AARCH64_H diff --git a/tools/include/nolibc/arch-arm.h b/tools/include/nolibc/arch-ar= m.h new file mode 100644 index 000000000000..66f687ad987f --- /dev/null +++ b/tools/include/nolibc/arch-arm.h @@ -0,0 +1,204 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * ARM specific definitions for NOLIBC + * Copyright (C) 2017-2022 Willy Tarreau + */ + +#ifndef _NOLIBC_ARCH_ARM_H +#define _NOLIBC_ARCH_ARM_H + +/* O_* macros for fcntl/open are architecture-specific */ +#define O_RDONLY 0 +#define O_WRONLY 1 +#define O_RDWR 2 +#define O_CREAT 0x40 +#define O_EXCL 0x80 +#define O_NOCTTY 0x100 +#define O_TRUNC 0x200 +#define O_APPEND 0x400 +#define O_NONBLOCK 0x800 +#define O_DIRECTORY 0x4000 + +/* The struct returned by the stat() syscall, 32-bit only, the syscall ret= urns + * exactly 56 bytes (stops before the unused array). In big endian, the fo= rmat + * differs as devices are returned as short only. + */ +struct sys_stat_struct { +#if defined(__ARMEB__) + unsigned short st_dev; + unsigned short __pad1; +#else + unsigned long st_dev; +#endif + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + +#if defined(__ARMEB__) + unsigned short st_rdev; + unsigned short __pad2; +#else + unsigned long st_rdev; +#endif + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + unsigned long st_mtime_nsec; + + unsigned long st_ctime; + unsigned long st_ctime_nsec; + unsigned long __unused[2]; +}; + +/* Syscalls for ARM in ARM or Thumb modes : + * - registers are 32-bit + * - stack is 8-byte aligned + * ( http://infocenter.arm.com/help/index.jsp?topic=3D/com.arm.doc.faq= s/ka4127.html) + * - syscall number is passed in r7 + * - arguments are in r0, r1, r2, r3, r4, r5 + * - the system call is performed by calling svc #0 + * - syscall return comes in r0. + * - only lr is clobbered. + * - the arguments are cast to long and assigned into the target registe= rs + * which are then simply passed as registers to the asm code, so that = we + * don't have to experience issues with register constraints. + * - the syscall number is always specified last in order to allow to fo= rce + * some registers before (gcc refuses a %-register at the last positio= n). + * + * Also, ARM supports the old_select syscall if newselect is not available + */ +#define __ARCH_WANT_SYS_OLD_SELECT + +#define my_syscall0(num) = \ +({ = \ + register long _num asm("r7") =3D (num); \ + register long _arg1 asm("r0"); \ + \ + asm volatile ( \ + "svc #0\n" \ + : "=3Dr"(_arg1) \ + : "r"(_num) \ + : "memory", "cc", "lr" \ + ); \ + _arg1; \ +}) + +#define my_syscall1(num, arg1) = \ +({ = \ + register long _num asm("r7") =3D (num); \ + register long _arg1 asm("r0") =3D (long)(arg1); \ + \ + asm volatile ( \ + "svc #0\n" \ + : "=3Dr"(_arg1) \ + : "r"(_arg1), \ + "r"(_num) \ + : "memory", "cc", "lr" \ + ); \ + _arg1; \ +}) + +#define my_syscall2(num, arg1, arg2) = \ +({ = \ + register long _num asm("r7") =3D (num); \ + register long _arg1 asm("r0") =3D (long)(arg1); \ + register long _arg2 asm("r1") =3D (long)(arg2); \ + \ + asm volatile ( \ + "svc #0\n" \ + : "=3Dr"(_arg1) \ + : "r"(_arg1), "r"(_arg2), \ + "r"(_num) \ + : "memory", "cc", "lr" \ + ); \ + _arg1; \ +}) + +#define my_syscall3(num, arg1, arg2, arg3) = \ +({ = \ + register long _num asm("r7") =3D (num); \ + register long _arg1 asm("r0") =3D (long)(arg1); \ + register long _arg2 asm("r1") =3D (long)(arg2); \ + register long _arg3 asm("r2") =3D (long)(arg3); \ + \ + asm volatile ( \ + "svc #0\n" \ + : "=3Dr"(_arg1) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ + "r"(_num) \ + : "memory", "cc", "lr" \ + ); \ + _arg1; \ +}) + +#define my_syscall4(num, arg1, arg2, arg3, arg4) = \ +({ = \ + register long _num asm("r7") =3D (num); \ + register long _arg1 asm("r0") =3D (long)(arg1); \ + register long _arg2 asm("r1") =3D (long)(arg2); \ + register long _arg3 asm("r2") =3D (long)(arg3); \ + register long _arg4 asm("r3") =3D (long)(arg4); \ + \ + asm volatile ( \ + "svc #0\n" \ + : "=3Dr"(_arg1) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ + "r"(_num) \ + : "memory", "cc", "lr" \ + ); \ + _arg1; \ +}) + +#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) = \ +({ = \ + register long _num asm("r7") =3D (num); \ + register long _arg1 asm("r0") =3D (long)(arg1); \ + register long _arg2 asm("r1") =3D (long)(arg2); \ + register long _arg3 asm("r2") =3D (long)(arg3); \ + register long _arg4 asm("r3") =3D (long)(arg4); \ + register long _arg5 asm("r4") =3D (long)(arg5); \ + \ + asm volatile ( \ + "svc #0\n" \ + : "=3Dr" (_arg1) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ + "r"(_num) \ + : "memory", "cc", "lr" \ + ); \ + _arg1; \ +}) + +/* startup code */ +asm(".section .text\n" + ".global _start\n" + "_start:\n" +#if defined(__THUMBEB__) || defined(__THUMBEL__) + /* We enter here in 32-bit mode but if some previous functions were in + * 16-bit mode, the assembler cannot know, so we need to tell it we're= in + * 32-bit now, then switch to 16-bit (is there a better way to do it t= han + * adding 1 by hand ?) and tell the asm we're now in 16-bit mode so th= at + * it generates correct instructions. Note that we do not support thum= b1. + */ + ".code 32\n" + "add r0, pc, #1\n" + "bx r0\n" + ".code 16\n" +#endif + "pop {%r0}\n" // argc was in the stack + "mov %r1, %sp\n" // argv =3D sp + "add %r2, %r1, %r0, lsl #2\n" // envp =3D argv + 4*argc ... + "add %r2, %r2, $4\n" // ... + 4 + "and %r3, %r1, $-8\n" // AAPCS : sp must be 8-byte aligned in = the + "mov %sp, %r3\n" // callee, an bl doesn't push (l= r=3Dpc) + "bl main\n" // main() returns the status code, we'll= exit with it. + "movs r7, $1\n" // NR_exit =3D=3D 1 + "svc $0x00\n" + ""); + +#endif // _NOLIBC_ARCH_ARM_H diff --git a/tools/include/nolibc/arch-i386.h b/tools/include/nolibc/arch-i= 386.h new file mode 100644 index 000000000000..32f42e2cee26 --- /dev/null +++ b/tools/include/nolibc/arch-i386.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * i386 specific definitions for NOLIBC + * Copyright (C) 2017-2022 Willy Tarreau + */ + +#ifndef _NOLIBC_ARCH_I386_H +#define _NOLIBC_ARCH_I386_H + +/* O_* macros for fcntl/open are architecture-specific */ +#define O_RDONLY 0 +#define O_WRONLY 1 +#define O_RDWR 2 +#define O_CREAT 0x40 +#define O_EXCL 0x80 +#define O_NOCTTY 0x100 +#define O_TRUNC 0x200 +#define O_APPEND 0x400 +#define O_NONBLOCK 0x800 +#define O_DIRECTORY 0x10000 + +/* The struct returned by the stat() syscall, 32-bit only, the syscall ret= urns + * exactly 56 bytes (stops before the unused array). + */ +struct sys_stat_struct { + unsigned long st_dev; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + + unsigned long st_rdev; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + unsigned long st_mtime_nsec; + + unsigned long st_ctime; + unsigned long st_ctime_nsec; + unsigned long __unused[2]; +}; + +/* Syscalls for i386 : + * - mostly similar to x86_64 + * - registers are 32-bit + * - syscall number is passed in eax + * - arguments are in ebx, ecx, edx, esi, edi, ebp respectively + * - all registers are preserved (except eax of course) + * - the system call is performed by calling int $0x80 + * - syscall return comes in eax + * - the arguments are cast to long and assigned into the target registe= rs + * which are then simply passed as registers to the asm code, so that = we + * don't have to experience issues with register constraints. + * - the syscall number is always specified last in order to allow to fo= rce + * some registers before (gcc refuses a %-register at the last positio= n). + * + * Also, i386 supports the old_select syscall if newselect is not available + */ +#define __ARCH_WANT_SYS_OLD_SELECT + +#define my_syscall0(num) = \ +({ = \ + long _ret; \ + register long _num asm("eax") =3D (num); \ + \ + asm volatile ( \ + "int $0x80\n" \ + : "=3Da" (_ret) \ + : "0"(_num) \ + : "memory", "cc" \ + ); \ + _ret; \ +}) + +#define my_syscall1(num, arg1) = \ +({ = \ + long _ret; \ + register long _num asm("eax") =3D (num); \ + register long _arg1 asm("ebx") =3D (long)(arg1); \ + \ + asm volatile ( \ + "int $0x80\n" \ + : "=3Da" (_ret) \ + : "r"(_arg1), \ + "0"(_num) \ + : "memory", "cc" \ + ); \ + _ret; \ +}) + +#define my_syscall2(num, arg1, arg2) = \ +({ = \ + long _ret; \ + register long _num asm("eax") =3D (num); \ + register long _arg1 asm("ebx") =3D (long)(arg1); \ + register long _arg2 asm("ecx") =3D (long)(arg2); \ + \ + asm volatile ( \ + "int $0x80\n" \ + : "=3Da" (_ret) \ + : "r"(_arg1), "r"(_arg2), \ + "0"(_num) \ + : "memory", "cc" \ + ); \ + _ret; \ +}) + +#define my_syscall3(num, arg1, arg2, arg3) = \ +({ = \ + long _ret; \ + register long _num asm("eax") =3D (num); \ + register long _arg1 asm("ebx") =3D (long)(arg1); \ + register long _arg2 asm("ecx") =3D (long)(arg2); \ + register long _arg3 asm("edx") =3D (long)(arg3); \ + \ + asm volatile ( \ + "int $0x80\n" \ + : "=3Da" (_ret) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ + "0"(_num) \ + : "memory", "cc" \ + ); \ + _ret; \ +}) + +#define my_syscall4(num, arg1, arg2, arg3, arg4) = \ +({ = \ + long _ret; \ + register long _num asm("eax") =3D (num); \ + register long _arg1 asm("ebx") =3D (long)(arg1); \ + register long _arg2 asm("ecx") =3D (long)(arg2); \ + register long _arg3 asm("edx") =3D (long)(arg3); \ + register long _arg4 asm("esi") =3D (long)(arg4); \ + \ + asm volatile ( \ + "int $0x80\n" \ + : "=3Da" (_ret) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ + "0"(_num) \ + : "memory", "cc" \ + ); \ + _ret; \ +}) + +#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) = \ +({ = \ + long _ret; \ + register long _num asm("eax") =3D (num); \ + register long _arg1 asm("ebx") =3D (long)(arg1); \ + register long _arg2 asm("ecx") =3D (long)(arg2); \ + register long _arg3 asm("edx") =3D (long)(arg3); \ + register long _arg4 asm("esi") =3D (long)(arg4); \ + register long _arg5 asm("edi") =3D (long)(arg5); \ + \ + asm volatile ( \ + "int $0x80\n" \ + : "=3Da" (_ret) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ + "0"(_num) \ + : "memory", "cc" \ + ); \ + _ret; \ +}) + +/* startup code */ +/* + * i386 System V ABI mandates: + * 1) last pushed argument must be 16-byte aligned. + * 2) The deepest stack frame should be set to zero + * + */ +asm(".section .text\n" + ".global _start\n" + "_start:\n" + "pop %eax\n" // argc (first arg, %eax) + "mov %esp, %ebx\n" // argv[] (second arg, %ebx) + "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx) + "xor %ebp, %ebp\n" // zero the stack frame + "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned b= efore + "sub $4, %esp\n" // the call instruction (args are aligned) + "push %ecx\n" // push all registers on the stack so that= we + "push %ebx\n" // support both regparm and plain stack mo= des + "push %eax\n" + "call main\n" // main() returns the status code in %eax + "mov %eax, %ebx\n" // retrieve exit code (32-bit int) + "movl $1, %eax\n" // NR_exit =3D=3D 1 + "int $0x80\n" // exit now + "hlt\n" // ensure it does not + ""); + +#endif // _NOLIBC_ARCH_I386_H diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-m= ips.h new file mode 100644 index 000000000000..e330201dde6a --- /dev/null +++ b/tools/include/nolibc/arch-mips.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * MIPS specific definitions for NOLIBC + * Copyright (C) 2017-2022 Willy Tarreau + */ + +#ifndef _NOLIBC_ARCH_MIPS_H +#define _NOLIBC_ARCH_MIPS_H + +/* O_* macros for fcntl/open are architecture-specific */ +#define O_RDONLY 0 +#define O_WRONLY 1 +#define O_RDWR 2 +#define O_APPEND 0x0008 +#define O_NONBLOCK 0x0080 +#define O_CREAT 0x0100 +#define O_TRUNC 0x0200 +#define O_EXCL 0x0400 +#define O_NOCTTY 0x0800 +#define O_DIRECTORY 0x10000 + +/* The struct returned by the stat() syscall. 88 bytes are returned by the + * syscall. + */ +struct sys_stat_struct { + unsigned int st_dev; + long st_pad1[3]; + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned int st_rdev; + long st_pad2[2]; + long st_size; + long st_pad3; + + long st_atime; + long st_atime_nsec; + long st_mtime; + long st_mtime_nsec; + + long st_ctime; + long st_ctime_nsec; + long st_blksize; + long st_blocks; + long st_pad4[14]; +}; + +/* Syscalls for MIPS ABI O32 : + * - WARNING! there's always a delayed slot! + * - WARNING again, the syntax is different, registers take a '$' and nu= mbers + * do not. + * - registers are 32-bit + * - stack is 8-byte aligned + * - syscall number is passed in v0 (starts at 0xfa0). + * - arguments are in a0, a1, a2, a3, then the stack. The caller needs to + * leave some room in the stack for the callee to save a0..a3 if neede= d. + * - Many registers are clobbered, in fact only a0..a2 and s0..s8 are + * preserved. See: https://www.linux-mips.org/wiki/Syscall as well as + * scall32-o32.S in the kernel sources. + * - the system call is performed by calling "syscall" + * - syscall return comes in v0, and register a3 needs to be checked to = know + * if an error occurred, in which case errno is in v0. + * - the arguments are cast to long and assigned into the target registe= rs + * which are then simply passed as registers to the asm code, so that = we + * don't have to experience issues with register constraints. + */ + +#define my_syscall0(num) = \ +({ = \ + register long _num asm("v0") =3D (num); \ + register long _arg4 asm("a3"); \ + \ + asm volatile ( \ + "addiu $sp, $sp, -32\n" \ + "syscall\n" \ + "addiu $sp, $sp, 32\n" \ + : "=3Dr"(_num), "=3Dr"(_arg4) \ + : "r"(_num) \ + : "memory", "cc", "at", "v1", "hi", "lo", \ + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ + ); \ + _arg4 ? -_num : _num; \ +}) + +#define my_syscall1(num, arg1) = \ +({ = \ + register long _num asm("v0") =3D (num); \ + register long _arg1 asm("a0") =3D (long)(arg1); \ + register long _arg4 asm("a3"); \ + \ + asm volatile ( \ + "addiu $sp, $sp, -32\n" \ + "syscall\n" \ + "addiu $sp, $sp, 32\n" \ + : "=3Dr"(_num), "=3Dr"(_arg4) \ + : "0"(_num), \ + "r"(_arg1) \ + : "memory", "cc", "at", "v1", "hi", "lo", \ + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ + ); \ + _arg4 ? -_num : _num; \ +}) + +#define my_syscall2(num, arg1, arg2) = \ +({ = \ + register long _num asm("v0") =3D (num); \ + register long _arg1 asm("a0") =3D (long)(arg1); \ + register long _arg2 asm("a1") =3D (long)(arg2); \ + register long _arg4 asm("a3"); \ + \ + asm volatile ( \ + "addiu $sp, $sp, -32\n" \ + "syscall\n" \ + "addiu $sp, $sp, 32\n" \ + : "=3Dr"(_num), "=3Dr"(_arg4) \ + : "0"(_num), \ + "r"(_arg1), "r"(_arg2) \ + : "memory", "cc", "at", "v1", "hi", "lo", \ + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ + ); \ + _arg4 ? -_num : _num; \ +}) + +#define my_syscall3(num, arg1, arg2, arg3) = \ +({ = \ + register long _num asm("v0") =3D (num); \ + register long _arg1 asm("a0") =3D (long)(arg1); \ + register long _arg2 asm("a1") =3D (long)(arg2); \ + register long _arg3 asm("a2") =3D (long)(arg3); \ + register long _arg4 asm("a3"); \ + \ + asm volatile ( \ + "addiu $sp, $sp, -32\n" \ + "syscall\n" \ + "addiu $sp, $sp, 32\n" \ + : "=3Dr"(_num), "=3Dr"(_arg4) \ + : "0"(_num), \ + "r"(_arg1), "r"(_arg2), "r"(_arg3) \ + : "memory", "cc", "at", "v1", "hi", "lo", \ + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ + ); \ + _arg4 ? -_num : _num; \ +}) + +#define my_syscall4(num, arg1, arg2, arg3, arg4) = \ +({ = \ + register long _num asm("v0") =3D (num); \ + register long _arg1 asm("a0") =3D (long)(arg1); \ + register long _arg2 asm("a1") =3D (long)(arg2); \ + register long _arg3 asm("a2") =3D (long)(arg3); \ + register long _arg4 asm("a3") =3D (long)(arg4); \ + \ + asm volatile ( \ + "addiu $sp, $sp, -32\n" \ + "syscall\n" \ + "addiu $sp, $sp, 32\n" \ + : "=3Dr" (_num), "=3Dr"(_arg4) \ + : "0"(_num), \ + "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \ + : "memory", "cc", "at", "v1", "hi", "lo", \ + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ + ); \ + _arg4 ? -_num : _num; \ +}) + +#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) = \ +({ = \ + register long _num asm("v0") =3D (num); \ + register long _arg1 asm("a0") =3D (long)(arg1); \ + register long _arg2 asm("a1") =3D (long)(arg2); \ + register long _arg3 asm("a2") =3D (long)(arg3); \ + register long _arg4 asm("a3") =3D (long)(arg4); \ + register long _arg5 =3D (long)(arg5); \ + \ + asm volatile ( \ + "addiu $sp, $sp, -32\n" \ + "sw %7, 16($sp)\n" \ + "syscall\n " \ + "addiu $sp, $sp, 32\n" \ + : "=3Dr" (_num), "=3Dr"(_arg4) \ + : "0"(_num), \ + "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \ + : "memory", "cc", "at", "v1", "hi", "lo", \ + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ + ); \ + _arg4 ? -_num : _num; \ +}) + +/* startup code, note that it's called __start on MIPS */ +asm(".section .text\n" + ".set nomips16\n" + ".global __start\n" + ".set noreorder\n" + ".option pic0\n" + ".ent __start\n" + "__start:\n" + "lw $a0,($sp)\n" // argc was in the stack + "addiu $a1, $sp, 4\n" // argv =3D sp + 4 + "sll $a2, $a0, 2\n" // a2 =3D argc * 4 + "add $a2, $a2, $a1\n" // envp =3D argv + 4*argc ... + "addiu $a2, $a2, 4\n" // ... + 4 + "li $t0, -8\n" + "and $sp, $sp, $t0\n" // sp must be 8-byte aligned + "addiu $sp,$sp,-16\n" // the callee expects to save a0..a3 the= re! + "jal main\n" // main() returns the status code, we'll= exit with it. + "nop\n" // delayed slot + "move $a0, $v0\n" // retrieve 32-bit exit code from v0 + "li $v0, 4001\n" // NR_exit =3D=3D 4001 + "syscall\n" + ".end __start\n" + ""); + +#endif // _NOLIBC_ARCH_MIPS_H diff --git a/tools/include/nolibc/arch-riscv.h b/tools/include/nolibc/arch-= riscv.h new file mode 100644 index 000000000000..9d5ff78f606b --- /dev/null +++ b/tools/include/nolibc/arch-riscv.h @@ -0,0 +1,204 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * RISCV (32 and 64) specific definitions for NOLIBC + * Copyright (C) 2017-2022 Willy Tarreau + */ + +#ifndef _NOLIBC_ARCH_RISCV_H +#define _NOLIBC_ARCH_RISCV_H + +/* O_* macros for fcntl/open are architecture-specific */ +#define O_RDONLY 0 +#define O_WRONLY 1 +#define O_RDWR 2 +#define O_CREAT 0x100 +#define O_EXCL 0x200 +#define O_NOCTTY 0x400 +#define O_TRUNC 0x1000 +#define O_APPEND 0x2000 +#define O_NONBLOCK 0x4000 +#define O_DIRECTORY 0x200000 + +struct sys_stat_struct { + unsigned long st_dev; /* Device. */ + unsigned long st_ino; /* File serial number. */ + unsigned int st_mode; /* File mode. */ + unsigned int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group. */ + unsigned long st_rdev; /* Device number, if device. */ + unsigned long __pad1; + long st_size; /* Size of file, in bytes. */ + int st_blksize; /* Optimal block size for I/O. */ + int __pad2; + long st_blocks; /* Number 512-byte blocks allocated. */ + long st_atime; /* Time of last access. */ + unsigned long st_atime_nsec; + long st_mtime; /* Time of last modification. */ + unsigned long st_mtime_nsec; + long st_ctime; /* Time of last status change. */ + unsigned long st_ctime_nsec; + unsigned int __unused4; + unsigned int __unused5; +}; + +#if __riscv_xlen =3D=3D 64 +#define PTRLOG "3" +#define SZREG "8" +#elif __riscv_xlen =3D=3D 32 +#define PTRLOG "2" +#define SZREG "4" +#endif + +/* Syscalls for RISCV : + * - stack is 16-byte aligned + * - syscall number is passed in a7 + * - arguments are in a0, a1, a2, a3, a4, a5 + * - the system call is performed by calling ecall + * - syscall return comes in a0 + * - the arguments are cast to long and assigned into the target + * registers which are then simply passed as registers to the asm code, + * so that we don't have to experience issues with register constraint= s. + * + * On riscv, select() is not implemented so we have to use pselect6(). + */ +#define __ARCH_WANT_SYS_PSELECT6 + +#define my_syscall0(num) = \ +({ = \ + register long _num asm("a7") =3D (num); \ + register long _arg1 asm("a0"); \ + \ + asm volatile ( \ + "ecall\n\t" \ + : "=3Dr"(_arg1) \ + : "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall1(num, arg1) = \ +({ = \ + register long _num asm("a7") =3D (num); \ + register long _arg1 asm("a0") =3D (long)(arg1); \ + \ + asm volatile ( \ + "ecall\n" \ + : "+r"(_arg1) \ + : "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall2(num, arg1, arg2) = \ +({ = \ + register long _num asm("a7") =3D (num); \ + register long _arg1 asm("a0") =3D (long)(arg1); \ + register long _arg2 asm("a1") =3D (long)(arg2); \ + \ + asm volatile ( \ + "ecall\n" \ + : "+r"(_arg1) \ + : "r"(_arg2), \ + "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall3(num, arg1, arg2, arg3) = \ +({ = \ + register long _num asm("a7") =3D (num); \ + register long _arg1 asm("a0") =3D (long)(arg1); \ + register long _arg2 asm("a1") =3D (long)(arg2); \ + register long _arg3 asm("a2") =3D (long)(arg3); \ + \ + asm volatile ( \ + "ecall\n\t" \ + : "+r"(_arg1) \ + : "r"(_arg2), "r"(_arg3), \ + "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall4(num, arg1, arg2, arg3, arg4) = \ +({ = \ + register long _num asm("a7") =3D (num); \ + register long _arg1 asm("a0") =3D (long)(arg1); \ + register long _arg2 asm("a1") =3D (long)(arg2); \ + register long _arg3 asm("a2") =3D (long)(arg3); \ + register long _arg4 asm("a3") =3D (long)(arg4); \ + \ + asm volatile ( \ + "ecall\n" \ + : "+r"(_arg1) \ + : "r"(_arg2), "r"(_arg3), "r"(_arg4), \ + "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) = \ +({ = \ + register long _num asm("a7") =3D (num); \ + register long _arg1 asm("a0") =3D (long)(arg1); \ + register long _arg2 asm("a1") =3D (long)(arg2); \ + register long _arg3 asm("a2") =3D (long)(arg3); \ + register long _arg4 asm("a3") =3D (long)(arg4); \ + register long _arg5 asm("a4") =3D (long)(arg5); \ + \ + asm volatile ( \ + "ecall\n" \ + : "+r"(_arg1) \ + : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ + "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) = \ +({ = \ + register long _num asm("a7") =3D (num); \ + register long _arg1 asm("a0") =3D (long)(arg1); \ + register long _arg2 asm("a1") =3D (long)(arg2); \ + register long _arg3 asm("a2") =3D (long)(arg3); \ + register long _arg4 asm("a3") =3D (long)(arg4); \ + register long _arg5 asm("a4") =3D (long)(arg5); \ + register long _arg6 asm("a5") =3D (long)(arg6); \ + \ + asm volatile ( \ + "ecall\n" \ + : "+r"(_arg1) \ + : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \ + "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +/* startup code */ +asm(".section .text\n" + ".global _start\n" + "_start:\n" + ".option push\n" + ".option norelax\n" + "lla gp, __global_pointer$\n" + ".option pop\n" + "ld a0, 0(sp)\n" // argc (a0) was in the stack + "add a1, sp, "SZREG"\n" // argv (a1) =3D sp + "slli a2, a0, "PTRLOG"\n" // envp (a2) =3D SZREG*argc ... + "add a2, a2, "SZREG"\n" // + SZREG (skip null) + "add a2,a2,a1\n" // + argv + "andi sp,a1,-16\n" // sp must be 16-byte aligned + "call main\n" // main() returns the status code, we'll = exit with it. + "li a7, 93\n" // NR_exit =3D=3D 93 + "ecall\n" + ""); + +#endif // _NOLIBC_ARCH_RISCV_H diff --git a/tools/include/nolibc/arch-x86_64.h b/tools/include/nolibc/arch= -x86_64.h new file mode 100644 index 000000000000..83c4b458ada7 --- /dev/null +++ b/tools/include/nolibc/arch-x86_64.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * x86_64 specific definitions for NOLIBC + * Copyright (C) 2017-2022 Willy Tarreau + */ + +#ifndef _NOLIBC_ARCH_X86_64_H +#define _NOLIBC_ARCH_X86_64_H + +/* O_* macros for fcntl/open are architecture-specific */ +#define O_RDONLY 0 +#define O_WRONLY 1 +#define O_RDWR 2 +#define O_CREAT 0x40 +#define O_EXCL 0x80 +#define O_NOCTTY 0x100 +#define O_TRUNC 0x200 +#define O_APPEND 0x400 +#define O_NONBLOCK 0x800 +#define O_DIRECTORY 0x10000 + +/* The struct returned by the stat() syscall, equivalent to stat64(). The + * syscall returns 116 bytes and stops in the middle of __unused. + */ +struct sys_stat_struct { + unsigned long st_dev; + unsigned long st_ino; + unsigned long st_nlink; + unsigned int st_mode; + unsigned int st_uid; + + unsigned int st_gid; + unsigned int __pad0; + unsigned long st_rdev; + long st_size; + long st_blksize; + + long st_blocks; + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + + unsigned long st_mtime_nsec; + unsigned long st_ctime; + unsigned long st_ctime_nsec; + long __unused[3]; +}; + +/* Syscalls for x86_64 : + * - registers are 64-bit + * - syscall number is passed in rax + * - arguments are in rdi, rsi, rdx, r10, r8, r9 respectively + * - the system call is performed by calling the syscall instruction + * - syscall return comes in rax + * - rcx and r11 are clobbered, others are preserved. + * - the arguments are cast to long and assigned into the target registe= rs + * which are then simply passed as registers to the asm code, so that = we + * don't have to experience issues with register constraints. + * - the syscall number is always specified last in order to allow to fo= rce + * some registers before (gcc refuses a %-register at the last positio= n). + * - see also x86-64 ABI section A.2 AMD64 Linux Kernel Conventions, A.2= .1 + * Calling Conventions. + * + * Link x86-64 ABI: https://gitlab.com/x86-psABIs/x86-64-ABI/-/wikis/x86-6= 4-psABI + * + */ + +#define my_syscall0(num) = \ +({ = \ + long _ret; \ + register long _num asm("rax") =3D (num); \ + \ + asm volatile ( \ + "syscall\n" \ + : "=3Da"(_ret) \ + : "0"(_num) \ + : "rcx", "r11", "memory", "cc" \ + ); \ + _ret; \ +}) + +#define my_syscall1(num, arg1) = \ +({ = \ + long _ret; \ + register long _num asm("rax") =3D (num); \ + register long _arg1 asm("rdi") =3D (long)(arg1); \ + \ + asm volatile ( \ + "syscall\n" \ + : "=3Da"(_ret) \ + : "r"(_arg1), \ + "0"(_num) \ + : "rcx", "r11", "memory", "cc" \ + ); \ + _ret; \ +}) + +#define my_syscall2(num, arg1, arg2) = \ +({ = \ + long _ret; \ + register long _num asm("rax") =3D (num); \ + register long _arg1 asm("rdi") =3D (long)(arg1); \ + register long _arg2 asm("rsi") =3D (long)(arg2); \ + \ + asm volatile ( \ + "syscall\n" \ + : "=3Da"(_ret) \ + : "r"(_arg1), "r"(_arg2), \ + "0"(_num) \ + : "rcx", "r11", "memory", "cc" \ + ); \ + _ret; \ +}) + +#define my_syscall3(num, arg1, arg2, arg3) = \ +({ = \ + long _ret; \ + register long _num asm("rax") =3D (num); \ + register long _arg1 asm("rdi") =3D (long)(arg1); \ + register long _arg2 asm("rsi") =3D (long)(arg2); \ + register long _arg3 asm("rdx") =3D (long)(arg3); \ + \ + asm volatile ( \ + "syscall\n" \ + : "=3Da"(_ret) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ + "0"(_num) \ + : "rcx", "r11", "memory", "cc" \ + ); \ + _ret; \ +}) + +#define my_syscall4(num, arg1, arg2, arg3, arg4) = \ +({ = \ + long _ret; \ + register long _num asm("rax") =3D (num); \ + register long _arg1 asm("rdi") =3D (long)(arg1); \ + register long _arg2 asm("rsi") =3D (long)(arg2); \ + register long _arg3 asm("rdx") =3D (long)(arg3); \ + register long _arg4 asm("r10") =3D (long)(arg4); \ + \ + asm volatile ( \ + "syscall\n" \ + : "=3Da"(_ret) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ + "0"(_num) \ + : "rcx", "r11", "memory", "cc" \ + ); \ + _ret; \ +}) + +#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) = \ +({ = \ + long _ret; \ + register long _num asm("rax") =3D (num); \ + register long _arg1 asm("rdi") =3D (long)(arg1); \ + register long _arg2 asm("rsi") =3D (long)(arg2); \ + register long _arg3 asm("rdx") =3D (long)(arg3); \ + register long _arg4 asm("r10") =3D (long)(arg4); \ + register long _arg5 asm("r8") =3D (long)(arg5); \ + \ + asm volatile ( \ + "syscall\n" \ + : "=3Da"(_ret) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ + "0"(_num) \ + : "rcx", "r11", "memory", "cc" \ + ); \ + _ret; \ +}) + +#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) = \ +({ = \ + long _ret; \ + register long _num asm("rax") =3D (num); \ + register long _arg1 asm("rdi") =3D (long)(arg1); \ + register long _arg2 asm("rsi") =3D (long)(arg2); \ + register long _arg3 asm("rdx") =3D (long)(arg3); \ + register long _arg4 asm("r10") =3D (long)(arg4); \ + register long _arg5 asm("r8") =3D (long)(arg5); \ + register long _arg6 asm("r9") =3D (long)(arg6); \ + \ + asm volatile ( \ + "syscall\n" \ + : "=3Da"(_ret) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ + "r"(_arg6), "0"(_num) \ + : "rcx", "r11", "memory", "cc" \ + ); \ + _ret; \ +}) + +/* startup code */ +/* + * x86-64 System V ABI mandates: + * 1) %rsp must be 16-byte aligned right before the function call. + * 2) The deepest stack frame should be zero (the %rbp). + * + */ +asm(".section .text\n" + ".global _start\n" + "_start:\n" + "pop %rdi\n" // argc (first arg, %rdi) + "mov %rsp, %rsi\n" // argv[] (second arg, %rsi) + "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx) + "xor %ebp, %ebp\n" // zero the stack frame + "and $-16, %rsp\n" // x86 ABI : esp must be 16-byte aligned b= efore call + "call main\n" // main() returns the status code, we'll e= xit with it. + "mov %eax, %edi\n" // retrieve exit code (32 bit) + "mov $60, %eax\n" // NR_exit =3D=3D 60 + "syscall\n" // really exit + "hlt\n" // ensure it does not return + ""); + +#endif // _NOLIBC_ARCH_X86_64_H diff --git a/tools/include/nolibc/arch.h b/tools/include/nolibc/arch.h new file mode 100644 index 000000000000..4c6992321b0d --- /dev/null +++ b/tools/include/nolibc/arch.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * Copyright (C) 2017-2022 Willy Tarreau + */ + +/* Below comes the architecture-specific code. For each architecture, we h= ave + * the syscall declarations and the _start code definition. This is the on= ly + * global part. On all architectures the kernel puts everything in the sta= ck + * before jumping to _start just above us, without any return address (_st= art + * is not a function but an entry pint). So at the stack pointer we find a= rgc. + * Then argv[] begins, and ends at the first NULL. Then we have envp which + * starts and ends with a NULL as well. So envp=3Dargv+argc+1. + */ + +#ifndef _NOLIBC_ARCH_H +#define _NOLIBC_ARCH_H + +#if defined(__x86_64__) +#include "arch-x86_64.h" +#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defin= ed(__i686__) +#include "arch-i386.h" +#elif defined(__ARM_EABI__) +#include "arch-arm.h" +#elif defined(__aarch64__) +#include "arch-aarch64.h" +#elif defined(__mips__) && defined(_ABIO32) +#include "arch-mips.h" +#elif defined(__riscv) +#include "arch-riscv.h" +#endif + +#endif /* _NOLIBC_ARCH_H */ diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index 3719959e6f57..ccad3998d824 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -94,6 +94,7 @@ #include #include #include +#include "arch.h" #include "types.h" =20 /* Used by programs to avoid std includes */ @@ -113,1192 +114,6 @@ static int errno; */ #define MAX_ERRNO 4095 =20 -/* Below comes the architecture-specific code. For each architecture, we h= ave - * the syscall declarations and the _start code definition. This is the on= ly - * global part. On all architectures the kernel puts everything in the sta= ck - * before jumping to _start just above us, without any return address (_st= art - * is not a function but an entry pint). So at the stack pointer we find a= rgc. - * Then argv[] begins, and ends at the first NULL. Then we have envp which - * starts and ends with a NULL as well. So envp=3Dargv+argc+1. - */ - -#if defined(__x86_64__) -/* Syscalls for x86_64 : - * - registers are 64-bit - * - syscall number is passed in rax - * - arguments are in rdi, rsi, rdx, r10, r8, r9 respectively - * - the system call is performed by calling the syscall instruction - * - syscall return comes in rax - * - rcx and r11 are clobbered, others are preserved. - * - the arguments are cast to long and assigned into the target registe= rs - * which are then simply passed as registers to the asm code, so that = we - * don't have to experience issues with register constraints. - * - the syscall number is always specified last in order to allow to fo= rce - * some registers before (gcc refuses a %-register at the last positio= n). - * - see also x86-64 ABI section A.2 AMD64 Linux Kernel Conventions, A.2= .1 - * Calling Conventions. - * - * Link x86-64 ABI: https://gitlab.com/x86-psABIs/x86-64-ABI/-/wikis/x86-6= 4-psABI - * - */ - -#define my_syscall0(num) = \ -({ = \ - long _ret; \ - register long _num asm("rax") =3D (num); \ - \ - asm volatile ( \ - "syscall\n" \ - : "=3Da"(_ret) \ - : "0"(_num) \ - : "rcx", "r11", "memory", "cc" \ - ); \ - _ret; \ -}) - -#define my_syscall1(num, arg1) = \ -({ = \ - long _ret; \ - register long _num asm("rax") =3D (num); \ - register long _arg1 asm("rdi") =3D (long)(arg1); \ - \ - asm volatile ( \ - "syscall\n" \ - : "=3Da"(_ret) \ - : "r"(_arg1), \ - "0"(_num) \ - : "rcx", "r11", "memory", "cc" \ - ); \ - _ret; \ -}) - -#define my_syscall2(num, arg1, arg2) = \ -({ = \ - long _ret; \ - register long _num asm("rax") =3D (num); \ - register long _arg1 asm("rdi") =3D (long)(arg1); \ - register long _arg2 asm("rsi") =3D (long)(arg2); \ - \ - asm volatile ( \ - "syscall\n" \ - : "=3Da"(_ret) \ - : "r"(_arg1), "r"(_arg2), \ - "0"(_num) \ - : "rcx", "r11", "memory", "cc" \ - ); \ - _ret; \ -}) - -#define my_syscall3(num, arg1, arg2, arg3) = \ -({ = \ - long _ret; \ - register long _num asm("rax") =3D (num); \ - register long _arg1 asm("rdi") =3D (long)(arg1); \ - register long _arg2 asm("rsi") =3D (long)(arg2); \ - register long _arg3 asm("rdx") =3D (long)(arg3); \ - \ - asm volatile ( \ - "syscall\n" \ - : "=3Da"(_ret) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ - "0"(_num) \ - : "rcx", "r11", "memory", "cc" \ - ); \ - _ret; \ -}) - -#define my_syscall4(num, arg1, arg2, arg3, arg4) = \ -({ = \ - long _ret; \ - register long _num asm("rax") =3D (num); \ - register long _arg1 asm("rdi") =3D (long)(arg1); \ - register long _arg2 asm("rsi") =3D (long)(arg2); \ - register long _arg3 asm("rdx") =3D (long)(arg3); \ - register long _arg4 asm("r10") =3D (long)(arg4); \ - \ - asm volatile ( \ - "syscall\n" \ - : "=3Da"(_ret) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ - "0"(_num) \ - : "rcx", "r11", "memory", "cc" \ - ); \ - _ret; \ -}) - -#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) = \ -({ = \ - long _ret; \ - register long _num asm("rax") =3D (num); \ - register long _arg1 asm("rdi") =3D (long)(arg1); \ - register long _arg2 asm("rsi") =3D (long)(arg2); \ - register long _arg3 asm("rdx") =3D (long)(arg3); \ - register long _arg4 asm("r10") =3D (long)(arg4); \ - register long _arg5 asm("r8") =3D (long)(arg5); \ - \ - asm volatile ( \ - "syscall\n" \ - : "=3Da"(_ret) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ - "0"(_num) \ - : "rcx", "r11", "memory", "cc" \ - ); \ - _ret; \ -}) - -#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) = \ -({ = \ - long _ret; \ - register long _num asm("rax") =3D (num); \ - register long _arg1 asm("rdi") =3D (long)(arg1); \ - register long _arg2 asm("rsi") =3D (long)(arg2); \ - register long _arg3 asm("rdx") =3D (long)(arg3); \ - register long _arg4 asm("r10") =3D (long)(arg4); \ - register long _arg5 asm("r8") =3D (long)(arg5); \ - register long _arg6 asm("r9") =3D (long)(arg6); \ - \ - asm volatile ( \ - "syscall\n" \ - : "=3Da"(_ret) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ - "r"(_arg6), "0"(_num) \ - : "rcx", "r11", "memory", "cc" \ - ); \ - _ret; \ -}) - -/* startup code */ -/* - * x86-64 System V ABI mandates: - * 1) %rsp must be 16-byte aligned right before the function call. - * 2) The deepest stack frame should be zero (the %rbp). - * - */ -asm(".section .text\n" - ".global _start\n" - "_start:\n" - "pop %rdi\n" // argc (first arg, %rdi) - "mov %rsp, %rsi\n" // argv[] (second arg, %rsi) - "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx) - "xor %ebp, %ebp\n" // zero the stack frame - "and $-16, %rsp\n" // x86 ABI : esp must be 16-byte aligned b= efore call - "call main\n" // main() returns the status code, we'll e= xit with it. - "mov %eax, %edi\n" // retrieve exit code (32 bit) - "mov $60, %eax\n" // NR_exit =3D=3D 60 - "syscall\n" // really exit - "hlt\n" // ensure it does not return - ""); - -/* fcntl / open */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_CREAT 0x40 -#define O_EXCL 0x80 -#define O_NOCTTY 0x100 -#define O_TRUNC 0x200 -#define O_APPEND 0x400 -#define O_NONBLOCK 0x800 -#define O_DIRECTORY 0x10000 - -/* The struct returned by the stat() syscall, equivalent to stat64(). The - * syscall returns 116 bytes and stops in the middle of __unused. - */ -struct sys_stat_struct { - unsigned long st_dev; - unsigned long st_ino; - unsigned long st_nlink; - unsigned int st_mode; - unsigned int st_uid; - - unsigned int st_gid; - unsigned int __pad0; - unsigned long st_rdev; - long st_size; - long st_blksize; - - long st_blocks; - unsigned long st_atime; - unsigned long st_atime_nsec; - unsigned long st_mtime; - - unsigned long st_mtime_nsec; - unsigned long st_ctime; - unsigned long st_ctime_nsec; - long __unused[3]; -}; - -#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defin= ed(__i686__) -/* Syscalls for i386 : - * - mostly similar to x86_64 - * - registers are 32-bit - * - syscall number is passed in eax - * - arguments are in ebx, ecx, edx, esi, edi, ebp respectively - * - all registers are preserved (except eax of course) - * - the system call is performed by calling int $0x80 - * - syscall return comes in eax - * - the arguments are cast to long and assigned into the target registe= rs - * which are then simply passed as registers to the asm code, so that = we - * don't have to experience issues with register constraints. - * - the syscall number is always specified last in order to allow to fo= rce - * some registers before (gcc refuses a %-register at the last positio= n). - * - * Also, i386 supports the old_select syscall if newselect is not available - */ -#define __ARCH_WANT_SYS_OLD_SELECT - -#define my_syscall0(num) = \ -({ = \ - long _ret; \ - register long _num asm("eax") =3D (num); \ - \ - asm volatile ( \ - "int $0x80\n" \ - : "=3Da" (_ret) \ - : "0"(_num) \ - : "memory", "cc" \ - ); \ - _ret; \ -}) - -#define my_syscall1(num, arg1) = \ -({ = \ - long _ret; \ - register long _num asm("eax") =3D (num); \ - register long _arg1 asm("ebx") =3D (long)(arg1); \ - \ - asm volatile ( \ - "int $0x80\n" \ - : "=3Da" (_ret) \ - : "r"(_arg1), \ - "0"(_num) \ - : "memory", "cc" \ - ); \ - _ret; \ -}) - -#define my_syscall2(num, arg1, arg2) = \ -({ = \ - long _ret; \ - register long _num asm("eax") =3D (num); \ - register long _arg1 asm("ebx") =3D (long)(arg1); \ - register long _arg2 asm("ecx") =3D (long)(arg2); \ - \ - asm volatile ( \ - "int $0x80\n" \ - : "=3Da" (_ret) \ - : "r"(_arg1), "r"(_arg2), \ - "0"(_num) \ - : "memory", "cc" \ - ); \ - _ret; \ -}) - -#define my_syscall3(num, arg1, arg2, arg3) = \ -({ = \ - long _ret; \ - register long _num asm("eax") =3D (num); \ - register long _arg1 asm("ebx") =3D (long)(arg1); \ - register long _arg2 asm("ecx") =3D (long)(arg2); \ - register long _arg3 asm("edx") =3D (long)(arg3); \ - \ - asm volatile ( \ - "int $0x80\n" \ - : "=3Da" (_ret) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ - "0"(_num) \ - : "memory", "cc" \ - ); \ - _ret; \ -}) - -#define my_syscall4(num, arg1, arg2, arg3, arg4) = \ -({ = \ - long _ret; \ - register long _num asm("eax") =3D (num); \ - register long _arg1 asm("ebx") =3D (long)(arg1); \ - register long _arg2 asm("ecx") =3D (long)(arg2); \ - register long _arg3 asm("edx") =3D (long)(arg3); \ - register long _arg4 asm("esi") =3D (long)(arg4); \ - \ - asm volatile ( \ - "int $0x80\n" \ - : "=3Da" (_ret) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ - "0"(_num) \ - : "memory", "cc" \ - ); \ - _ret; \ -}) - -#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) = \ -({ = \ - long _ret; \ - register long _num asm("eax") =3D (num); \ - register long _arg1 asm("ebx") =3D (long)(arg1); \ - register long _arg2 asm("ecx") =3D (long)(arg2); \ - register long _arg3 asm("edx") =3D (long)(arg3); \ - register long _arg4 asm("esi") =3D (long)(arg4); \ - register long _arg5 asm("edi") =3D (long)(arg5); \ - \ - asm volatile ( \ - "int $0x80\n" \ - : "=3Da" (_ret) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ - "0"(_num) \ - : "memory", "cc" \ - ); \ - _ret; \ -}) - -/* startup code */ -/* - * i386 System V ABI mandates: - * 1) last pushed argument must be 16-byte aligned. - * 2) The deepest stack frame should be set to zero - * - */ -asm(".section .text\n" - ".global _start\n" - "_start:\n" - "pop %eax\n" // argc (first arg, %eax) - "mov %esp, %ebx\n" // argv[] (second arg, %ebx) - "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx) - "xor %ebp, %ebp\n" // zero the stack frame - "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned b= efore - "sub $4, %esp\n" // the call instruction (args are aligned) - "push %ecx\n" // push all registers on the stack so that= we - "push %ebx\n" // support both regparm and plain stack mo= des - "push %eax\n" - "call main\n" // main() returns the status code in %eax - "mov %eax, %ebx\n" // retrieve exit code (32-bit int) - "movl $1, %eax\n" // NR_exit =3D=3D 1 - "int $0x80\n" // exit now - "hlt\n" // ensure it does not - ""); - -/* fcntl / open */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_CREAT 0x40 -#define O_EXCL 0x80 -#define O_NOCTTY 0x100 -#define O_TRUNC 0x200 -#define O_APPEND 0x400 -#define O_NONBLOCK 0x800 -#define O_DIRECTORY 0x10000 - -/* The struct returned by the stat() syscall, 32-bit only, the syscall ret= urns - * exactly 56 bytes (stops before the unused array). - */ -struct sys_stat_struct { - unsigned long st_dev; - unsigned long st_ino; - unsigned short st_mode; - unsigned short st_nlink; - unsigned short st_uid; - unsigned short st_gid; - - unsigned long st_rdev; - unsigned long st_size; - unsigned long st_blksize; - unsigned long st_blocks; - - unsigned long st_atime; - unsigned long st_atime_nsec; - unsigned long st_mtime; - unsigned long st_mtime_nsec; - - unsigned long st_ctime; - unsigned long st_ctime_nsec; - unsigned long __unused[2]; -}; - -#elif defined(__ARM_EABI__) -/* Syscalls for ARM in ARM or Thumb modes : - * - registers are 32-bit - * - stack is 8-byte aligned - * ( http://infocenter.arm.com/help/index.jsp?topic=3D/com.arm.doc.faq= s/ka4127.html) - * - syscall number is passed in r7 - * - arguments are in r0, r1, r2, r3, r4, r5 - * - the system call is performed by calling svc #0 - * - syscall return comes in r0. - * - only lr is clobbered. - * - the arguments are cast to long and assigned into the target registe= rs - * which are then simply passed as registers to the asm code, so that = we - * don't have to experience issues with register constraints. - * - the syscall number is always specified last in order to allow to fo= rce - * some registers before (gcc refuses a %-register at the last positio= n). - * - * Also, ARM supports the old_select syscall if newselect is not available - */ -#define __ARCH_WANT_SYS_OLD_SELECT - -#define my_syscall0(num) = \ -({ = \ - register long _num asm("r7") =3D (num); \ - register long _arg1 asm("r0"); \ - \ - asm volatile ( \ - "svc #0\n" \ - : "=3Dr"(_arg1) \ - : "r"(_num) \ - : "memory", "cc", "lr" \ - ); \ - _arg1; \ -}) - -#define my_syscall1(num, arg1) = \ -({ = \ - register long _num asm("r7") =3D (num); \ - register long _arg1 asm("r0") =3D (long)(arg1); \ - \ - asm volatile ( \ - "svc #0\n" \ - : "=3Dr"(_arg1) \ - : "r"(_arg1), \ - "r"(_num) \ - : "memory", "cc", "lr" \ - ); \ - _arg1; \ -}) - -#define my_syscall2(num, arg1, arg2) = \ -({ = \ - register long _num asm("r7") =3D (num); \ - register long _arg1 asm("r0") =3D (long)(arg1); \ - register long _arg2 asm("r1") =3D (long)(arg2); \ - \ - asm volatile ( \ - "svc #0\n" \ - : "=3Dr"(_arg1) \ - : "r"(_arg1), "r"(_arg2), \ - "r"(_num) \ - : "memory", "cc", "lr" \ - ); \ - _arg1; \ -}) - -#define my_syscall3(num, arg1, arg2, arg3) = \ -({ = \ - register long _num asm("r7") =3D (num); \ - register long _arg1 asm("r0") =3D (long)(arg1); \ - register long _arg2 asm("r1") =3D (long)(arg2); \ - register long _arg3 asm("r2") =3D (long)(arg3); \ - \ - asm volatile ( \ - "svc #0\n" \ - : "=3Dr"(_arg1) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ - "r"(_num) \ - : "memory", "cc", "lr" \ - ); \ - _arg1; \ -}) - -#define my_syscall4(num, arg1, arg2, arg3, arg4) = \ -({ = \ - register long _num asm("r7") =3D (num); \ - register long _arg1 asm("r0") =3D (long)(arg1); \ - register long _arg2 asm("r1") =3D (long)(arg2); \ - register long _arg3 asm("r2") =3D (long)(arg3); \ - register long _arg4 asm("r3") =3D (long)(arg4); \ - \ - asm volatile ( \ - "svc #0\n" \ - : "=3Dr"(_arg1) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ - "r"(_num) \ - : "memory", "cc", "lr" \ - ); \ - _arg1; \ -}) - -#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) = \ -({ = \ - register long _num asm("r7") =3D (num); \ - register long _arg1 asm("r0") =3D (long)(arg1); \ - register long _arg2 asm("r1") =3D (long)(arg2); \ - register long _arg3 asm("r2") =3D (long)(arg3); \ - register long _arg4 asm("r3") =3D (long)(arg4); \ - register long _arg5 asm("r4") =3D (long)(arg5); \ - \ - asm volatile ( \ - "svc #0\n" \ - : "=3Dr" (_arg1) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ - "r"(_num) \ - : "memory", "cc", "lr" \ - ); \ - _arg1; \ -}) - -/* startup code */ -asm(".section .text\n" - ".global _start\n" - "_start:\n" -#if defined(__THUMBEB__) || defined(__THUMBEL__) - /* We enter here in 32-bit mode but if some previous functions were in - * 16-bit mode, the assembler cannot know, so we need to tell it we're= in - * 32-bit now, then switch to 16-bit (is there a better way to do it t= han - * adding 1 by hand ?) and tell the asm we're now in 16-bit mode so th= at - * it generates correct instructions. Note that we do not support thum= b1. - */ - ".code 32\n" - "add r0, pc, #1\n" - "bx r0\n" - ".code 16\n" -#endif - "pop {%r0}\n" // argc was in the stack - "mov %r1, %sp\n" // argv =3D sp - "add %r2, %r1, %r0, lsl #2\n" // envp =3D argv + 4*argc ... - "add %r2, %r2, $4\n" // ... + 4 - "and %r3, %r1, $-8\n" // AAPCS : sp must be 8-byte aligned in = the - "mov %sp, %r3\n" // callee, an bl doesn't push (l= r=3Dpc) - "bl main\n" // main() returns the status code, we'll= exit with it. - "movs r7, $1\n" // NR_exit =3D=3D 1 - "svc $0x00\n" - ""); - -/* fcntl / open */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_CREAT 0x40 -#define O_EXCL 0x80 -#define O_NOCTTY 0x100 -#define O_TRUNC 0x200 -#define O_APPEND 0x400 -#define O_NONBLOCK 0x800 -#define O_DIRECTORY 0x4000 - -/* The struct returned by the stat() syscall, 32-bit only, the syscall ret= urns - * exactly 56 bytes (stops before the unused array). In big endian, the fo= rmat - * differs as devices are returned as short only. - */ -struct sys_stat_struct { -#if defined(__ARMEB__) - unsigned short st_dev; - unsigned short __pad1; -#else - unsigned long st_dev; -#endif - unsigned long st_ino; - unsigned short st_mode; - unsigned short st_nlink; - unsigned short st_uid; - unsigned short st_gid; -#if defined(__ARMEB__) - unsigned short st_rdev; - unsigned short __pad2; -#else - unsigned long st_rdev; -#endif - unsigned long st_size; - unsigned long st_blksize; - unsigned long st_blocks; - unsigned long st_atime; - unsigned long st_atime_nsec; - unsigned long st_mtime; - unsigned long st_mtime_nsec; - unsigned long st_ctime; - unsigned long st_ctime_nsec; - unsigned long __unused[2]; -}; - -#elif defined(__aarch64__) -/* Syscalls for AARCH64 : - * - registers are 64-bit - * - stack is 16-byte aligned - * - syscall number is passed in x8 - * - arguments are in x0, x1, x2, x3, x4, x5 - * - the system call is performed by calling svc 0 - * - syscall return comes in x0. - * - the arguments are cast to long and assigned into the target registe= rs - * which are then simply passed as registers to the asm code, so that = we - * don't have to experience issues with register constraints. - * - * On aarch64, select() is not implemented so we have to use pselect6(). - */ -#define __ARCH_WANT_SYS_PSELECT6 - -#define my_syscall0(num) = \ -({ = \ - register long _num asm("x8") =3D (num); \ - register long _arg1 asm("x0"); \ - \ - asm volatile ( \ - "svc #0\n" \ - : "=3Dr"(_arg1) \ - : "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -#define my_syscall1(num, arg1) = \ -({ = \ - register long _num asm("x8") =3D (num); \ - register long _arg1 asm("x0") =3D (long)(arg1); \ - \ - asm volatile ( \ - "svc #0\n" \ - : "=3Dr"(_arg1) \ - : "r"(_arg1), \ - "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -#define my_syscall2(num, arg1, arg2) = \ -({ = \ - register long _num asm("x8") =3D (num); \ - register long _arg1 asm("x0") =3D (long)(arg1); \ - register long _arg2 asm("x1") =3D (long)(arg2); \ - \ - asm volatile ( \ - "svc #0\n" \ - : "=3Dr"(_arg1) \ - : "r"(_arg1), "r"(_arg2), \ - "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -#define my_syscall3(num, arg1, arg2, arg3) = \ -({ = \ - register long _num asm("x8") =3D (num); \ - register long _arg1 asm("x0") =3D (long)(arg1); \ - register long _arg2 asm("x1") =3D (long)(arg2); \ - register long _arg3 asm("x2") =3D (long)(arg3); \ - \ - asm volatile ( \ - "svc #0\n" \ - : "=3Dr"(_arg1) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ - "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -#define my_syscall4(num, arg1, arg2, arg3, arg4) = \ -({ = \ - register long _num asm("x8") =3D (num); \ - register long _arg1 asm("x0") =3D (long)(arg1); \ - register long _arg2 asm("x1") =3D (long)(arg2); \ - register long _arg3 asm("x2") =3D (long)(arg3); \ - register long _arg4 asm("x3") =3D (long)(arg4); \ - \ - asm volatile ( \ - "svc #0\n" \ - : "=3Dr"(_arg1) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ - "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) = \ -({ = \ - register long _num asm("x8") =3D (num); \ - register long _arg1 asm("x0") =3D (long)(arg1); \ - register long _arg2 asm("x1") =3D (long)(arg2); \ - register long _arg3 asm("x2") =3D (long)(arg3); \ - register long _arg4 asm("x3") =3D (long)(arg4); \ - register long _arg5 asm("x4") =3D (long)(arg5); \ - \ - asm volatile ( \ - "svc #0\n" \ - : "=3Dr" (_arg1) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ - "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) = \ -({ = \ - register long _num asm("x8") =3D (num); \ - register long _arg1 asm("x0") =3D (long)(arg1); \ - register long _arg2 asm("x1") =3D (long)(arg2); \ - register long _arg3 asm("x2") =3D (long)(arg3); \ - register long _arg4 asm("x3") =3D (long)(arg4); \ - register long _arg5 asm("x4") =3D (long)(arg5); \ - register long _arg6 asm("x5") =3D (long)(arg6); \ - \ - asm volatile ( \ - "svc #0\n" \ - : "=3Dr" (_arg1) \ - : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ - "r"(_arg6), "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -/* startup code */ -asm(".section .text\n" - ".global _start\n" - "_start:\n" - "ldr x0, [sp]\n" // argc (x0) was in the stack - "add x1, sp, 8\n" // argv (x1) =3D sp - "lsl x2, x0, 3\n" // envp (x2) =3D 8*argc ... - "add x2, x2, 8\n" // + 8 (skip null) - "add x2, x2, x1\n" // + argv - "and sp, x1, -16\n" // sp must be 16-byte aligned in the cal= lee - "bl main\n" // main() returns the status code, we'll= exit with it. - "mov x8, 93\n" // NR_exit =3D=3D 93 - "svc #0\n" - ""); - -/* fcntl / open */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_CREAT 0x40 -#define O_EXCL 0x80 -#define O_NOCTTY 0x100 -#define O_TRUNC 0x200 -#define O_APPEND 0x400 -#define O_NONBLOCK 0x800 -#define O_DIRECTORY 0x4000 - -/* The struct returned by the newfstatat() syscall. Differs slightly from = the - * x86_64's stat one by field ordering, so be careful. - */ -struct sys_stat_struct { - unsigned long st_dev; - unsigned long st_ino; - unsigned int st_mode; - unsigned int st_nlink; - unsigned int st_uid; - unsigned int st_gid; - - unsigned long st_rdev; - unsigned long __pad1; - long st_size; - int st_blksize; - int __pad2; - - long st_blocks; - long st_atime; - unsigned long st_atime_nsec; - long st_mtime; - - unsigned long st_mtime_nsec; - long st_ctime; - unsigned long st_ctime_nsec; - unsigned int __unused[2]; -}; - -#elif defined(__mips__) && defined(_ABIO32) -/* Syscalls for MIPS ABI O32 : - * - WARNING! there's always a delayed slot! - * - WARNING again, the syntax is different, registers take a '$' and nu= mbers - * do not. - * - registers are 32-bit - * - stack is 8-byte aligned - * - syscall number is passed in v0 (starts at 0xfa0). - * - arguments are in a0, a1, a2, a3, then the stack. The caller needs to - * leave some room in the stack for the callee to save a0..a3 if neede= d. - * - Many registers are clobbered, in fact only a0..a2 and s0..s8 are - * preserved. See: https://www.linux-mips.org/wiki/Syscall as well as - * scall32-o32.S in the kernel sources. - * - the system call is performed by calling "syscall" - * - syscall return comes in v0, and register a3 needs to be checked to = know - * if an error occurred, in which case errno is in v0. - * - the arguments are cast to long and assigned into the target registe= rs - * which are then simply passed as registers to the asm code, so that = we - * don't have to experience issues with register constraints. - */ - -#define my_syscall0(num) = \ -({ = \ - register long _num asm("v0") =3D (num); \ - register long _arg4 asm("a3"); \ - \ - asm volatile ( \ - "addiu $sp, $sp, -32\n" \ - "syscall\n" \ - "addiu $sp, $sp, 32\n" \ - : "=3Dr"(_num), "=3Dr"(_arg4) \ - : "r"(_num) \ - : "memory", "cc", "at", "v1", "hi", "lo", \ - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ - ); \ - _arg4 ? -_num : _num; \ -}) - -#define my_syscall1(num, arg1) = \ -({ = \ - register long _num asm("v0") =3D (num); \ - register long _arg1 asm("a0") =3D (long)(arg1); \ - register long _arg4 asm("a3"); \ - \ - asm volatile ( \ - "addiu $sp, $sp, -32\n" \ - "syscall\n" \ - "addiu $sp, $sp, 32\n" \ - : "=3Dr"(_num), "=3Dr"(_arg4) \ - : "0"(_num), \ - "r"(_arg1) \ - : "memory", "cc", "at", "v1", "hi", "lo", \ - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ - ); \ - _arg4 ? -_num : _num; \ -}) - -#define my_syscall2(num, arg1, arg2) = \ -({ = \ - register long _num asm("v0") =3D (num); \ - register long _arg1 asm("a0") =3D (long)(arg1); \ - register long _arg2 asm("a1") =3D (long)(arg2); \ - register long _arg4 asm("a3"); \ - \ - asm volatile ( \ - "addiu $sp, $sp, -32\n" \ - "syscall\n" \ - "addiu $sp, $sp, 32\n" \ - : "=3Dr"(_num), "=3Dr"(_arg4) \ - : "0"(_num), \ - "r"(_arg1), "r"(_arg2) \ - : "memory", "cc", "at", "v1", "hi", "lo", \ - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ - ); \ - _arg4 ? -_num : _num; \ -}) - -#define my_syscall3(num, arg1, arg2, arg3) = \ -({ = \ - register long _num asm("v0") =3D (num); \ - register long _arg1 asm("a0") =3D (long)(arg1); \ - register long _arg2 asm("a1") =3D (long)(arg2); \ - register long _arg3 asm("a2") =3D (long)(arg3); \ - register long _arg4 asm("a3"); \ - \ - asm volatile ( \ - "addiu $sp, $sp, -32\n" \ - "syscall\n" \ - "addiu $sp, $sp, 32\n" \ - : "=3Dr"(_num), "=3Dr"(_arg4) \ - : "0"(_num), \ - "r"(_arg1), "r"(_arg2), "r"(_arg3) \ - : "memory", "cc", "at", "v1", "hi", "lo", \ - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ - ); \ - _arg4 ? -_num : _num; \ -}) - -#define my_syscall4(num, arg1, arg2, arg3, arg4) = \ -({ = \ - register long _num asm("v0") =3D (num); \ - register long _arg1 asm("a0") =3D (long)(arg1); \ - register long _arg2 asm("a1") =3D (long)(arg2); \ - register long _arg3 asm("a2") =3D (long)(arg3); \ - register long _arg4 asm("a3") =3D (long)(arg4); \ - \ - asm volatile ( \ - "addiu $sp, $sp, -32\n" \ - "syscall\n" \ - "addiu $sp, $sp, 32\n" \ - : "=3Dr" (_num), "=3Dr"(_arg4) \ - : "0"(_num), \ - "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \ - : "memory", "cc", "at", "v1", "hi", "lo", \ - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ - ); \ - _arg4 ? -_num : _num; \ -}) - -#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) = \ -({ = \ - register long _num asm("v0") =3D (num); \ - register long _arg1 asm("a0") =3D (long)(arg1); \ - register long _arg2 asm("a1") =3D (long)(arg2); \ - register long _arg3 asm("a2") =3D (long)(arg3); \ - register long _arg4 asm("a3") =3D (long)(arg4); \ - register long _arg5 =3D (long)(arg5); \ - \ - asm volatile ( \ - "addiu $sp, $sp, -32\n" \ - "sw %7, 16($sp)\n" \ - "syscall\n " \ - "addiu $sp, $sp, 32\n" \ - : "=3Dr" (_num), "=3Dr"(_arg4) \ - : "0"(_num), \ - "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \ - : "memory", "cc", "at", "v1", "hi", "lo", \ - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ - ); \ - _arg4 ? -_num : _num; \ -}) - -/* startup code, note that it's called __start on MIPS */ -asm(".section .text\n" - ".set nomips16\n" - ".global __start\n" - ".set noreorder\n" - ".option pic0\n" - ".ent __start\n" - "__start:\n" - "lw $a0,($sp)\n" // argc was in the stack - "addiu $a1, $sp, 4\n" // argv =3D sp + 4 - "sll $a2, $a0, 2\n" // a2 =3D argc * 4 - "add $a2, $a2, $a1\n" // envp =3D argv + 4*argc ... - "addiu $a2, $a2, 4\n" // ... + 4 - "li $t0, -8\n" - "and $sp, $sp, $t0\n" // sp must be 8-byte aligned - "addiu $sp,$sp,-16\n" // the callee expects to save a0..a3 the= re! - "jal main\n" // main() returns the status code, we'll= exit with it. - "nop\n" // delayed slot - "move $a0, $v0\n" // retrieve 32-bit exit code from v0 - "li $v0, 4001\n" // NR_exit =3D=3D 4001 - "syscall\n" - ".end __start\n" - ""); - -/* fcntl / open */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_APPEND 0x0008 -#define O_NONBLOCK 0x0080 -#define O_CREAT 0x0100 -#define O_TRUNC 0x0200 -#define O_EXCL 0x0400 -#define O_NOCTTY 0x0800 -#define O_DIRECTORY 0x10000 - -/* The struct returned by the stat() syscall. 88 bytes are returned by the - * syscall. - */ -struct sys_stat_struct { - unsigned int st_dev; - long st_pad1[3]; - unsigned long st_ino; - unsigned int st_mode; - unsigned int st_nlink; - unsigned int st_uid; - unsigned int st_gid; - unsigned int st_rdev; - long st_pad2[2]; - long st_size; - long st_pad3; - long st_atime; - long st_atime_nsec; - long st_mtime; - long st_mtime_nsec; - long st_ctime; - long st_ctime_nsec; - long st_blksize; - long st_blocks; - long st_pad4[14]; -}; - -#elif defined(__riscv) - -#if __riscv_xlen =3D=3D 64 -#define PTRLOG "3" -#define SZREG "8" -#elif __riscv_xlen =3D=3D 32 -#define PTRLOG "2" -#define SZREG "4" -#endif - -/* Syscalls for RISCV : - * - stack is 16-byte aligned - * - syscall number is passed in a7 - * - arguments are in a0, a1, a2, a3, a4, a5 - * - the system call is performed by calling ecall - * - syscall return comes in a0 - * - the arguments are cast to long and assigned into the target - * registers which are then simply passed as registers to the asm code, - * so that we don't have to experience issues with register constraint= s. - * - * On riscv, select() is not implemented so we have to use pselect6(). - */ -#define __ARCH_WANT_SYS_PSELECT6 - -#define my_syscall0(num) = \ -({ = \ - register long _num asm("a7") =3D (num); \ - register long _arg1 asm("a0"); \ - \ - asm volatile ( \ - "ecall\n\t" \ - : "=3Dr"(_arg1) \ - : "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -#define my_syscall1(num, arg1) = \ -({ = \ - register long _num asm("a7") =3D (num); \ - register long _arg1 asm("a0") =3D (long)(arg1); \ - \ - asm volatile ( \ - "ecall\n" \ - : "+r"(_arg1) \ - : "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -#define my_syscall2(num, arg1, arg2) = \ -({ = \ - register long _num asm("a7") =3D (num); \ - register long _arg1 asm("a0") =3D (long)(arg1); \ - register long _arg2 asm("a1") =3D (long)(arg2); \ - \ - asm volatile ( \ - "ecall\n" \ - : "+r"(_arg1) \ - : "r"(_arg2), \ - "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -#define my_syscall3(num, arg1, arg2, arg3) = \ -({ = \ - register long _num asm("a7") =3D (num); \ - register long _arg1 asm("a0") =3D (long)(arg1); \ - register long _arg2 asm("a1") =3D (long)(arg2); \ - register long _arg3 asm("a2") =3D (long)(arg3); \ - \ - asm volatile ( \ - "ecall\n\t" \ - : "+r"(_arg1) \ - : "r"(_arg2), "r"(_arg3), \ - "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -#define my_syscall4(num, arg1, arg2, arg3, arg4) = \ -({ = \ - register long _num asm("a7") =3D (num); \ - register long _arg1 asm("a0") =3D (long)(arg1); \ - register long _arg2 asm("a1") =3D (long)(arg2); \ - register long _arg3 asm("a2") =3D (long)(arg3); \ - register long _arg4 asm("a3") =3D (long)(arg4); \ - \ - asm volatile ( \ - "ecall\n" \ - : "+r"(_arg1) \ - : "r"(_arg2), "r"(_arg3), "r"(_arg4), \ - "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) = \ -({ = \ - register long _num asm("a7") =3D (num); \ - register long _arg1 asm("a0") =3D (long)(arg1); \ - register long _arg2 asm("a1") =3D (long)(arg2); \ - register long _arg3 asm("a2") =3D (long)(arg3); \ - register long _arg4 asm("a3") =3D (long)(arg4); \ - register long _arg5 asm("a4") =3D (long)(arg5); \ - \ - asm volatile ( \ - "ecall\n" \ - : "+r"(_arg1) \ - : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ - "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) = \ -({ = \ - register long _num asm("a7") =3D (num); \ - register long _arg1 asm("a0") =3D (long)(arg1); \ - register long _arg2 asm("a1") =3D (long)(arg2); \ - register long _arg3 asm("a2") =3D (long)(arg3); \ - register long _arg4 asm("a3") =3D (long)(arg4); \ - register long _arg5 asm("a4") =3D (long)(arg5); \ - register long _arg6 asm("a5") =3D (long)(arg6); \ - \ - asm volatile ( \ - "ecall\n" \ - : "+r"(_arg1) \ - : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \ - "r"(_num) \ - : "memory", "cc" \ - ); \ - _arg1; \ -}) - -/* startup code */ -asm(".section .text\n" - ".global _start\n" - "_start:\n" - ".option push\n" - ".option norelax\n" - "lla gp, __global_pointer$\n" - ".option pop\n" - "ld a0, 0(sp)\n" // argc (a0) was in the stack - "add a1, sp, "SZREG"\n" // argv (a1) =3D sp - "slli a2, a0, "PTRLOG"\n" // envp (a2) =3D SZREG*argc ... - "add a2, a2, "SZREG"\n" // + SZREG (skip null) - "add a2,a2,a1\n" // + argv - "andi sp,a1,-16\n" // sp must be 16-byte aligned - "call main\n" // main() returns the status code, we'll = exit with it. - "li a7, 93\n" // NR_exit =3D=3D 93 - "ecall\n" - ""); - -/* fcntl / open */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_CREAT 0x100 -#define O_EXCL 0x200 -#define O_NOCTTY 0x400 -#define O_TRUNC 0x1000 -#define O_APPEND 0x2000 -#define O_NONBLOCK 0x4000 -#define O_DIRECTORY 0x200000 - -struct sys_stat_struct { - unsigned long st_dev; /* Device. */ - unsigned long st_ino; /* File serial number. */ - unsigned int st_mode; /* File mode. */ - unsigned int st_nlink; /* Link count. */ - unsigned int st_uid; /* User ID of the file's owner. */ - unsigned int st_gid; /* Group ID of the file's group. */ - unsigned long st_rdev; /* Device number, if device. */ - unsigned long __pad1; - long st_size; /* Size of file, in bytes. */ - int st_blksize; /* Optimal block size for I/O. */ - int __pad2; - long st_blocks; /* Number 512-byte blocks allocated. */ - long st_atime; /* Time of last access. */ - unsigned long st_atime_nsec; - long st_mtime; /* Time of last modification. */ - unsigned long st_mtime_nsec; - long st_ctime; /* Time of last status change. */ - unsigned long st_ctime_nsec; - unsigned int __unused4; - unsigned int __unused5; -}; - -#endif - =20 /* Below are the C functions used to declare the raw syscalls. They try to= be * architecture-agnostic, and return either a success or -errno. Declaring= them --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E8BA3C35275 for ; Mon, 7 Feb 2022 16:45:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1382580AbiBGQoG (ORCPT ); Mon, 7 Feb 2022 11:44:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41774 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390705AbiBGQfk (ORCPT ); Mon, 7 Feb 2022 11:35:40 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E4113C0401CE for ; Mon, 7 Feb 2022 08:35:33 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GObcX014389; Mon, 7 Feb 2022 17:24:37 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 06/42] tools/nolibc/sys: split the syscall definitions into their own file Date: Mon, 7 Feb 2022 17:23:18 +0100 Message-Id: <20220207162354.14293-7-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The syscall definitions were moved to sys.h. They were arranged in a more easily maintainable order, whereby the sys_xxx() and xxx() functions were grouped together, which also enlights the occasional mappings such as wait relying on wait4(). Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 965 +------------------------- tools/include/nolibc/sys.h | 1189 +++++++++++++++++++++++++++++++++ 2 files changed, 1192 insertions(+), 962 deletions(-) create mode 100644 tools/include/nolibc/sys.h diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index ccad3998d824..2af56ec760e2 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -83,869 +83,18 @@ #ifndef _NOLIBC_H #define _NOLIBC_H =20 -/* standard type definitions */ #include "std.h" - -/* system includes */ -#include -#include // for SIGCHLD -#include -#include -#include -#include -#include #include "arch.h" #include "types.h" +#include "sys.h" =20 /* Used by programs to avoid std includes */ #define NOLIBC =20 -/* this way it will be removed if unused */ -static int errno; - -#ifndef NOLIBC_IGNORE_ERRNO -#define SET_ERRNO(v) do { errno =3D (v); } while (0) -#else -#define SET_ERRNO(v) do { } while (0) -#endif - -/* errno codes all ensure that they will not conflict with a valid pointer - * because they all correspond to the highest addressable memory page. - */ -#define MAX_ERRNO 4095 - - -/* Below are the C functions used to declare the raw syscalls. They try to= be - * architecture-agnostic, and return either a success or -errno. Declaring= them - * static will lead to them being inlined in most cases, but it's still po= ssible - * to reference them by a pointer if needed. - */ static __attribute__((unused)) -void *sys_brk(void *addr) +int tcsetpgrp(int fd, pid_t pid) { - return (void *)my_syscall1(__NR_brk, addr); -} - -static __attribute__((noreturn,unused)) -void sys_exit(int status) -{ - my_syscall1(__NR_exit, status & 255); - while(1); // shut the "noreturn" warnings. -} - -static __attribute__((unused)) -int sys_chdir(const char *path) -{ - return my_syscall1(__NR_chdir, path); -} - -static __attribute__((unused)) -int sys_chmod(const char *path, mode_t mode) -{ -#ifdef __NR_fchmodat - return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0); -#elif defined(__NR_chmod) - return my_syscall2(__NR_chmod, path, mode); -#else -#error Neither __NR_fchmodat nor __NR_chmod defined, cannot implement sys_= chmod() -#endif -} - -static __attribute__((unused)) -int sys_chown(const char *path, uid_t owner, gid_t group) -{ -#ifdef __NR_fchownat - return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0); -#elif defined(__NR_chown) - return my_syscall3(__NR_chown, path, owner, group); -#else -#error Neither __NR_fchownat nor __NR_chown defined, cannot implement sys_= chown() -#endif -} - -static __attribute__((unused)) -int sys_chroot(const char *path) -{ - return my_syscall1(__NR_chroot, path); -} - -static __attribute__((unused)) -int sys_close(int fd) -{ - return my_syscall1(__NR_close, fd); -} - -static __attribute__((unused)) -int sys_dup(int fd) -{ - return my_syscall1(__NR_dup, fd); -} - -#ifdef __NR_dup3 -static __attribute__((unused)) -int sys_dup3(int old, int new, int flags) -{ - return my_syscall3(__NR_dup3, old, new, flags); -} -#endif - -static __attribute__((unused)) -int sys_dup2(int old, int new) -{ -#ifdef __NR_dup3 - return my_syscall3(__NR_dup3, old, new, 0); -#elif defined(__NR_dup2) - return my_syscall2(__NR_dup2, old, new); -#else -#error Neither __NR_dup3 nor __NR_dup2 defined, cannot implement sys_dup2() -#endif -} - -static __attribute__((unused)) -int sys_execve(const char *filename, char *const argv[], char *const envp[= ]) -{ - return my_syscall3(__NR_execve, filename, argv, envp); -} - -static __attribute__((unused)) -pid_t sys_fork(void) -{ -#ifdef __NR_clone - /* note: some archs only have clone() and not fork(). Different archs - * have a different API, but most archs have the flags on first arg and - * will not use the rest with no other flag. - */ - return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0); -#elif defined(__NR_fork) - return my_syscall0(__NR_fork); -#else -#error Neither __NR_clone nor __NR_fork defined, cannot implement sys_fork= () -#endif -} - -static __attribute__((unused)) -int sys_fsync(int fd) -{ - return my_syscall1(__NR_fsync, fd); -} - -static __attribute__((unused)) -int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count) -{ - return my_syscall3(__NR_getdents64, fd, dirp, count); -} - -static __attribute__((unused)) -pid_t sys_getpgid(pid_t pid) -{ - return my_syscall1(__NR_getpgid, pid); -} - -static __attribute__((unused)) -pid_t sys_getpgrp(void) -{ - return sys_getpgid(0); -} - -static __attribute__((unused)) -pid_t sys_getpid(void) -{ - return my_syscall0(__NR_getpid); -} - -static __attribute__((unused)) -pid_t sys_gettid(void) -{ - return my_syscall0(__NR_gettid); -} - -static __attribute__((unused)) -int sys_gettimeofday(struct timeval *tv, struct timezone *tz) -{ - return my_syscall2(__NR_gettimeofday, tv, tz); -} - -static __attribute__((unused)) -int sys_ioctl(int fd, unsigned long req, void *value) -{ - return my_syscall3(__NR_ioctl, fd, req, value); -} - -static __attribute__((unused)) -int sys_kill(pid_t pid, int signal) -{ - return my_syscall2(__NR_kill, pid, signal); -} - -static __attribute__((unused)) -int sys_link(const char *old, const char *new) -{ -#ifdef __NR_linkat - return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); -#elif defined(__NR_link) - return my_syscall2(__NR_link, old, new); -#else -#error Neither __NR_linkat nor __NR_link defined, cannot implement sys_lin= k() -#endif -} - -static __attribute__((unused)) -off_t sys_lseek(int fd, off_t offset, int whence) -{ - return my_syscall3(__NR_lseek, fd, offset, whence); -} - -static __attribute__((unused)) -int sys_mkdir(const char *path, mode_t mode) -{ -#ifdef __NR_mkdirat - return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); -#elif defined(__NR_mkdir) - return my_syscall2(__NR_mkdir, path, mode); -#else -#error Neither __NR_mkdirat nor __NR_mkdir defined, cannot implement sys_m= kdir() -#endif -} - -static __attribute__((unused)) -long sys_mknod(const char *path, mode_t mode, dev_t dev) -{ -#ifdef __NR_mknodat - return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); -#elif defined(__NR_mknod) - return my_syscall3(__NR_mknod, path, mode, dev); -#else -#error Neither __NR_mknodat nor __NR_mknod defined, cannot implement sys_m= knod() -#endif -} - -static __attribute__((unused)) -int sys_mount(const char *src, const char *tgt, const char *fst, - unsigned long flags, const void *data) -{ - return my_syscall5(__NR_mount, src, tgt, fst, flags, data); -} - -static __attribute__((unused)) -int sys_open(const char *path, int flags, mode_t mode) -{ -#ifdef __NR_openat - return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode); -#elif defined(__NR_open) - return my_syscall3(__NR_open, path, flags, mode); -#else -#error Neither __NR_openat nor __NR_open defined, cannot implement sys_ope= n() -#endif -} - -static __attribute__((unused)) -int sys_pivot_root(const char *new, const char *old) -{ - return my_syscall2(__NR_pivot_root, new, old); -} - -static __attribute__((unused)) -int sys_poll(struct pollfd *fds, int nfds, int timeout) -{ -#if defined(__NR_ppoll) - struct timespec t; - - if (timeout >=3D 0) { - t.tv_sec =3D timeout / 1000; - t.tv_nsec =3D (timeout % 1000) * 1000000; - } - return my_syscall4(__NR_ppoll, fds, nfds, (timeout >=3D 0) ? &t : NULL, N= ULL); -#elif defined(__NR_poll) - return my_syscall3(__NR_poll, fds, nfds, timeout); -#else -#error Neither __NR_ppoll nor __NR_poll defined, cannot implement sys_poll= () -#endif -} - -static __attribute__((unused)) -ssize_t sys_read(int fd, void *buf, size_t count) -{ - return my_syscall3(__NR_read, fd, buf, count); -} - -static __attribute__((unused)) -ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg) -{ - return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg); -} - -static __attribute__((unused)) -int sys_sched_yield(void) -{ - return my_syscall0(__NR_sched_yield); -} - -static __attribute__((unused)) -int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct = timeval *timeout) -{ -#if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect) - struct sel_arg_struct { - unsigned long n; - fd_set *r, *w, *e; - struct timeval *t; - } arg =3D { .n =3D nfds, .r =3D rfds, .w =3D wfds, .e =3D efds, .t =3D ti= meout }; - return my_syscall1(__NR_select, &arg); -#elif defined(__ARCH_WANT_SYS_PSELECT6) && defined(__NR_pselect6) - struct timespec t; - - if (timeout) { - t.tv_sec =3D timeout->tv_sec; - t.tv_nsec =3D timeout->tv_usec * 1000; - } - return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : = NULL, NULL); -#elif defined(__NR__newselect) || defined(__NR_select) -#ifndef __NR__newselect -#define __NR__newselect __NR_select -#endif - return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); -#else -#error None of __NR_select, __NR_pselect6, nor __NR__newselect defined, ca= nnot implement sys_select() -#endif -} - -static __attribute__((unused)) -int sys_setpgid(pid_t pid, pid_t pgid) -{ - return my_syscall2(__NR_setpgid, pid, pgid); -} - -static __attribute__((unused)) -pid_t sys_setsid(void) -{ - return my_syscall0(__NR_setsid); -} - -static __attribute__((unused)) -int sys_stat(const char *path, struct stat *buf) -{ - struct sys_stat_struct stat; - long ret; - -#ifdef __NR_newfstatat - /* only solution for arm64 */ - ret =3D my_syscall4(__NR_newfstatat, AT_FDCWD, path, &stat, 0); -#elif defined(__NR_stat) - ret =3D my_syscall2(__NR_stat, path, &stat); -#else -#error Neither __NR_newfstatat nor __NR_stat defined, cannot implement sys= _stat() -#endif - buf->st_dev =3D stat.st_dev; - buf->st_ino =3D stat.st_ino; - buf->st_mode =3D stat.st_mode; - buf->st_nlink =3D stat.st_nlink; - buf->st_uid =3D stat.st_uid; - buf->st_gid =3D stat.st_gid; - buf->st_rdev =3D stat.st_rdev; - buf->st_size =3D stat.st_size; - buf->st_blksize =3D stat.st_blksize; - buf->st_blocks =3D stat.st_blocks; - buf->st_atime =3D stat.st_atime; - buf->st_mtime =3D stat.st_mtime; - buf->st_ctime =3D stat.st_ctime; - return ret; -} - - -static __attribute__((unused)) -int sys_symlink(const char *old, const char *new) -{ -#ifdef __NR_symlinkat - return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); -#elif defined(__NR_symlink) - return my_syscall2(__NR_symlink, old, new); -#else -#error Neither __NR_symlinkat nor __NR_symlink defined, cannot implement s= ys_symlink() -#endif -} - -static __attribute__((unused)) -mode_t sys_umask(mode_t mode) -{ - return my_syscall1(__NR_umask, mode); -} - -static __attribute__((unused)) -int sys_umount2(const char *path, int flags) -{ - return my_syscall2(__NR_umount2, path, flags); -} - -static __attribute__((unused)) -int sys_unlink(const char *path) -{ -#ifdef __NR_unlinkat - return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); -#elif defined(__NR_unlink) - return my_syscall1(__NR_unlink, path); -#else -#error Neither __NR_unlinkat nor __NR_unlink defined, cannot implement sys= _unlink() -#endif -} - -static __attribute__((unused)) -pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage) -{ - return my_syscall4(__NR_wait4, pid, status, options, rusage); -} - -static __attribute__((unused)) -pid_t sys_waitpid(pid_t pid, int *status, int options) -{ - return sys_wait4(pid, status, options, 0); -} - -static __attribute__((unused)) -pid_t sys_wait(int *status) -{ - return sys_waitpid(-1, status, 0); -} - -static __attribute__((unused)) -ssize_t sys_write(int fd, const void *buf, size_t count) -{ - return my_syscall3(__NR_write, fd, buf, count); -} - - -/* Below are the libc-compatible syscalls which return x or -1 and set err= no. - * They rely on the functions above. Similarly they're marked static so th= at it - * is possible to assign pointers to them if needed. - */ - -static __attribute__((unused)) -int brk(void *addr) -{ - void *ret =3D sys_brk(addr); - - if (!ret) { - SET_ERRNO(ENOMEM); - return -1; - } - return 0; -} - -static __attribute__((noreturn,unused)) -void exit(int status) -{ - sys_exit(status); -} - -static __attribute__((unused)) -int chdir(const char *path) -{ - int ret =3D sys_chdir(path); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int chmod(const char *path, mode_t mode) -{ - int ret =3D sys_chmod(path, mode); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int chown(const char *path, uid_t owner, gid_t group) -{ - int ret =3D sys_chown(path, owner, group); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int chroot(const char *path) -{ - int ret =3D sys_chroot(path); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int close(int fd) -{ - int ret =3D sys_close(fd); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int dup(int fd) -{ - int ret =3D sys_dup(fd); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int dup2(int old, int new) -{ - int ret =3D sys_dup2(old, new); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -#ifdef __NR_dup3 -static __attribute__((unused)) -int dup3(int old, int new, int flags) -{ - int ret =3D sys_dup3(old, new, flags); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} -#endif - -static __attribute__((unused)) -int execve(const char *filename, char *const argv[], char *const envp[]) -{ - int ret =3D sys_execve(filename, argv, envp); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -pid_t fork(void) -{ - pid_t ret =3D sys_fork(); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int fsync(int fd) -{ - int ret =3D sys_fsync(fd); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int getdents64(int fd, struct linux_dirent64 *dirp, int count) -{ - int ret =3D sys_getdents64(fd, dirp, count); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -pid_t getpgid(pid_t pid) -{ - pid_t ret =3D sys_getpgid(pid); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -pid_t getpgrp(void) -{ - pid_t ret =3D sys_getpgrp(); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -pid_t getpid(void) -{ - pid_t ret =3D sys_getpid(); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -pid_t gettid(void) -{ - pid_t ret =3D sys_gettid(); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int gettimeofday(struct timeval *tv, struct timezone *tz) -{ - int ret =3D sys_gettimeofday(tv, tz); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int ioctl(int fd, unsigned long req, void *value) -{ - int ret =3D sys_ioctl(fd, req, value); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int kill(pid_t pid, int signal) -{ - int ret =3D sys_kill(pid, signal); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int link(const char *old, const char *new) -{ - int ret =3D sys_link(old, new); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -off_t lseek(int fd, off_t offset, int whence) -{ - off_t ret =3D sys_lseek(fd, offset, whence); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int mkdir(const char *path, mode_t mode) -{ - int ret =3D sys_mkdir(path, mode); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int mknod(const char *path, mode_t mode, dev_t dev) -{ - int ret =3D sys_mknod(path, mode, dev); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int mount(const char *src, const char *tgt, - const char *fst, unsigned long flags, - const void *data) -{ - int ret =3D sys_mount(src, tgt, fst, flags, data); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int open(const char *path, int flags, mode_t mode) -{ - int ret =3D sys_open(path, flags, mode); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int pivot_root(const char *new, const char *old) -{ - int ret =3D sys_pivot_root(new, old); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int poll(struct pollfd *fds, int nfds, int timeout) -{ - int ret =3D sys_poll(fds, nfds, timeout); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -ssize_t read(int fd, void *buf, size_t count) -{ - ssize_t ret =3D sys_read(fd, buf, count); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int reboot(int cmd) -{ - int ret =3D sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -void *sbrk(intptr_t inc) -{ - void *ret; - - /* first call to find current end */ - if ((ret =3D sys_brk(0)) && (sys_brk(ret + inc) =3D=3D ret + inc)) - return ret + inc; - - SET_ERRNO(ENOMEM); - return (void *)-1; -} - -static __attribute__((unused)) -int sched_yield(void) -{ - int ret =3D sys_sched_yield(); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct time= val *timeout) -{ - int ret =3D sys_select(nfds, rfds, wfds, efds, timeout); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int setpgid(pid_t pid, pid_t pgid) -{ - int ret =3D sys_setpgid(pid, pgid); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -pid_t setsid(void) -{ - pid_t ret =3D sys_setsid(); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; + return ioctl(fd, TIOCSPGRP, &pid); } =20 static __attribute__((unused)) @@ -972,114 +121,6 @@ int msleep(unsigned int msecs) return 0; } =20 -static __attribute__((unused)) -int stat(const char *path, struct stat *buf) -{ - int ret =3D sys_stat(path, buf); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int symlink(const char *old, const char *new) -{ - int ret =3D sys_symlink(old, new); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int tcsetpgrp(int fd, pid_t pid) -{ - return ioctl(fd, TIOCSPGRP, &pid); -} - -static __attribute__((unused)) -mode_t umask(mode_t mode) -{ - return sys_umask(mode); -} - -static __attribute__((unused)) -int umount2(const char *path, int flags) -{ - int ret =3D sys_umount2(path, flags); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -int unlink(const char *path) -{ - int ret =3D sys_unlink(path); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage) -{ - pid_t ret =3D sys_wait4(pid, status, options, rusage); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -pid_t waitpid(pid_t pid, int *status, int options) -{ - pid_t ret =3D sys_waitpid(pid, status, options); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -pid_t wait(int *status) -{ - pid_t ret =3D sys_wait(status); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - -static __attribute__((unused)) -ssize_t write(int fd, const void *buf, size_t count) -{ - ssize_t ret =3D sys_write(fd, buf, count); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; -} - /* some size-optimized reimplementations of a few common str* and mem* * functions. They're marked static, except memcpy() and raise() which are= used * by libgcc on ARM, so they are marked weak instead in order not to cause= an diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h new file mode 100644 index 000000000000..98689f668ed3 --- /dev/null +++ b/tools/include/nolibc/sys.h @@ -0,0 +1,1189 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * Syscall definitions for NOLIBC (those in man(2)) + * Copyright (C) 2017-2021 Willy Tarreau + */ + +#ifndef _NOLIBC_SYS_H +#define _NOLIBC_SYS_H + +#include "std.h" + +/* system includes */ +#include +#include // for SIGCHLD +#include +#include +#include +#include +#include + +#include "arch.h" +#include "types.h" + +/* this way it will be removed if unused */ +static int errno; + +#ifndef NOLIBC_IGNORE_ERRNO +#define SET_ERRNO(v) do { errno =3D (v); } while (0) +#else +#define SET_ERRNO(v) do { } while (0) +#endif + + +/* errno codes all ensure that they will not conflict with a valid pointer + * because they all correspond to the highest addressable memory page. + */ +#define MAX_ERRNO 4095 + + +/* Functions in this file only describe syscalls. They're declared static = so + * that the compiler usually decides to inline them while still being allo= wed + * to pass a pointer to one of their instances. Each syscall exists in two + * versions: + * - the "internal" ones, which matches the raw syscall interface at the + * kernel level, which may sometimes slightly differ from the document= ed + * libc-level ones. For example most of them return either a valid val= ue + * or -errno. All of these are prefixed with "sys_". They may be called + * by non-portable applications if desired. + * + * - the "exported" ones, whose interface must closely match the one + * documented in man(2), that applications are supposed to expect. The= se + * ones rely on the internal ones, and set errno. + * + * Each syscall will be defined with the two functions, sorted in alphabet= ical + * order applied to the exported names. + * + * In case of doubt about the relevance of a function here, only those whi= ch + * set errno should be defined here. Wrappers like those appearing in man(= 3) + * should not be placed here. + */ + + +/* + * int brk(void *addr); + * void *sbrk(intptr_t inc) + */ + +static __attribute__((unused)) +void *sys_brk(void *addr) +{ + return (void *)my_syscall1(__NR_brk, addr); +} + +static __attribute__((unused)) +int brk(void *addr) +{ + void *ret =3D sys_brk(addr); + + if (!ret) { + SET_ERRNO(ENOMEM); + return -1; + } + return 0; +} + +static __attribute__((unused)) +void *sbrk(intptr_t inc) +{ + void *ret; + + /* first call to find current end */ + if ((ret =3D sys_brk(0)) && (sys_brk(ret + inc) =3D=3D ret + inc)) + return ret + inc; + + SET_ERRNO(ENOMEM); + return (void *)-1; +} + + +/* + * int chdir(const char *path); + */ + +static __attribute__((unused)) +int sys_chdir(const char *path) +{ + return my_syscall1(__NR_chdir, path); +} + +static __attribute__((unused)) +int chdir(const char *path) +{ + int ret =3D sys_chdir(path); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int chmod(const char *path, mode_t mode); + */ + +static __attribute__((unused)) +int sys_chmod(const char *path, mode_t mode) +{ +#ifdef __NR_fchmodat + return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0); +#elif defined(__NR_chmod) + return my_syscall2(__NR_chmod, path, mode); +#else +#error Neither __NR_fchmodat nor __NR_chmod defined, cannot implement sys_= chmod() +#endif +} + +static __attribute__((unused)) +int chmod(const char *path, mode_t mode) +{ + int ret =3D sys_chmod(path, mode); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int chown(const char *path, uid_t owner, gid_t group); + */ + +static __attribute__((unused)) +int sys_chown(const char *path, uid_t owner, gid_t group) +{ +#ifdef __NR_fchownat + return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0); +#elif defined(__NR_chown) + return my_syscall3(__NR_chown, path, owner, group); +#else +#error Neither __NR_fchownat nor __NR_chown defined, cannot implement sys_= chown() +#endif +} + +static __attribute__((unused)) +int chown(const char *path, uid_t owner, gid_t group) +{ + int ret =3D sys_chown(path, owner, group); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int chroot(const char *path); + */ + +static __attribute__((unused)) +int sys_chroot(const char *path) +{ + return my_syscall1(__NR_chroot, path); +} + +static __attribute__((unused)) +int chroot(const char *path) +{ + int ret =3D sys_chroot(path); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int close(int fd); + */ + +static __attribute__((unused)) +int sys_close(int fd) +{ + return my_syscall1(__NR_close, fd); +} + +static __attribute__((unused)) +int close(int fd) +{ + int ret =3D sys_close(fd); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int dup(int fd); + */ + +static __attribute__((unused)) +int sys_dup(int fd) +{ + return my_syscall1(__NR_dup, fd); +} + +static __attribute__((unused)) +int dup(int fd) +{ + int ret =3D sys_dup(fd); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int dup2(int old, int new); + */ + +static __attribute__((unused)) +int sys_dup2(int old, int new) +{ +#ifdef __NR_dup3 + return my_syscall3(__NR_dup3, old, new, 0); +#elif defined(__NR_dup2) + return my_syscall2(__NR_dup2, old, new); +#else +#error Neither __NR_dup3 nor __NR_dup2 defined, cannot implement sys_dup2() +#endif +} + +static __attribute__((unused)) +int dup2(int old, int new) +{ + int ret =3D sys_dup2(old, new); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int dup3(int old, int new, int flags); + */ + +#ifdef __NR_dup3 +static __attribute__((unused)) +int sys_dup3(int old, int new, int flags) +{ + return my_syscall3(__NR_dup3, old, new, flags); +} + +static __attribute__((unused)) +int dup3(int old, int new, int flags) +{ + int ret =3D sys_dup3(old, new, flags); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} +#endif + + +/* + * int execve(const char *filename, char *const argv[], char *const envp[]= ); + */ + +static __attribute__((unused)) +int sys_execve(const char *filename, char *const argv[], char *const envp[= ]) +{ + return my_syscall3(__NR_execve, filename, argv, envp); +} + +static __attribute__((unused)) +int execve(const char *filename, char *const argv[], char *const envp[]) +{ + int ret =3D sys_execve(filename, argv, envp); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * void exit(int status); + */ + +static __attribute__((noreturn,unused)) +void sys_exit(int status) +{ + my_syscall1(__NR_exit, status & 255); + while(1); // shut the "noreturn" warnings. +} + +static __attribute__((noreturn,unused)) +void exit(int status) +{ + sys_exit(status); +} + + +/* + * pid_t fork(void); + */ + +static __attribute__((unused)) +pid_t sys_fork(void) +{ +#ifdef __NR_clone + /* note: some archs only have clone() and not fork(). Different archs + * have a different API, but most archs have the flags on first arg and + * will not use the rest with no other flag. + */ + return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0); +#elif defined(__NR_fork) + return my_syscall0(__NR_fork); +#else +#error Neither __NR_clone nor __NR_fork defined, cannot implement sys_fork= () +#endif +} + +static __attribute__((unused)) +pid_t fork(void) +{ + pid_t ret =3D sys_fork(); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int fsync(int fd); + */ + +static __attribute__((unused)) +int sys_fsync(int fd) +{ + return my_syscall1(__NR_fsync, fd); +} + +static __attribute__((unused)) +int fsync(int fd) +{ + int ret =3D sys_fsync(fd); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int getdents64(int fd, struct linux_dirent64 *dirp, int count); + */ + +static __attribute__((unused)) +int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count) +{ + return my_syscall3(__NR_getdents64, fd, dirp, count); +} + +static __attribute__((unused)) +int getdents64(int fd, struct linux_dirent64 *dirp, int count) +{ + int ret =3D sys_getdents64(fd, dirp, count); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * pid_t getpgid(pid_t pid); + */ + +static __attribute__((unused)) +pid_t sys_getpgid(pid_t pid) +{ + return my_syscall1(__NR_getpgid, pid); +} + +static __attribute__((unused)) +pid_t getpgid(pid_t pid) +{ + pid_t ret =3D sys_getpgid(pid); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * pid_t getpgrp(void); + */ + +static __attribute__((unused)) +pid_t sys_getpgrp(void) +{ + return sys_getpgid(0); +} + +static __attribute__((unused)) +pid_t getpgrp(void) +{ + pid_t ret =3D sys_getpgrp(); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * pid_t getpid(void); + */ + +static __attribute__((unused)) +pid_t sys_getpid(void) +{ + return my_syscall0(__NR_getpid); +} + +static __attribute__((unused)) +pid_t getpid(void) +{ + pid_t ret =3D sys_getpid(); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * pid_t gettid(void); + */ + +static __attribute__((unused)) +pid_t sys_gettid(void) +{ + return my_syscall0(__NR_gettid); +} + +static __attribute__((unused)) +pid_t gettid(void) +{ + pid_t ret =3D sys_gettid(); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int gettimeofday(struct timeval *tv, struct timezone *tz); + */ + +static __attribute__((unused)) +int sys_gettimeofday(struct timeval *tv, struct timezone *tz) +{ + return my_syscall2(__NR_gettimeofday, tv, tz); +} + +static __attribute__((unused)) +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + int ret =3D sys_gettimeofday(tv, tz); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int ioctl(int fd, unsigned long req, void *value); + */ + +static __attribute__((unused)) +int sys_ioctl(int fd, unsigned long req, void *value) +{ + return my_syscall3(__NR_ioctl, fd, req, value); +} + +static __attribute__((unused)) +int ioctl(int fd, unsigned long req, void *value) +{ + int ret =3D sys_ioctl(fd, req, value); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + +/* + * int kill(pid_t pid, int signal); + */ + +static __attribute__((unused)) +int sys_kill(pid_t pid, int signal) +{ + return my_syscall2(__NR_kill, pid, signal); +} + +static __attribute__((unused)) +int kill(pid_t pid, int signal) +{ + int ret =3D sys_kill(pid, signal); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int link(const char *old, const char *new); + */ + +static __attribute__((unused)) +int sys_link(const char *old, const char *new) +{ +#ifdef __NR_linkat + return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); +#elif defined(__NR_link) + return my_syscall2(__NR_link, old, new); +#else +#error Neither __NR_linkat nor __NR_link defined, cannot implement sys_lin= k() +#endif +} + +static __attribute__((unused)) +int link(const char *old, const char *new) +{ + int ret =3D sys_link(old, new); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * off_t lseek(int fd, off_t offset, int whence); + */ + +static __attribute__((unused)) +off_t sys_lseek(int fd, off_t offset, int whence) +{ + return my_syscall3(__NR_lseek, fd, offset, whence); +} + +static __attribute__((unused)) +off_t lseek(int fd, off_t offset, int whence) +{ + off_t ret =3D sys_lseek(fd, offset, whence); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int mkdir(const char *path, mode_t mode); + */ + +static __attribute__((unused)) +int sys_mkdir(const char *path, mode_t mode) +{ +#ifdef __NR_mkdirat + return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); +#elif defined(__NR_mkdir) + return my_syscall2(__NR_mkdir, path, mode); +#else +#error Neither __NR_mkdirat nor __NR_mkdir defined, cannot implement sys_m= kdir() +#endif +} + +static __attribute__((unused)) +int mkdir(const char *path, mode_t mode) +{ + int ret =3D sys_mkdir(path, mode); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int mknod(const char *path, mode_t mode, dev_t dev); + */ + +static __attribute__((unused)) +long sys_mknod(const char *path, mode_t mode, dev_t dev) +{ +#ifdef __NR_mknodat + return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); +#elif defined(__NR_mknod) + return my_syscall3(__NR_mknod, path, mode, dev); +#else +#error Neither __NR_mknodat nor __NR_mknod defined, cannot implement sys_m= knod() +#endif +} + +static __attribute__((unused)) +int mknod(const char *path, mode_t mode, dev_t dev) +{ + int ret =3D sys_mknod(path, mode, dev); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int mount(const char *source, const char *target, + * const char *fstype, unsigned long flags, + * const void *data); + */ +static __attribute__((unused)) +int sys_mount(const char *src, const char *tgt, const char *fst, + unsigned long flags, const void *data) +{ + return my_syscall5(__NR_mount, src, tgt, fst, flags, data); +} + +static __attribute__((unused)) +int mount(const char *src, const char *tgt, + const char *fst, unsigned long flags, + const void *data) +{ + int ret =3D sys_mount(src, tgt, fst, flags, data); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int open(const char *path, int flags, mode_t mode); + */ + +static __attribute__((unused)) +int sys_open(const char *path, int flags, mode_t mode) +{ +#ifdef __NR_openat + return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode); +#elif defined(__NR_open) + return my_syscall3(__NR_open, path, flags, mode); +#else +#error Neither __NR_openat nor __NR_open defined, cannot implement sys_ope= n() +#endif +} + +static __attribute__((unused)) +int open(const char *path, int flags, mode_t mode) +{ + int ret =3D sys_open(path, flags, mode); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int pivot_root(const char *new, const char *old); + */ + +static __attribute__((unused)) +int sys_pivot_root(const char *new, const char *old) +{ + return my_syscall2(__NR_pivot_root, new, old); +} + +static __attribute__((unused)) +int pivot_root(const char *new, const char *old) +{ + int ret =3D sys_pivot_root(new, old); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int poll(struct pollfd *fds, int nfds, int timeout); + */ + +static __attribute__((unused)) +int sys_poll(struct pollfd *fds, int nfds, int timeout) +{ +#if defined(__NR_ppoll) + struct timespec t; + + if (timeout >=3D 0) { + t.tv_sec =3D timeout / 1000; + t.tv_nsec =3D (timeout % 1000) * 1000000; + } + return my_syscall4(__NR_ppoll, fds, nfds, (timeout >=3D 0) ? &t : NULL, N= ULL); +#elif defined(__NR_poll) + return my_syscall3(__NR_poll, fds, nfds, timeout); +#else +#error Neither __NR_ppoll nor __NR_poll defined, cannot implement sys_poll= () +#endif +} + +static __attribute__((unused)) +int poll(struct pollfd *fds, int nfds, int timeout) +{ + int ret =3D sys_poll(fds, nfds, timeout); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * ssize_t read(int fd, void *buf, size_t count); + */ + +static __attribute__((unused)) +ssize_t sys_read(int fd, void *buf, size_t count) +{ + return my_syscall3(__NR_read, fd, buf, count); +} + +static __attribute__((unused)) +ssize_t read(int fd, void *buf, size_t count) +{ + ssize_t ret =3D sys_read(fd, buf, count); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int reboot(int cmd); + * is among LINUX_REBOOT_CMD_* + */ + +static __attribute__((unused)) +ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg) +{ + return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg); +} + +static __attribute__((unused)) +int reboot(int cmd) +{ + int ret =3D sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int sched_yield(void); + */ + +static __attribute__((unused)) +int sys_sched_yield(void) +{ + return my_syscall0(__NR_sched_yield); +} + +static __attribute__((unused)) +int sched_yield(void) +{ + int ret =3D sys_sched_yield(); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int select(int nfds, fd_set *read_fds, fd_set *write_fds, + * fd_set *except_fds, struct timeval *timeout); + */ + +static __attribute__((unused)) +int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct = timeval *timeout) +{ +#if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect) + struct sel_arg_struct { + unsigned long n; + fd_set *r, *w, *e; + struct timeval *t; + } arg =3D { .n =3D nfds, .r =3D rfds, .w =3D wfds, .e =3D efds, .t =3D ti= meout }; + return my_syscall1(__NR_select, &arg); +#elif defined(__ARCH_WANT_SYS_PSELECT6) && defined(__NR_pselect6) + struct timespec t; + + if (timeout) { + t.tv_sec =3D timeout->tv_sec; + t.tv_nsec =3D timeout->tv_usec * 1000; + } + return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : = NULL, NULL); +#elif defined(__NR__newselect) || defined(__NR_select) +#ifndef __NR__newselect +#define __NR__newselect __NR_select +#endif + return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); +#else +#error None of __NR_select, __NR_pselect6, nor __NR__newselect defined, ca= nnot implement sys_select() +#endif +} + +static __attribute__((unused)) +int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct time= val *timeout) +{ + int ret =3D sys_select(nfds, rfds, wfds, efds, timeout); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int setpgid(pid_t pid, pid_t pgid); + */ + +static __attribute__((unused)) +int sys_setpgid(pid_t pid, pid_t pgid) +{ + return my_syscall2(__NR_setpgid, pid, pgid); +} + +static __attribute__((unused)) +int setpgid(pid_t pid, pid_t pgid) +{ + int ret =3D sys_setpgid(pid, pgid); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * pid_t setsid(void); + */ + +static __attribute__((unused)) +pid_t sys_setsid(void) +{ + return my_syscall0(__NR_setsid); +} + +static __attribute__((unused)) +pid_t setsid(void) +{ + pid_t ret =3D sys_setsid(); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int stat(const char *path, struct stat *buf); + * Warning: the struct stat's layout is arch-dependent. + */ + +static __attribute__((unused)) +int sys_stat(const char *path, struct stat *buf) +{ + struct sys_stat_struct stat; + long ret; + +#ifdef __NR_newfstatat + /* only solution for arm64 */ + ret =3D my_syscall4(__NR_newfstatat, AT_FDCWD, path, &stat, 0); +#elif defined(__NR_stat) + ret =3D my_syscall2(__NR_stat, path, &stat); +#else +#error Neither __NR_newfstatat nor __NR_stat defined, cannot implement sys= _stat() +#endif + buf->st_dev =3D stat.st_dev; + buf->st_ino =3D stat.st_ino; + buf->st_mode =3D stat.st_mode; + buf->st_nlink =3D stat.st_nlink; + buf->st_uid =3D stat.st_uid; + buf->st_gid =3D stat.st_gid; + buf->st_rdev =3D stat.st_rdev; + buf->st_size =3D stat.st_size; + buf->st_blksize =3D stat.st_blksize; + buf->st_blocks =3D stat.st_blocks; + buf->st_atime =3D stat.st_atime; + buf->st_mtime =3D stat.st_mtime; + buf->st_ctime =3D stat.st_ctime; + return ret; +} + +static __attribute__((unused)) +int stat(const char *path, struct stat *buf) +{ + int ret =3D sys_stat(path, buf); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int symlink(const char *old, const char *new); + */ + +static __attribute__((unused)) +int sys_symlink(const char *old, const char *new) +{ +#ifdef __NR_symlinkat + return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); +#elif defined(__NR_symlink) + return my_syscall2(__NR_symlink, old, new); +#else +#error Neither __NR_symlinkat nor __NR_symlink defined, cannot implement s= ys_symlink() +#endif +} + +static __attribute__((unused)) +int symlink(const char *old, const char *new) +{ + int ret =3D sys_symlink(old, new); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * mode_t umask(mode_t mode); + */ + +static __attribute__((unused)) +mode_t sys_umask(mode_t mode) +{ + return my_syscall1(__NR_umask, mode); +} + +static __attribute__((unused)) +mode_t umask(mode_t mode) +{ + return sys_umask(mode); +} + + +/* + * int umount2(const char *path, int flags); + */ + +static __attribute__((unused)) +int sys_umount2(const char *path, int flags) +{ + return my_syscall2(__NR_umount2, path, flags); +} + +static __attribute__((unused)) +int umount2(const char *path, int flags) +{ + int ret =3D sys_umount2(path, flags); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * int unlink(const char *path); + */ + +static __attribute__((unused)) +int sys_unlink(const char *path) +{ +#ifdef __NR_unlinkat + return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); +#elif defined(__NR_unlink) + return my_syscall1(__NR_unlink, path); +#else +#error Neither __NR_unlinkat nor __NR_unlink defined, cannot implement sys= _unlink() +#endif +} + +static __attribute__((unused)) +int unlink(const char *path) +{ + int ret =3D sys_unlink(path); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * pid_t wait(int *status); + * pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage); + * pid_t waitpid(pid_t pid, int *status, int options); + */ + +static __attribute__((unused)) +pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage) +{ + return my_syscall4(__NR_wait4, pid, status, options, rusage); +} + +static __attribute__((unused)) +pid_t wait(int *status) +{ + pid_t ret =3D sys_wait4(-1, status, 0, NULL); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + +static __attribute__((unused)) +pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage) +{ + pid_t ret =3D sys_wait4(pid, status, options, rusage); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +static __attribute__((unused)) +pid_t waitpid(pid_t pid, int *status, int options) +{ + pid_t ret =3D sys_wait4(pid, status, options, NULL); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +/* + * ssize_t write(int fd, const void *buf, size_t count); + */ + +static __attribute__((unused)) +ssize_t sys_write(int fd, const void *buf, size_t count) +{ + return my_syscall3(__NR_write, fd, buf, count); +} + +static __attribute__((unused)) +ssize_t write(int fd, const void *buf, size_t count) +{ + ssize_t ret =3D sys_write(fd, buf, count); + + if (ret < 0) { + SET_ERRNO(-ret); + ret =3D -1; + } + return ret; +} + + +#endif /* _NOLIBC_SYS_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9FF08C47082 for ; Mon, 7 Feb 2022 16:45:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1384027AbiBGQoV (ORCPT ); Mon, 7 Feb 2022 11:44:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41554 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390653AbiBGQfY (ORCPT ); Mon, 7 Feb 2022 11:35:24 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 35B6FC0401D2 for ; Mon, 7 Feb 2022 08:35:22 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GObk2014390; Mon, 7 Feb 2022 17:24:37 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 07/42] tools/nolibc/stdlib: extract the stdlib-specific functions to their own file Date: Mon, 7 Feb 2022 17:23:19 +0100 Message-Id: <20220207162354.14293-8-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The new file stdlib.h contains the definitions of functions that are usually found in stdlib.h. Many more could certainly be added. Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 67 +-------------------------- tools/include/nolibc/stdlib.h | 85 +++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 66 deletions(-) create mode 100644 tools/include/nolibc/stdlib.h diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index 2af56ec760e2..ed909a8daa1a 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -87,40 +87,11 @@ #include "arch.h" #include "types.h" #include "sys.h" +#include "stdlib.h" =20 /* Used by programs to avoid std includes */ #define NOLIBC =20 -static __attribute__((unused)) -int tcsetpgrp(int fd, pid_t pid) -{ - return ioctl(fd, TIOCSPGRP, &pid); -} - -static __attribute__((unused)) -unsigned int sleep(unsigned int seconds) -{ - struct timeval my_timeval =3D { seconds, 0 }; - - if (sys_select(0, 0, 0, 0, &my_timeval) < 0) - return my_timeval.tv_sec + !!my_timeval.tv_usec; - else - return 0; -} - -static __attribute__((unused)) -int msleep(unsigned int msecs) -{ - struct timeval my_timeval =3D { msecs / 1000, (msecs % 1000) * 1000 }; - - if (sys_select(0, 0, 0, 0, &my_timeval) < 0) - return (my_timeval.tv_sec * 1000) + - (my_timeval.tv_usec / 1000) + - !!(my_timeval.tv_usec % 1000); - else - return 0; -} - /* some size-optimized reimplementations of a few common str* and mem* * functions. They're marked static, except memcpy() and raise() which are= used * by libgcc on ARM, so they are marked weak instead in order not to cause= an @@ -216,35 +187,6 @@ int isdigit(int c) return (unsigned int)(c - '0') <=3D 9; } =20 -static __attribute__((unused)) -long atol(const char *s) -{ - unsigned long ret =3D 0; - unsigned long d; - int neg =3D 0; - - if (*s =3D=3D '-') { - neg =3D 1; - s++; - } - - while (1) { - d =3D (*s++) - '0'; - if (d > 9) - break; - ret *=3D 10; - ret +=3D d; - } - - return neg ? -ret : ret; -} - -static __attribute__((unused)) -int atoi(const char *s) -{ - return atol(s); -} - static __attribute__((unused)) const char *ltoa(long in) { @@ -273,13 +215,6 @@ void *memcpy(void *dst, const void *src, size_t len) return memmove(dst, src, len); } =20 -/* needed by libgcc for divide by zero */ -__attribute__((weak,unused)) -int raise(int signal) -{ - return kill(getpid(), signal); -} - /* Here come a few helper functions */ =20 static __attribute__((unused)) diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h new file mode 100644 index 000000000000..09a506aadbbe --- /dev/null +++ b/tools/include/nolibc/stdlib.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * stdlib function definitions for NOLIBC + * Copyright (C) 2017-2021 Willy Tarreau + */ + +#ifndef _NOLIBC_STDLIB_H +#define _NOLIBC_STDLIB_H + +#include "std.h" +#include "arch.h" +#include "types.h" +#include "sys.h" + +/* + * As much as possible, please keep functions alphabetically sorted. + */ + +static __attribute__((unused)) +long atol(const char *s) +{ + unsigned long ret =3D 0; + unsigned long d; + int neg =3D 0; + + if (*s =3D=3D '-') { + neg =3D 1; + s++; + } + + while (1) { + d =3D (*s++) - '0'; + if (d > 9) + break; + ret *=3D 10; + ret +=3D d; + } + + return neg ? -ret : ret; +} + +static __attribute__((unused)) +int atoi(const char *s) +{ + return atol(s); +} + +static __attribute__((unused)) +int msleep(unsigned int msecs) +{ + struct timeval my_timeval =3D { msecs / 1000, (msecs % 1000) * 1000 }; + + if (sys_select(0, 0, 0, 0, &my_timeval) < 0) + return (my_timeval.tv_sec * 1000) + + (my_timeval.tv_usec / 1000) + + !!(my_timeval.tv_usec % 1000); + else + return 0; +} + +/* This one is not marked static as it's needed by libgcc for divide by ze= ro */ +__attribute__((weak,unused)) +int raise(int signal) +{ + return kill(getpid(), signal); +} + +static __attribute__((unused)) +unsigned int sleep(unsigned int seconds) +{ + struct timeval my_timeval =3D { seconds, 0 }; + + if (sys_select(0, 0, 0, 0, &my_timeval) < 0) + return my_timeval.tv_sec + !!my_timeval.tv_usec; + else + return 0; +} + +static __attribute__((unused)) +int tcsetpgrp(int fd, pid_t pid) +{ + return ioctl(fd, TIOCSPGRP, &pid); +} + +#endif /* _NOLIBC_STDLIB_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 08B2FC3527B for ; Mon, 7 Feb 2022 16:45:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1385376AbiBGQo3 (ORCPT ); Mon, 7 Feb 2022 11:44:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41620 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390685AbiBGQf1 (ORCPT ); Mon, 7 Feb 2022 11:35:27 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id C47AEC0401D5 for ; Mon, 7 Feb 2022 08:35:26 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GObmP014391; Mon, 7 Feb 2022 17:24:37 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 08/42] tools/nolibc/string: split the string functions into string.h Date: Mon, 7 Feb 2022 17:23:20 +0100 Message-Id: <20220207162354.14293-9-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The string manipulation functions (mem*, str*) are now found in string.h. The file depends on almost nothing and will be usable from other includes if needed. Maybe more functions could be added. Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 96 +----------------------------- tools/include/nolibc/string.h | 107 ++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 95 deletions(-) create mode 100644 tools/include/nolibc/string.h diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index ed909a8daa1a..b06bd5cb5651 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -88,99 +88,11 @@ #include "types.h" #include "sys.h" #include "stdlib.h" +#include "string.h" =20 /* Used by programs to avoid std includes */ #define NOLIBC =20 -/* some size-optimized reimplementations of a few common str* and mem* - * functions. They're marked static, except memcpy() and raise() which are= used - * by libgcc on ARM, so they are marked weak instead in order not to cause= an - * error when building a program made of multiple files (not recommended). - */ - -static __attribute__((unused)) -void *memmove(void *dst, const void *src, size_t len) -{ - ssize_t pos =3D (dst <=3D src) ? -1 : (long)len; - void *ret =3D dst; - - while (len--) { - pos +=3D (dst <=3D src) ? 1 : -1; - ((char *)dst)[pos] =3D ((char *)src)[pos]; - } - return ret; -} - -static __attribute__((unused)) -void *memset(void *dst, int b, size_t len) -{ - char *p =3D dst; - - while (len--) - *(p++) =3D b; - return dst; -} - -static __attribute__((unused)) -int memcmp(const void *s1, const void *s2, size_t n) -{ - size_t ofs =3D 0; - char c1 =3D 0; - - while (ofs < n && !(c1 =3D ((char *)s1)[ofs] - ((char *)s2)[ofs])) { - ofs++; - } - return c1; -} - -static __attribute__((unused)) -char *strcpy(char *dst, const char *src) -{ - char *ret =3D dst; - - while ((*dst++ =3D *src++)); - return ret; -} - -static __attribute__((unused)) -char *strchr(const char *s, int c) -{ - while (*s) { - if (*s =3D=3D (char)c) - return (char *)s; - s++; - } - return NULL; -} - -static __attribute__((unused)) -char *strrchr(const char *s, int c) -{ - const char *ret =3D NULL; - - while (*s) { - if (*s =3D=3D (char)c) - ret =3D s; - s++; - } - return (char *)ret; -} - -static __attribute__((unused)) -size_t nolibc_strlen(const char *str) -{ - size_t len; - - for (len =3D 0; str[len]; len++); - return len; -} - -#define strlen(str) ({ \ - __builtin_constant_p((str)) ? \ - __builtin_strlen((str)) : \ - nolibc_strlen((str)); \ -}) - static __attribute__((unused)) int isdigit(int c) { @@ -209,12 +121,6 @@ const char *ltoa(long in) return pos + 1; } =20 -__attribute__((weak,unused)) -void *memcpy(void *dst, const void *src, size_t len) -{ - return memmove(dst, src, len); -} - /* Here come a few helper functions */ =20 static __attribute__((unused)) diff --git a/tools/include/nolibc/string.h b/tools/include/nolibc/string.h new file mode 100644 index 000000000000..8a23cda2d450 --- /dev/null +++ b/tools/include/nolibc/string.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * string function definitions for NOLIBC + * Copyright (C) 2017-2021 Willy Tarreau + */ + +#ifndef _NOLIBC_STRING_H +#define _NOLIBC_STRING_H + +#include "std.h" + +/* + * As much as possible, please keep functions alphabetically sorted. + */ + +static __attribute__((unused)) +int memcmp(const void *s1, const void *s2, size_t n) +{ + size_t ofs =3D 0; + char c1 =3D 0; + + while (ofs < n && !(c1 =3D ((char *)s1)[ofs] - ((char *)s2)[ofs])) { + ofs++; + } + return c1; +} + +static __attribute__((unused)) +void *memmove(void *dst, const void *src, size_t len) +{ + ssize_t pos =3D (dst <=3D src) ? -1 : (long)len; + void *ret =3D dst; + + while (len--) { + pos +=3D (dst <=3D src) ? 1 : -1; + ((char *)dst)[pos] =3D ((char *)src)[pos]; + } + return ret; +} + +/* must be exported, as it's used by libgcc on ARM */ +__attribute__((weak,unused)) +void *memcpy(void *dst, const void *src, size_t len) +{ + return memmove(dst, src, len); +} + +static __attribute__((unused)) +void *memset(void *dst, int b, size_t len) +{ + char *p =3D dst; + + while (len--) + *(p++) =3D b; + return dst; +} + +static __attribute__((unused)) +char *strchr(const char *s, int c) +{ + while (*s) { + if (*s =3D=3D (char)c) + return (char *)s; + s++; + } + return NULL; +} + +static __attribute__((unused)) +char *strcpy(char *dst, const char *src) +{ + char *ret =3D dst; + + while ((*dst++ =3D *src++)); + return ret; +} + +/* this function is only used with arguments that are not constants */ +static __attribute__((unused)) +size_t nolibc_strlen(const char *str) +{ + size_t len; + + for (len =3D 0; str[len]; len++); + return len; +} + +#define strlen(str) ({ \ + __builtin_constant_p((str)) ? \ + __builtin_strlen((str)) : \ + nolibc_strlen((str)); \ +}) + +static __attribute__((unused)) +char *strrchr(const char *s, int c) +{ + const char *ret =3D NULL; + + while (*s) { + if (*s =3D=3D (char)c) + ret =3D s; + s++; + } + return (char *)ret; +} + +#endif /* _NOLIBC_STRING_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 093E2C4167E for ; Mon, 7 Feb 2022 16:33:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1382211AbiBGQaX (ORCPT ); Mon, 7 Feb 2022 11:30:23 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60792 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1382075AbiBGQZy (ORCPT ); Mon, 7 Feb 2022 11:25:54 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 3CF66C0401CE for ; Mon, 7 Feb 2022 08:25:54 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GObTb014392; Mon, 7 Feb 2022 17:24:37 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 09/42] tools/nolibc/ctype: split the is* functions to ctype.h Date: Mon, 7 Feb 2022 17:23:21 +0100 Message-Id: <20220207162354.14293-10-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" In fact there's only isdigit() for now. More should definitely be added. Signed-off-by: Willy Tarreau --- tools/include/nolibc/ctype.h | 22 ++++++++++++++++++++++ tools/include/nolibc/nolibc.h | 7 +------ 2 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 tools/include/nolibc/ctype.h diff --git a/tools/include/nolibc/ctype.h b/tools/include/nolibc/ctype.h new file mode 100644 index 000000000000..6735bd906f25 --- /dev/null +++ b/tools/include/nolibc/ctype.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * ctype function definitions for NOLIBC + * Copyright (C) 2017-2021 Willy Tarreau + */ + +#ifndef _NOLIBC_CTYPE_H +#define _NOLIBC_CTYPE_H + +#include "std.h" + +/* + * As much as possible, please keep functions alphabetically sorted. + */ + +static __attribute__((unused)) +int isdigit(int c) +{ + return (unsigned int)(c - '0') <=3D 9; +} + +#endif /* _NOLIBC_CTYPE_H */ diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index b06bd5cb5651..c96c6cb7f3ae 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -87,18 +87,13 @@ #include "arch.h" #include "types.h" #include "sys.h" +#include "ctype.h" #include "stdlib.h" #include "string.h" =20 /* Used by programs to avoid std includes */ #define NOLIBC =20 -static __attribute__((unused)) -int isdigit(int c) -{ - return (unsigned int)(c - '0') <=3D 9; -} - static __attribute__((unused)) const char *ltoa(long in) { --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 84326C3526E for ; Mon, 7 Feb 2022 16:33:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1385093AbiBGQab (ORCPT ); Mon, 7 Feb 2022 11:30:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60848 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1388549AbiBGQ0D (ORCPT ); Mon, 7 Feb 2022 11:26:03 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id BBCE2C0401CE for ; Mon, 7 Feb 2022 08:26:02 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOc0w014393; Mon, 7 Feb 2022 17:24:38 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 10/42] tools/nolibc/ctype: add the missing is* functions Date: Mon, 7 Feb 2022 17:23:22 +0100 Message-Id: <20220207162354.14293-11-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" There was only isdigit, this commit adds the other ones. Signed-off-by: Willy Tarreau --- tools/include/nolibc/ctype.h | 79 +++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/tools/include/nolibc/ctype.h b/tools/include/nolibc/ctype.h index 6735bd906f25..e3000b2992d7 100644 --- a/tools/include/nolibc/ctype.h +++ b/tools/include/nolibc/ctype.h @@ -13,10 +13,87 @@ * As much as possible, please keep functions alphabetically sorted. */ =20 +static __attribute__((unused)) +int isascii(int c) +{ + /* 0x00..0x7f */ + return (unsigned int)c <=3D 0x7f; +} + +static __attribute__((unused)) +int isblank(int c) +{ + return c =3D=3D '\t' || c =3D=3D ' '; +} + +static __attribute__((unused)) +int iscntrl(int c) +{ + /* 0x00..0x1f, 0x7f */ + return (unsigned int)c < 0x20 || c =3D=3D 0x7f; +} + static __attribute__((unused)) int isdigit(int c) { - return (unsigned int)(c - '0') <=3D 9; + return (unsigned int)(c - '0') < 10; +} + +static __attribute__((unused)) +int isgraph(int c) +{ + /* 0x21..0x7e */ + return (unsigned int)(c - 0x21) < 0x5e; +} + +static __attribute__((unused)) +int islower(int c) +{ + return (unsigned int)(c - 'a') < 26; +} + +static __attribute__((unused)) +int isprint(int c) +{ + /* 0x20..0x7e */ + return (unsigned int)(c - 0x20) < 0x5f; +} + +static __attribute__((unused)) +int isspace(int c) +{ + /* \t is 0x9, \n is 0xA, \v is 0xB, \f is 0xC, \r is 0xD */ + return ((unsigned int)c =3D=3D ' ') || (unsigned int)(c - 0x09) < 5; +} + +static __attribute__((unused)) +int isupper(int c) +{ + return (unsigned int)(c - 'A') < 26; +} + +static __attribute__((unused)) +int isxdigit(int c) +{ + return isdigit(c) || (unsigned int)(c - 'A') < 6 || (unsigned int)(c - 'a= ') < 6; +} + +static __attribute__((unused)) +int isalpha(int c) +{ + return islower(c) || isupper(c); +} + +static __attribute__((unused)) +int isalnum(int c) +{ + return isalpha(c) || isdigit(c); +} + +static __attribute__((unused)) +int ispunct(int c) +{ + return isgraph(c) && !isalnum(c); } =20 #endif /* _NOLIBC_CTYPE_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BA340C4167E for ; Mon, 7 Feb 2022 16:31:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1382007AbiBGQ3z (ORCPT ); Mon, 7 Feb 2022 11:29:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60898 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238296AbiBGQ0O (ORCPT ); Mon, 7 Feb 2022 11:26:14 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id DE015C0401CE for ; Mon, 7 Feb 2022 08:26:11 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOcVm014394; Mon, 7 Feb 2022 17:24:38 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 11/42] tools/nolibc/types: move the FD_* functions to macros in types.h Date: Mon, 7 Feb 2022 17:23:23 +0100 Message-Id: <20220207162354.14293-12-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" FD_SET, FD_CLR, FD_ISSET, FD_ZERO are supposed to be macros and not functions. In addition we already have a file dedicated to such macros and types used by syscalls, it's types.h, so let's move them there and turn them to macros. FD_CLR() and FD_ISSET() were missing, so they were added. FD_ZERO() now deals with its own loop so that it doesn't rely on memset() that sets one byte at a time. Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 14 -------------- tools/include/nolibc/types.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index c96c6cb7f3ae..2267d98337ea 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -118,20 +118,6 @@ const char *ltoa(long in) =20 /* Here come a few helper functions */ =20 -static __attribute__((unused)) -void FD_ZERO(fd_set *set) -{ - memset(set, 0, sizeof(*set)); -} - -static __attribute__((unused)) -void FD_SET(int fd, fd_set *set) -{ - if (fd < 0 || fd >=3D FD_SETSIZE) - return; - set->fd32[fd / 32] |=3D 1 << (fd & 31); -} - /* WARNING, it only deals with the 4096 first majors and 256 first minors = */ static __attribute__((unused)) dev_t makedev(unsigned int major, unsigned int minor) diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h index 2f09abaf95f1..b79e10025780 100644 --- a/tools/include/nolibc/types.h +++ b/tools/include/nolibc/types.h @@ -75,6 +75,36 @@ typedef struct { uint32_t fd32[FD_SETSIZE / 32]; } fd_set; =20 +#define FD_CLR(fd, set) do { \ + int __fd =3D (int)(fd); \ + fd_set *__set =3D (fd_set *)(set); \ + if (__fd >=3D 0 && __fd < FD_SETSIZE) \ + __set->fd32[__fd / 32] &=3D ~(1U << (__fd & 31)); \ + } while (0) + +#define FD_SET(fd, set) do { \ + int __fd =3D (int)(fd); \ + fd_set *__set =3D (fd_set *)(set); \ + if (__fd >=3D 0 && __fd < FD_SETSIZE) \ + __set->fd32[__fd / 32] |=3D 1U << (__fd & 31); \ + } while (0) + +#define FD_ISSET(fd, set) ({ \ + int __fd =3D (int)(fd); \ + fd_set *__set =3D (fd_set *)(set); \ + if (__fd >=3D 0 && __fd < FD_SETSIZE) \ + !!(__set->fd32[__fd / 32] & 1U << (__fd & 31)); \ + else \ + 0; \ + }) + +#define FD_ZERO(set) do { \ + int __idx; \ + fd_set *__set =3D (fd_set *)(set); \ + for (__idx =3D 0; __idx < FD_SETSIZE / 32; __idx ++) \ + __set->fd32[__idx] =3D 0; \ + } while (0) + /* for poll() */ struct pollfd { int fd; --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C2F38C47080 for ; Mon, 7 Feb 2022 16:45:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1382415AbiBGQoE (ORCPT ); Mon, 7 Feb 2022 11:44:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40896 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390553AbiBGQfD (ORCPT ); Mon, 7 Feb 2022 11:35:03 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 6D02DC0401D1 for ; Mon, 7 Feb 2022 08:35:02 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOcUE014395; Mon, 7 Feb 2022 17:24:38 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 12/42] tools/nolibc/types: make FD_SETSIZE configurable Date: Mon, 7 Feb 2022 17:23:24 +0100 Message-Id: <20220207162354.14293-13-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The macro was hard-coded to 256 but it's common to see it redefined. Let's support this and make sure we always allocate enough entries for the cases where it wouldn't be multiple of 32. Signed-off-by: Willy Tarreau --- tools/include/nolibc/types.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h index b79e10025780..81f69fd5826c 100644 --- a/tools/include/nolibc/types.h +++ b/tools/include/nolibc/types.h @@ -45,7 +45,9 @@ #define DT_SOCK 0xc =20 /* commonly an fd_set represents 256 FDs */ +#ifndef FD_SETSIZE #define FD_SETSIZE 256 +#endif =20 /* Special FD used by all the *at functions */ #ifndef AT_FDCWD @@ -72,7 +74,7 @@ =20 /* for select() */ typedef struct { - uint32_t fd32[FD_SETSIZE / 32]; + uint32_t fd32[(FD_SETSIZE + 31) / 32]; } fd_set; =20 #define FD_CLR(fd, set) do { \ @@ -101,7 +103,7 @@ typedef struct { #define FD_ZERO(set) do { \ int __idx; \ fd_set *__set =3D (fd_set *)(set); \ - for (__idx =3D 0; __idx < FD_SETSIZE / 32; __idx ++) \ + for (__idx =3D 0; __idx < (FD_SETSIZE+31) / 32; __idx ++) \ __set->fd32[__idx] =3D 0; \ } while (0) =20 --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1A5DDC35276 for ; Mon, 7 Feb 2022 16:45:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1383259AbiBGQoL (ORCPT ); Mon, 7 Feb 2022 11:44:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40968 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351628AbiBGQfH (ORCPT ); Mon, 7 Feb 2022 11:35:07 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 77051C0401E2 for ; Mon, 7 Feb 2022 08:35:05 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOcOx014396; Mon, 7 Feb 2022 17:24:38 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 13/42] tools/nolibc/types: move makedev to types.h and make it a macro Date: Mon, 7 Feb 2022 17:23:25 +0100 Message-Id: <20220207162354.14293-14-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The makedev() man page says it's supposed to be a macro and that some OSes have it with the other ones in sys/types.h so it now makes sense to move it to types.h as a macro. Let's also define major() and minor() that perform the reverse operation. Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 9 --------- tools/include/nolibc/types.h | 5 +++++ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index 2267d98337ea..23fb81414b1b 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -116,13 +116,4 @@ const char *ltoa(long in) return pos + 1; } =20 -/* Here come a few helper functions */ - -/* WARNING, it only deals with the 4096 first majors and 256 first minors = */ -static __attribute__((unused)) -dev_t makedev(unsigned int major, unsigned int minor) -{ - return ((major & 0xfff) << 8) | (minor & 0xff); -} - #endif /* _NOLIBC_H */ diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h index 81f69fd5826c..fb4d35f60850 100644 --- a/tools/include/nolibc/types.h +++ b/tools/include/nolibc/types.h @@ -162,4 +162,9 @@ struct stat { time_t st_ctime; /* time of last status change */ }; =20 +/* WARNING, it only deals with the 4096 first majors and 256 first minors = */ +#define makedev(major, minor) ((dev_t)((((major) & 0xfff) << 8) | ((minor)= & 0xff))) +#define major(dev) ((unsigned int)(((dev) >> 8) & 0xfff)) +#define minor(dev) ((unsigned int)(((dev) & 0xff)) + #endif /* _NOLIBC_TYPES_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05232C4707F for ; Mon, 7 Feb 2022 16:33:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1389765AbiBGQam (ORCPT ); Mon, 7 Feb 2022 11:30:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60998 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1378418AbiBGQ0V (ORCPT ); Mon, 7 Feb 2022 11:26:21 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E8BF9C0401D3 for ; Mon, 7 Feb 2022 08:26:19 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOcrX014397; Mon, 7 Feb 2022 17:24:38 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 14/42] tools/nolibc/stdlib: move ltoa() to stdlib.h Date: Mon, 7 Feb 2022 17:23:26 +0100 Message-Id: <20220207162354.14293-15-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This function is not standard and performs the opposite of atol(). Let's move it with atol(). It's been split between a reentrant function and one using a static buffer. There's no more definition in nolibc.h anymore now. Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 22 ---------------------- tools/include/nolibc/stdlib.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index 23fb81414b1b..a349c88c45ff 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -94,26 +94,4 @@ /* Used by programs to avoid std includes */ #define NOLIBC =20 -static __attribute__((unused)) -const char *ltoa(long in) -{ - /* large enough for -9223372036854775808 */ - static char buffer[21]; - char *pos =3D buffer + sizeof(buffer) - 1; - int neg =3D in < 0; - unsigned long n =3D neg ? -in : in; - - *pos-- =3D '\0'; - do { - *pos-- =3D '0' + n % 10; - n /=3D 10; - if (pos < buffer) - return pos + 1; - } while (n); - - if (neg) - *pos-- =3D '-'; - return pos + 1; -} - #endif /* _NOLIBC_H */ diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index 09a506aadbbe..84fc4353fb01 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -45,6 +45,38 @@ int atoi(const char *s) return atol(s); } =20 +/* performs the opposite of atol() using a user-fed buffer. The buffer mus= t be + * at least 21 bytes long (large enough for "-9223372036854775808"). + */ +static __attribute__((unused)) +const char *ltoa_r(long in, char *buffer) +{ + char *pos =3D buffer + 21 - 1; + int neg =3D in < 0; + unsigned long n =3D neg ? -in : in; + + *pos-- =3D '\0'; + do { + *pos-- =3D '0' + n % 10; + n /=3D 10; + if (pos < buffer) + return pos + 1; + } while (n); + + if (neg) + *pos-- =3D '-'; + return pos + 1; +} + +/* performs the opposite of atol() using a statically allocated buffer */ +static __attribute__((unused)) +const char *ltoa(long in) +{ + /* large enough for -9223372036854775808 */ + static char buffer[21]; + return ltoa_r(in, buffer); +} + static __attribute__((unused)) int msleep(unsigned int msecs) { --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2A271C35278 for ; Mon, 7 Feb 2022 16:33:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1389818AbiBGQaq (ORCPT ); Mon, 7 Feb 2022 11:30:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32866 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1380060AbiBGQ03 (ORCPT ); Mon, 7 Feb 2022 11:26:29 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 12693C0401CF for ; Mon, 7 Feb 2022 08:26:27 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOcV3014398; Mon, 7 Feb 2022 17:24:38 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 15/42] tools/nolibc/stdlib: replace the ltoa() function with more efficient ones Date: Mon, 7 Feb 2022 17:23:27 +0100 Message-Id: <20220207162354.14293-16-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The original ltoa() function and the reentrant one ltoa_r() present a number of drawbacks. The divide by 10 generates calls to external code from libgcc_s, and the number does not necessarily start at the beginning of the buffer. Let's rewrite these functions so that they do not involve a divide and only use loops on powers of 10, and implement both signed and unsigned variants, always starting from the buffer's first character. Instead of using a static buffer for each function, we're now using a common one. In order to avoid confusion with the ltoa() name, the new functions are called itoa_r() and utoa_r() to distinguish the signed and unsigned versions, and for convenience for their callers, these functions now reutrn the number of characters emitted. The ltoa_r() function is just an inline mapping to the signed one and which returns the buffer. The functions are quite small (86 bytes on x86_64, 68 on armv7) and do not depend anymore on external code. Signed-off-by: Willy Tarreau --- tools/include/nolibc/stdlib.h | 107 +++++++++++++++++++++++++++------- 1 file changed, 87 insertions(+), 20 deletions(-) diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index 84fc4353fb01..dbb45631c7ca 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -12,6 +12,13 @@ #include "types.h" #include "sys.h" =20 + +/* Buffer used to store int-to-ASCII conversions. Will only be implemented= if + * any of the related functions is implemented. The area is large enough to + * store "18446744073709551615" or "-9223372036854775808" and the final ze= ro. + */ +static __attribute__((unused)) char itoa_buffer[21]; + /* * As much as possible, please keep functions alphabetically sorted. */ @@ -45,36 +52,96 @@ int atoi(const char *s) return atol(s); } =20 -/* performs the opposite of atol() using a user-fed buffer. The buffer mus= t be - * at least 21 bytes long (large enough for "-9223372036854775808"). +/* Converts the unsigned long integer to its string representation in= to + * buffer , which must be long enough to store the number and the + * trailing zero (21 bytes for 18446744073709551615 in 64-bit, 11 for + * 4294967295 in 32-bit). The buffer is filled from the first byte, and the + * number of characters emitted (not counting the trailing zero) is return= ed. + * The function is constructed in a way to optimize the code size and avoid + * any divide that could add a dependency on large external functions. */ static __attribute__((unused)) -const char *ltoa_r(long in, char *buffer) +int utoa_r(unsigned long in, char *buffer) { - char *pos =3D buffer + 21 - 1; - int neg =3D in < 0; - unsigned long n =3D neg ? -in : in; + unsigned long lim; + int digits =3D 0; + int pos =3D (~0UL > 0xfffffffful) ? 19 : 9; + int dig; =20 - *pos-- =3D '\0'; do { - *pos-- =3D '0' + n % 10; - n /=3D 10; - if (pos < buffer) - return pos + 1; - } while (n); + for (dig =3D 0, lim =3D 1; dig < pos; dig++) + lim *=3D 10; =20 - if (neg) - *pos-- =3D '-'; - return pos + 1; + if (digits || in >=3D lim || !pos) { + for (dig =3D 0; in >=3D lim; dig++) + in -=3D lim; + buffer[digits++] =3D '0' + dig; + } + } while (pos--); + + buffer[digits] =3D 0; + return digits; } =20 -/* performs the opposite of atol() using a statically allocated buffer */ +/* Converts the signed long integer to its string representation into + * buffer , which must be long enough to store the number and the + * trailing zero (21 bytes for -9223372036854775808 in 64-bit, 12 for + * -2147483648 in 32-bit). The buffer is filled from the first byte, and t= he + * number of characters emitted (not counting the trailing zero) is return= ed. + */ static __attribute__((unused)) -const char *ltoa(long in) +int itoa_r(long in, char *buffer) { - /* large enough for -9223372036854775808 */ - static char buffer[21]; - return ltoa_r(in, buffer); + char *ptr =3D buffer; + int len =3D 0; + + if (in < 0) { + in =3D -in; + *(ptr++) =3D '-'; + len++; + } + len +=3D utoa_r(in, ptr); + return len; +} + +/* for historical compatibility, same as above but returns the pointer to = the + * buffer. + */ +static inline __attribute__((unused)) +char *ltoa_r(long in, char *buffer) +{ + itoa_r(in, buffer); + return buffer; +} + +/* converts long integer to a string using the static itoa_buffer and + * returns the pointer to that string. + */ +static inline __attribute__((unused)) +char *itoa(long in) +{ + itoa_r(in, itoa_buffer); + return itoa_buffer; +} + +/* converts long integer to a string using the static itoa_buffer and + * returns the pointer to that string. Same as above, for compatibility. + */ +static inline __attribute__((unused)) +char *ltoa(long in) +{ + itoa_r(in, itoa_buffer); + return itoa_buffer; +} + +/* converts unsigned long integer to a string using the static itoa_b= uffer + * and returns the pointer to that string. + */ +static inline __attribute__((unused)) +char *utoa(unsigned long in) +{ + utoa_r(in, itoa_buffer); + return itoa_buffer; } =20 static __attribute__((unused)) --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1AD9AC35275 for ; Mon, 7 Feb 2022 16:33:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1389810AbiBGQao (ORCPT ); Mon, 7 Feb 2022 11:30:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32990 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1389584AbiBGQ0o (ORCPT ); Mon, 7 Feb 2022 11:26:44 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 46126C0401CF for ; Mon, 7 Feb 2022 08:26:43 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOc8C014399; Mon, 7 Feb 2022 17:24:38 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 16/42] tools/nolibc/stdlib: add i64toa() and u64toa() Date: Mon, 7 Feb 2022 17:23:28 +0100 Message-Id: <20220207162354.14293-17-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" These are 64-bit variants of the itoa() and utoa() functions. They also support reentrant ones, and use the same itoa_buffer. The functions are a bit larger than the previous ones in 32-bit mode (86 and 98 bytes on x86_64 and armv7 respectively), which is why we continue to provide them as separate functions. Signed-off-by: Willy Tarreau --- tools/include/nolibc/stdlib.h | 72 +++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index dbb45631c7ca..d972871bf2ba 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -144,6 +144,78 @@ char *utoa(unsigned long in) return itoa_buffer; } =20 +/* Converts the unsigned 64-bit integer to its string representation = into + * buffer , which must be long enough to store the number and the + * trailing zero (21 bytes for 18446744073709551615). The buffer is filled= from + * the first byte, and the number of characters emitted (not counting the + * trailing zero) is returned. The function is constructed in a way to opt= imize + * the code size and avoid any divide that could add a dependency on large + * external functions. + */ +static __attribute__((unused)) +int u64toa_r(uint64_t in, char *buffer) +{ + unsigned long long lim; + int digits =3D 0; + int pos =3D 19; /* start with the highest possible digit */ + int dig; + + do { + for (dig =3D 0, lim =3D 1; dig < pos; dig++) + lim *=3D 10; + + if (digits || in >=3D lim || !pos) { + for (dig =3D 0; in >=3D lim; dig++) + in -=3D lim; + buffer[digits++] =3D '0' + dig; + } + } while (pos--); + + buffer[digits] =3D 0; + return digits; +} + +/* Converts the signed 64-bit integer to its string representation in= to + * buffer , which must be long enough to store the number and the + * trailing zero (21 bytes for -9223372036854775808). The buffer is filled= from + * the first byte, and the number of characters emitted (not counting the + * trailing zero) is returned. + */ +static __attribute__((unused)) +int i64toa_r(int64_t in, char *buffer) +{ + char *ptr =3D buffer; + int len =3D 0; + + if (in < 0) { + in =3D -in; + *(ptr++) =3D '-'; + len++; + } + len +=3D u64toa_r(in, ptr); + return len; +} + +/* converts int64_t to a string using the static itoa_buffer and retu= rns + * the pointer to that string. + */ +static inline __attribute__((unused)) +char *i64toa(int64_t in) +{ + i64toa_r(in, itoa_buffer); + return itoa_buffer; +} + +/* converts uint64_t to a string using the static itoa_buffer and ret= urns + * the pointer to that string. + */ +static inline __attribute__((unused)) +char *u64toa(uint64_t in) +{ + u64toa_r(in, itoa_buffer); + return itoa_buffer; +} + static __attribute__((unused)) int msleep(unsigned int msecs) { --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05198C41535 for ; Mon, 7 Feb 2022 16:45:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376507AbiBGQnn (ORCPT ); Mon, 7 Feb 2022 11:43:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41434 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390627AbiBGQfS (ORCPT ); Mon, 7 Feb 2022 11:35:18 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E8E53C0401CE for ; Mon, 7 Feb 2022 08:35:16 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOcQT014400; Mon, 7 Feb 2022 17:24:38 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 17/42] tools/nolibc/stdlib: add utoh() and u64toh() Date: Mon, 7 Feb 2022 17:23:29 +0100 Message-Id: <20220207162354.14293-18-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This adds a pair of functions to emit hex values. Signed-off-by: Willy Tarreau --- tools/include/nolibc/stdlib.h | 80 +++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index d972871bf2ba..82a4cf606d3c 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -52,6 +52,46 @@ int atoi(const char *s) return atol(s); } =20 +/* Converts the unsigned long integer to its hex representation into + * buffer , which must be long enough to store the number and the + * trailing zero (17 bytes for "ffffffffffffffff" or 9 for "ffffffff"). The + * buffer is filled from the first byte, and the number of characters emit= ted + * (not counting the trailing zero) is returned. The function is construct= ed + * in a way to optimize the code size and avoid any divide that could add a + * dependency on large external functions. + */ +static __attribute__((unused)) +int utoh_r(unsigned long in, char *buffer) +{ + signed char pos =3D (~0UL > 0xfffffffful) ? 60 : 28; + int digits =3D 0; + int dig; + + do { + dig =3D in >> pos; + in -=3D (uint64_t)dig << pos; + pos -=3D 4; + if (dig || digits || pos < 0) { + if (dig > 9) + dig +=3D 'a' - '0' - 10; + buffer[digits++] =3D '0' + dig; + } + } while (pos >=3D 0); + + buffer[digits] =3D 0; + return digits; +} + +/* converts unsigned long to an hex string using the static itoa_buff= er + * and returns the pointer to that string. + */ +static inline __attribute__((unused)) +char *utoh(unsigned long in) +{ + utoh_r(in, itoa_buffer); + return itoa_buffer; +} + /* Converts the unsigned long integer to its string representation in= to * buffer , which must be long enough to store the number and the * trailing zero (21 bytes for 18446744073709551615 in 64-bit, 11 for @@ -144,6 +184,46 @@ char *utoa(unsigned long in) return itoa_buffer; } =20 +/* Converts the unsigned 64-bit integer to its hex representation into + * buffer , which must be long enough to store the number and the + * trailing zero (17 bytes for "ffffffffffffffff"). The buffer is filled f= rom + * the first byte, and the number of characters emitted (not counting the + * trailing zero) is returned. The function is constructed in a way to opt= imize + * the code size and avoid any divide that could add a dependency on large + * external functions. + */ +static __attribute__((unused)) +int u64toh_r(uint64_t in, char *buffer) +{ + signed char pos =3D 60; + int digits =3D 0; + int dig; + + do { + dig =3D in >> pos; + in -=3D (uint64_t)dig << pos; + pos -=3D 4; + if (dig || digits || pos < 0) { + if (dig > 9) + dig +=3D 'a' - '0' - 10; + buffer[digits++] =3D '0' + dig; + } + } while (pos >=3D 0); + + buffer[digits] =3D 0; + return digits; +} + +/* converts uint64_t to an hex string using the static itoa_buffer and + * returns the pointer to that string. + */ +static inline __attribute__((unused)) +char *u64toh(uint64_t in) +{ + u64toh_r(in, itoa_buffer); + return itoa_buffer; +} + /* Converts the unsigned 64-bit integer to its string representation = into * buffer , which must be long enough to store the number and the * trailing zero (21 bytes for 18446744073709551615). The buffer is filled= from --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E5B95C3527D for ; Mon, 7 Feb 2022 16:45:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1385229AbiBGQo2 (ORCPT ); Mon, 7 Feb 2022 11:44:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41038 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1380469AbiBGQfI (ORCPT ); Mon, 7 Feb 2022 11:35:08 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2E3EBC0401E9 for ; Mon, 7 Feb 2022 08:35:06 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOdNr014401; Mon, 7 Feb 2022 17:24:39 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 18/42] tools/nolibc/stdio: add a minimal set of stdio functions Date: Mon, 7 Feb 2022 17:23:30 +0100 Message-Id: <20220207162354.14293-19-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This only provides getchar(), putchar(), and puts(). Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 1 + tools/include/nolibc/stdio.h | 57 +++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 tools/include/nolibc/stdio.h diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index a349c88c45ff..7eaa09fe9f4d 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -88,6 +88,7 @@ #include "types.h" #include "sys.h" #include "ctype.h" +#include "stdio.h" #include "stdlib.h" #include "string.h" =20 diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h new file mode 100644 index 000000000000..4c6af3016e2e --- /dev/null +++ b/tools/include/nolibc/stdio.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * minimal stdio function definitions for NOLIBC + * Copyright (C) 2017-2021 Willy Tarreau + */ + +#ifndef _NOLIBC_STDIO_H +#define _NOLIBC_STDIO_H + +#include "std.h" +#include "arch.h" +#include "types.h" +#include "sys.h" +#include "stdlib.h" +#include "string.h" + +#ifndef EOF +#define EOF (-1) +#endif + +static __attribute__((unused)) +int getchar(void) +{ + unsigned char ch; + + if (read(0, &ch, 1) <=3D 0) + return EOF; + return ch; +} + +static __attribute__((unused)) +int putchar(int c) +{ + unsigned char ch =3D c; + + if (write(1, &ch, 1) <=3D 0) + return EOF; + return ch; +} + +static __attribute__((unused)) +int puts(const char *s) +{ + size_t len =3D strlen(s); + ssize_t ret; + + while (len > 0) { + ret =3D write(1, s, len); + if (ret <=3D 0) + return EOF; + s +=3D ret; + len -=3D ret; + } + return putchar('\n'); +} + +#endif /* _NOLIBC_STDIO_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D30B5C4167D for ; Mon, 7 Feb 2022 16:45:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1358350AbiBGQnj (ORCPT ); Mon, 7 Feb 2022 11:43:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41500 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390650AbiBGQfW (ORCPT ); Mon, 7 Feb 2022 11:35:22 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B08BAC0401D2 for ; Mon, 7 Feb 2022 08:35:21 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOdun014402; Mon, 7 Feb 2022 17:24:39 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 19/42] tools/nolibc/stdio: add stdin/stdout/stderr and fget*/fput* functions Date: Mon, 7 Feb 2022 17:23:31 +0100 Message-Id: <20220207162354.14293-20-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The standard puts() function always emits the trailing LF which makes it unconvenient for small string concatenation. fputs() ought to be used instead but it requires a FILE*. This adds 3 dummy FILE* values (stdin, stdout, stderr) which are in fact pointers to struct FILE of one byte. We reserve 3 pointer values for them, -3, -2 and -1, so that they are ordered, easing the tests and mapping to integer. From this, fgetc(), fputc(), fgets() and fputs() were implemented, and the previous putchar() and getchar() now remap to these. The standard getc() and putc() macros were also implemented as pointing to these ones. There is absolutely no buffering, fgetc() and fgets() read one byte at a time, fputc() writes one byte at a time, and only fputs() which knows the string's length writes all of it at once. Signed-off-by: Willy Tarreau --- tools/include/nolibc/stdio.h | 95 +++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 6 deletions(-) diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h index 4c6af3016e2e..149c5ca59aad 100644 --- a/tools/include/nolibc/stdio.h +++ b/tools/include/nolibc/stdio.h @@ -18,40 +18,123 @@ #define EOF (-1) #endif =20 +/* just define FILE as a non-empty type */ +typedef struct FILE { + char dummy[1]; +} FILE; + +/* We define the 3 common stdio files as constant invalid pointers that + * are easily recognized. + */ +static __attribute__((unused)) FILE* const stdin =3D (FILE*)-3; +static __attribute__((unused)) FILE* const stdout =3D (FILE*)-2; +static __attribute__((unused)) FILE* const stderr =3D (FILE*)-1; + +/* getc(), fgetc(), getchar() */ + +#define getc(stream) fgetc(stream) + static __attribute__((unused)) -int getchar(void) +int fgetc(FILE* stream) { unsigned char ch; + int fd; =20 - if (read(0, &ch, 1) <=3D 0) + if (stream < stdin || stream > stderr) + return EOF; + + fd =3D 3 + (long)stream; + + if (read(fd, &ch, 1) <=3D 0) return EOF; return ch; } =20 static __attribute__((unused)) -int putchar(int c) +int getchar(void) +{ + return fgetc(stdin); +} + + +/* putc(), fputc(), putchar() */ + +#define putc(c, stream) fputc(c, stream) + +static __attribute__((unused)) +int fputc(int c, FILE* stream) { unsigned char ch =3D c; + int fd; =20 - if (write(1, &ch, 1) <=3D 0) + if (stream < stdin || stream > stderr) + return EOF; + + fd =3D 3 + (long)stream; + + if (write(fd, &ch, 1) <=3D 0) return EOF; return ch; } =20 static __attribute__((unused)) -int puts(const char *s) +int putchar(int c) +{ + return fputc(c, stdout); +} + + +/* puts(), fputs(). Note that puts() emits '\n' but not fputs(). */ + +static __attribute__((unused)) +int fputs(const char *s, FILE *stream) { size_t len =3D strlen(s); ssize_t ret; + int fd; + + if (stream < stdin || stream > stderr) + return EOF; + + fd =3D 3 + (long)stream; =20 while (len > 0) { - ret =3D write(1, s, len); + ret =3D write(fd, s, len); if (ret <=3D 0) return EOF; s +=3D ret; len -=3D ret; } + return 0; +} + +static __attribute__((unused)) +int puts(const char *s) +{ + if (fputs(s, stdout) =3D=3D EOF) + return EOF; return putchar('\n'); } =20 + +/* fgets() */ +static __attribute__((unused)) +char *fgets(char *s, int size, FILE *stream) +{ + int ofs; + int c; + + for (ofs =3D 0; ofs + 1 < size;) { + c =3D fgetc(stream); + if (c =3D=3D EOF) + break; + s[ofs++] =3D c; + if (c =3D=3D '\n') + break; + } + if (ofs < size) + s[ofs] =3D 0; + return ofs ? s : NULL; +} + #endif /* _NOLIBC_STDIO_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 34A33C46467 for ; Mon, 7 Feb 2022 16:45:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1381615AbiBGQnu (ORCPT ); Mon, 7 Feb 2022 11:43:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41090 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390557AbiBGQfK (ORCPT ); Mon, 7 Feb 2022 11:35:10 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 8907EC0401CC for ; Mon, 7 Feb 2022 08:35:08 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOdq6014403; Mon, 7 Feb 2022 17:24:39 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 20/42] tools/nolibc/stdio: add fwrite() to stdio Date: Mon, 7 Feb 2022 17:23:32 +0100 Message-Id: <20220207162354.14293-21-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" We'll use it to write substrings. It relies on a simpler _fwrite() that only takes one size. fputs() was also modified to rely on it. Signed-off-by: Willy Tarreau --- tools/include/nolibc/stdio.h | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h index 149c5ca59aad..996bf89a30d2 100644 --- a/tools/include/nolibc/stdio.h +++ b/tools/include/nolibc/stdio.h @@ -84,12 +84,14 @@ int putchar(int c) } =20 =20 -/* puts(), fputs(). Note that puts() emits '\n' but not fputs(). */ +/* fwrite(), puts(), fputs(). Note that puts() emits '\n' but not fputs().= */ =20 +/* internal fwrite()-like function which only takes a size and returns 0 on + * success or EOF on error. It automatically retries on short writes. + */ static __attribute__((unused)) -int fputs(const char *s, FILE *stream) +int _fwrite(const void *buf, size_t size, FILE *stream) { - size_t len =3D strlen(s); ssize_t ret; int fd; =20 @@ -98,16 +100,35 @@ int fputs(const char *s, FILE *stream) =20 fd =3D 3 + (long)stream; =20 - while (len > 0) { - ret =3D write(fd, s, len); + while (size) { + ret =3D write(fd, buf, size); if (ret <=3D 0) return EOF; - s +=3D ret; - len -=3D ret; + size -=3D ret; + buf +=3D ret; } return 0; } =20 +static __attribute__((unused)) +size_t fwrite(const void *s, size_t size, size_t nmemb, FILE *stream) +{ + size_t written; + + for (written =3D 0; written < nmemb; written++) { + if (_fwrite(s, size, stream) !=3D 0) + break; + s +=3D size; + } + return written; +} + +static __attribute__((unused)) +int fputs(const char *s, FILE *stream) +{ + return _fwrite(s, strlen(s), stream); +} + static __attribute__((unused)) int puts(const char *s) { --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5A5DEC4707A for ; Mon, 7 Feb 2022 16:45:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1382296AbiBGQnx (ORCPT ); Mon, 7 Feb 2022 11:43:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41486 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390634AbiBGQfV (ORCPT ); Mon, 7 Feb 2022 11:35:21 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 11A00C0401D9 for ; Mon, 7 Feb 2022 08:35:18 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOdng014404; Mon, 7 Feb 2022 17:24:39 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 21/42] tools/nolibc/stdio: add a minimal [vf]printf() implementation Date: Mon, 7 Feb 2022 17:23:33 +0100 Message-Id: <20220207162354.14293-22-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This adds a minimal vfprintf() implementation as well as the commonly used fprintf() and printf() that rely on it. For now the function supports: - formats: %s, %c, %u, %d, %x - modifiers: %l and %ll - unknown chars are considered as modifiers and are ignored It is designed to remain minimalist, despite this printf() is 549 bytes on x86_64. It would be wise not to add too many formats. Signed-off-by: Willy Tarreau --- tools/include/nolibc/stdio.h | 128 +++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h index 996bf89a30d2..a73cf24cb68d 100644 --- a/tools/include/nolibc/stdio.h +++ b/tools/include/nolibc/stdio.h @@ -7,6 +7,8 @@ #ifndef _NOLIBC_STDIO_H #define _NOLIBC_STDIO_H =20 +#include + #include "std.h" #include "arch.h" #include "types.h" @@ -158,4 +160,130 @@ char *fgets(char *s, int size, FILE *stream) return ofs ? s : NULL; } =20 + +/* minimal vfprintf(). It supports the following formats: + * - %[l*]{d,u,c,x} + * - %s + * - unknown modifiers are ignored. + */ +static __attribute__((unused)) +int vfprintf(FILE *stream, const char *fmt, va_list args) +{ + char escape, lpref, c; + unsigned long long v; + unsigned int written; + size_t len, ofs; + char tmpbuf[21]; + const char *outstr; + + written =3D ofs =3D escape =3D lpref =3D 0; + while (1) { + c =3D fmt[ofs++]; + + if (escape) { + /* we're in an escape sequence, ofs =3D=3D 1 */ + escape =3D 0; + if (c =3D=3D 'c' || c =3D=3D 'd' || c =3D=3D 'u' || c =3D=3D 'x') { + if (lpref) { + if (lpref > 1) + v =3D va_arg(args, unsigned long long); + else + v =3D va_arg(args, unsigned long); + } else + v =3D va_arg(args, unsigned int); + + if (c =3D=3D 'd') { + /* sign-extend the value */ + if (lpref =3D=3D 0) + v =3D (long long)(int)v; + else if (lpref =3D=3D 1) + v =3D (long long)(long)v; + } + + switch (c) { + case 'd': + i64toa_r(v, tmpbuf); + break; + case 'u': + u64toa_r(v, tmpbuf); + break; + case 'x': + u64toh_r(v, tmpbuf); + break; + default: /* 'c' */ + tmpbuf[0] =3D v; + tmpbuf[1] =3D 0; + break; + } + outstr =3D tmpbuf; + } + else if (c =3D=3D 's') { + outstr =3D va_arg(args, char *); + } + else if (c =3D=3D '%') { + /* queue it verbatim */ + continue; + } + else { + /* modifiers or final 0 */ + if (c =3D=3D 'l') { + /* long format prefix, maintain the escape */ + lpref++; + } + escape =3D 1; + goto do_escape; + } + len =3D strlen(outstr); + goto flush_str; + } + + /* not an escape sequence */ + if (c =3D=3D 0 || c =3D=3D '%') { + /* flush pending data on escape or end */ + escape =3D 1; + lpref =3D 0; + outstr =3D fmt; + len =3D ofs - 1; + flush_str: + if (_fwrite(outstr, len, stream) !=3D 0) + break; + + written +=3D len; + do_escape: + if (c =3D=3D 0) + break; + fmt +=3D ofs; + ofs =3D 0; + continue; + } + + /* literal char, just queue it */ + } + return written; +} + +static __attribute__((unused)) +int fprintf(FILE *stream, const char *fmt, ...) +{ + va_list args; + int ret; + + va_start(args, fmt); + ret =3D vfprintf(stream, fmt, args); + va_end(args); + return ret; +} + +static __attribute__((unused)) +int printf(const char *fmt, ...) +{ + va_list args; + int ret; + + va_start(args, fmt); + ret =3D vfprintf(stdout, fmt, args); + va_end(args); + return ret; +} + #endif /* _NOLIBC_STDIO_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9AC5EC4707F for ; Mon, 7 Feb 2022 16:45:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1382382AbiBGQoA (ORCPT ); Mon, 7 Feb 2022 11:44:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40414 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390449AbiBGQeq (ORCPT ); Mon, 7 Feb 2022 11:34:46 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B99D1C0401D1 for ; Mon, 7 Feb 2022 08:34:43 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOdSv014405; Mon, 7 Feb 2022 17:24:39 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 22/42] tools/nolibc/types: define EXIT_SUCCESS and EXIT_FAILURE Date: Mon, 7 Feb 2022 17:23:34 +0100 Message-Id: <20220207162354.14293-23-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" These ones are found in some examples found in man pages and ease portability tests. Signed-off-by: Willy Tarreau --- tools/include/nolibc/types.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h index fb4d35f60850..dac1cc186dab 100644 --- a/tools/include/nolibc/types.h +++ b/tools/include/nolibc/types.h @@ -71,6 +71,9 @@ #define WEXITSTATUS(status) (((status) & 0xff00) >> 8) #define WIFEXITED(status) (((status) & 0x7f) =3D=3D 0) =20 +/* standard exit() codes */ +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 =20 /* for select() */ typedef struct { --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E2FB3C4167B for ; Mon, 7 Feb 2022 16:45:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1359519AbiBGQnk (ORCPT ); Mon, 7 Feb 2022 11:43:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40664 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390502AbiBGQex (ORCPT ); Mon, 7 Feb 2022 11:34:53 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id D2807C0401CE for ; Mon, 7 Feb 2022 08:34:50 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOdBd014406; Mon, 7 Feb 2022 17:24:39 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 23/42] tools/nolibc/stdio: add perror() to report the errno value Date: Mon, 7 Feb 2022 17:23:35 +0100 Message-Id: <20220207162354.14293-24-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" It doesn't contain the text for the error codes, but instead displays "errno=3D" followed by the errno value. Just like the regular errno, if a non-empty message is passed, it's placed followed with ": " on the output before the errno code. The message is emitted on stderr. Signed-off-by: Willy Tarreau --- tools/include/nolibc/stdio.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h index a73cf24cb68d..5f1cf32470d3 100644 --- a/tools/include/nolibc/stdio.h +++ b/tools/include/nolibc/stdio.h @@ -286,4 +286,10 @@ int printf(const char *fmt, ...) return ret; } =20 +static __attribute__((unused)) +void perror(const char *msg) +{ + fprintf(stderr, "%s%serrno=3D%d\n", (msg && *msg) ? msg : "", (msg && *ms= g) ? ": " : "", errno); +} + #endif /* _NOLIBC_STDIO_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 46165C35273 for ; Mon, 7 Feb 2022 16:31:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1389910AbiBGQbA (ORCPT ); Mon, 7 Feb 2022 11:31:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60808 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1387440AbiBGQZ5 (ORCPT ); Mon, 7 Feb 2022 11:25:57 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 784DCC0401CE for ; Mon, 7 Feb 2022 08:25:56 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOd4U014407; Mon, 7 Feb 2022 17:24:39 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 24/42] tools/nolibc/sys: make open() take a vararg on the 3rd argument Date: Mon, 7 Feb 2022 17:23:36 +0100 Message-Id: <20220207162354.14293-25-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Let's pass a vararg to open() so that it remains compatible with existing code. The arg is only dereferenced when flags contain O_CREAT. The function is generally not inlined anymore, causing an extra call (total 16 extra bytes) but it's still optimized for constant propagation, limiting the excess to no more than 16 bytes in practice when open() is called without O_CREAT, and ~40 with O_CREAT, which remains reasonable. Signed-off-by: Willy Tarreau --- tools/include/nolibc/sys.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index 98689f668ed3..539af457a91b 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -7,6 +7,7 @@ #ifndef _NOLIBC_SYS_H #define _NOLIBC_SYS_H =20 +#include #include "std.h" =20 /* system includes */ @@ -719,7 +720,7 @@ int mount(const char *src, const char *tgt, =20 =20 /* - * int open(const char *path, int flags, mode_t mode); + * int open(const char *path, int flags[, mode_t mode]); */ =20 static __attribute__((unused)) @@ -735,9 +736,20 @@ int sys_open(const char *path, int flags, mode_t mode) } =20 static __attribute__((unused)) -int open(const char *path, int flags, mode_t mode) +int open(const char *path, int flags, ...) { - int ret =3D sys_open(path, flags, mode); + mode_t mode =3D 0; + int ret; + + if (flags & O_CREAT) { + va_list args; + + va_start(args, flags); + mode =3D va_arg(args, mode_t); + va_end(args); + } + + ret =3D sys_open(path, flags, mode); =20 if (ret < 0) { SET_ERRNO(-ret); --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 30120C433EF for ; Mon, 7 Feb 2022 16:44:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241483AbiBGQnm (ORCPT ); Mon, 7 Feb 2022 11:43:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40704 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390544AbiBGQfB (ORCPT ); Mon, 7 Feb 2022 11:35:01 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2CFD2C0401D1 for ; Mon, 7 Feb 2022 08:35:00 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOemG014408; Mon, 7 Feb 2022 17:24:40 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 25/42] tools/nolibc/stdlib: avoid a 64-bit shift in u64toh_r() Date: Mon, 7 Feb 2022 17:23:37 +0100 Message-Id: <20220207162354.14293-26-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The build of printf() on mips requires libgcc for functions __ashldi3 and __lshrdi3 due to 64-bit shifts when scanning the input number. These are not really needed in fact since we scan the number 4 bits at a time. Let's arrange the loop to perform two 32-bit shifts instead on 32-bit platforms. Signed-off-by: Willy Tarreau --- tools/include/nolibc/stdlib.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index 82a4cf606d3c..db47362a750f 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -200,14 +200,18 @@ int u64toh_r(uint64_t in, char *buffer) int dig; =20 do { - dig =3D in >> pos; - in -=3D (uint64_t)dig << pos; + if (sizeof(long) >=3D 8) { + dig =3D (in >> pos) & 0xF; + } else { + /* 32-bit platforms: avoid a 64-bit shift */ + uint32_t d =3D (pos >=3D 32) ? (in >> 32) : in; + dig =3D (d >> (pos & 31)) & 0xF; + } + if (dig > 9) + dig +=3D 'a' - '0' - 10; pos -=3D 4; - if (dig || digits || pos < 0) { - if (dig > 9) - dig +=3D 'a' - '0' - 10; + if (dig || digits || pos < 0) buffer[digits++] =3D '0' + dig; - } } while (pos >=3D 0); =20 buffer[digits] =3D 0; --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4426DC3526C for ; Mon, 7 Feb 2022 16:45:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1382192AbiBGQnv (ORCPT ); Mon, 7 Feb 2022 11:43:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40514 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390467AbiBGQes (ORCPT ); Mon, 7 Feb 2022 11:34:48 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id D1C83C0401D5 for ; Mon, 7 Feb 2022 08:34:46 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOeTa014409; Mon, 7 Feb 2022 17:24:40 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 26/42] tools/nolibc/stdlib: make raise() use the lower level syscalls only Date: Mon, 7 Feb 2022 17:23:38 +0100 Message-Id: <20220207162354.14293-27-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" raise() doesn't set errno, so there's no point calling kill(), better call sys_kill(), which also reduces the function's size. Signed-off-by: Willy Tarreau --- tools/include/nolibc/stdlib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index db47362a750f..4cc1fdf6791e 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -317,7 +317,7 @@ int msleep(unsigned int msecs) __attribute__((weak,unused)) int raise(int signal) { - return kill(getpid(), signal); + return sys_kill(sys_getpid(), signal); } =20 static __attribute__((unused)) --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 88C9AC433FE for ; Mon, 7 Feb 2022 16:45:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1356238AbiBGQnd (ORCPT ); Mon, 7 Feb 2022 11:43:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40824 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390538AbiBGQfA (ORCPT ); Mon, 7 Feb 2022 11:35:00 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id EBD9DC0401EF for ; Mon, 7 Feb 2022 08:34:58 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOedx014410; Mon, 7 Feb 2022 17:24:40 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 27/42] tools/nolibc/sys: make getpgrp(), getpid(), gettid() not set errno Date: Mon, 7 Feb 2022 17:23:39 +0100 Message-Id: <20220207162354.14293-28-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" These syscalls never fail so there is no need to extract and set errno for them. Signed-off-by: Willy Tarreau --- tools/include/nolibc/sys.h | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index 539af457a91b..ef017cc0a580 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -458,13 +458,7 @@ pid_t sys_getpgrp(void) static __attribute__((unused)) pid_t getpgrp(void) { - pid_t ret =3D sys_getpgrp(); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; + return sys_getpgrp(); } =20 =20 @@ -481,13 +475,7 @@ pid_t sys_getpid(void) static __attribute__((unused)) pid_t getpid(void) { - pid_t ret =3D sys_getpid(); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; + return sys_getpid(); } =20 =20 @@ -504,13 +492,7 @@ pid_t sys_gettid(void) static __attribute__((unused)) pid_t gettid(void) { - pid_t ret =3D sys_gettid(); - - if (ret < 0) { - SET_ERRNO(-ret); - ret =3D -1; - } - return ret; + return sys_gettid(); } =20 =20 --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A728EC433FE for ; Mon, 7 Feb 2022 16:33:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1351430AbiBGQaJ (ORCPT ); Mon, 7 Feb 2022 11:30:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60860 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1389572AbiBGQ0F (ORCPT ); Mon, 7 Feb 2022 11:26:05 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 3C264C0401CE for ; Mon, 7 Feb 2022 08:26:05 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOeMr014411; Mon, 7 Feb 2022 17:24:40 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 28/42] tools/nolibc/string: use unidirectional variants for memcpy() Date: Mon, 7 Feb 2022 17:23:40 +0100 Message-Id: <20220207162354.14293-29-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Till now memcpy() relies on memmove(), but it's always included for libgcc, so we have a larger than needed function. Let's implement two unidirectional variants to copy from bottom to top and from top to bottom, and use the former for memcpy(). The variants are optimized to be compact, and at the same time the compiler is sometimes able to detect the loop and to replace it with a "rep movsb". The new function is 24 bytes instead of 52 on x86_64. Signed-off-by: Willy Tarreau --- tools/include/nolibc/string.h | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tools/include/nolibc/string.h b/tools/include/nolibc/string.h index 8a23cda2d450..6d8fad7a92e6 100644 --- a/tools/include/nolibc/string.h +++ b/tools/include/nolibc/string.h @@ -25,6 +25,28 @@ int memcmp(const void *s1, const void *s2, size_t n) return c1; } =20 +static __attribute__((unused)) +void *_nolibc_memcpy_up(void *dst, const void *src, size_t len) +{ + size_t pos =3D 0; + + while (pos < len) { + ((char *)dst)[pos] =3D ((const char *)src)[pos]; + pos++; + } + return dst; +} + +static __attribute__((unused)) +void *_nolibc_memcpy_down(void *dst, const void *src, size_t len) +{ + while (len) { + len--; + ((char *)dst)[len] =3D ((const char *)src)[len]; + } + return dst; +} + static __attribute__((unused)) void *memmove(void *dst, const void *src, size_t len) { @@ -42,7 +64,7 @@ void *memmove(void *dst, const void *src, size_t len) __attribute__((weak,unused)) void *memcpy(void *dst, const void *src, size_t len) { - return memmove(dst, src, len); + return _nolibc_memcpy_up(dst, src, len); } =20 static __attribute__((unused)) --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CA20CC35273 for ; Mon, 7 Feb 2022 16:33:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1388555AbiBGQaj (ORCPT ); Mon, 7 Feb 2022 11:30:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60916 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242367AbiBGQ0O (ORCPT ); Mon, 7 Feb 2022 11:26:14 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id EE3E5C0401D1 for ; Mon, 7 Feb 2022 08:26:13 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOexf014412; Mon, 7 Feb 2022 17:24:40 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 29/42] tools/nolibc/string: slightly simplify memmove() Date: Mon, 7 Feb 2022 17:23:41 +0100 Message-Id: <20220207162354.14293-30-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The direction test inside the loop was not always completely optimized, resulting in a larger than necessary function. This change adds a direction variable that is set out of the loop. Now the function is down to 48 bytes on x86, 32 on ARM and 68 on mips. It's worth noting that other approaches were attempted (including relying on the up and down functions) but they were only slightly beneficial on x86 and cost more on others. Signed-off-by: Willy Tarreau --- tools/include/nolibc/string.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/tools/include/nolibc/string.h b/tools/include/nolibc/string.h index 6d8fad7a92e6..b831a02de83f 100644 --- a/tools/include/nolibc/string.h +++ b/tools/include/nolibc/string.h @@ -50,14 +50,22 @@ void *_nolibc_memcpy_down(void *dst, const void *src, s= ize_t len) static __attribute__((unused)) void *memmove(void *dst, const void *src, size_t len) { - ssize_t pos =3D (dst <=3D src) ? -1 : (long)len; - void *ret =3D dst; + size_t dir, pos; =20 - while (len--) { - pos +=3D (dst <=3D src) ? 1 : -1; - ((char *)dst)[pos] =3D ((char *)src)[pos]; + pos =3D len; + dir =3D -1; + + if (dst < src) { + pos =3D -1; + dir =3D 1; + } + + while (len) { + pos +=3D dir; + ((char *)dst)[pos] =3D ((const char *)src)[pos]; + len--; } - return ret; + return dst; } =20 /* must be exported, as it's used by libgcc on ARM */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E9BFBC35274 for ; Mon, 7 Feb 2022 16:33:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1389790AbiBGQan (ORCPT ); Mon, 7 Feb 2022 11:30:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32826 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1380026AbiBGQ0X (ORCPT ); Mon, 7 Feb 2022 11:26:23 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 21EE4C0401CF for ; Mon, 7 Feb 2022 08:26:20 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOeRj014413; Mon, 7 Feb 2022 17:24:40 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 30/42] tools/nolibc/string: add strncpy() and strlcpy() Date: Mon, 7 Feb 2022 17:23:42 +0100 Message-Id: <20220207162354.14293-31-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" These are minimal variants. strncpy() always fills the destination for chars, while strlcpy() copies no more than including the zero and returns the source's length. The respective sizes on various archs are: strncpy(): x86:0x1f mips:0x30 arm:0x20 strlcpy(): x86:0x17 mips:0x34 arm:0x1a Signed-off-by: Willy Tarreau --- tools/include/nolibc/string.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tools/include/nolibc/string.h b/tools/include/nolibc/string.h index b831a02de83f..7c274efcdfae 100644 --- a/tools/include/nolibc/string.h +++ b/tools/include/nolibc/string.h @@ -121,6 +121,34 @@ size_t nolibc_strlen(const char *str) nolibc_strlen((str)); \ }) =20 +static __attribute__((unused)) +size_t strlcpy(char *dst, const char *src, size_t size) +{ + size_t len; + char c; + + for (len =3D 0;;) { + c =3D src[len]; + if (len < size) + dst[len] =3D c; + if (!c) + break; + len++; + } + return len; +} + +static __attribute__((unused)) +char *strncpy(char *dst, const char *src, size_t size) +{ + size_t len; + + for (len =3D 0; len < size; len++) + if ((dst[len] =3D *src)) + src++; + return dst; +} + static __attribute__((unused)) char *strrchr(const char *s, int c) { --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7362EC433EF for ; Mon, 7 Feb 2022 16:33:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1389849AbiBGQaw (ORCPT ); Mon, 7 Feb 2022 11:30:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32948 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1387635AbiBGQ0j (ORCPT ); Mon, 7 Feb 2022 11:26:39 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id C2B0BC0401CE for ; Mon, 7 Feb 2022 08:26:37 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOeL4014415; Mon, 7 Feb 2022 17:24:40 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 31/42] tools/nolibc/string: add tiny versions of strncat() and strlcat() Date: Mon, 7 Feb 2022 17:23:43 +0100 Message-Id: <20220207162354.14293-32-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" While these functions are often dangerous, forcing the user to work around their absence is often much worse. Let's provide small versions of each of them. The respective sizes in bytes on a few architectures are: strncat(): x86:0x33 mips:0x68 arm:0x3c strlcat(): x86:0x25 mips:0x4c arm:0x2c The two are quite different, and strncat() is even different from strncpy() in that it limits the amount of data it copies and will always terminate the output by one zero, while strlcat() will always limit the total output to the specified size and will put a zero if possible. Signed-off-by: Willy Tarreau --- tools/include/nolibc/string.h | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tools/include/nolibc/string.h b/tools/include/nolibc/string.h index 7c274efcdfae..c550c9ba8f4c 100644 --- a/tools/include/nolibc/string.h +++ b/tools/include/nolibc/string.h @@ -121,6 +121,28 @@ size_t nolibc_strlen(const char *str) nolibc_strlen((str)); \ }) =20 +static __attribute__((unused)) +size_t strlcat(char *dst, const char *src, size_t size) +{ + size_t len; + char c; + + for (len =3D 0; dst[len]; len++) + ; + + for (;;) { + c =3D *src; + if (len < size) + dst[len] =3D c; + if (!c) + break; + len++; + src++; + } + + return len; +} + static __attribute__((unused)) size_t strlcpy(char *dst, const char *src, size_t size) { @@ -138,6 +160,25 @@ size_t strlcpy(char *dst, const char *src, size_t size) return len; } =20 +static __attribute__((unused)) +char *strncat(char *dst, const char *src, size_t size) +{ + char *orig =3D dst; + + while (*dst) + dst++; + + while (size && (*dst =3D *src)) { + src++; + dst++; + size--; + } + + *dst =3D 0; + return orig; +} + + static __attribute__((unused)) char *strncpy(char *dst, const char *src, size_t size) { --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 18C28C4167D for ; Mon, 7 Feb 2022 16:33:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1382229AbiBGQaZ (ORCPT ); Mon, 7 Feb 2022 11:30:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33108 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1389773AbiBGQ04 (ORCPT ); Mon, 7 Feb 2022 11:26:56 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id DD5CFC0401CF for ; Mon, 7 Feb 2022 08:26:53 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOfEK014416; Mon, 7 Feb 2022 17:24:41 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 32/42] tools/nolibc: move exported functions to their own section Date: Mon, 7 Feb 2022 17:23:44 +0100 Message-Id: <20220207162354.14293-33-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Some functions like raise() and memcpy() are permanently exported because they're needed by libgcc on certain platforms. However most of the time they are not needed and needlessly take space. Let's move them to their own sub-section, called .text.nolibc_. This allows ld to get rid of them if unused when passed --gc-sections. Signed-off-by: Willy Tarreau --- tools/include/nolibc/stdlib.h | 2 +- tools/include/nolibc/string.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index 4cc1fdf6791e..da08ff30c15a 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -314,7 +314,7 @@ int msleep(unsigned int msecs) } =20 /* This one is not marked static as it's needed by libgcc for divide by ze= ro */ -__attribute__((weak,unused)) +__attribute__((weak,unused,section(".text.nolibc_raise"))) int raise(int signal) { return sys_kill(sys_getpid(), signal); diff --git a/tools/include/nolibc/string.h b/tools/include/nolibc/string.h index c550c9ba8f4c..c1661589cb3c 100644 --- a/tools/include/nolibc/string.h +++ b/tools/include/nolibc/string.h @@ -69,7 +69,7 @@ void *memmove(void *dst, const void *src, size_t len) } =20 /* must be exported, as it's used by libgcc on ARM */ -__attribute__((weak,unused)) +__attribute__((weak,unused,section(".text.nolibc_memcpy"))) void *memcpy(void *dst, const void *src, size_t len) { return _nolibc_memcpy_up(dst, src, len); --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 69C01C3526E for ; Mon, 7 Feb 2022 16:45:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1382316AbiBGQnz (ORCPT ); Mon, 7 Feb 2022 11:43:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41184 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390609AbiBGQfO (ORCPT ); Mon, 7 Feb 2022 11:35:14 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 5DA84C0401DA for ; Mon, 7 Feb 2022 08:35:13 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOfFi014417; Mon, 7 Feb 2022 17:24:41 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 33/42] tools/nolibc/arch: mark the _start symbol as weak Date: Mon, 7 Feb 2022 17:23:45 +0100 Message-Id: <20220207162354.14293-34-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" By doing so we can link together multiple C files that have been compiled with nolibc and which each have a _start symbol. Signed-off-by: Willy Tarreau --- tools/include/nolibc/arch-aarch64.h | 1 + tools/include/nolibc/arch-arm.h | 1 + tools/include/nolibc/arch-i386.h | 1 + tools/include/nolibc/arch-mips.h | 1 + tools/include/nolibc/arch-riscv.h | 1 + tools/include/nolibc/arch-x86_64.h | 1 + 6 files changed, 6 insertions(+) diff --git a/tools/include/nolibc/arch-aarch64.h b/tools/include/nolibc/arc= h-aarch64.h index 443de5fb7f54..87d9e434820c 100644 --- a/tools/include/nolibc/arch-aarch64.h +++ b/tools/include/nolibc/arch-aarch64.h @@ -183,6 +183,7 @@ struct sys_stat_struct { =20 /* startup code */ asm(".section .text\n" + ".weak _start\n" ".global _start\n" "_start:\n" "ldr x0, [sp]\n" // argc (x0) was in the stack diff --git a/tools/include/nolibc/arch-arm.h b/tools/include/nolibc/arch-ar= m.h index 66f687ad987f..001a3c8c9ad5 100644 --- a/tools/include/nolibc/arch-arm.h +++ b/tools/include/nolibc/arch-arm.h @@ -176,6 +176,7 @@ struct sys_stat_struct { =20 /* startup code */ asm(".section .text\n" + ".weak _start\n" ".global _start\n" "_start:\n" #if defined(__THUMBEB__) || defined(__THUMBEL__) diff --git a/tools/include/nolibc/arch-i386.h b/tools/include/nolibc/arch-i= 386.h index 32f42e2cee26..d7e4d53325a3 100644 --- a/tools/include/nolibc/arch-i386.h +++ b/tools/include/nolibc/arch-i386.h @@ -175,6 +175,7 @@ struct sys_stat_struct { * */ asm(".section .text\n" + ".weak _start\n" ".global _start\n" "_start:\n" "pop %eax\n" // argc (first arg, %eax) diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-m= ips.h index e330201dde6a..c9a6aac87c6d 100644 --- a/tools/include/nolibc/arch-mips.h +++ b/tools/include/nolibc/arch-mips.h @@ -190,6 +190,7 @@ struct sys_stat_struct { =20 /* startup code, note that it's called __start on MIPS */ asm(".section .text\n" + ".weak __start\n" ".set nomips16\n" ".global __start\n" ".set noreorder\n" diff --git a/tools/include/nolibc/arch-riscv.h b/tools/include/nolibc/arch-= riscv.h index 9d5ff78f606b..bc10b7b5706d 100644 --- a/tools/include/nolibc/arch-riscv.h +++ b/tools/include/nolibc/arch-riscv.h @@ -184,6 +184,7 @@ struct sys_stat_struct { =20 /* startup code */ asm(".section .text\n" + ".weak _start\n" ".global _start\n" "_start:\n" ".option push\n" diff --git a/tools/include/nolibc/arch-x86_64.h b/tools/include/nolibc/arch= -x86_64.h index 83c4b458ada7..fe517c16cd4d 100644 --- a/tools/include/nolibc/arch-x86_64.h +++ b/tools/include/nolibc/arch-x86_64.h @@ -198,6 +198,7 @@ struct sys_stat_struct { * */ asm(".section .text\n" + ".weak _start\n" ".global _start\n" "_start:\n" "pop %rdi\n" // argc (first arg, %rdi) --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6D131C3527A for ; Mon, 7 Feb 2022 16:45:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1383554AbiBGQoR (ORCPT ); Mon, 7 Feb 2022 11:44:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40732 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390507AbiBGQe4 (ORCPT ); Mon, 7 Feb 2022 11:34:56 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 927EDC0401DA for ; Mon, 7 Feb 2022 08:34:52 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOfPn014418; Mon, 7 Feb 2022 17:24:41 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 34/42] tools/nolibc/types: define PATH_MAX and MAXPATHLEN Date: Mon, 7 Feb 2022 17:23:46 +0100 Message-Id: <20220207162354.14293-35-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" These ones are often used and commonly set by applications to fallback values. Let's fix them both to agree on PATH_MAX=3D4096 by default, as is already present in linux/limits.h. Signed-off-by: Willy Tarreau --- tools/include/nolibc/types.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h index dac1cc186dab..9ab922bc2f09 100644 --- a/tools/include/nolibc/types.h +++ b/tools/include/nolibc/types.h @@ -49,6 +49,17 @@ #define FD_SETSIZE 256 #endif =20 +/* PATH_MAX and MAXPATHLEN are often used and found with plenty of differe= nt + * values. + */ +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +#ifndef MAXPATHLEN +#define MAXPATHLEN (PATH_MAX) +#endif + /* Special FD used by all the *at functions */ #ifndef AT_FDCWD #define AT_FDCWD (-100) --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9EC63C43217 for ; Mon, 7 Feb 2022 16:45:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1356994AbiBGQne (ORCPT ); Mon, 7 Feb 2022 11:43:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40956 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244922AbiBGQfF (ORCPT ); Mon, 7 Feb 2022 11:35:05 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2591EC0401DD for ; Mon, 7 Feb 2022 08:35:03 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOfQI014419; Mon, 7 Feb 2022 17:24:41 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 35/42] tools/nolibc/string: export memset() and memmove() Date: Mon, 7 Feb 2022 17:23:47 +0100 Message-Id: <20220207162354.14293-36-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" "clang -Os" and "gcc -Ofast" without -ffreestanding may ignore memset() and memmove(), hoping to provide their builtin equivalents, and finally not find them. Thus we must export these functions for these rare cases. Note that as they're set in their own sections, they will be eliminated by the linker if not used. In addition, they do not prevent gcc from identifying them and replacing them with the shorter "rep movsb" or "rep stosb" when relevant. Signed-off-by: Willy Tarreau --- tools/include/nolibc/string.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/include/nolibc/string.h b/tools/include/nolibc/string.h index c1661589cb3c..4554b6fcb400 100644 --- a/tools/include/nolibc/string.h +++ b/tools/include/nolibc/string.h @@ -47,7 +47,10 @@ void *_nolibc_memcpy_down(void *dst, const void *src, si= ze_t len) return dst; } =20 -static __attribute__((unused)) +/* might be ignored by the compiler without -ffreestanding, then found as + * missing. + */ +__attribute__((weak,unused,section(".text.nolibc_memmove"))) void *memmove(void *dst, const void *src, size_t len) { size_t dir, pos; @@ -75,7 +78,10 @@ void *memcpy(void *dst, const void *src, size_t len) return _nolibc_memcpy_up(dst, src, len); } =20 -static __attribute__((unused)) +/* might be ignored by the compiler without -ffreestanding, then found as + * missing. + */ +__attribute__((weak,unused,section(".text.nolibc_memset"))) void *memset(void *dst, int b, size_t len) { char *p =3D dst; --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1F38AC47085 for ; Mon, 7 Feb 2022 16:45:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1385707AbiBGQoc (ORCPT ); Mon, 7 Feb 2022 11:44:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41150 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390594AbiBGQfM (ORCPT ); Mon, 7 Feb 2022 11:35:12 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 0E69BC0401ED for ; Mon, 7 Feb 2022 08:35:11 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOf4u014420; Mon, 7 Feb 2022 17:24:41 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 36/42] tools/nolibc/errno: extract errno.h from sys.h Date: Mon, 7 Feb 2022 17:23:48 +0100 Message-Id: <20220207162354.14293-37-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This allows us to provide a minimal errno.h to ease porting applications that use it. Signed-off-by: Willy Tarreau --- tools/include/nolibc/errno.h | 27 +++++++++++++++++++++++++++ tools/include/nolibc/stdio.h | 1 + tools/include/nolibc/sys.h | 17 +---------------- 3 files changed, 29 insertions(+), 16 deletions(-) create mode 100644 tools/include/nolibc/errno.h diff --git a/tools/include/nolibc/errno.h b/tools/include/nolibc/errno.h new file mode 100644 index 000000000000..06893d6dfb7a --- /dev/null +++ b/tools/include/nolibc/errno.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * Minimal errno definitions for NOLIBC + * Copyright (C) 2017-2022 Willy Tarreau + */ + +#ifndef _NOLIBC_ERRNO_H +#define _NOLIBC_ERRNO_H + +#include + +/* this way it will be removed if unused */ +static int errno; + +#ifndef NOLIBC_IGNORE_ERRNO +#define SET_ERRNO(v) do { errno =3D (v); } while (0) +#else +#define SET_ERRNO(v) do { } while (0) +#endif + + +/* errno codes all ensure that they will not conflict with a valid pointer + * because they all correspond to the highest addressable memory page. + */ +#define MAX_ERRNO 4095 + +#endif /* _NOLIBC_ERRNO_H */ diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h index 5f1cf32470d3..cb4d3ab3a565 100644 --- a/tools/include/nolibc/stdio.h +++ b/tools/include/nolibc/stdio.h @@ -11,6 +11,7 @@ =20 #include "std.h" #include "arch.h" +#include "errno.h" #include "types.h" #include "sys.h" #include "stdlib.h" diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index ef017cc0a580..28437863c63f 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -14,29 +14,14 @@ #include #include // for SIGCHLD #include -#include #include #include #include =20 #include "arch.h" +#include "errno.h" #include "types.h" =20 -/* this way it will be removed if unused */ -static int errno; - -#ifndef NOLIBC_IGNORE_ERRNO -#define SET_ERRNO(v) do { errno =3D (v); } while (0) -#else -#define SET_ERRNO(v) do { } while (0) -#endif - - -/* errno codes all ensure that they will not conflict with a valid pointer - * because they all correspond to the highest addressable memory page. - */ -#define MAX_ERRNO 4095 - =20 /* Functions in this file only describe syscalls. They're declared static = so * that the compiler usually decides to inline them while still being allo= wed --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7B10AC4707E for ; Mon, 7 Feb 2022 16:45:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1382342AbiBGQn4 (ORCPT ); Mon, 7 Feb 2022 11:43:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41388 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390623AbiBGQfQ (ORCPT ); Mon, 7 Feb 2022 11:35:16 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 7A12CC0401D3 for ; Mon, 7 Feb 2022 08:35:15 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOfL2014421; Mon, 7 Feb 2022 17:24:41 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 37/42] tools/nolibc/unistd: extract msleep(), sleep(), tcsetpgrp() to unistd.h Date: Mon, 7 Feb 2022 17:23:49 +0100 Message-Id: <20220207162354.14293-38-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" These functions are normally provided by unistd.h. For ease of porting, let's create the file and move them there. Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 1 + tools/include/nolibc/stdlib.h | 30 ----------------------- tools/include/nolibc/unistd.h | 46 +++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 30 deletions(-) create mode 100644 tools/include/nolibc/unistd.h diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index 7eaa09fe9f4d..686726518431 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -91,6 +91,7 @@ #include "stdio.h" #include "stdlib.h" #include "string.h" +#include "unistd.h" =20 /* Used by programs to avoid std includes */ #define NOLIBC diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index da08ff30c15a..0e6bca4ee089 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -300,19 +300,6 @@ char *u64toa(uint64_t in) return itoa_buffer; } =20 -static __attribute__((unused)) -int msleep(unsigned int msecs) -{ - struct timeval my_timeval =3D { msecs / 1000, (msecs % 1000) * 1000 }; - - if (sys_select(0, 0, 0, 0, &my_timeval) < 0) - return (my_timeval.tv_sec * 1000) + - (my_timeval.tv_usec / 1000) + - !!(my_timeval.tv_usec % 1000); - else - return 0; -} - /* This one is not marked static as it's needed by libgcc for divide by ze= ro */ __attribute__((weak,unused,section(".text.nolibc_raise"))) int raise(int signal) @@ -320,21 +307,4 @@ int raise(int signal) return sys_kill(sys_getpid(), signal); } =20 -static __attribute__((unused)) -unsigned int sleep(unsigned int seconds) -{ - struct timeval my_timeval =3D { seconds, 0 }; - - if (sys_select(0, 0, 0, 0, &my_timeval) < 0) - return my_timeval.tv_sec + !!my_timeval.tv_usec; - else - return 0; -} - -static __attribute__((unused)) -int tcsetpgrp(int fd, pid_t pid) -{ - return ioctl(fd, TIOCSPGRP, &pid); -} - #endif /* _NOLIBC_STDLIB_H */ diff --git a/tools/include/nolibc/unistd.h b/tools/include/nolibc/unistd.h new file mode 100644 index 000000000000..87b448ff2191 --- /dev/null +++ b/tools/include/nolibc/unistd.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * unistd function definitions for NOLIBC + * Copyright (C) 2017-2022 Willy Tarreau + */ + +#ifndef _NOLIBC_UNISTD_H +#define _NOLIBC_UNISTD_H + +#include "std.h" +#include "arch.h" +#include "types.h" +#include "sys.h" + + +static __attribute__((unused)) +int msleep(unsigned int msecs) +{ + struct timeval my_timeval =3D { msecs / 1000, (msecs % 1000) * 1000 }; + + if (sys_select(0, 0, 0, 0, &my_timeval) < 0) + return (my_timeval.tv_sec * 1000) + + (my_timeval.tv_usec / 1000) + + !!(my_timeval.tv_usec % 1000); + else + return 0; +} + +static __attribute__((unused)) +unsigned int sleep(unsigned int seconds) +{ + struct timeval my_timeval =3D { seconds, 0 }; + + if (sys_select(0, 0, 0, 0, &my_timeval) < 0) + return my_timeval.tv_sec + !!my_timeval.tv_usec; + else + return 0; +} + +static __attribute__((unused)) +int tcsetpgrp(int fd, pid_t pid) +{ + return ioctl(fd, TIOCSPGRP, &pid); +} + +#endif /* _NOLIBC_UNISTD_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B75DBC43219 for ; Mon, 7 Feb 2022 16:33:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1377698AbiBGQaL (ORCPT ); Mon, 7 Feb 2022 11:30:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60774 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1382045AbiBGQZx (ORCPT ); Mon, 7 Feb 2022 11:25:53 -0500 X-Greylist: delayed 60 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Mon, 07 Feb 2022 08:25:51 PST Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 346D9C0401CF for ; Mon, 7 Feb 2022 08:25:50 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOfTp014422; Mon, 7 Feb 2022 17:24:41 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 38/42] tools/nolibc/unistd: add usleep() Date: Mon, 7 Feb 2022 17:23:50 +0100 Message-Id: <20220207162354.14293-39-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This call is trivial to implement based on select() to complete sleep() and msleep(), let's add it. Signed-off-by: Willy Tarreau --- tools/include/nolibc/unistd.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/include/nolibc/unistd.h b/tools/include/nolibc/unistd.h index 87b448ff2191..1c25e20ee360 100644 --- a/tools/include/nolibc/unistd.h +++ b/tools/include/nolibc/unistd.h @@ -37,6 +37,14 @@ unsigned int sleep(unsigned int seconds) return 0; } =20 +static __attribute__((unused)) +int usleep(unsigned int usecs) +{ + struct timeval my_timeval =3D { usecs / 1000000, usecs % 1000000 }; + + return sys_select(0, 0, 0, 0, &my_timeval); +} + static __attribute__((unused)) int tcsetpgrp(int fd, pid_t pid) { --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CFD9CC433EF for ; Mon, 7 Feb 2022 16:45:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1384866AbiBGQo1 (ORCPT ); Mon, 7 Feb 2022 11:44:27 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41158 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390579AbiBGQfM (ORCPT ); Mon, 7 Feb 2022 11:35:12 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 75D04C0401DB for ; Mon, 7 Feb 2022 08:35:10 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOgP1014423; Mon, 7 Feb 2022 17:24:42 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 39/42] tools/nolibc/signal: move raise() to signal.h Date: Mon, 7 Feb 2022 17:23:51 +0100 Message-Id: <20220207162354.14293-40-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This function is normally found in signal.h, and providing the file eases porting of existing programs. Let's move it there. Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 1 + tools/include/nolibc/signal.h | 22 ++++++++++++++++++++++ tools/include/nolibc/stdlib.h | 7 ------- 3 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 tools/include/nolibc/signal.h diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index 686726518431..0f375e901a36 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -88,6 +88,7 @@ #include "types.h" #include "sys.h" #include "ctype.h" +#include "signal.h" #include "stdio.h" #include "stdlib.h" #include "string.h" diff --git a/tools/include/nolibc/signal.h b/tools/include/nolibc/signal.h new file mode 100644 index 000000000000..ef47e71e2be3 --- /dev/null +++ b/tools/include/nolibc/signal.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * signal function definitions for NOLIBC + * Copyright (C) 2017-2022 Willy Tarreau + */ + +#ifndef _NOLIBC_SIGNAL_H +#define _NOLIBC_SIGNAL_H + +#include "std.h" +#include "arch.h" +#include "types.h" +#include "sys.h" + +/* This one is not marked static as it's needed by libgcc for divide by ze= ro */ +__attribute__((weak,unused,section(".text.nolibc_raise"))) +int raise(int signal) +{ + return sys_kill(sys_getpid(), signal); +} + +#endif /* _NOLIBC_SIGNAL_H */ diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index 0e6bca4ee089..b46bebd48ba2 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -300,11 +300,4 @@ char *u64toa(uint64_t in) return itoa_buffer; } =20 -/* This one is not marked static as it's needed by libgcc for divide by ze= ro */ -__attribute__((weak,unused,section(".text.nolibc_raise"))) -int raise(int signal) -{ - return sys_kill(sys_getpid(), signal); -} - #endif /* _NOLIBC_STDLIB_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2644AC35272 for ; Mon, 7 Feb 2022 16:31:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1389885AbiBGQa5 (ORCPT ); Mon, 7 Feb 2022 11:30:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60820 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1387604AbiBGQZ7 (ORCPT ); Mon, 7 Feb 2022 11:25:59 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 9CE12C0401CE for ; Mon, 7 Feb 2022 08:25:58 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOga5014424; Mon, 7 Feb 2022 17:24:42 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 40/42] tools/nolibc/time: create time.h with time() Date: Mon, 7 Feb 2022 17:23:52 +0100 Message-Id: <20220207162354.14293-41-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The time() syscall is used by a few simple applications, and is trivial to implement based on gettimeofday() that we already have. Let's create the file to ease porting and provide the function. It never returns any error, though it may segfault in case of invalid pointer, like other implementations relying on gettimeofday(). Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 1 + tools/include/nolibc/time.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tools/include/nolibc/time.h diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index 0f375e901a36..561dcdb83cee 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -92,6 +92,7 @@ #include "stdio.h" #include "stdlib.h" #include "string.h" +#include "time.h" #include "unistd.h" =20 /* Used by programs to avoid std includes */ diff --git a/tools/include/nolibc/time.h b/tools/include/nolibc/time.h new file mode 100644 index 000000000000..d18b7661fdd7 --- /dev/null +++ b/tools/include/nolibc/time.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * time function definitions for NOLIBC + * Copyright (C) 2017-2022 Willy Tarreau + */ + +#ifndef _NOLIBC_TIME_H +#define _NOLIBC_TIME_H + +#include "std.h" +#include "arch.h" +#include "types.h" +#include "sys.h" + +static __attribute__((unused)) +time_t time(time_t *tptr) +{ + struct timeval tv; + + /* note, cannot fail here */ + sys_gettimeofday(&tv, NULL); + + if (tptr) + *tptr =3D tv.tv_sec; + return tv.tv_sec; +} + +#endif /* _NOLIBC_TIME_H */ --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 317F3C433FE for ; Mon, 7 Feb 2022 16:31:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350709AbiBGQ3l (ORCPT ); Mon, 7 Feb 2022 11:29:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60874 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1389692AbiBGQ0I (ORCPT ); Mon, 7 Feb 2022 11:26:08 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 9BFDCC0401CE for ; Mon, 7 Feb 2022 08:26:07 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOg9S014427; Mon, 7 Feb 2022 17:24:42 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 41/42] tools/nolibc: also mention how to build by just setting the include path Date: Mon, 7 Feb 2022 17:23:53 +0100 Message-Id: <20220207162354.14293-42-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Now that a few basic include files are provided, some simple portable programs may build, which will save them from having to surround their includes with #ifndef NOLIBC. This patch mentions how to proceed, and enumerates the list of files that are covered. A comprehensive list of required include files is available here: https://en.cppreference.com/w/c/header Signed-off-by: Willy Tarreau --- tools/include/nolibc/nolibc.h | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index 561dcdb83cee..b2bc48d3cfe4 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -57,22 +57,32 @@ * having to specify anything. * * Finally some very common libc-level functions are provided. It is the c= ase - * for a few functions usually found in string.h, ctype.h, or stdlib.h. No= thing - * is currently provided regarding stdio emulation. + * for a few functions usually found in string.h, ctype.h, or stdlib.h. * - * The macro NOLIBC is always defined, so that it is possible for a progra= m to - * check this macro to know if it is being built against and decide to dis= able - * some features or simply not to include some standard libc files. - * - * Ideally this file should be split in multiple files for easier long term - * maintenance, but provided as a single file as it is now, it's quite - * convenient to use. Maybe some variations involving a set of includes at= the - * top could work. + * The nolibc.h file is only a convenient entry point which includes all o= ther + * files. It also defines the NOLIBC macro, so that it is possible for a + * program to check this macro to know if it is being built against and de= cide + * to disable some features or simply not to include some standard libc fi= les. * * A simple static executable may be built this way : * $ gcc -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \ * -static -include nolibc.h -o hello hello.c -lgcc * + * Simple programs meant to be reasonably portable to various libc and usi= ng + * only a few common includes, may also be built by simply making the incl= ude + * path point to the nolibc directory: + * $ gcc -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \ + * -I../nolibc -o hello hello.c -lgcc + * + * The available standard (but limited) include files are: + * ctype.h, errno.h, signal.h, stdio.h, stdlib.h, string.h, time.h + * + * In addition, the following ones are expected to be provided by the comp= iler: + * float.h, stdarg.h, stddef.h + * + * The following ones which are part to the C standard are not provided: + * assert.h, locale.h, math.h, setjmp.h, limits.h + * * A very useful calling convention table may be found here : * http://man7.org/linux/man-pages/man2/syscall.2.html * --=20 2.35.1 From nobody Mon Jun 29 15:59:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C5D35C433FE for ; Mon, 7 Feb 2022 16:43:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239664AbiBGQmd (ORCPT ); Mon, 7 Feb 2022 11:42:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40800 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390521AbiBGQfA (ORCPT ); Mon, 7 Feb 2022 11:35:00 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E8C75C0401E4 for ; Mon, 7 Feb 2022 08:34:53 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 217GOgET014428; Mon, 7 Feb 2022 17:24:42 +0100 From: Willy Tarreau To: "Paul E . McKenney" Cc: Mark Brown , linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 42/42] tools/nolibc/stdlib: implement abort() Date: Mon, 7 Feb 2022 17:23:54 +0100 Message-Id: <20220207162354.14293-43-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20220207162354.14293-1-w@1wt.eu> References: <20220207162354.14293-1-w@1wt.eu> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" libgcc uses it for certain divide functions, so it must be exported. Like for memset() we do that in its own section so that the linker can strip it when not needed. Signed-off-by: Willy Tarreau --- tools/include/nolibc/stdlib.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index b46bebd48ba2..733105c574ee 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -23,6 +23,14 @@ static __attribute__((unused)) char itoa_buffer[21]; * As much as possible, please keep functions alphabetically sorted. */ =20 +/* must be exported, as it's used by libgcc for various divide functions */ +__attribute__((weak,unused,noreturn,section(".text.nolibc_abort"))) +void abort(void) +{ + sys_kill(sys_getpid(), SIGABRT); + for (;;); +} + static __attribute__((unused)) long atol(const char *s) { --=20 2.35.1