From: Benjamin Berg benjamin.berg@intel.com
For a while now, we have discussed that it may be better to avoid using libc inside UML as it may be interfering in unexpected ways with kernel functionality. A major point of concern is that there is no guarantee that the libc is not using any address space that may conflict with kernel addresses.
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.
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_STARTCODE compile flag for it * Finally nolibc build support for UML and switching two files
The first two parts could be merged independently. The last step to use nolibc inside UML obviously depends on the first two.
Benjamin
Benjamin Berg (9): tools compiler.h: fix __used definition um: use tools/include for user files tools/nolibc/stdio: remove perror if NOLIBC_IGNORE_ERRNO is set tools/nolibc/dirent: avoid errno in readdir_r tools/nolibc: use __fallthrough__ rather than fallthrough tools/nolibc: add option to disable startup code um: add infrastructure to build files using nolibc um: use nolibc for the --showconfig implementation um: switch ptrace FP register access to nolibc
arch/um/Makefile | 32 ++++++++++++++++--- .../um/include/shared/generated/asm-offsets.h | 1 + .../include/shared/generated/user_constants.h | 1 + arch/um/include/shared/init.h | 2 +- arch/um/include/shared/os.h | 2 ++ arch/um/include/shared/user.h | 5 --- 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 | 22 +++++-------- arch/x86/um/user-offsets.c | 1 - tools/include/linux/compiler.h | 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/stackprotector.h | 2 ++ tools/include/nolibc/stdio.h | 2 ++ tools/include/nolibc/stdlib.h | 2 ++ tools/include/nolibc/sys.h | 3 +- tools/include/nolibc/sys/auxv.h | 3 ++ 36 files changed, 108 insertions(+), 47 deletions(-) create mode 120000 arch/um/include/shared/generated/asm-offsets.h create mode 120000 arch/um/include/shared/generated/user_constants.h
From: Benjamin Berg benjamin.berg@intel.com
The define mapped to __attribute__((__unused__)) instead of using __used__.
Fixes: e58e871becec ("tools/lib/lockdep: Remove private kernel headers") Signed-off-by: Benjamin Berg benjamin.berg@intel.com --- 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
On 2025-09-15 09:11:07+0200, Benjamin Berg wrote:
From: Benjamin Berg benjamin.berg@intel.com
The define mapped to __attribute__((__unused__)) instead of using __used__.
Can you explain why it is a problem and add that it now matches the definition in the regular include/linux/compiler.h?
Anyways:
Reviewed-by: Thomas Weißschuh linux@weissschuh.net
Fixes: e58e871becec ("tools/lib/lockdep: Remove private kernel headers") Signed-off-by: Benjamin Berg benjamin.berg@intel.com
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
2.51.0
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 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 --- arch/um/Makefile | 11 +++++++---- arch/um/include/shared/generated/asm-offsets.h | 1 + arch/um/include/shared/generated/user_constants.h | 1 + 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 - 12 files changed, 22 insertions(+), 22 deletions(-) create mode 120000 arch/um/include/shared/generated/asm-offsets.h create mode 120000 arch/um/include/shared/generated/user_constants.h
diff --git a/arch/um/Makefile b/arch/um/Makefile index 7be0143b5ba3..a3f27d791cc0 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -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 $(srctree)/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 diff --git a/arch/um/include/shared/generated/asm-offsets.h b/arch/um/include/shared/generated/asm-offsets.h new file mode 120000 index 000000000000..22fd929dbac7 --- /dev/null +++ b/arch/um/include/shared/generated/asm-offsets.h @@ -0,0 +1 @@ +../../../../../include/generated/asm-offsets.h \ No newline at end of file diff --git a/arch/um/include/shared/generated/user_constants.h b/arch/um/include/shared/generated/user_constants.h new file mode 120000 index 000000000000..5f67c190ec09 --- /dev/null +++ b/arch/um/include/shared/generated/user_constants.h @@ -0,0 +1 @@ +../../../../../include/generated/user_constants.h \ No newline at end of file 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..e5f1658a8f9d 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 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)"); \
Hi Benjamin,
kernel test robot noticed the following build errors:
[auto build test ERROR on uml/next] [also build test ERROR on uml/fixes linus/master v6.17-rc6 next-20250912] [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/20250915071115.1429196-3-benjamin%40sipsolutions.n... patch subject: [PATCH 2/9] um: use tools/include for user files config: um-allnoconfig (https://download.01.org/0day-ci/archive/20250915/202509151828.S0qPk6Du-lkp@i...) compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 65ad21d730d25789454d18e811f8ff5db79cb5d4) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250915/202509151828.S0qPk6Du-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/oe-kbuild-all/202509151828.S0qPk6Du-lkp@intel.com/
All errors (new ones prefixed by >>):
<built-in>:3:10: fatal error: 'include/generated/autoconf.h' file not found
3 | #include "include/generated/autoconf.h" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. make[3]: *** [scripts/Makefile.build:182: arch/x86/um/user-offsets.s] Error 1 make[3]: Target 'include/generated/user_constants.h' not remade because of errors. make[2]: *** [arch/um/Makefile:121: archprepare] Error 2 make[2]: Target 'prepare' not remade because of errors. make[1]: *** [Makefile:248: __sub-make] Error 2 make[1]: Target 'prepare' not remade because of errors. make: *** [Makefile:248: __sub-make] Error 2 make: Target 'prepare' not remade because of errors.
From: Benjamin Berg benjamin.berg@intel.com
There is no errno variable when NOLIBC_IGNORE_ERRNO is defined. As such, the perror function does not make any sense then and cannot compile.
Fixes: acab7bcdb1bc ("tools/nolibc/stdio: add perror() to report the errno value") Signed-off-by: Benjamin Berg benjamin.berg@intel.com --- tools/include/nolibc/stdio.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h index 7630234408c5..c512159b8374 100644 --- a/tools/include/nolibc/stdio.h +++ b/tools/include/nolibc/stdio.h @@ -597,11 +597,13 @@ int sscanf(const char *str, const char *format, ...) return ret; }
+#ifndef NOLIBC_IGNORE_ERRNO static __attribute__((unused)) void perror(const char *msg) { fprintf(stderr, "%s%serrno=%d\n", (msg && *msg) ? msg : "", (msg && *msg) ? ": " : "", errno); } +#endif
static __attribute__((unused)) int setvbuf(FILE *stream __attribute__((unused)),
On 2025-09-15 09:11:09+0200, Benjamin Berg wrote:
From: Benjamin Berg benjamin.berg@intel.com
There is no errno variable when NOLIBC_IGNORE_ERRNO is defined. As such, the perror function does not make any sense then and cannot compile.
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
tools/include/nolibc/stdio.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h index 7630234408c5..c512159b8374 100644 --- a/tools/include/nolibc/stdio.h +++ b/tools/include/nolibc/stdio.h @@ -597,11 +597,13 @@ int sscanf(const char *str, const char *format, ...) return ret; } +#ifndef NOLIBC_IGNORE_ERRNO static __attribute__((unused)) void perror(const char *msg) { fprintf(stderr, "%s%serrno=%d\n", (msg && *msg) ? msg : "", (msg && *msg) ? ": " : "", errno); } +#endif static __attribute__((unused)) int setvbuf(FILE *stream __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 --- 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 */
On 2025-09-15 09:11:10+0200, Benjamin Berg wrote:
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 */ -- 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 --- 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) */
On 2025-09-15 09:11:11+0200, Benjamin Berg wrote:
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.
Not a really big fan, but as the underscore variant is documented there shouldn't be an issue.
Acked-by: Thomas Weißschuh linux@weissschuh.net
Signed-off-by: Benjamin Berg benjamin.berg@intel.com
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) */
2.51.0
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_STARTCODE 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 --- 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..24ad348cc1e8 100644 --- a/tools/include/nolibc/arch-arm.h +++ b/tools/include/nolibc/arch-arm.h @@ -185,6 +185,7 @@ })
/* startup code */ +#ifndef NOLIBC_NO_STARTCODE void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { __asm__ volatile ( @@ -193,5 +194,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_STARTCODE */
#endif /* _NOLIBC_ARCH_ARM_H */ diff --git a/tools/include/nolibc/arch-arm64.h b/tools/include/nolibc/arch-arm64.h index 02a3f74c8ec8..554ebb51c761 100644 --- a/tools/include/nolibc/arch-arm64.h +++ b/tools/include/nolibc/arch-arm64.h @@ -142,6 +142,7 @@ })
/* startup code */ +#ifndef NOLIBC_NO_STARTCODE void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { __asm__ volatile ( @@ -150,4 +151,5 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_STARTCODE */ #endif /* _NOLIBC_ARCH_ARM64_H */ diff --git a/tools/include/nolibc/arch-loongarch.h b/tools/include/nolibc/arch-loongarch.h index 5511705303ea..cf14f7bf4081 100644 --- a/tools/include/nolibc/arch-loongarch.h +++ b/tools/include/nolibc/arch-loongarch.h @@ -143,6 +143,7 @@ })
/* startup code */ +#ifndef NOLIBC_NO_STARTCODE void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { __asm__ volatile ( @@ -151,5 +152,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_STARTCODE */
#endif /* _NOLIBC_ARCH_LOONGARCH_H */ diff --git a/tools/include/nolibc/arch-m68k.h b/tools/include/nolibc/arch-m68k.h index 6dac1845f298..dc0d48a10c14 100644 --- a/tools/include/nolibc/arch-m68k.h +++ b/tools/include/nolibc/arch-m68k.h @@ -128,6 +128,7 @@ _num; \ })
+#ifndef NOLIBC_NO_STARTCODE 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_STARTCODE */
#endif /* _NOLIBC_ARCH_M68K_H */ diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h index 0cbac63b249a..6c6a65a99029 100644 --- a/tools/include/nolibc/arch-mips.h +++ b/tools/include/nolibc/arch-mips.h @@ -246,6 +246,7 @@ #endif /* _ABIO32 */
/* startup code, note that it's called __start on MIPS */ +#ifndef NOLIBC_NO_STARTCODE 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_STARTCODE */
#endif /* _NOLIBC_ARCH_MIPS_H */ diff --git a/tools/include/nolibc/arch-powerpc.h b/tools/include/nolibc/arch-powerpc.h index 204564bbcd32..7a01278e569c 100644 --- a/tools/include/nolibc/arch-powerpc.h +++ b/tools/include/nolibc/arch-powerpc.h @@ -184,6 +184,7 @@ #endif /* !__powerpc64__ */
/* startup code */ +#ifndef NOLIBC_NO_STARTCODE void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { #ifdef __powerpc64__ @@ -215,5 +216,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s #endif __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_STARTCODE */
#endif /* _NOLIBC_ARCH_POWERPC_H */ diff --git a/tools/include/nolibc/arch-riscv.h b/tools/include/nolibc/arch-riscv.h index 885383a86c38..12ca37b8d964 100644 --- a/tools/include/nolibc/arch-riscv.h +++ b/tools/include/nolibc/arch-riscv.h @@ -140,6 +140,7 @@ })
/* startup code */ +#ifndef NOLIBC_NO_STARTCODE void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { __asm__ volatile ( @@ -152,5 +153,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_STARTCODE */
#endif /* _NOLIBC_ARCH_RISCV_H */ diff --git a/tools/include/nolibc/arch-s390.h b/tools/include/nolibc/arch-s390.h index df4c3cc713ac..fb0d312847b8 100644 --- a/tools/include/nolibc/arch-s390.h +++ b/tools/include/nolibc/arch-s390.h @@ -140,6 +140,7 @@ })
/* startup code */ +#ifndef NOLIBC_NO_STARTCODE void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { __asm__ volatile ( @@ -155,6 +156,7 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_STARTCODE */
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..038bf364aa27 100644 --- a/tools/include/nolibc/arch-sh.h +++ b/tools/include/nolibc/arch-sh.h @@ -141,6 +141,7 @@ })
/* startup code */ +#ifndef NOLIBC_NO_STARTCODE 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_STARTCODE */
#endif /* _NOLIBC_ARCH_SH_H */ diff --git a/tools/include/nolibc/arch-sparc.h b/tools/include/nolibc/arch-sparc.h index ca420d843e25..062eae1fa92d 100644 --- a/tools/include/nolibc/arch-sparc.h +++ b/tools/include/nolibc/arch-sparc.h @@ -153,6 +153,7 @@ })
/* startup code */ +#ifndef NOLIBC_NO_STARTCODE void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { __asm__ volatile ( @@ -169,6 +170,7 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_STARTCODE */
static pid_t getpid(void);
diff --git a/tools/include/nolibc/arch-x86.h b/tools/include/nolibc/arch-x86.h index d3efc0c3b8ad..b4981e99f0a0 100644 --- a/tools/include/nolibc/arch-x86.h +++ b/tools/include/nolibc/arch-x86.h @@ -164,6 +164,7 @@ * 2) The deepest stack frame should be set to zero * */ +#ifndef NOLIBC_NO_STARTCODE void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { __asm__ volatile ( @@ -176,6 +177,7 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_STARTCODE */
#else /* !defined(__x86_64__) */
@@ -330,6 +332,7 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s * 2) The deepest stack frame should be zero (the %rbp). * */ +#ifndef NOLIBC_NO_STARTCODE void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { __asm__ volatile ( @@ -340,6 +343,7 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_STARTCODE */
#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..d72e616eeec9 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_STARTCODE + #include "compiler.h"
char **environ __attribute__((weak)); @@ -88,4 +90,5 @@ void _start_c(long *sp) exit(exitcode); }
+#endif /* NOLIBC_NO_STARTCODE */ #endif /* _NOLIBC_CRT_H */ diff --git a/tools/include/nolibc/stackprotector.h b/tools/include/nolibc/stackprotector.h index c71a2c257177..3dd4d3e53ca6 100644 --- a/tools/include/nolibc/stackprotector.h +++ b/tools/include/nolibc/stackprotector.h @@ -9,6 +9,7 @@
#include "compiler.h"
+#ifndef NOLIBC_NO_STARTCODE #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_STARTCODE */
#endif /* _NOLIBC_STACKPROTECTOR_H */ diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index 5fd99a480f82..ed12c9119aab 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -107,6 +107,7 @@ void free(void *ptr) * environment variable exists its value is returned otherwise NULL is * returned. */ +#ifndef NOLIBC_NO_STARTCODE static __attribute__((unused)) char *getenv(const char *name) { @@ -122,6 +123,7 @@ char *getenv(const char *name) } return NULL; } +#endif /* NOLIBC_NO_STARTCODE */
static __attribute__((unused)) void *malloc(size_t len) diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index 295e71d34aba..c518a1b4af97 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_STARTCODE static unsigned long getauxval(unsigned long key);
/* @@ -520,7 +521,7 @@ int getpagesize(void) { return __sysret((int)getauxval(AT_PAGESZ) ?: -ENOENT); } - +#endif /* NOLIBC_NO_STARTCODE */
/* * uid_t getuid(void); diff --git a/tools/include/nolibc/sys/auxv.h b/tools/include/nolibc/sys/auxv.h index c52463d6c18d..35d339146463 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_STARTCODE + #include "../crt.h"
static __attribute__((unused)) @@ -38,4 +40,5 @@ unsigned long getauxval(unsigned long type) return ret; }
+#endif /* NOLIBC_NO_STARTCODE */ #endif /* _NOLIBC_SYS_AUXV_H */
On 2025-09-15 09:11:12+0200, Benjamin Berg wrote:
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_STARTCODE compile time option to disable it entirely and also remove anything that depends on it.
Not a big fan of the naming. More than only _start()/_start_c() are disabled. Maybe NOLIBC_NO_RUNTIME? I'm horrible at naming...
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
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..24ad348cc1e8 100644 --- a/tools/include/nolibc/arch-arm.h +++ b/tools/include/nolibc/arch-arm.h @@ -185,6 +185,7 @@ }) /* startup code */ +#ifndef NOLIBC_NO_STARTCODE
I'd prefer the ifdef around the comments.
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) { __asm__ volatile ( @@ -193,5 +194,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s ); __nolibc_entrypoint_epilogue(); } +#endif /* NOLIBC_NO_STARTCODE */
(...)
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.
Guard the syscall definition as it is a macro in nolibc.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com --- arch/um/Makefile | 21 ++++++++++++++++++++- arch/um/include/shared/os.h | 2 ++ arch/um/scripts/Makefile.rules | 8 +++++++- 3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/arch/um/Makefile b/arch/um/Makefile index a3f27d791cc0..54aa26fcc32b 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -78,6 +78,25 @@ 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__ -D__UM_NOLIBC__ \ + -DNOLIBC_NO_STARTCODE \ + -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 $(srctree)/include/generated/autoconf.h \ + -include $(srctree)/tools/include/linux/kconfig.h \ + -include $(srctree)/include/linux/kern_levels.h \ + -include $(srctree)/tools/include/nolibc/nolibc.h \ + -include $(srctree)/$(ARCH_DIR)/include/shared/user.h + #This will adjust *FLAGS accordingly to the platform. include $(srctree)/$(ARCH_DIR)/Makefile-os-Linux
@@ -157,4 +176,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..3e9f3ae61658 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);
+#ifndef syscall long syscall(long number, ...); +#endif
/* irqflags tracing */ extern void block_signals_trace(void); 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-15 09:11:13+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.
Guard the syscall definition as it is a macro in nolibc.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com
arch/um/Makefile | 21 ++++++++++++++++++++- arch/um/include/shared/os.h | 2 ++ arch/um/scripts/Makefile.rules | 8 +++++++- 3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/arch/um/Makefile b/arch/um/Makefile index a3f27d791cc0..54aa26fcc32b 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -78,6 +78,25 @@ 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__ -D__UM_NOLIBC__ \
-DNOLIBC_NO_STARTCODE \
-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 $(srctree)/include/generated/autoconf.h \
-include $(srctree)/tools/include/linux/kconfig.h \
-include $(srctree)/include/linux/kern_levels.h \
-include $(srctree)/tools/include/nolibc/nolibc.h \
This is not needed. It doesn't hurt though.
-include $(srctree)/$(ARCH_DIR)/include/shared/user.h
#This will adjust *FLAGS accordingly to the platform. include $(srctree)/$(ARCH_DIR)/Makefile-os-Linux @@ -157,4 +176,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..3e9f3ae61658 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); +#ifndef syscall
You could use 'ifndef NOLIBC' to make the reason clear.
long syscall(long number, ...); +#endif /* irqflags tracing */ extern void block_signals_trace(void);
(...)
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
From: Benjamin Berg benjamin.berg@intel.com
The registers.c file only contain the routines for floating point register access in ptrace mode and initial size detection. The file can be moved over to nolibc by replacing the ptrace libc call with a simple wrapper that does a direct syscall.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com --- arch/x86/um/os-Linux/Makefile | 5 ++++- arch/x86/um/os-Linux/registers.c | 22 ++++++++-------------- 2 files changed, 12 insertions(+), 15 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..55bce0d3f5d2 100644 --- a/arch/x86/um/os-Linux/registers.c +++ b/arch/x86/um/os-Linux/registers.c @@ -6,18 +6,20 @@
#include <errno.h> #include <stdlib.h> -#include <sys/ptrace.h> +#include <linux/ptrace.h> #ifdef __i386__ #include <sys/user.h> #endif #include <longjmp.h> #include <sysdep/ptrace_user.h> -#include <sys/uio.h> +#include <linux/uio.h> #include <asm/sigcontext.h> #include <linux/elf.h> #include <registers.h> #include <sys/mman.h>
+#define my_ptrace(...) my_syscall4(__NR_ptrace, __VA_ARGS__) + static unsigned long ptrace_regset; unsigned long host_fp_size;
@@ -28,9 +30,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 my_ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov); }
int put_fp_registers(int pid, unsigned long *regs) @@ -40,9 +40,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 my_ptrace(PTRACE_SETREGSET, pid, ptrace_regset, &iov); }
int arch_init_registers(int pid) @@ -60,9 +58,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 = my_ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov);
if (ret == -ENODEV) { #ifdef CONFIG_X86_32 @@ -71,9 +67,7 @@ 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 = my_ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov); }
munmap(iov.iov_base, 2 * 1024 * 1024);
On 2025-09-15 09:11:15+0200, Benjamin Berg wrote:
From: Benjamin Berg benjamin.berg@intel.com
The registers.c file only contain the routines for floating point register access in ptrace mode and initial size detection. The file can be moved over to nolibc by replacing the ptrace libc call with a simple wrapper that does a direct syscall.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com
arch/x86/um/os-Linux/Makefile | 5 ++++- arch/x86/um/os-Linux/registers.c | 22 ++++++++-------------- 2 files changed, 12 insertions(+), 15 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..55bce0d3f5d2 100644 --- a/arch/x86/um/os-Linux/registers.c +++ b/arch/x86/um/os-Linux/registers.c @@ -6,18 +6,20 @@ #include <errno.h>
Given that you are explicitly disabling errno support for nolibc, is this include necessary?
#include <stdlib.h> -#include <sys/ptrace.h> +#include <linux/ptrace.h> #ifdef __i386__ #include <sys/user.h> #endif #include <longjmp.h> #include <sysdep/ptrace_user.h> -#include <sys/uio.h> +#include <linux/uio.h>
It looks fairly trivial to add sys/uio.h to nolibc. Only 'struct iovec' (already provided by the UAPI) and readv()/writev() are necessary.
#include <asm/sigcontext.h> #include <linux/elf.h> #include <registers.h> #include <sys/mman.h> +#define my_ptrace(...) my_syscall4(__NR_ptrace, __VA_ARGS__)
Why not add sys/ptrace.h to nolibc and then use sys_ptrace()? In general I'm not a fan of the my_syscall() naming scheme and would like to change this in nolibc itself, so having fewer external users would be nice.
static unsigned long ptrace_regset; unsigned long host_fp_size;
(...)
Hi,
On Mon, 2025-09-15 at 11:07 +0200, Thomas Weißschuh wrote:
On 2025-09-15 09:11:15+0200, Benjamin Berg wrote:
From: Benjamin Berg benjamin.berg@intel.com
The registers.c file only contain the routines for floating point register access in ptrace mode and initial size detection. The file can be moved over to nolibc by replacing the ptrace libc call with a simple wrapper that does a direct syscall.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com
arch/x86/um/os-Linux/Makefile | 5 ++++- arch/x86/um/os-Linux/registers.c | 22 ++++++++-------------- 2 files changed, 12 insertions(+), 15 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..55bce0d3f5d2 100644 --- a/arch/x86/um/os-Linux/registers.c +++ b/arch/x86/um/os-Linux/registers.c @@ -6,18 +6,20 @@ #include <errno.h>
Given that you are explicitly disabling errno support for nolibc, is this include necessary?
I think it is technically correct as we do need ENODEV and ENOMEM to be defined. Not that we actually need the include if we pull in nolibc.h.
Considering we would never build against libc, should we maybe just do an explicit nolibc.h include and rely on it pulling in the rest automatically? That seems a bit weird to me, but as-is we will never notice when we forget an include.
#include <stdlib.h> -#include <sys/ptrace.h> +#include <linux/ptrace.h> #ifdef __i386__ #include <sys/user.h> #endif #include <longjmp.h> #include <sysdep/ptrace_user.h> -#include <sys/uio.h> +#include <linux/uio.h>
It looks fairly trivial to add sys/uio.h to nolibc. Only 'struct iovec' (already provided by the UAPI) and readv()/writev() are necessary.
#include <asm/sigcontext.h> #include <linux/elf.h> #include <registers.h> #include <sys/mman.h> +#define my_ptrace(...) my_syscall4(__NR_ptrace, __VA_ARGS__)
Why not add sys/ptrace.h to nolibc and then use sys_ptrace()?
Honestly, I just got a bit lazy at that point and this was a reasonable proof that mixing nolibc with libc works fine. You are absolutely right that it would be better to add this to nolibc.
In general I'm not a fan of the my_syscall() naming scheme and would like to change this in nolibc itself, so having fewer external users would be nice.
How about adding a sys_syscall macro? That would match the naming scheme of the other functions. Then, once all users are ported, one can simply change the my_ prefix to __nolibc_.
Benjamin
static unsigned long ptrace_regset; unsigned long host_fp_size;
(...)
Intel Deutschland GmbH Registered Address: Am Campeon 10, 85579 Neubiberg, Germany Tel: +49 89 99 8853-0, www.intel.de Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva Chairperson of the Supervisory Board: Nicole Lau Registered Office: Munich Commercial Register: Amtsgericht Muenchen HRB 186928
On 2025-09-15 11:09:40+0000, Berg, Benjamin wrote:
On Mon, 2025-09-15 at 11:07 +0200, Thomas Weißschuh wrote:
On 2025-09-15 09:11:15+0200, Benjamin Berg wrote:
From: Benjamin Berg benjamin.berg@intel.com
The registers.c file only contain the routines for floating point register access in ptrace mode and initial size detection. The file can be moved over to nolibc by replacing the ptrace libc call with a simple wrapper that does a direct syscall.
Signed-off-by: Benjamin Berg benjamin.berg@intel.com
arch/x86/um/os-Linux/Makefile | 5 ++++- arch/x86/um/os-Linux/registers.c | 22 ++++++++-------------- 2 files changed, 12 insertions(+), 15 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..55bce0d3f5d2 100644 --- a/arch/x86/um/os-Linux/registers.c +++ b/arch/x86/um/os-Linux/registers.c @@ -6,18 +6,20 @@ #include <errno.h>
Given that you are explicitly disabling errno support for nolibc, is this include necessary?
I think it is technically correct as we do need ENODEV and ENOMEM to be defined. Not that we actually need the include if we pull in nolibc.h.
Yes, indeed.
Considering we would never build against libc, should we maybe just do an explicit nolibc.h include and rely on it pulling in the rest automatically? That seems a bit weird to me, but as-is we will never notice when we forget an include.
Your choice. nolibc will always include itself fully transitively in any case. So you won't notice a missing include that way either. The different headers mostly exist to structure the nolibc sources themselves and to let the application code look normal. I would go with normal includes.
#include <stdlib.h> -#include <sys/ptrace.h> +#include <linux/ptrace.h> #ifdef __i386__ #include <sys/user.h> #endif #include <longjmp.h> #include <sysdep/ptrace_user.h> -#include <sys/uio.h> +#include <linux/uio.h>
It looks fairly trivial to add sys/uio.h to nolibc. Only 'struct iovec' (already provided by the UAPI) and readv()/writev() are necessary.
#include <asm/sigcontext.h> #include <linux/elf.h> #include <registers.h> #include <sys/mman.h> +#define my_ptrace(...) my_syscall4(__NR_ptrace, __VA_ARGS__)
Why not add sys/ptrace.h to nolibc and then use sys_ptrace()?
Honestly, I just got a bit lazy at that point and this was a reasonable proof that mixing nolibc with libc works fine.
Fair enough :-)
You are absolutely right that it would be better to add this to nolibc.
In general I'm not a fan of the my_syscall() naming scheme and would like to change this in nolibc itself, so having fewer external users would be nice.
How about adding a sys_syscall macro? That would match the naming scheme of the other functions. Then, once all users are ported, one can simply change the my_ prefix to __nolibc_.
sys_syscall() looks weird. Personally I would have gone with _syscall(). Let's just sidestep the issue for now by adding sys_ptrace() to nolibc.
(...)
linux-kselftest-mirror@lists.linaro.org