From: Benjamin Berg benjamin.berg@intel.com
This patchset is an attempt to start a nolibc port of UML. The goal is to port UML to use nolibc in smaller chunks to make the switch more manageable.
Using nolibc has the advantage that it is a smaller runtime and it allows us to be in full control about all memory mappings that are done. Another libc on the other hand might map memory unaware of UML, causing collisions with the UML memory layout. Such mappings could even happen before UML has fully initialized (e.g. rseq being mapped into the physical or vmalloc memory areas).
There are three parts to this patchset: * Two patches to use tools/include headers instead of kernel headers for userspace files. * A few nolibc fixes and a new NOLIBC_NO_RUNTIME compile flag for it * Finally nolibc build support for UML and switching two files while adding the appropriate support in nolibc itself.
v1 of this patchset was https://lore.kernel.org/all/20250915071115.1429196-1-benjamin@sipsolutions.n...
v2: https://lore.kernel.org/all/20250919153420.727385-1-benjamin@sipsolutions.ne...
Changes in v3: - sys_ptrace is now not a varadic function - improve printf %m implementation - keep perror as function available with NOLIBC_IGNORE_ERRNO - change syscall guard and fix i386 build
Changes in v2: - add sys/uio.h and sys/ptrace.h to nolibc - Use NOLIBC_NO_RUNTIME to disable nolibc startup code - Fix out-of-tree build - various small improvements and cleanups
Benjamin
Benjamin Berg (12): tools compiler.h: fix __used definition um: use tools/include for user files tools/nolibc/stdio: let perror work when NOLIBC_IGNORE_ERRNO is set tools/nolibc/dirent: avoid errno in readdir_r tools/nolibc: implement %m if errno is not defined tools/nolibc: use __fallthrough__ rather than fallthrough tools/nolibc: add option to disable runtime um: add infrastructure to build files using nolibc um: use nolibc for the --showconfig implementation tools/nolibc: add uio.h with readv and writev tools/nolibc: add ptrace support um: switch ptrace FP register access to nolibc
arch/um/Makefile | 38 ++++++++++++--- arch/um/include/shared/init.h | 2 +- arch/um/include/shared/os.h | 2 + arch/um/include/shared/user.h | 6 --- arch/um/kernel/Makefile | 2 +- arch/um/kernel/skas/stub.c | 1 + arch/um/kernel/skas/stub_exe.c | 4 +- arch/um/os-Linux/skas/process.c | 6 +-- arch/um/os-Linux/start_up.c | 4 +- arch/um/scripts/Makefile.rules | 10 +++- arch/x86/um/Makefile | 6 ++- arch/x86/um/os-Linux/Makefile | 5 +- arch/x86/um/os-Linux/registers.c | 20 ++------ arch/x86/um/user-offsets.c | 1 - tools/include/linux/compiler.h | 2 +- tools/include/nolibc/Makefile | 2 + 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/compiler.h | 4 +- tools/include/nolibc/crt.h | 3 ++ tools/include/nolibc/dirent.h | 6 +-- tools/include/nolibc/nolibc.h | 2 + tools/include/nolibc/stackprotector.h | 2 + tools/include/nolibc/stdio.h | 10 +++- tools/include/nolibc/stdlib.h | 2 + tools/include/nolibc/sys.h | 3 +- tools/include/nolibc/sys/auxv.h | 3 ++ tools/include/nolibc/sys/ptrace.h | 44 ++++++++++++++++++ tools/include/nolibc/sys/uio.h | 49 ++++++++++++++++++++ tools/testing/selftests/nolibc/nolibc-test.c | 11 +++++ 39 files changed, 221 insertions(+), 53 deletions(-) create mode 100644 tools/include/nolibc/sys/ptrace.h create mode 100644 tools/include/nolibc/sys/uio.h
From: Benjamin Berg benjamin.berg@intel.com
The define mapped to __attribute__((__unused__)) instead of using __used__. Having the wrong definition here may result in the linker incorrectly removing the symbol. Also, this now matches the definition in include/linux/compiler_attributes.h.
Fixes: e58e871becec ("tools/lib/lockdep: Remove private kernel headers") Signed-off-by: Benjamin Berg benjamin.berg@intel.com Reviewed-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/linux/compiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h index 33411ca0cc90..b2c40621d441 100644 --- a/tools/include/linux/compiler.h +++ b/tools/include/linux/compiler.h @@ -127,7 +127,7 @@ #endif
#ifndef __used -# define __used __attribute__((__unused__)) +# define __used __attribute__((__used__)) #endif
#ifndef __packed
From: Benjamin Berg benjamin.berg@intel.com
Using the kernel headers directly from the userspace parts of UML is problematic. Switch to use the headers from the tools/include subdirectory instead. These contain stripped down versions that work well for UML and only relatively small adjustments are needed to make it work.
This adds code to create two symlinks so that the userspace code can still find asm-offsets.h and user_constants.h. Other than that, some includes are moved into USER_CFLAGS instead of handling them in Makefile.rules.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com
--- v2: - Fix out-of-tree building --- arch/um/Makefile | 18 ++++++++++++------ arch/um/include/shared/init.h | 2 +- arch/um/include/shared/user.h | 5 ----- arch/um/kernel/skas/stub.c | 1 + arch/um/kernel/skas/stub_exe.c | 4 ++-- arch/um/os-Linux/skas/process.c | 6 ++---- arch/um/os-Linux/start_up.c | 4 ++-- arch/um/scripts/Makefile.rules | 2 +- arch/x86/um/Makefile | 6 ++++-- arch/x86/um/user-offsets.c | 1 - 10 files changed, 25 insertions(+), 24 deletions(-)
diff --git a/arch/um/Makefile b/arch/um/Makefile index 7be0143b5ba3..f7c509262568 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -42,7 +42,7 @@ include $(srctree)/$(HOST_DIR)/Makefile.um core-y += $(HOST_DIR)/um/
SHARED_HEADERS := $(ARCH_DIR)/include/shared -ARCH_INCLUDE := -I$(srctree)/$(SHARED_HEADERS) +ARCH_INCLUDE := -I$(srctree)/$(SHARED_HEADERS) -I$(objtree)/$(SHARED_HEADERS) ARCH_INCLUDE += -I$(srctree)/$(HOST_DIR)/um/shared KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/um
@@ -70,10 +70,13 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \ $(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \ - -D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \ - -idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__ \ - -include $(srctree)/include/linux/compiler-version.h \ - -include $(srctree)/include/linux/kconfig.h + -idirafter $(srctree)/tools/include \ + -D__UM_HOST__ \ + -include $(srctree)/tools/include/linux/compiler.h \ + -include $(srctree)/tools/include/linux/kconfig.h \ + -include $(objtree)/include/generated/autoconf.h \ + -include $(srctree)/include/linux/kern_levels.h \ + -include $(srctree)/$(ARCH_DIR)/include/shared/user.h
#This will adjust *FLAGS accordingly to the platform. include $(srctree)/$(ARCH_DIR)/Makefile-os-Linux @@ -116,6 +119,9 @@ archheaders:
archprepare: $(Q)$(MAKE) $(build)=$(HOST_DIR)/um include/generated/user_constants.h + $(Q)mkdir -p $(ARCH_DIR)/include/shared/generated + $(Q)ln -fs ../../../../../include/generated/user_constants.h $(ARCH_DIR)/include/shared/generated/ + $(Q)ln -fs ../../../../../include/generated/asm-offsets.h $(ARCH_DIR)/include/shared/generated/
LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static LINK-$(CONFIG_LD_SCRIPT_DYN) += -no-pie @@ -147,7 +153,7 @@ export CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE) $(CC_FLAGS_ # When cleaning we don't include .config, so we don't include # TT or skas makefiles and don't clean skas_ptregs.h. CLEAN_FILES += linux x.i gmon.out -MRPROPER_FILES += $(HOST_DIR)/include/generated +MRPROPER_FILES += $(HOST_DIR)/include/generated $(ARCH_DIR)/include/shared/generated
archclean: @find . ( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ diff --git a/arch/um/include/shared/init.h b/arch/um/include/shared/init.h index 1a659e2e8cc3..d201705bedb3 100644 --- a/arch/um/include/shared/init.h +++ b/arch/um/include/shared/init.h @@ -41,7 +41,7 @@ typedef int (*initcall_t)(void); typedef void (*exitcall_t)(void);
-#include <linux/compiler_types.h> +#define __section(section) __attribute__((__section__(section)))
/* These are for everybody (although not all archs will actually discard it in modules) */ diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h index 139eb78a4767..c9b853e1282f 100644 --- a/arch/um/include/shared/user.h +++ b/arch/um/include/shared/user.h @@ -16,13 +16,8 @@ */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-/* This is to get size_t and NULL */ -#ifndef __UM_HOST__ #include <linux/types.h> -#else #include <stddef.h> -#include <sys/types.h> -#endif
extern void panic(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); diff --git a/arch/um/kernel/skas/stub.c b/arch/um/kernel/skas/stub.c index 67cab46a602c..6c9bb1511ea2 100644 --- a/arch/um/kernel/skas/stub.c +++ b/arch/um/kernel/skas/stub.c @@ -5,6 +5,7 @@
#include <sysdep/stub.h>
+#include <linux/init.h> #include <linux/futex.h> #include <sys/socket.h> #include <errno.h> diff --git a/arch/um/kernel/skas/stub_exe.c b/arch/um/kernel/skas/stub_exe.c index cbafaa684e66..0563838c01d1 100644 --- a/arch/um/kernel/skas/stub_exe.c +++ b/arch/um/kernel/skas/stub_exe.c @@ -4,8 +4,8 @@ #include <asm/unistd.h> #include <sysdep/stub.h> #include <stub-data.h> -#include <linux/filter.h> -#include <linux/seccomp.h> +#include <uapi/linux/filter.h> +#include <uapi/linux/seccomp.h> #include <generated/asm-offsets.h>
void _start(void); diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 78f48fa9db8b..8ad7e863af97 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -29,9 +29,7 @@ #include <sysdep/stub.h> #include <sysdep/mcontext.h> #include <linux/futex.h> -#include <linux/threads.h> #include <timetravel.h> -#include <asm-generic/rwonce.h> #include "../internal.h"
int is_skas_winch(int pid, int fd, void *data) @@ -204,7 +202,7 @@ void wait_stub_done_seccomp(struct mm_id *mm_idp, int running, int wait_sigsys) * Either way, if PID is negative, then we have no * choice but to kill the task. */ - if (__READ_ONCE(mm_idp->pid) < 0) + if (READ_ONCE(mm_idp->pid) < 0) goto out_kill;
ret = syscall(__NR_futex, &data->futex, @@ -217,7 +215,7 @@ void wait_stub_done_seccomp(struct mm_id *mm_idp, int running, int wait_sigsys) } } while (data->futex == FUTEX_IN_CHILD);
- if (__READ_ONCE(mm_idp->pid) < 0) + if (READ_ONCE(mm_idp->pid) < 0) goto out_kill;
running = 0; diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index a827c2e01aa5..8971f4fdddab 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -28,8 +28,8 @@ #include <stdbool.h> #include <stub-data.h> #include <sys/prctl.h> -#include <linux/seccomp.h> -#include <linux/filter.h> +#include <uapi/linux/seccomp.h> +#include <uapi/linux/filter.h> #include <sysdep/mcontext.h> #include <sysdep/stub.h> #include <registers.h> diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules index a8b7d9dab0a6..b4a2e0058503 100644 --- a/arch/um/scripts/Makefile.rules +++ b/arch/um/scripts/Makefile.rules @@ -9,7 +9,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(USER_SINGLE_OBJS)) USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS:.o=.%): \ - c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include $(srctree)/include/linux/kern_levels.h -include user.h $(CFLAGS_$(basetarget).o) + c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(basetarget).o)
# These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of # using it directly. diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile index b42c31cd2390..d8a120bace25 100644 --- a/arch/x86/um/Makefile +++ b/arch/x86/um/Makefile @@ -38,8 +38,10 @@ subarch-$(CONFIG_MODULES) += ../kernel/module.o
USER_OBJS := bugs_$(BITS).o ptrace_user.o fault.o
-$(obj)/user-offsets.s: c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) \ - -Iarch/x86/include/generated +$(obj)/user-offsets.s: c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) \ + -Iarch/x86/include/generated \ + -include $(srctree)/include/linux/kbuild.h + targets += user-offsets.s
include/generated/user_constants.h: $(obj)/user-offsets.s FORCE diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c index d6e1cd9956bf..74fc9763b76e 100644 --- a/arch/x86/um/user-offsets.c +++ b/arch/x86/um/user-offsets.c @@ -8,7 +8,6 @@ #define __FRAME_OFFSETS #include <linux/ptrace.h> #include <asm/types.h> -#include <linux/kbuild.h>
#define DEFINE_LONGS(sym, val) \ COMMENT(#val " / sizeof(unsigned long)"); \
From: Benjamin Berg benjamin.berg@intel.com
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 benjamin.berg@intel.com
--- v3: - Change the message instead of removing perror entirely --- tools/include/nolibc/stdio.h | 4 ++++ 1 file changed, 4 insertions(+)
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))
On 2025-09-24 16:20:50+0200, Benjamin Berg wrote:
From: Benjamin Berg benjamin.berg@intel.com
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 benjamin.berg@intel.com
Acked-by: Thomas Weißschuh linux@weissschuh.net
v3:
- Change the message instead of removing perror entirely
tools/include/nolibc/stdio.h | 4 ++++ 1 file changed, 4 insertions(+)
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)) -- 2.51.0
From: Benjamin Berg benjamin.berg@intel.com
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 benjamin.berg@intel.com Acked-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/dirent.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
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 */
From: Benjamin Berg benjamin.berg@intel.com
For improved compatibility, print %m as "unknown error" when nolibc is compiled using NOLIBC_IGNORE_ERRNO.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com --- tools/include/nolibc/stdio.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
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;
On 2025-09-24 16:20:52+0200, Benjamin Berg wrote:
From: Benjamin Berg benjamin.berg@intel.com
For improved compatibility, print %m as "unknown error" when nolibc is compiled using NOLIBC_IGNORE_ERRNO.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com
Thanks for taking care of this.
Acked-by: Thomas Weißschuh linux@weissschuh.net
tools/include/nolibc/stdio.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
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;
-- 2.51.0
From: Benjamin Berg benjamin.berg@intel.com
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 benjamin.berg@intel.com Acked-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/compiler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
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) */
From: Benjamin Berg benjamin.berg@intel.com
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 benjamin.berg@intel.com Acked-by: Thomas Weißschuh linux@weissschuh.net
--- v2: - Renamed from NOLIBC_NO_STARTCODE to NOLIBC_NO_RUNTIME - Put the #ifdef around relevant comments --- 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(-)
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 d3efc0c3b8ad..11abb8bd7eec 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 <name> 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 295e71d34aba..a48f5117bfce 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -509,6 +509,7 @@ pid_t gettid(void) return sys_gettid(); }
+#ifndef NOLIBC_NO_RUNTIME static unsigned long getauxval(unsigned long key);
/* @@ -520,7 +521,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 */
From: Benjamin Berg benjamin.berg@intel.com
Add NOLIBC_CFLAGS and NOLIBC_OBJS to build files against nolibc rather than libc. With this it is possible to move to nolibc in smaller steps.
Set NOLIBC_IGNORE_ERRNO, as the nolibc errno implementation is overly simple and cannot handle threading. nolibc provides sys_* functions that do not emulate the libc errno behaviour and can be used instead.
Leave the syscall definition for kernel code for now, but guard it as it is a macro in nolibc.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com
--- v3: - Change the syscall guard to use __KERNEL__
v2: - Do not include nolibc.h via CFLAGS - Make syscall guard more explicit - Remove __UM_NOLIBC__ define, it is not needed - Fix out-of-tree building --- arch/um/Makefile | 20 +++++++++++++++++++- arch/um/include/shared/os.h | 2 ++ arch/um/include/shared/user.h | 1 - arch/um/scripts/Makefile.rules | 8 +++++++- 4 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/arch/um/Makefile b/arch/um/Makefile index f7c509262568..c3a81df50911 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -78,6 +78,24 @@ USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \ -include $(srctree)/include/linux/kern_levels.h \ -include $(srctree)/$(ARCH_DIR)/include/shared/user.h
+NOLIBC_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \ + $(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \ + -I $(srctree)/tools/include \ + -D__EXPORTED_HEADERS__ \ + -D__UM_HOST__ \ + -DNOLIBC_NO_RUNTIME \ + -DNOLIBC_IGNORE_ERRNO \ + -nostdlib -nostdinc -static \ + -I$(srctree)/include/uapi \ + -I$(srctree)/$(HOST_DIR)/include/uapi \ + -I$(objtree)/$(HOST_DIR)/include/generated/uapi \ + -I $(srctree)/tools/include/nolibc \ + -I $(srctree)/usr/include \ + -include $(objtree)/include/generated/autoconf.h \ + -include $(srctree)/tools/include/linux/kconfig.h \ + -include $(srctree)/include/linux/kern_levels.h \ + -include $(srctree)/$(ARCH_DIR)/include/shared/user.h + #This will adjust *FLAGS accordingly to the platform. include $(srctree)/$(ARCH_DIR)/Makefile-os-Linux
@@ -160,4 +178,4 @@ archclean: -o -name '*.gcov' ) -type f -print | xargs rm -f $(Q)$(MAKE) -f $(srctree)/Makefile ARCH=$(HEADER_ARCH) clean
-export HEADER_ARCH SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING DEV_NULL_PATH +export HEADER_ARCH SUBARCH USER_CFLAGS NOLIBC_CFLAGS CFLAGS_NO_HARDENING DEV_NULL_PATH diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index b35cc8ce333b..5dae5635b1f8 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h @@ -327,7 +327,9 @@ extern int __ignore_sigio_fd(int fd); /* tty.c */ extern int get_pty(void);
+#ifdef __KERNEL__ long syscall(long number, ...); +#endif
/* irqflags tracing */ extern void block_signals_trace(void); diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h index c9b853e1282f..e32bdd032029 100644 --- a/arch/um/include/shared/user.h +++ b/arch/um/include/shared/user.h @@ -16,7 +16,6 @@ */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-#include <linux/types.h> #include <stddef.h>
extern void panic(const char *fmt, ...) diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules index b4a2e0058503..5f07551935c3 100644 --- a/arch/um/scripts/Makefile.rules +++ b/arch/um/scripts/Makefile.rules @@ -11,6 +11,12 @@ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) $(USER_OBJS:.o=.%): \ c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(basetarget).o)
+# Similar USER_OBJS but compiled against nolibc (may include kernel headers?) +NOLIBC_OBJS := $(foreach file,$(NOLIBC_OBJS),$(obj)/$(file)) + +$(NOLIBC_OBJS:.o=.%): \ + c_flags = -Wp,-MD,$(depfile) $(NOLIBC_CFLAGS) $(CFLAGS_$(basetarget).o) + # These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of # using it directly. UNPROFILE_OBJS := $(foreach file,$(UNPROFILE_OBJS),$(obj)/$(file)) @@ -18,7 +24,7 @@ UNPROFILE_OBJS := $(foreach file,$(UNPROFILE_OBJS),$(obj)/$(file)) $(UNPROFILE_OBJS:.o=.%): \ c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS)) $(CFLAGS_$(basetarget).o)
-$(USER_OBJS) $(UNPROFILE_OBJS): \ +$(USER_OBJS) $(NOLIBC_OBJS) $(UNPROFILE_OBJS): \ CHECKFLAGS := $(patsubst $(NOSTDINC_FLAGS),,$(CHECKFLAGS))
# The stubs can't try to call mcount or update basic block data
On 2025-09-24 16:20:55+0200, Benjamin Berg wrote:
From: Benjamin Berg benjamin.berg@intel.com
Add NOLIBC_CFLAGS and NOLIBC_OBJS to build files against nolibc rather than libc. With this it is possible to move to nolibc in smaller steps.
Set NOLIBC_IGNORE_ERRNO, as the nolibc errno implementation is overly simple and cannot handle threading. nolibc provides sys_* functions that do not emulate the libc errno behaviour and can be used instead.
Leave the syscall definition for kernel code for now, but guard it as it is a macro in nolibc.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com
v3:
- Change the syscall guard to use __KERNEL__
v2:
- Do not include nolibc.h via CFLAGS
- Make syscall guard more explicit
- Remove __UM_NOLIBC__ define, it is not needed
- Fix out-of-tree building
arch/um/Makefile | 20 +++++++++++++++++++- arch/um/include/shared/os.h | 2 ++ arch/um/include/shared/user.h | 1 - arch/um/scripts/Makefile.rules | 8 +++++++- 4 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/arch/um/Makefile b/arch/um/Makefile index f7c509262568..c3a81df50911 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -78,6 +78,24 @@ USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \ -include $(srctree)/include/linux/kern_levels.h \ -include $(srctree)/$(ARCH_DIR)/include/shared/user.h +NOLIBC_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
$(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \
-I $(srctree)/tools/include \
-D__EXPORTED_HEADERS__ \
-D__UM_HOST__ \
-DNOLIBC_NO_RUNTIME \
-DNOLIBC_IGNORE_ERRNO \
-nostdlib -nostdinc -static \
-I$(srctree)/include/uapi \
-I$(srctree)/$(HOST_DIR)/include/uapi \
-I$(objtree)/$(HOST_DIR)/include/generated/uapi \
-I $(srctree)/tools/include/nolibc \
-I $(srctree)/usr/include \
This looks incorrect. The UAPI headers would be installed to $(objtree). But UML does not even use CONFIG_HEADERS_INSTALL. Also the whitespace is inconsistent between different lines.
-include $(objtree)/include/generated/autoconf.h \
-include $(srctree)/tools/include/linux/kconfig.h \
-include $(srctree)/include/linux/kern_levels.h \
-include $(srctree)/$(ARCH_DIR)/include/shared/user.h
#This will adjust *FLAGS accordingly to the platform. include $(srctree)/$(ARCH_DIR)/Makefile-os-Linux @@ -160,4 +178,4 @@ archclean: -o -name '*.gcov' ) -type f -print | xargs rm -f $(Q)$(MAKE) -f $(srctree)/Makefile ARCH=$(HEADER_ARCH) clean -export HEADER_ARCH SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING DEV_NULL_PATH +export HEADER_ARCH SUBARCH USER_CFLAGS NOLIBC_CFLAGS CFLAGS_NO_HARDENING DEV_NULL_PATH
(...)
From: Benjamin Berg benjamin.berg@intel.com
This is one of the simplest files and it can be switched over to use nolibc without any modifications.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com --- arch/um/kernel/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index b8f4e9281599..4b206a40b611 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -26,7 +26,7 @@ obj-$(CONFIG_OF) += dtb.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_STACKTRACE) += stacktrace.o
-USER_OBJS := config.o +NOLIBC_OBJS := config.o
include $(srctree)/arch/um/scripts/Makefile.rules
Hi Benjamin,
kernel test robot noticed the following build warnings:
[auto build test WARNING on uml/next] [also build test WARNING on uml/fixes shuah-kselftest/next shuah-kselftest/fixes linus/master v6.17-rc7 next-20250925] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Benjamin-Berg/tools-compiler-... base: https://git.kernel.org/pub/scm/linux/kernel/git/uml/linux next patch link: https://lore.kernel.org/r/20250924142059.527768-10-benjamin%40sipsolutions.n... patch subject: [PATCH v3 09/12] um: use nolibc for the --showconfig implementation :::::: branch date: 2 days ago :::::: commit date: 2 days ago config: um-randconfig-r111-20250926 (https://download.01.org/0day-ci/archive/20250926/202509261452.g5peaXCc-lkp@i...) compiler: gcc-14 (Debian 14.2.0-19) 14.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250926/202509261452.g5peaXCc-lkp@i...)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot lkp@intel.com | Closes: https://lore.kernel.org/r/202509261452.g5peaXCc-lkp@intel.com/
sparse warnings: (new ones prefixed by >>) command-line: note: in included file (through tools/include/nolibc/nolibc.h, tools/include/nolibc/stddef.h, arch/um/include/shared/user.h, builtin):
tools/include/nolibc/sys.h:109:29: sparse: sparse: Using plain integer as NULL pointer
command-line: note: in included file (through tools/include/nolibc/nolibc.h, tools/include/nolibc/stddef.h, arch/um/include/shared/user.h, builtin):
tools/include/nolibc/sys/reboot.h:31:16: sparse: sparse: Using plain integer as NULL pointer tools/include/nolibc/sys/reboot.h:31:16: sparse: sparse: Using plain integer as NULL pointer
command-line: note: in included file (through tools/include/nolibc/nolibc.h, tools/include/nolibc/stddef.h, arch/um/include/shared/user.h, builtin):
tools/include/nolibc/unistd.h:57:27: sparse: sparse: Using plain integer as NULL pointer
tools/include/nolibc/unistd.h:57:30: sparse: sparse: Using plain integer as NULL pointer tools/include/nolibc/unistd.h:57:33: sparse: sparse: Using plain integer as NULL pointer tools/include/nolibc/unistd.h:70:27: sparse: sparse: Using plain integer as NULL pointer tools/include/nolibc/unistd.h:70:30: sparse: sparse: Using plain integer as NULL pointer tools/include/nolibc/unistd.h:70:33: sparse: sparse: Using plain integer as NULL pointer tools/include/nolibc/unistd.h:81:30: sparse: sparse: Using plain integer as NULL pointer tools/include/nolibc/unistd.h:81:33: sparse: sparse: Using plain integer as NULL pointer tools/include/nolibc/unistd.h:81:36: sparse: sparse: Using plain integer as NULL pointer command-line: note: in included file (through tools/include/nolibc/stdio.h, tools/include/nolibc/nolibc.h, tools/include/nolibc/stddef.h, ...): tools/include/nolibc/stdlib.h:56:6: sparse: sparse: symbol 'abort' redeclared with different type (different modifiers): tools/include/nolibc/stdlib.h:56:6: sparse: void extern [addressable] [noreturn] [toplevel] [unused] abort( ... ) tools/include/nolibc/stdlib.h:54:6: sparse: note: previously declared as: tools/include/nolibc/stdlib.h:54:6: sparse: void extern [addressable] [toplevel] abort( ... ) command-line: note: in included file (through tools/include/nolibc/nolibc.h, tools/include/nolibc/stddef.h, arch/um/include/shared/user.h, builtin): tools/include/nolibc/getopt.h:19:6: sparse: sparse: symbol 'optarg' was not declared. Should it be static? tools/include/nolibc/getopt.h:22:5: sparse: sparse: symbol 'optind' was not declared. Should it be static? tools/include/nolibc/getopt.h:22:17: sparse: sparse: symbol 'opterr' was not declared. Should it be static? tools/include/nolibc/getopt.h:22:29: sparse: sparse: symbol 'optopt' was not declared. Should it be static?
tools/include/nolibc/getopt.h:81:26: sparse: sparse: Using plain integer as NULL pointer
vim +109 tools/include/nolibc/sys.h
bd8c8fbb866fe5 Willy Tarreau 2022-02-07 104 bd8c8fbb866fe5 Willy Tarreau 2022-02-07 105 static __attribute__((unused)) bd8c8fbb866fe5 Willy Tarreau 2022-02-07 106 void *sbrk(intptr_t inc) bd8c8fbb866fe5 Willy Tarreau 2022-02-07 107 { bd8c8fbb866fe5 Willy Tarreau 2022-02-07 108 /* first call to find current end */ 4201cfce15fe35 Zhangjin Wu 2023-07-07 @109 void *ret = sys_brk(0); 4201cfce15fe35 Zhangjin Wu 2023-07-07 110 4201cfce15fe35 Zhangjin Wu 2023-07-07 111 if (ret && sys_brk(ret + inc) == ret + inc) bd8c8fbb866fe5 Willy Tarreau 2022-02-07 112 return ret + inc; bd8c8fbb866fe5 Willy Tarreau 2022-02-07 113 fb01ff635efd0a Willy Tarreau 2023-08-15 114 SET_ERRNO(ENOMEM); fb01ff635efd0a Willy Tarreau 2023-08-15 115 return (void *)-1; bd8c8fbb866fe5 Willy Tarreau 2022-02-07 116 } bd8c8fbb866fe5 Willy Tarreau 2022-02-07 117
From: Benjamin Berg benjamin.berg@intel.com
This is generally useful and struct iovec is also needed for other purposes such as ptrace.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com Acked-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/Makefile | 1 + tools/include/nolibc/nolibc.h | 1 + tools/include/nolibc/sys/uio.h | 49 ++++++++++++++++++++ tools/testing/selftests/nolibc/nolibc-test.c | 9 ++++ 4 files changed, 60 insertions(+) create mode 100644 tools/include/nolibc/sys/uio.h
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 c199ade200c2..b4bc1c9b883d 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 w@1wt.eu + * 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 <linux/uio.h> + + +/* + * 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 */ diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index a297ee0d6d07..1907128bc3f6 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -25,6 +25,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 <dirent.h> @@ -1283,6 +1284,10 @@ int run_syscall(int min, int max) int proc; int test; int tmp; + struct iovec iov_one = { + .iov_base = &tmp, + .iov_len = 1, + }; int ret = 0; void *p1, *p2; int has_gettid = 1; @@ -1395,6 +1400,10 @@ int run_syscall(int min, int max) CASE_TEST(waitpid_child); EXPECT_SYSER(1, waitpid(getpid(), &tmp, WNOHANG), -1, ECHILD); break; CASE_TEST(write_badf); EXPECT_SYSER(1, write(-1, &tmp, 1), -1, EBADF); break; CASE_TEST(write_zero); EXPECT_SYSZR(1, write(1, &tmp, 0)); break; + CASE_TEST(readv_badf); EXPECT_SYSER(1, readv(-1, &iov_one, 1), -1, EBADF); break; + CASE_TEST(readv_zero); EXPECT_SYSZR(1, readv(1, NULL, 0)); break; + CASE_TEST(writev_badf); EXPECT_SYSER(1, writev(-1, &iov_one, 1), -1, EBADF); break; + CASE_TEST(writev_zero); EXPECT_SYSZR(1, writev(1, NULL, 0)); break; CASE_TEST(syscall_noargs); EXPECT_SYSEQ(1, syscall(__NR_getpid), getpid()); break; CASE_TEST(syscall_args); EXPECT_SYSER(1, syscall(__NR_statx, 0, NULL, 0, 0, NULL), -1, EFAULT); break; CASE_TEST(namespace); EXPECT_SYSZR(euid0 && proc, test_namespace()); break;
From: Benjamin Berg benjamin.berg@intel.com
Add ptrace support, as it will be useful in UML.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com
--- v3: - Only use variardic for ptrace and not for sys_ptrace --- tools/include/nolibc/Makefile | 1 + tools/include/nolibc/nolibc.h | 1 + tools/include/nolibc/sys/ptrace.h | 44 ++++++++++++++++++++ tools/testing/selftests/nolibc/nolibc-test.c | 2 + 4 files changed, 48 insertions(+) create mode 100644 tools/include/nolibc/sys/ptrace.h
diff --git a/tools/include/nolibc/Makefile b/tools/include/nolibc/Makefile index 9bbbba32dac6..8e0cac3ac522 100644 --- a/tools/include/nolibc/Makefile +++ b/tools/include/nolibc/Makefile @@ -53,6 +53,7 @@ all_files := \ sys/mman.h \ sys/mount.h \ sys/prctl.h \ + sys/ptrace.h \ sys/random.h \ sys/reboot.h \ sys/resource.h \ diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h index b4bc1c9b883d..590eef545ca6 100644 --- a/tools/include/nolibc/nolibc.h +++ b/tools/include/nolibc/nolibc.h @@ -101,6 +101,7 @@ #include "sys/mman.h" #include "sys/mount.h" #include "sys/prctl.h" +#include "sys/ptrace.h" #include "sys/random.h" #include "sys/reboot.h" #include "sys/resource.h" diff --git a/tools/include/nolibc/sys/ptrace.h b/tools/include/nolibc/sys/ptrace.h new file mode 100644 index 000000000000..5d1e52965878 --- /dev/null +++ b/tools/include/nolibc/sys/ptrace.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * ptrace for NOLIBC + * Copyright (C) 2017-2021 Willy Tarreau w@1wt.eu + * Copyright (C) 2025 Intel Corporation + */ + +/* make sure to include all global symbols */ +#include "../nolibc.h" + +#ifndef _NOLIBC_SYS_PTRACE_H +#define _NOLIBC_SYS_PTRACE_H + +#include "../sys.h" +#include "uio.h" + + +#include <linux/ptrace.h> + +/* + * long ptrace(int op, pid_t pid, void *addr, void *data); + */ +static __attribute__((unused)) +long sys_ptrace(int op, pid_t pid, void *addr, void *data) +{ + return my_syscall4(__NR_ptrace, op, pid, addr, data); +} + +static __attribute__((unused)) +ssize_t ptrace(int op, pid_t pid, ...) +{ + ssize_t ret; + va_list args; + + va_start(args, pid); + ret = __sysret(sys_ptrace(op, pid, + va_arg(args, void *), + va_arg(args, void *))); + va_end(args); + + return ret; +} + +#endif /* _NOLIBC_SYS_PTRACE_H */ diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 1907128bc3f6..4c1b9ee32b7d 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -17,6 +17,7 @@ #include <sys/mman.h> #include <sys/mount.h> #include <sys/prctl.h> +#include <sys/ptrace.h> #include <sys/random.h> #include <sys/reboot.h> #include <sys/resource.h> @@ -1404,6 +1405,7 @@ int run_syscall(int min, int max) CASE_TEST(readv_zero); EXPECT_SYSZR(1, readv(1, NULL, 0)); break; CASE_TEST(writev_badf); EXPECT_SYSER(1, writev(-1, &iov_one, 1), -1, EBADF); break; CASE_TEST(writev_zero); EXPECT_SYSZR(1, writev(1, NULL, 0)); break; + CASE_TEST(ptrace); EXPECT_SYSER(1, ptrace(PTRACE_CONT, getpid(), NULL, NULL), -1, ESRCH); break; CASE_TEST(syscall_noargs); EXPECT_SYSEQ(1, syscall(__NR_getpid), getpid()); break; CASE_TEST(syscall_args); EXPECT_SYSER(1, syscall(__NR_statx, 0, NULL, 0, 0, NULL), -1, EFAULT); break; CASE_TEST(namespace); EXPECT_SYSZR(euid0 && proc, test_namespace()); break;
On 2025-09-24 16:20:58+0200, Benjamin Berg wrote:
From: Benjamin Berg benjamin.berg@intel.com
Add ptrace support, as it will be useful in UML.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com
v3:
- Only use variardic for ptrace and not for sys_ptrace
tools/include/nolibc/Makefile | 1 + tools/include/nolibc/nolibc.h | 1 + tools/include/nolibc/sys/ptrace.h | 44 ++++++++++++++++++++ tools/testing/selftests/nolibc/nolibc-test.c | 2 + 4 files changed, 48 insertions(+) create mode 100644 tools/include/nolibc/sys/ptrace.h
(...)
diff --git a/tools/include/nolibc/sys/ptrace.h b/tools/include/nolibc/sys/ptrace.h new file mode 100644 index 000000000000..5d1e52965878 --- /dev/null +++ b/tools/include/nolibc/sys/ptrace.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/*
- ptrace for NOLIBC
- Copyright (C) 2017-2021 Willy Tarreau w@1wt.eu
- Copyright (C) 2025 Intel Corporation
- */
+/* make sure to include all global symbols */ +#include "../nolibc.h"
+#ifndef _NOLIBC_SYS_PTRACE_H +#define _NOLIBC_SYS_PTRACE_H
+#include "../sys.h" +#include "uio.h"
+#include <linux/ptrace.h>
+/*
- long ptrace(int op, pid_t pid, void *addr, void *data);
- */
+static __attribute__((unused)) +long sys_ptrace(int op, pid_t pid, void *addr, void *data) +{
- return my_syscall4(__NR_ptrace, op, pid, addr, data);
+}
+static __attribute__((unused)) +ssize_t ptrace(int op, pid_t pid, ...) +{
- ssize_t ret;
- va_list args;
- va_start(args, pid);
- ret = __sysret(sys_ptrace(op, pid,
va_arg(args, void *),
va_arg(args, void *)));
- va_end(args);
My understanding of the last discussion was not to use varargs here either. Instead I wanted to stick to the prototype from the manpage.
- return ret;
+}
+#endif /* _NOLIBC_SYS_PTRACE_H */
(...)
From: Benjamin Berg benjamin.berg@intel.com
The registers.c file only contains the routines for floating point register access in ptrace mode and initial size detection. After the addition of sys/uio.h and sys/ptrace.h to nolibc it can be moved to use it by using the sys_ptrace() wrapper.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com
--- v3: - Cast argument to (void *) - Remove unused sys/user.h include which does not exist in nolibc
v2: - Use new sys_ptrace from nolibc --- arch/x86/um/os-Linux/Makefile | 5 ++++- arch/x86/um/os-Linux/registers.c | 20 +++++--------------- 2 files changed, 9 insertions(+), 16 deletions(-)
diff --git a/arch/x86/um/os-Linux/Makefile b/arch/x86/um/os-Linux/Makefile index 77a308aaa5ec..d37320430822 100644 --- a/arch/x86/um/os-Linux/Makefile +++ b/arch/x86/um/os-Linux/Makefile @@ -3,10 +3,13 @@ # Licensed under the GPL #
-obj-y = registers.o mcontext.o +obj-y = mcontext.o
obj-$(CONFIG_X86_32) += tls.o
USER_OBJS := $(obj-y)
+obj-y += registers.o +NOLIBC_OBJS := registers.o + include $(srctree)/arch/um/scripts/Makefile.rules diff --git a/arch/x86/um/os-Linux/registers.c b/arch/x86/um/os-Linux/registers.c index eb1cdadc8a61..72c7493f3b89 100644 --- a/arch/x86/um/os-Linux/registers.c +++ b/arch/x86/um/os-Linux/registers.c @@ -7,9 +7,6 @@ #include <errno.h> #include <stdlib.h> #include <sys/ptrace.h> -#ifdef __i386__ -#include <sys/user.h> -#endif #include <longjmp.h> #include <sysdep/ptrace_user.h> #include <sys/uio.h> @@ -28,9 +25,7 @@ int get_fp_registers(int pid, unsigned long *regs) .iov_len = host_fp_size, };
- if (ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov) < 0) - return -errno; - return 0; + return sys_ptrace(PTRACE_GETREGSET, pid, (void *)ptrace_regset, &iov); }
int put_fp_registers(int pid, unsigned long *regs) @@ -40,9 +35,7 @@ int put_fp_registers(int pid, unsigned long *regs) .iov_len = host_fp_size, };
- if (ptrace(PTRACE_SETREGSET, pid, ptrace_regset, &iov) < 0) - return -errno; - return 0; + return sys_ptrace(PTRACE_SETREGSET, pid, (void *)ptrace_regset, &iov); }
int arch_init_registers(int pid) @@ -60,9 +53,7 @@ int arch_init_registers(int pid)
/* GDB has x86_xsave_length, which uses x86_cpuid_count */ ptrace_regset = NT_X86_XSTATE; - ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov); - if (ret) - ret = -errno; + ret = sys_ptrace(PTRACE_GETREGSET, pid, (void *)ptrace_regset, &iov);
if (ret == -ENODEV) { #ifdef CONFIG_X86_32 @@ -71,9 +62,8 @@ int arch_init_registers(int pid) ptrace_regset = NT_PRFPREG; #endif iov.iov_len = 2 * 1024 * 1024; - ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov); - if (ret) - ret = -errno; + ret = sys_ptrace(PTRACE_GETREGSET, pid, + (void *)ptrace_regset, &iov); }
munmap(iov.iov_base, 2 * 1024 * 1024);
linux-kselftest-mirror@lists.linaro.org