From 812f223fe9be03dc22abb85240b6f075135d2386 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Fri, 26 Sep 2025 16:26:58 +0200 Subject: tools/nolibc: handle NULL wstatus argument to waitpid() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wstatus is allowed to be NULL. Avoid a segmentation fault in this case. Fixes: 0c89abf5ab3f ("tools/nolibc: implement waitpid() in terms of waitid()") Signed-off-by: Thomas Weißschuh Acked-by: Willy Tarreau Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/sys/wait.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/sys/wait.h b/tools/include/nolibc/sys/wait.h index 4e66e1f7a03e..9d9319ba92cb 100644 --- a/tools/include/nolibc/sys/wait.h +++ b/tools/include/nolibc/sys/wait.h @@ -65,23 +65,29 @@ pid_t waitpid(pid_t pid, int *status, int options) switch (info.si_code) { case 0: - *status = 0; + if (status) + *status = 0; break; case CLD_EXITED: - *status = (info.si_status & 0xff) << 8; + if (status) + *status = (info.si_status & 0xff) << 8; break; case CLD_KILLED: - *status = info.si_status & 0x7f; + if (status) + *status = info.si_status & 0x7f; break; case CLD_DUMPED: - *status = (info.si_status & 0x7f) | 0x80; + if (status) + *status = (info.si_status & 0x7f) | 0x80; break; case CLD_STOPPED: case CLD_TRAPPED: - *status = (info.si_status << 8) + 0x7f; + if (status) + *status = (info.si_status << 8) + 0x7f; break; case CLD_CONTINUED: - *status = 0xffff; + if (status) + *status = 0xffff; break; default: return -1; -- cgit From 2602949b22330f1275138e2b5aea5d49126b9757 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 27 Oct 2025 11:24:57 +0100 Subject: tools/nolibc: x86: fix section mismatch caused by asm "mem*" functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I recently got occasional build failures at -Os or -Oz that would always involve waitpid(), where the assembler would complain about this: init.s: Error: .size expression for waitpid.constprop.0 does not evaluate to a constant And without -fno-asynchronous-unwind-tables it could also spit such errors: init.s:836: Error: CFI instruction used without previous .cfi_startproc init.s:838: Error: .cfi_endproc without corresponding .cfi_startproc init.s: Error: open CFI at the end of file; missing .cfi_endproc directive A trimmed down reproducer is as simple as this: int main(int argc, char **argv) { int ret, status; if (argc == 0) ret = waitpid(-1, &status, 0); else ret = waitpid(-1, &status, 0); return status; } It produces the following asm code on x86_64: .text .section .text.nolibc_memmove_memcpy .weak memmove .weak memcpy memmove: memcpy: movq %rdx, %rcx (...) retq .section .text.nolibc_memset .weak memset memset: xchgl %eax, %esi movq %rdx, %rcx pushq %rdi rep stosb popq %rax retq .type waitpid.constprop.0.isra.0, @function waitpid.constprop.0.isra.0: subq $8, %rsp (...) jmp *.L5(,%rax,8) .section .rodata .align 8 .align 4 .L5: .quad .L10 (...) .quad .L4 .text .L10: (...) .cfi_def_cfa_offset 8 ret .cfi_endproc .LFE273: .size waitpid.constprop.0.isra.0, .-waitpid.constprop.0.isra.0 It's a bit dense, but here's the explanation: the compiler has emitted a ".text" statement because it knows it's working in the .text section. Then, our hand-written asm code for the mem* functions forced the section to .text.something without the compiler knowing about it, so it thinks the code is still being emitted for .text. As such, without any .section statement, the waitpid.constprop.0.isra.0 label is in fact placed in the previously created section, here .text.nolibc_memset. The waitpid() function involves a switch/case statement that can be turned to a jump table, which is what the compiler does with the .rodata section, and after that it restores .text, which is no longer the previous .text.nolibc_memset section. Then the CFI statements cross a section, so does the .size calculation, which explains the error. While a first approach consisting in placing an explicit ".text" at the end of these functions was verified to work, it's still unreliable as it depends on what the compiler remembers having emitted previously. A better approach is to replace the ".section" with ".pushsection", and place a ".popsection" at the end, so that these code blocks are agnostic to where they're placed relative to other blocks. Fixes: 553845eebd60 ("tools/nolibc: x86-64: Use `rep movsb` for `memcpy()` and `memmove()`") Fixes: 12108aa8c1a1 ("tools/nolibc: x86-64: Use `rep stosb` for `memset()`") Signed-off-by: Willy Tarreau Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/arch-x86.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/arch-x86.h b/tools/include/nolibc/arch-x86.h index d3efc0c3b8ad..c8b0c3e624a5 100644 --- a/tools/include/nolibc/arch-x86.h +++ b/tools/include/nolibc/arch-x86.h @@ -351,7 +351,7 @@ void *memcpy(void *dst, const void *src, size_t len); void *memset(void *dst, int c, size_t len); __asm__ ( -".section .text.nolibc_memmove_memcpy\n" +".pushsection .text.nolibc_memmove_memcpy\n" ".weak memmove\n" ".weak memcpy\n" "memmove:\n" @@ -371,8 +371,9 @@ __asm__ ( "rep movsb\n\t" "cld\n\t" "retq\n" +".popsection\n" -".section .text.nolibc_memset\n" +".pushsection .text.nolibc_memset\n" ".weak memset\n" "memset:\n" "xchgl %eax, %esi\n\t" @@ -381,6 +382,7 @@ __asm__ ( "rep stosb\n\t" "popq %rax\n\t" "retq\n" +".popsection\n" ); #endif /* !defined(__x86_64__) */ -- cgit From 089c0a9853ae6b297adf6e2f3b94e4f75dc1f97f Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Tue, 28 Oct 2025 09:13:18 +0100 Subject: tools/nolibc: remove outdated comment about __sysret() in mmap() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit fb01ff635efd ("tools/nolibc: keep brk(), sbrk(), mmap() away from __sysret()") the implementation of mmap() does not use the __sysret() macro anymore. Remove the outdated comment. Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/sys/mman.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/sys/mman.h b/tools/include/nolibc/sys/mman.h index 5228751b458c..77084ac3405a 100644 --- a/tools/include/nolibc/sys/mman.h +++ b/tools/include/nolibc/sys/mman.h @@ -31,11 +31,6 @@ void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd, } #endif -/* Note that on Linux, MAP_FAILED is -1 so we can use the generic __sysret() - * which returns -1 upon error and still satisfy user land that checks for - * MAP_FAILED. - */ - static __attribute__((unused)) void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { -- cgit From c485ca3aff2442adea4c08ceb5183e671ebed22a Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 24 Sep 2025 16:20:50 +0200 Subject: tools/nolibc/stdio: let perror work when NOLIBC_IGNORE_ERRNO is set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no errno variable when NOLIBC_IGNORE_ERRNO is defined. As such, simply print the message with "unknown error" rather than the integer value of errno. Fixes: acab7bcdb1bc ("tools/nolibc/stdio: add perror() to report the errno value") Signed-off-by: Benjamin Berg Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/stdio.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h index 7630234408c5..724d05ce6962 100644 --- a/tools/include/nolibc/stdio.h +++ b/tools/include/nolibc/stdio.h @@ -600,7 +600,11 @@ int sscanf(const char *str, const char *format, ...) static __attribute__((unused)) void perror(const char *msg) { +#ifdef NOLIBC_IGNORE_ERRNO + fprintf(stderr, "%s%sunknown error\n", (msg && *msg) ? msg : "", (msg && *msg) ? ": " : ""); +#else fprintf(stderr, "%s%serrno=%d\n", (msg && *msg) ? msg : "", (msg && *msg) ? ": " : "", errno); +#endif } static __attribute__((unused)) -- cgit From 4ada5679f18dbbe92d87c37a842c3368e6ab5e4a Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 24 Sep 2025 16:20:51 +0200 Subject: tools/nolibc/dirent: avoid errno in readdir_r MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using errno is not possible when NOLIBC_IGNORE_ERRNO is set. Use sys_lseek instead of lseek as that avoids using errno. Fixes: 665fa8dea90d ("tools/nolibc: add support for directory access") Signed-off-by: Benjamin Berg Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/dirent.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/dirent.h b/tools/include/nolibc/dirent.h index 758b95c48e7a..61a122a60327 100644 --- a/tools/include/nolibc/dirent.h +++ b/tools/include/nolibc/dirent.h @@ -86,9 +86,9 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) * readdir() can only return one entry at a time. * Make sure the non-returned ones are not skipped. */ - ret = lseek(fd, ldir->d_off, SEEK_SET); - if (ret == -1) - return errno; + ret = sys_lseek(fd, ldir->d_off, SEEK_SET); + if (ret < 0) + return -ret; entry->d_ino = ldir->d_ino; /* the destination should always be big enough */ -- cgit From fbd1b7f6b322a63b21ebbf00c732a17bb8bdb5d4 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 24 Sep 2025 16:20:52 +0200 Subject: tools/nolibc: implement %m if errno is not defined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For improved compatibility, print %m as "unknown error" when nolibc is compiled using NOLIBC_IGNORE_ERRNO. Signed-off-by: Benjamin Berg Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/stdio.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h index 724d05ce6962..1f16dab2ac88 100644 --- a/tools/include/nolibc/stdio.h +++ b/tools/include/nolibc/stdio.h @@ -321,11 +321,13 @@ int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char if (!outstr) outstr="(null)"; } -#ifndef NOLIBC_IGNORE_ERRNO else if (c == 'm') { +#ifdef NOLIBC_IGNORE_ERRNO + outstr = "unknown error"; +#else outstr = strerror(errno); - } #endif /* NOLIBC_IGNORE_ERRNO */ + } else if (c == '%') { /* queue it verbatim */ continue; -- cgit From 2cb6cc8361da803ede847ed1ca8afeb3af6df6ff Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 24 Sep 2025 16:20:53 +0200 Subject: tools/nolibc: use __fallthrough__ rather than fallthrough MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the version of the attribute with underscores to avoid issues if fallthrough has been defined by another header file already. Signed-off-by: Benjamin Berg Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/compiler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/compiler.h b/tools/include/nolibc/compiler.h index 369cfb5a0e78..87090bbc53e0 100644 --- a/tools/include/nolibc/compiler.h +++ b/tools/include/nolibc/compiler.h @@ -41,8 +41,8 @@ # define __no_stack_protector __attribute__((__optimize__("-fno-stack-protector"))) #endif /* __nolibc_has_attribute(no_stack_protector) */ -#if __nolibc_has_attribute(fallthrough) -# define __nolibc_fallthrough do { } while (0); __attribute__((fallthrough)) +#if __nolibc_has_attribute(__fallthrough__) +# define __nolibc_fallthrough do { } while (0); __attribute__((__fallthrough__)) #else # define __nolibc_fallthrough do { } while (0) #endif /* __nolibc_has_attribute(fallthrough) */ -- cgit From 3d66c4e14fbf4d59ca4665391d133655fa668042 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 24 Sep 2025 16:20:54 +0200 Subject: tools/nolibc: add option to disable runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In principle, it is possible to use nolibc for only some object files in a program. In that case, the startup code in _start and _start_c is not going to be used. Add the NOLIBC_NO_RUNTIME compile time option to disable it entirely and also remove anything that depends on it. Doing this avoids warnings from modpost for UML as the _start_c code references the main function from the .init.text section while it is not inside .init itself. Signed-off-by: Benjamin Berg Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/arch-arm.h | 2 ++ tools/include/nolibc/arch-arm64.h | 2 ++ tools/include/nolibc/arch-loongarch.h | 2 ++ tools/include/nolibc/arch-m68k.h | 2 ++ tools/include/nolibc/arch-mips.h | 2 ++ tools/include/nolibc/arch-powerpc.h | 2 ++ tools/include/nolibc/arch-riscv.h | 2 ++ tools/include/nolibc/arch-s390.h | 2 ++ tools/include/nolibc/arch-sh.h | 2 ++ tools/include/nolibc/arch-sparc.h | 2 ++ tools/include/nolibc/arch-x86.h | 4 ++++ tools/include/nolibc/crt.h | 3 +++ tools/include/nolibc/stackprotector.h | 2 ++ tools/include/nolibc/stdlib.h | 2 ++ tools/include/nolibc/sys.h | 3 ++- tools/include/nolibc/sys/auxv.h | 3 +++ 16 files changed, 36 insertions(+), 1 deletion(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/arch-arm.h b/tools/include/nolibc/arch-arm.h index 1f66e7e5a444..251c42579028 100644 --- a/tools/include/nolibc/arch-arm.h +++ b/tools/include/nolibc/arch-arm.h @@ -184,6 +184,7 @@ _arg1; \ }) +#ifndef NOLIBC_NO_RUNTIME /* startup code */ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { @@ -193,5 +194,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_RUNTIME */ #endif /* _NOLIBC_ARCH_ARM_H */ diff --git a/tools/include/nolibc/arch-arm64.h b/tools/include/nolibc/arch-arm64.h index 02a3f74c8ec8..080a55a7144e 100644 --- a/tools/include/nolibc/arch-arm64.h +++ b/tools/include/nolibc/arch-arm64.h @@ -141,6 +141,7 @@ _arg1; \ }) +#ifndef NOLIBC_NO_RUNTIME /* startup code */ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { @@ -150,4 +151,5 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_RUNTIME */ #endif /* _NOLIBC_ARCH_ARM64_H */ diff --git a/tools/include/nolibc/arch-loongarch.h b/tools/include/nolibc/arch-loongarch.h index 5511705303ea..c894176c3f89 100644 --- a/tools/include/nolibc/arch-loongarch.h +++ b/tools/include/nolibc/arch-loongarch.h @@ -142,6 +142,7 @@ _arg1; \ }) +#ifndef NOLIBC_NO_RUNTIME /* startup code */ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { @@ -151,5 +152,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_RUNTIME */ #endif /* _NOLIBC_ARCH_LOONGARCH_H */ diff --git a/tools/include/nolibc/arch-m68k.h b/tools/include/nolibc/arch-m68k.h index 6dac1845f298..2a4fbada5e79 100644 --- a/tools/include/nolibc/arch-m68k.h +++ b/tools/include/nolibc/arch-m68k.h @@ -128,6 +128,7 @@ _num; \ }) +#ifndef NOLIBC_NO_RUNTIME void _start(void); void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { @@ -137,5 +138,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_RUNTIME */ #endif /* _NOLIBC_ARCH_M68K_H */ diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h index 0cbac63b249a..a72506ceec6b 100644 --- a/tools/include/nolibc/arch-mips.h +++ b/tools/include/nolibc/arch-mips.h @@ -245,6 +245,7 @@ #endif /* _ABIO32 */ +#ifndef NOLIBC_NO_RUNTIME /* startup code, note that it's called __start on MIPS */ void __start(void); void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector __start(void) @@ -266,5 +267,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector __ ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_RUNTIME */ #endif /* _NOLIBC_ARCH_MIPS_H */ diff --git a/tools/include/nolibc/arch-powerpc.h b/tools/include/nolibc/arch-powerpc.h index 204564bbcd32..e0c7e0b81f7c 100644 --- a/tools/include/nolibc/arch-powerpc.h +++ b/tools/include/nolibc/arch-powerpc.h @@ -183,6 +183,7 @@ #endif #endif /* !__powerpc64__ */ +#ifndef NOLIBC_NO_RUNTIME /* startup code */ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { @@ -215,5 +216,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s #endif __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_RUNTIME */ #endif /* _NOLIBC_ARCH_POWERPC_H */ diff --git a/tools/include/nolibc/arch-riscv.h b/tools/include/nolibc/arch-riscv.h index 885383a86c38..1c00cacf57e1 100644 --- a/tools/include/nolibc/arch-riscv.h +++ b/tools/include/nolibc/arch-riscv.h @@ -139,6 +139,7 @@ _arg1; \ }) +#ifndef NOLIBC_NO_RUNTIME /* startup code */ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { @@ -152,5 +153,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_RUNTIME */ #endif /* _NOLIBC_ARCH_RISCV_H */ diff --git a/tools/include/nolibc/arch-s390.h b/tools/include/nolibc/arch-s390.h index df4c3cc713ac..6237211385c0 100644 --- a/tools/include/nolibc/arch-s390.h +++ b/tools/include/nolibc/arch-s390.h @@ -139,6 +139,7 @@ _arg1; \ }) +#ifndef NOLIBC_NO_RUNTIME /* startup code */ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { @@ -155,6 +156,7 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_RUNTIME */ struct s390_mmap_arg_struct { unsigned long addr; diff --git a/tools/include/nolibc/arch-sh.h b/tools/include/nolibc/arch-sh.h index a96b8914607e..7a421197d104 100644 --- a/tools/include/nolibc/arch-sh.h +++ b/tools/include/nolibc/arch-sh.h @@ -140,6 +140,7 @@ _ret; \ }) +#ifndef NOLIBC_NO_RUNTIME /* startup code */ void _start_wrapper(void); void __attribute__((weak,noreturn)) __nolibc_entrypoint __no_stack_protector _start_wrapper(void) @@ -158,5 +159,6 @@ void __attribute__((weak,noreturn)) __nolibc_entrypoint __no_stack_protector _st ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_RUNTIME */ #endif /* _NOLIBC_ARCH_SH_H */ diff --git a/tools/include/nolibc/arch-sparc.h b/tools/include/nolibc/arch-sparc.h index ca420d843e25..2ebb5686e105 100644 --- a/tools/include/nolibc/arch-sparc.h +++ b/tools/include/nolibc/arch-sparc.h @@ -152,6 +152,7 @@ _arg1; \ }) +#ifndef NOLIBC_NO_RUNTIME /* startup code */ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { @@ -169,6 +170,7 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_RUNTIME */ static pid_t getpid(void); diff --git a/tools/include/nolibc/arch-x86.h b/tools/include/nolibc/arch-x86.h index c8b0c3e624a5..f6c43ac5377b 100644 --- a/tools/include/nolibc/arch-x86.h +++ b/tools/include/nolibc/arch-x86.h @@ -157,6 +157,7 @@ _eax; \ }) +#ifndef NOLIBC_NO_RUNTIME /* startup code */ /* * i386 System V ABI mandates: @@ -176,6 +177,7 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_RUNTIME */ #else /* !defined(__x86_64__) */ @@ -323,6 +325,7 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s _ret; \ }) +#ifndef NOLIBC_NO_RUNTIME /* startup code */ /* * x86-64 System V ABI mandates: @@ -340,6 +343,7 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_RUNTIME */ #define NOLIBC_ARCH_HAS_MEMMOVE void *memmove(void *dst, const void *src, size_t len); diff --git a/tools/include/nolibc/crt.h b/tools/include/nolibc/crt.h index 961cfe777c35..d9262998dae9 100644 --- a/tools/include/nolibc/crt.h +++ b/tools/include/nolibc/crt.h @@ -7,6 +7,8 @@ #ifndef _NOLIBC_CRT_H #define _NOLIBC_CRT_H +#ifndef NOLIBC_NO_RUNTIME + #include "compiler.h" char **environ __attribute__((weak)); @@ -88,4 +90,5 @@ void _start_c(long *sp) exit(exitcode); } +#endif /* NOLIBC_NO_RUNTIME */ #endif /* _NOLIBC_CRT_H */ diff --git a/tools/include/nolibc/stackprotector.h b/tools/include/nolibc/stackprotector.h index c71a2c257177..7123aa056cb0 100644 --- a/tools/include/nolibc/stackprotector.h +++ b/tools/include/nolibc/stackprotector.h @@ -9,6 +9,7 @@ #include "compiler.h" +#ifndef NOLIBC_NO_RUNTIME #if defined(_NOLIBC_STACKPROTECTOR) #include "sys.h" @@ -49,5 +50,6 @@ static __no_stack_protector void __stack_chk_init(void) #else /* !defined(_NOLIBC_STACKPROTECTOR) */ static void __stack_chk_init(void) {} #endif /* defined(_NOLIBC_STACKPROTECTOR) */ +#endif /* NOLIBC_NO_RUNTIME */ #endif /* _NOLIBC_STACKPROTECTOR_H */ diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index 5fd99a480f82..f184e108ed0a 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -100,6 +100,7 @@ void free(void *ptr) munmap(heap, heap->len); } +#ifndef NOLIBC_NO_RUNTIME /* getenv() tries to find the environment variable named in the * environment array pointed to by global variable "environ" which must be * declared as a char **, and must be terminated by a NULL (it is recommended @@ -122,6 +123,7 @@ char *getenv(const char *name) } return NULL; } +#endif /* NOLIBC_NO_RUNTIME */ static __attribute__((unused)) void *malloc(size_t len) diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index c5564f57deec..386ed80aead0 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -512,6 +512,7 @@ pid_t gettid(void) return sys_gettid(); } +#ifndef NOLIBC_NO_RUNTIME static unsigned long getauxval(unsigned long key); /* @@ -523,7 +524,7 @@ int getpagesize(void) { return __sysret((int)getauxval(AT_PAGESZ) ?: -ENOENT); } - +#endif /* NOLIBC_NO_RUNTIME */ /* * uid_t getuid(void); diff --git a/tools/include/nolibc/sys/auxv.h b/tools/include/nolibc/sys/auxv.h index c52463d6c18d..0e98325e7347 100644 --- a/tools/include/nolibc/sys/auxv.h +++ b/tools/include/nolibc/sys/auxv.h @@ -10,6 +10,8 @@ #ifndef _NOLIBC_SYS_AUXV_H #define _NOLIBC_SYS_AUXV_H +#ifndef NOLIBC_NO_RUNTIME + #include "../crt.h" static __attribute__((unused)) @@ -38,4 +40,5 @@ unsigned long getauxval(unsigned long type) return ret; } +#endif /* NOLIBC_NO_RUNTIME */ #endif /* _NOLIBC_SYS_AUXV_H */ -- cgit From 4bb30188c787176f934aab71872f7c5f43ae6d6f Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 24 Sep 2025 16:20:57 +0200 Subject: tools/nolibc: add uio.h with readv and writev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is generally useful and struct iovec is also needed for other purposes such as ptrace. Signed-off-by: Benjamin Berg Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/Makefile | 1 + tools/include/nolibc/nolibc.h | 1 + tools/include/nolibc/sys/uio.h | 49 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 tools/include/nolibc/sys/uio.h (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/Makefile b/tools/include/nolibc/Makefile index 143c2d2c2ba6..9bbbba32dac6 100644 --- a/tools/include/nolibc/Makefile +++ b/tools/include/nolibc/Makefile @@ -62,6 +62,7 @@ all_files := \ sys/time.h \ sys/timerfd.h \ sys/types.h \ + sys/uio.h \ sys/utsname.h \ sys/wait.h \ time.h \ diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index d2f5aa085f8e..05e2d655c43e 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -109,6 +109,7 @@ #include "sys/sysmacros.h" #include "sys/time.h" #include "sys/timerfd.h" +#include "sys/uio.h" #include "sys/utsname.h" #include "sys/wait.h" #include "ctype.h" diff --git a/tools/include/nolibc/sys/uio.h b/tools/include/nolibc/sys/uio.h new file mode 100644 index 000000000000..7ad42b927d2f --- /dev/null +++ b/tools/include/nolibc/sys/uio.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * uio for NOLIBC + * Copyright (C) 2017-2021 Willy Tarreau + * Copyright (C) 2025 Intel Corporation + */ + +/* make sure to include all global symbols */ +#include "../nolibc.h" + +#ifndef _NOLIBC_SYS_UIO_H +#define _NOLIBC_SYS_UIO_H + +#include "../sys.h" +#include + + +/* + * ssize_t readv(int fd, const struct iovec *iovec, int count); + */ +static __attribute__((unused)) +ssize_t sys_readv(int fd, const struct iovec *iovec, int count) +{ + return my_syscall3(__NR_readv, fd, iovec, count); +} + +static __attribute__((unused)) +ssize_t readv(int fd, const struct iovec *iovec, int count) +{ + return __sysret(sys_readv(fd, iovec, count)); +} + +/* + * ssize_t writev(int fd, const struct iovec *iovec, int count); + */ +static __attribute__((unused)) +ssize_t sys_writev(int fd, const struct iovec *iovec, int count) +{ + return my_syscall3(__NR_writev, fd, iovec, count); +} + +static __attribute__((unused)) +ssize_t writev(int fd, const struct iovec *iovec, int count) +{ + return __sysret(sys_writev(fd, iovec, count)); +} + + +#endif /* _NOLIBC_SYS_UIO_H */ -- cgit From 09c873c91fc10eeff5f7aecb408e1ac06ffbf83b Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 2 Nov 2025 11:46:08 +0100 Subject: tools/nolibc: fix misleading help message regarding installation path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The help message says the headers are going to be installed into tools/include/nolibc but this is only the default if $OUTPUT is not set, so better clarify this (the current value of $OUTPUT is already shown). Signed-off-by: Willy Tarreau Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/Makefile b/tools/include/nolibc/Makefile index 9bbbba32dac6..615ffc4d6daa 100644 --- a/tools/include/nolibc/Makefile +++ b/tools/include/nolibc/Makefile @@ -80,7 +80,7 @@ help: @echo "Supported targets under nolibc:" @echo " all call \"headers\"" @echo " clean clean the sysroot" - @echo " headers prepare a sysroot in tools/include/nolibc/sysroot" + @echo " headers prepare a sysroot in \$${OUTPUT}sysroot" @echo " headers_standalone like \"headers\", and also install kernel headers" @echo " help this help" @echo "" -- cgit From db75042e93cfb0bb1ecd55771cc873917074f565 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 2 Nov 2025 11:46:10 +0100 Subject: tools/nolibc: add missing memchr() to string.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Surprisingly we forgot to add this common one. It was added with a per-arch guard allowing to later implement it in arch-specific asm code like was done for a few other ones. The test verifies that we don't search past the indicated length. Signed-off-by: Willy Tarreau Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/string.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/string.h b/tools/include/nolibc/string.h index 163a17e7dd38..4000926f44ac 100644 --- a/tools/include/nolibc/string.h +++ b/tools/include/nolibc/string.h @@ -93,6 +93,21 @@ void *memset(void *dst, int b, size_t len) } #endif /* #ifndef NOLIBC_ARCH_HAS_MEMSET */ +#ifndef NOLIBC_ARCH_HAS_MEMCHR +static __attribute__((unused)) +void *memchr(const void *s, int c, size_t len) +{ + char *p = (char *)s; + + while (len--) { + if (*p == (char)c) + return p; + p++; + } + return NULL; +} +#endif /* #ifndef NOLIBC_ARCH_HAS_MEMCHR */ + static __attribute__((unused)) char *strchr(const char *s, int c) { -- cgit From 10f407c66061524f0da0384de76827e30268f98a Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 2 Nov 2025 11:46:11 +0100 Subject: tools/nolibc: provide the portable sys/select.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modern programs tend to include sys/select.h to get FD_SET() and FD_CLR() definitions as well as struct fd_set, but in our case it didn't exist. The definitions were moved from types.h to sys/select.h, which is now included from nolibc.h, and the sys_select() definition moved there as well from sys.h. Signed-off-by: Willy Tarreau [Thomas: adapt to current -next branch] Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/Makefile | 1 + tools/include/nolibc/nolibc.h | 1 + tools/include/nolibc/sys.h | 45 ----------------- tools/include/nolibc/sys/select.h | 103 ++++++++++++++++++++++++++++++++++++++ tools/include/nolibc/types.h | 47 ----------------- 5 files changed, 105 insertions(+), 92 deletions(-) create mode 100644 tools/include/nolibc/sys/select.h (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/Makefile b/tools/include/nolibc/Makefile index 615ffc4d6daa..5a07e1d37adf 100644 --- a/tools/include/nolibc/Makefile +++ b/tools/include/nolibc/Makefile @@ -56,6 +56,7 @@ all_files := \ sys/random.h \ sys/reboot.h \ sys/resource.h \ + sys/select.h \ sys/stat.h \ sys/syscall.h \ sys/sysmacros.h \ diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index 05e2d655c43e..272dfc961158 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -104,6 +104,7 @@ #include "sys/random.h" #include "sys/reboot.h" #include "sys/resource.h" +#include "sys/select.h" #include "sys/stat.h" #include "sys/syscall.h" #include "sys/sysmacros.h" diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index 386ed80aead0..d0ba30ba029c 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -756,51 +756,6 @@ int sched_yield(void) } -/* - * 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 = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout }; - return my_syscall1(__NR_select, &arg); -#elif defined(__NR__newselect) - return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); -#elif defined(__NR_select) - return my_syscall5(__NR_select, nfds, rfds, wfds, efds, timeout); -#elif defined(__NR_pselect6) - struct timespec t; - - if (timeout) { - t.tv_sec = timeout->tv_sec; - t.tv_nsec = timeout->tv_usec * 1000; - } - return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); -#else - struct __kernel_timespec t; - - if (timeout) { - t.tv_sec = timeout->tv_sec; - t.tv_nsec = timeout->tv_usec * 1000; - } - return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); -#endif -} - -static __attribute__((unused)) -int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) -{ - return __sysret(sys_select(nfds, rfds, wfds, efds, timeout)); -} - - /* * int setpgid(pid_t pid, pid_t pgid); */ diff --git a/tools/include/nolibc/sys/select.h b/tools/include/nolibc/sys/select.h new file mode 100644 index 000000000000..2a5619c01277 --- /dev/null +++ b/tools/include/nolibc/sys/select.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ + +#include "../nolibc.h" + +#ifndef _NOLIBC_SYS_SELECT_H +#define _NOLIBC_SYS_SELECT_H + +#include +#include + +/* commonly an fd_set represents 256 FDs */ +#ifndef FD_SETSIZE +#define FD_SETSIZE 256 +#endif + +#define FD_SETIDXMASK (8 * sizeof(unsigned long)) +#define FD_SETBITMASK (8 * sizeof(unsigned long)-1) + +/* for select() */ +typedef struct { + unsigned long fds[(FD_SETSIZE + FD_SETBITMASK) / FD_SETIDXMASK]; +} fd_set; + +#define FD_CLR(fd, set) do { \ + fd_set *__set = (set); \ + int __fd = (fd); \ + if (__fd >= 0) \ + __set->fds[__fd / FD_SETIDXMASK] &= \ + ~(1U << (__fd & FD_SETBITMASK)); \ + } while (0) + +#define FD_SET(fd, set) do { \ + fd_set *__set = (set); \ + int __fd = (fd); \ + if (__fd >= 0) \ + __set->fds[__fd / FD_SETIDXMASK] |= \ + 1 << (__fd & FD_SETBITMASK); \ + } while (0) + +#define FD_ISSET(fd, set) ({ \ + fd_set *__set = (set); \ + int __fd = (fd); \ + int __r = 0; \ + if (__fd >= 0) \ + __r = !!(__set->fds[__fd / FD_SETIDXMASK] & \ +1U << (__fd & FD_SETBITMASK)); \ + __r; \ + }) + +#define FD_ZERO(set) do { \ + fd_set *__set = (set); \ + int __idx; \ + int __size = (FD_SETSIZE+FD_SETBITMASK) / FD_SETIDXMASK;\ + for (__idx = 0; __idx < __size; __idx++) \ + __set->fds[__idx] = 0; \ + } while (0) + +/* + * 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 = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout }; + return my_syscall1(__NR_select, &arg); +#elif defined(__NR__newselect) + return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); +#elif defined(__NR_select) + return my_syscall5(__NR_select, nfds, rfds, wfds, efds, timeout); +#elif defined(__NR_pselect6) + struct timespec t; + + if (timeout) { + t.tv_sec = timeout->tv_sec; + t.tv_nsec = timeout->tv_usec * 1000; + } + return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); +#else + struct __kernel_timespec t; + + if (timeout) { + t.tv_sec = timeout->tv_sec; + t.tv_nsec = timeout->tv_usec * 1000; + } + return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); +#endif +} + +static __attribute__((unused)) +int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) +{ + return __sysret(sys_select(nfds, rfds, wfds, efds, timeout)); +} + + +#endif /* _NOLIBC_SYS_SELECT_H */ diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h index 16c6e9ec9451..470a5f77bc0f 100644 --- a/tools/include/nolibc/types.h +++ b/tools/include/nolibc/types.h @@ -70,11 +70,6 @@ #define DT_LNK 0xa #define DT_SOCK 0xc -/* commonly an fd_set represents 256 FDs */ -#ifndef FD_SETSIZE -#define FD_SETSIZE 256 -#endif - /* PATH_MAX and MAXPATHLEN are often used and found with plenty of different * values. */ @@ -115,48 +110,6 @@ #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 -#define FD_SETIDXMASK (8 * sizeof(unsigned long)) -#define FD_SETBITMASK (8 * sizeof(unsigned long)-1) - -/* for select() */ -typedef struct { - unsigned long fds[(FD_SETSIZE + FD_SETBITMASK) / FD_SETIDXMASK]; -} fd_set; - -#define FD_CLR(fd, set) do { \ - fd_set *__set = (set); \ - int __fd = (fd); \ - if (__fd >= 0) \ - __set->fds[__fd / FD_SETIDXMASK] &= \ - ~(1U << (__fd & FD_SETBITMASK)); \ - } while (0) - -#define FD_SET(fd, set) do { \ - fd_set *__set = (set); \ - int __fd = (fd); \ - if (__fd >= 0) \ - __set->fds[__fd / FD_SETIDXMASK] |= \ - 1 << (__fd & FD_SETBITMASK); \ - } while (0) - -#define FD_ISSET(fd, set) ({ \ - fd_set *__set = (set); \ - int __fd = (fd); \ - int __r = 0; \ - if (__fd >= 0) \ - __r = !!(__set->fds[__fd / FD_SETIDXMASK] & \ -1U << (__fd & FD_SETBITMASK)); \ - __r; \ - }) - -#define FD_ZERO(set) do { \ - fd_set *__set = (set); \ - int __idx; \ - int __size = (FD_SETSIZE+FD_SETBITMASK) / FD_SETIDXMASK;\ - for (__idx = 0; __idx < __size; __idx++) \ - __set->fds[__idx] = 0; \ - } while (0) - /* for getdents64() */ struct linux_dirent64 { uint64_t d_ino; -- cgit From 44bf8bbe29fd50ed2b8dfd1873bd22f76ca2f4d9 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 2 Nov 2025 14:21:28 +0100 Subject: tools/nolibc: add the more portable inttypes.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's often recommended to only use inttypes.h instead of stdint.h for portability reasons since the former is always present when the latter is present, but not conversely, and the former includes the latter. Due to this some simple programs fail to build when including inttypes.h. Let's add one that simply includes nolibc.h to better support these programs. Signed-off-by: Willy Tarreau Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/Makefile | 1 + tools/include/nolibc/inttypes.h | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 tools/include/nolibc/inttypes.h (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/Makefile b/tools/include/nolibc/Makefile index 5a07e1d37adf..6e31187c89aa 100644 --- a/tools/include/nolibc/Makefile +++ b/tools/include/nolibc/Makefile @@ -33,6 +33,7 @@ all_files := \ errno.h \ fcntl.h \ getopt.h \ + inttypes.h \ limits.h \ math.h \ nolibc.h \ diff --git a/tools/include/nolibc/inttypes.h b/tools/include/nolibc/inttypes.h new file mode 100644 index 000000000000..1977bd74bfeb --- /dev/null +++ b/tools/include/nolibc/inttypes.h @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ + +#include "nolibc.h" -- cgit From 1868c027b6527abfa9ab8172a905acc5809849ee Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 2 Nov 2025 15:10:45 +0100 Subject: tools/nolibc: make the "headers" target install all supported archs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The efforts we go through by installing a single arch are counter productive when the base directory already supports them all, and the arch-specific files are really small. Let's make the "headers" target simply install headers for all supported archs and stop trying to build a hybrid "arch.h" file on the fly, to instead keep the generic one. Now the same nolibc headers installation will be usable with any arch-specific uapi installation. Signed-off-by: Willy Tarreau Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/Makefile | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/Makefile b/tools/include/nolibc/Makefile index 6e31187c89aa..8118e22844f1 100644 --- a/tools/include/nolibc/Makefile +++ b/tools/include/nolibc/Makefile @@ -23,7 +23,7 @@ else Q=@ endif -arch_file := arch-$(ARCH).h +arch_files := arch.h $(wildcard arch-*.h) all_files := \ compiler.h \ crt.h \ @@ -82,7 +82,7 @@ help: @echo "Supported targets under nolibc:" @echo " all call \"headers\"" @echo " clean clean the sysroot" - @echo " headers prepare a sysroot in \$${OUTPUT}sysroot" + @echo " headers prepare a multi-arch sysroot in \$${OUTPUT}sysroot" @echo " headers_standalone like \"headers\", and also install kernel headers" @echo " help this help" @echo "" @@ -93,18 +93,11 @@ help: @echo " OUTPUT = $(OUTPUT)" @echo "" +# installs headers for all archs at once. headers: - $(Q)mkdir -p $(OUTPUT)sysroot - $(Q)mkdir -p $(OUTPUT)sysroot/include - $(Q)cp --parents $(all_files) $(OUTPUT)sysroot/include/ - $(Q)if [ "$(ARCH)" = "i386" -o "$(ARCH)" = "x86_64" ]; then \ - cat arch-x86.h; \ - elif [ -e "$(arch_file)" ]; then \ - cat $(arch_file); \ - else \ - echo "Fatal: architecture $(ARCH) not yet supported by nolibc." >&2; \ - exit 1; \ - fi > $(OUTPUT)sysroot/include/arch.h + $(Q)mkdir -p "$(OUTPUT)sysroot" + $(Q)mkdir -p "$(OUTPUT)sysroot/include" + $(Q)cp --parents $(arch_files) $(all_files) "$(OUTPUT)sysroot/include/" headers_standalone: headers $(Q)$(MAKE) -C $(srctree) headers -- cgit From 7534b9bfe691836eb7ab66332505629a4bfa4eed Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 2 Nov 2025 15:25:48 +0100 Subject: tools/nolibc: clean up outdated comments in generic arch.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Along the code reorganizations, the file has been keeping the original comments about argv and envp which are no longer relevant to this file anymore. Let's just drop them. Acked-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/include/nolibc/arch.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/arch.h b/tools/include/nolibc/arch.h index 426c89198135..0871c439be7d 100644 --- a/tools/include/nolibc/arch.h +++ b/tools/include/nolibc/arch.h @@ -3,15 +3,6 @@ * Copyright (C) 2017-2022 Willy Tarreau */ -/* Below comes the architecture-specific code. For each architecture, we have - * the syscall declarations and the _start code definition. This is the only - * global part. On all architectures the kernel puts everything in the stack - * before jumping to _start just above us, without any return address (_start - * is not a function but an entry point). So at the stack pointer we find argc. - * Then argv[] begins, and ends at the first NULL. Then we have envp which - * starts and ends with a NULL as well. So envp=argv+argc+1. - */ - #ifndef _NOLIBC_ARCH_H #define _NOLIBC_ARCH_H -- cgit From 107eb8336e8782ae8e98b60962852a1e29aca715 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Fri, 7 Nov 2025 15:13:38 +0100 Subject: tools/nolibc: add support for fchdir() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for the file descriptor based variant of chdir(). Signed-off-by: Thomas Weißschuh Acked-by: Willy Tarreau Signed-off-by: Thomas Weißschuh --- tools/include/nolibc/sys.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index d0ba30ba029c..28481feedb37 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -118,6 +118,7 @@ void *sbrk(intptr_t inc) /* * int chdir(const char *path); + * int fchdir(int fildes); */ static __attribute__((unused)) @@ -132,6 +133,18 @@ int chdir(const char *path) return __sysret(sys_chdir(path)); } +static __attribute__((unused)) +int sys_fchdir(int fildes) +{ + return my_syscall1(__NR_fchdir, fildes); +} + +static __attribute__((unused)) +int fchdir(int fildes) +{ + return __sysret(sys_fchdir(fildes)); +} + /* * int chmod(const char *path, mode_t mode); -- cgit From 2d8482959efee5721456d199106b9c256c11b11b Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Sun, 9 Nov 2025 20:27:29 +0100 Subject: tools/nolibc: avoid using plain integer as NULL pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While an integer zero is a valid NULL pointer as per the C standard, sparse will complain about it. Use explicit NULL pointers instead. Reported-by: kernel test robot Closes: https://lore.kernel.org/r/202509261452.g5peaXCc-lkp@intel.com/ Signed-off-by: Thomas Weißschuh Acked-by: Willy Tarreau --- tools/include/nolibc/getopt.h | 2 +- tools/include/nolibc/sys.h | 2 +- tools/include/nolibc/sys/reboot.h | 2 +- tools/include/nolibc/unistd.h | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/getopt.h b/tools/include/nolibc/getopt.h index 217abb95264b..87565e3b6a33 100644 --- a/tools/include/nolibc/getopt.h +++ b/tools/include/nolibc/getopt.h @@ -78,7 +78,7 @@ int getopt(int argc, char * const argv[], const char *optstring) return '?'; } if (optstring[i] == ':') { - optarg = 0; + optarg = NULL; if (optstring[i + 1] != ':' || __optpos) { optarg = argv[optind++]; if (__optpos) diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index 28481feedb37..fcc36cffad4d 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -106,7 +106,7 @@ static __attribute__((unused)) void *sbrk(intptr_t inc) { /* first call to find current end */ - void *ret = sys_brk(0); + void *ret = sys_brk(NULL); if (ret && sys_brk(ret + inc) == ret + inc) return ret + inc; diff --git a/tools/include/nolibc/sys/reboot.h b/tools/include/nolibc/sys/reboot.h index 4a1e435be669..38274c64a722 100644 --- a/tools/include/nolibc/sys/reboot.h +++ b/tools/include/nolibc/sys/reboot.h @@ -28,7 +28,7 @@ ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg) static __attribute__((unused)) int reboot(int cmd) { - return __sysret(sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0)); + return __sysret(sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, NULL)); } #endif /* _NOLIBC_SYS_REBOOT_H */ diff --git a/tools/include/nolibc/unistd.h b/tools/include/nolibc/unistd.h index 7405fa2b89ba..bb5e80f3f05d 100644 --- a/tools/include/nolibc/unistd.h +++ b/tools/include/nolibc/unistd.h @@ -54,7 +54,7 @@ int msleep(unsigned int msecs) { struct timeval my_timeval = { msecs / 1000, (msecs % 1000) * 1000 }; - if (sys_select(0, 0, 0, 0, &my_timeval) < 0) + if (sys_select(0, NULL, NULL, NULL, &my_timeval) < 0) return (my_timeval.tv_sec * 1000) + (my_timeval.tv_usec / 1000) + !!(my_timeval.tv_usec % 1000); @@ -67,7 +67,7 @@ unsigned int sleep(unsigned int seconds) { struct timeval my_timeval = { seconds, 0 }; - if (sys_select(0, 0, 0, 0, &my_timeval) < 0) + if (sys_select(0, NULL, NULL, NULL, &my_timeval) < 0) return my_timeval.tv_sec + !!my_timeval.tv_usec; else return 0; @@ -78,7 +78,7 @@ int usleep(unsigned int usecs) { struct timeval my_timeval = { usecs / 1000000, usecs % 1000000 }; - return sys_select(0, 0, 0, 0, &my_timeval); + return sys_select(0, NULL, NULL, NULL, &my_timeval); } static __attribute__((unused)) -- cgit From 87506e44cb85cc1c2bf70b3d496b674178f219bd Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Wed, 29 Oct 2025 17:02:51 +0100 Subject: tools/nolibc: use 64-bit ino_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kernel uses 64-bit values for inode numbers. Currently these might be truncated to 32-bit when assigned to nolibc's ino_t values. Switch to 64-bit ino_t consistently. As ino_t is never used directly in kernel ABIs, no systemcall wrappers need to be adapted. Suggested-by: Arnd Bergmann Link: https://lore.kernel.org/lkml/cec27d94-c99d-4c57-9a12-275ea663dda8@app.fastmail.com/ Signed-off-by: Thomas Weißschuh Acked-by: Willy Tarreau --- tools/include/nolibc/std.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/std.h b/tools/include/nolibc/std.h index 2c1ad23b9b5c..eae457d60858 100644 --- a/tools/include/nolibc/std.h +++ b/tools/include/nolibc/std.h @@ -20,7 +20,7 @@ /* those are commonly provided by sys/types.h */ typedef unsigned int dev_t; -typedef unsigned long ino_t; +typedef uint64_t ino_t; typedef unsigned int mode_t; typedef signed int pid_t; typedef unsigned int uid_t; -- cgit From d93d0593dd65b8cd72d6dc9bda7fc4982fd65afb Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Wed, 29 Oct 2025 17:02:52 +0100 Subject: tools/nolibc: handle 64-bit off_t for llseek MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correctly handle 64-bit off_t values in preparation for 64-bit off_t on 32-bit architectures. Signed-off-by: Thomas Weißschuh Acked-by: Arnd Bergmann Acked-by: Willy Tarreau --- tools/include/nolibc/sys.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index fcc36cffad4d..2b186d1af52e 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -612,8 +612,7 @@ off_t sys_lseek(int fd, off_t offset, int whence) off_t result; int ret; - /* Only exists on 32bit where nolibc off_t is also 32bit */ - ret = my_syscall5(__NR_llseek, fd, 0, offset, &loff, whence); + ret = my_syscall5(__NR_llseek, fd, offset >> 32, (uint32_t)offset, &loff, whence); if (ret < 0) result = ret; else if (loff != (off_t)loff) -- cgit From 19c5a681b2262fe30c027aefb3df637f69df140f Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Wed, 29 Oct 2025 17:02:53 +0100 Subject: tools/nolibc: prefer the llseek syscall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure to always use the 64-bit safe system call in preparation for 64-bit off_t on 32 bit architectures. Signed-off-by: Thomas Weißschuh Acked-by: Willy Tarreau --- tools/include/nolibc/sys.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index 2b186d1af52e..32815c299365 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -605,9 +605,7 @@ int link(const char *old, const char *new) static __attribute__((unused)) off_t sys_lseek(int fd, off_t offset, int whence) { -#if defined(__NR_lseek) - return my_syscall3(__NR_lseek, fd, offset, whence); -#else +#if defined(__NR_llseek) __kernel_loff_t loff = 0; off_t result; int ret; @@ -621,6 +619,8 @@ off_t sys_lseek(int fd, off_t offset, int whence) result = loff; return result; +#else + return my_syscall3(__NR_lseek, fd, offset, whence); #endif } -- cgit From e800e9446867c78eeccb790de68375d4fe77ab65 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Wed, 29 Oct 2025 17:02:54 +0100 Subject: tools/nolibc: use 64-bit off_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kernel uses 64-bit values for file offsets. Currently these might be truncated to 32-bit when assigned to nolibc's off_t values. Switch to 64-bit off_t consistently. Suggested-by: Arnd Bergmann Link: https://lore.kernel.org/lkml/cec27d94-c99d-4c57-9a12-275ea663dda8@app.fastmail.com/ Signed-off-by: Thomas Weißschuh Acked-by: Willy Tarreau --- tools/include/nolibc/std.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/std.h b/tools/include/nolibc/std.h index eae457d60858..392f4dd94158 100644 --- a/tools/include/nolibc/std.h +++ b/tools/include/nolibc/std.h @@ -26,7 +26,7 @@ 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 int64_t off_t; typedef signed long blksize_t; typedef signed long blkcnt_t; typedef __kernel_time_t time_t; -- cgit From 3e1da545db4c26c39955bd2eee2d71b62d1ba045 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Wed, 29 Oct 2025 17:02:55 +0100 Subject: tools/nolibc: remove now superfluous overflow check in llseek MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As off_t is now always 64-bit wide this overflow can not happen anymore, remove the check. Signed-off-by: Thomas Weißschuh Acked-by: Willy Tarreau Reviewed-by: Arnd Bergmann --- tools/include/nolibc/sys.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index 32815c299365..847af1ccbdc9 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -613,8 +613,6 @@ off_t sys_lseek(int fd, off_t offset, int whence) ret = my_syscall5(__NR_llseek, fd, offset >> 32, (uint32_t)offset, &loff, whence); if (ret < 0) result = ret; - else if (loff != (off_t)loff) - result = -EOVERFLOW; else result = loff; -- cgit From 31b4d3af63f9afcb2661b9be554f0cf55c86573b Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Wed, 29 Oct 2025 17:02:56 +0100 Subject: tools/nolibc: remove more __nolibc_enosys() fallbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit e6366101ce1f ("tools/nolibc: remove __nolibc_enosys() fallback from time64-related functions") removed many of these fallbacks but forgot a few. Finish the job. Signed-off-by: Thomas Weißschuh Acked-by: Willy Tarreau --- tools/include/nolibc/time.h | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'tools/include/nolibc') diff --git a/tools/include/nolibc/time.h b/tools/include/nolibc/time.h index 6c276b8d646a..48e78f8becf9 100644 --- a/tools/include/nolibc/time.h +++ b/tools/include/nolibc/time.h @@ -89,13 +89,11 @@ int sys_clock_settime(clockid_t clockid, struct timespec *tp) { #if defined(__NR_clock_settime) return my_syscall2(__NR_clock_settime, clockid, tp); -#elif defined(__NR_clock_settime64) +#else struct __kernel_timespec ktp; __nolibc_timespec_user_to_kernel(tp, &ktp); return my_syscall2(__NR_clock_settime64, clockid, &ktp); -#else - return __nolibc_enosys(__func__, clockid, tp); #endif } @@ -111,7 +109,7 @@ int sys_clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqt { #if defined(__NR_clock_nanosleep) return my_syscall4(__NR_clock_nanosleep, clockid, flags, rqtp, rmtp); -#elif defined(__NR_clock_nanosleep_time64) +#else struct __kernel_timespec krqtp, krmtp; int ret; @@ -120,8 +118,6 @@ int sys_clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqt if (rmtp) __nolibc_timespec_kernel_to_user(&krmtp, rmtp); return ret; -#else - return __nolibc_enosys(__func__, clockid, flags, rqtp, rmtp); #endif } @@ -195,7 +191,7 @@ int sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value) { #if defined(__NR_timer_gettime) return my_syscall2(__NR_timer_gettime, timerid, curr_value); -#elif defined(__NR_timer_gettime64) +#else struct __kernel_itimerspec kcurr_value; int ret; @@ -203,8 +199,6 @@ int sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value) __nolibc_timespec_kernel_to_user(&kcurr_value.it_interval, &curr_value->it_interval); __nolibc_timespec_kernel_to_user(&kcurr_value.it_value, &curr_value->it_value); return ret; -#else - return __nolibc_enosys(__func__, timerid, curr_value); #endif } @@ -220,7 +214,7 @@ int sys_timer_settime(timer_t timerid, int flags, { #if defined(__NR_timer_settime) return my_syscall4(__NR_timer_settime, timerid, flags, new_value, old_value); -#elif defined(__NR_timer_settime64) +#else struct __kernel_itimerspec knew_value, kold_value; int ret; @@ -232,8 +226,6 @@ int sys_timer_settime(timer_t timerid, int flags, __nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value); } return ret; -#else - return __nolibc_enosys(__func__, timerid, flags, new_value, old_value); #endif } -- cgit