linux_kselftest-nolibc-6.12-rc1

This nolibc update for Linux 6.12-rc1 consists of:
 
 Highlights
 ----------
 
 * Clang support (including LTO)
 
 Other Changes
 -------------
 
 * stdbool.h support
 * argc/argv/envp arguments for constructors
 * Small #include ordering fix
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEPZKym/RZuOCGeA/kCwJExA0NQxwFAmbovjQACgkQCwJExA0N
 QxzUlQ//W82aSMj5UVFtTvIsezeN87JbS1kswzynqlm4bpNfDlwdF1Ui3WrhTWpt
 PcRzJtTOq1jQL2snvC7yihbcgEnsKkxgdCVwYlc1RYFd4+baUjZg5409taQHfzo9
 kWat4fsCK+Bev5oHlyMXxEysHhd2LqLwheHmqh+yfMNGFHrzlTwkgAXYU4PvJ2mG
 IQto22xAuf5Y1S2vLTrz4DbM8/qa2gEk17U9rbXcGDCH0IaTYTBswLDCZAzoB/N5
 BuERfa2CjXFvWlun8vSCNkPMKKYR37qPdoRdgGzvque9eUZTfzvbZ4IFE8uGolxn
 P03S57KwNPBsq9/8VPKVJDFvrGl/wdNgNdsyKBtJA4yXAi60kma+q5D2UE+aU9fX
 qBnkcyv6pUTvnJprVqaEy7w0u42/laDQfiIW9lnQEueThmYvaT028NihrNH3VFNp
 nVt26v4JPFXz2uWDk6ZgO6EKmSlBxAAr7AD5vg979XgNyMVZuXzEuh97MTL2yeTZ
 s0N49VW95URshjlQdjC1rTI6dV6bSslgbaEYqVofYTYBidZqTfKMVdn4qyn0scL/
 5DPe3q7xkgRpeLxHqNbwtrhLBzHR6FYllRlXWuP4hdpNjMYIpIUGpMW8420Dj0KN
 0WfMQteQovQwrtqEbOXUiJ853hEwCJVMBWLVOWxMwcOingk/VjQ=
 =DswX
 -----END PGP SIGNATURE-----

Merge tag 'linux_kselftest-nolibc-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull nolibc updates from Shuah Khan:
 "Highlights:

   - Clang support (including LTO)

  Other Changes:

   - stdbool.h support

   - argc/argv/envp arguments for constructors

   - Small #include ordering fix"

* tag 'linux_kselftest-nolibc-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (21 commits)
  tools/nolibc: x86_64: use local label in memcpy/memmove
  tools/nolibc: stackprotector: mark implicitly used symbols as used
  tools/nolibc: crt: mark _start_c() as used
  selftests/nolibc: run-tests.sh: allow building through LLVM
  selftests/nolibc: use correct clang target for s390/systemz
  selftests/nolibc: don't use libgcc when building with clang
  selftests/nolibc: run-tests.sh: avoid overwriting CFLAGS_EXTRA
  selftests/nolibc: add cc-option compatible with clang cross builds
  selftests/nolibc: add support for LLVM= parameter
  selftests/nolibc: determine $(srctree) first
  selftests/nolibc: avoid passing NULL to printf("%s")
  selftests/nolibc: report failure if no testcase passed
  tools/nolibc: compiler: use attribute((naked)) if available
  tools/nolibc: move entrypoint specifics to compiler.h
  tools/nolibc: compiler: introduce __nolibc_has_attribute()
  tools/nolibc: powerpc: limit stack-protector workaround to GCC
  tools/nolibc: mips: load current function to $t9
  tools/nolibc: arm: use clang-compatible asm syntax
  tools/nolibc: pass argc, argv and envp to constructors
  tools/nolibc: add stdbool.h header
  ...
This commit is contained in:
Linus Torvalds 2024-09-17 16:47:17 +02:00
commit 395b15778e
19 changed files with 123 additions and 67 deletions

View File

@ -35,6 +35,7 @@ all_files := \
stackprotector.h \
std.h \
stdarg.h \
stdbool.h \
stdint.h \
stdlib.h \
string.h \

View File

@ -142,13 +142,13 @@
})
/* startup code */
void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
{
__asm__ volatile (
"mov x0, sp\n" /* save stack pointer to x0, as arg1 of _start_c */
"and sp, x0, -16\n" /* sp must be 16-byte aligned in the callee */
"bl _start_c\n" /* transfer to c runtime */
);
__builtin_unreachable();
__nolibc_entrypoint_epilogue();
}
#endif /* _NOLIBC_ARCH_AARCH64_H */

View File

@ -185,15 +185,15 @@
})
/* startup code */
void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
{
__asm__ volatile (
"mov %r0, sp\n" /* save stack pointer to %r0, as arg1 of _start_c */
"and ip, %r0, #-8\n" /* sp must be 8-byte aligned in the callee */
"mov r0, sp\n" /* save stack pointer to %r0, as arg1 of _start_c */
"and ip, r0, #-8\n" /* sp must be 8-byte aligned in the callee */
"mov sp, ip\n"
"bl _start_c\n" /* transfer to c runtime */
);
__builtin_unreachable();
__nolibc_entrypoint_epilogue();
}
#endif /* _NOLIBC_ARCH_ARM_H */

View File

@ -162,7 +162,7 @@
* 2) The deepest stack frame should be set to zero
*
*/
void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
{
__asm__ volatile (
"xor %ebp, %ebp\n" /* zero the stack frame */
@ -174,7 +174,7 @@ void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_
"call _start_c\n" /* transfer to c runtime */
"hlt\n" /* ensure it does not return */
);
__builtin_unreachable();
__nolibc_entrypoint_epilogue();
}
#endif /* _NOLIBC_ARCH_I386_H */

View File

@ -149,14 +149,14 @@
#endif
/* startup code */
void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
{
__asm__ volatile (
"move $a0, $sp\n" /* save stack pointer to $a0, as arg1 of _start_c */
LONG_BSTRINS " $sp, $zero, 3, 0\n" /* $sp must be 16-byte aligned */
"bl _start_c\n" /* transfer to c runtime */
);
__builtin_unreachable();
__nolibc_entrypoint_epilogue();
}
#endif /* _NOLIBC_ARCH_LOONGARCH_H */

View File

@ -179,7 +179,7 @@
})
/* startup code, note that it's called __start on MIPS */
void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector __start(void)
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector __start(void)
{
__asm__ volatile (
".set push\n"
@ -194,11 +194,13 @@ void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_
"li $t0, -8\n"
"and $sp, $sp, $t0\n" /* $sp must be 8-byte aligned */
"addiu $sp, $sp, -16\n" /* the callee expects to save a0..a3 there */
"jal _start_c\n" /* transfer to c runtime */
"lui $t9, %hi(_start_c)\n" /* ABI requires current function address in $t9 */
"ori $t9, %lo(_start_c)\n"
"jalr $t9\n" /* transfer to c runtime */
" nop\n" /* delayed slot */
".set pop\n"
);
__builtin_unreachable();
__nolibc_entrypoint_epilogue();
}
#endif /* _NOLIBC_ARCH_MIPS_H */

View File

@ -172,7 +172,7 @@
_ret; \
})
#ifndef __powerpc64__
#if !defined(__powerpc64__) && !defined(__clang__)
/* FIXME: For 32-bit PowerPC, with newer gcc compilers (e.g. gcc 13.1.0),
* "omit-frame-pointer" fails with __attribute__((no_stack_protector)) but
* works with __attribute__((__optimize__("-fno-stack-protector")))
@ -184,7 +184,7 @@
#endif /* !__powerpc64__ */
/* startup code */
void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
{
#ifdef __powerpc64__
#if _CALL_ELF == 2
@ -215,7 +215,7 @@ void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_
"bl _start_c\n" /* transfer to c runtime */
);
#endif
__builtin_unreachable();
__nolibc_entrypoint_epilogue();
}
#endif /* _NOLIBC_ARCH_POWERPC_H */

View File

@ -140,7 +140,7 @@
})
/* startup code */
void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
{
__asm__ volatile (
".option push\n"
@ -151,7 +151,7 @@ void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_
"andi sp, a0, -16\n" /* sp must be 16-byte aligned */
"call _start_c\n" /* transfer to c runtime */
);
__builtin_unreachable();
__nolibc_entrypoint_epilogue();
}
#endif /* _NOLIBC_ARCH_RISCV_H */

View File

@ -139,7 +139,7 @@
})
/* startup code */
void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
{
__asm__ volatile (
"lgr %r2, %r15\n" /* save stack pointer to %r2, as arg1 of _start_c */
@ -147,7 +147,7 @@ void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_
"xc 0(8,%r15), 0(%r15)\n" /* clear backchain */
"brasl %r14, _start_c\n" /* transfer to c runtime */
);
__builtin_unreachable();
__nolibc_entrypoint_epilogue();
}
struct s390_mmap_arg_struct {

View File

@ -161,7 +161,7 @@
* 2) The deepest stack frame should be zero (the %rbp).
*
*/
void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
{
__asm__ volatile (
"xor %ebp, %ebp\n" /* zero the stack frame */
@ -170,7 +170,7 @@ void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_
"call _start_c\n" /* transfer to c runtime */
"hlt\n" /* ensure it does not return */
);
__builtin_unreachable();
__nolibc_entrypoint_epilogue();
}
#define NOLIBC_ARCH_HAS_MEMMOVE
@ -193,10 +193,10 @@ __asm__ (
"movq %rdi, %rdx\n\t"
"subq %rsi, %rdx\n\t"
"cmpq %rcx, %rdx\n\t"
"jb .Lbackward_copy\n\t"
"jb 1f\n\t"
"rep movsb\n\t"
"retq\n"
".Lbackward_copy:"
"1:" /* backward copy */
"leaq -1(%rdi, %rcx, 1), %rdi\n\t"
"leaq -1(%rsi, %rcx, 1), %rsi\n\t"
"std\n\t"

View File

@ -6,20 +6,30 @@
#ifndef _NOLIBC_COMPILER_H
#define _NOLIBC_COMPILER_H
#if defined(__has_attribute)
# define __nolibc_has_attribute(attr) __has_attribute(attr)
#else
# define __nolibc_has_attribute(attr) 0
#endif
#if __nolibc_has_attribute(naked)
# define __nolibc_entrypoint __attribute__((naked))
# define __nolibc_entrypoint_epilogue()
#else
# define __nolibc_entrypoint __attribute__((optimize("Os", "omit-frame-pointer")))
# define __nolibc_entrypoint_epilogue() __builtin_unreachable()
#endif /* __nolibc_has_attribute(naked) */
#if defined(__SSP__) || defined(__SSP_STRONG__) || defined(__SSP_ALL__) || defined(__SSP_EXPLICIT__)
#define _NOLIBC_STACKPROTECTOR
#endif /* defined(__SSP__) ... */
#if defined(__has_attribute)
# if __has_attribute(no_stack_protector)
# define __no_stack_protector __attribute__((no_stack_protector))
# else
# define __no_stack_protector __attribute__((__optimize__("-fno-stack-protector")))
# endif
#if __nolibc_has_attribute(no_stack_protector)
# define __no_stack_protector __attribute__((no_stack_protector))
#else
# define __no_stack_protector __attribute__((__optimize__("-fno-stack-protector")))
#endif /* defined(__has_attribute) */
#endif /* __nolibc_has_attribute(no_stack_protector) */
#endif /* _NOLIBC_COMPILER_H */

View File

@ -13,23 +13,24 @@ const unsigned long *_auxv __attribute__((weak));
static void __stack_chk_init(void);
static void exit(int);
extern void (*const __preinit_array_start[])(void) __attribute__((weak));
extern void (*const __preinit_array_end[])(void) __attribute__((weak));
extern void (*const __preinit_array_start[])(int, char **, char**) __attribute__((weak));
extern void (*const __preinit_array_end[])(int, char **, char**) __attribute__((weak));
extern void (*const __init_array_start[])(void) __attribute__((weak));
extern void (*const __init_array_end[])(void) __attribute__((weak));
extern void (*const __init_array_start[])(int, char **, char**) __attribute__((weak));
extern void (*const __init_array_end[])(int, char **, char**) __attribute__((weak));
extern void (*const __fini_array_start[])(void) __attribute__((weak));
extern void (*const __fini_array_end[])(void) __attribute__((weak));
__attribute__((weak))
__attribute__((weak,used))
void _start_c(long *sp)
{
long argc;
char **argv;
char **envp;
int exitcode;
void (* const *func)(void);
void (* const *ctor_func)(int, char **, char **);
void (* const *dtor_func)(void);
const unsigned long *auxv;
/* silence potential warning: conflicting types for 'main' */
int _nolibc_main(int, char **, char **) __asm__ ("main");
@ -66,16 +67,16 @@ void _start_c(long *sp)
;
_auxv = auxv;
for (func = __preinit_array_start; func < __preinit_array_end; func++)
(*func)();
for (func = __init_array_start; func < __init_array_end; func++)
(*func)();
for (ctor_func = __preinit_array_start; ctor_func < __preinit_array_end; ctor_func++)
(*ctor_func)(argc, argv, envp);
for (ctor_func = __init_array_start; ctor_func < __init_array_end; ctor_func++)
(*ctor_func)(argc, argv, envp);
/* go to application */
exitcode = _nolibc_main(argc, argv, envp);
for (func = __fini_array_end; func > __fini_array_start;)
(*--func)();
for (dtor_func = __fini_array_end; dtor_func > __fini_array_start;)
(*--dtor_func)();
exit(exitcode);
}

View File

@ -74,7 +74,8 @@
* -I../nolibc -o hello hello.c -lgcc
*
* The available standard (but limited) include files are:
* ctype.h, errno.h, signal.h, stdarg.h, stdio.h, stdlib.h, string.h, time.h
* ctype.h, errno.h, signal.h, stdarg.h, stdbool.h stdio.h, stdlib.h,
* string.h, time.h
*
* In addition, the following ones are expected to be provided by the compiler:
* float.h, stddef.h

View File

@ -18,7 +18,7 @@
* triggering stack protector errors themselves
*/
__attribute__((weak,noreturn,section(".text.nolibc_stack_chk")))
__attribute__((weak,used,noreturn,section(".text.nolibc_stack_chk")))
void __stack_chk_fail(void)
{
pid_t pid;
@ -34,7 +34,7 @@ void __stack_chk_fail_local(void)
__stack_chk_fail();
}
__attribute__((weak,section(".data.nolibc_stack_chk")))
__attribute__((weak,used,section(".data.nolibc_stack_chk")))
uintptr_t __stack_chk_guard;
static __no_stack_protector void __stack_chk_init(void)

View File

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
/*
* Boolean types support for NOLIBC
* Copyright (C) 2024 Thomas Weißschuh <linux@weissschuh.net>
*/
#ifndef _NOLIBC_STDBOOL_H
#define _NOLIBC_STDBOOL_H
#define bool _Bool
#define true 1
#define false 0
#define __bool_true_false_are_defined 1
#endif /* _NOLIBC_STDBOOL_H */

View File

@ -7,6 +7,7 @@
#ifndef _NOLIBC_STRING_H
#define _NOLIBC_STRING_H
#include "arch.h"
#include "std.h"
static void *malloc(size_t len);

View File

@ -1,19 +1,21 @@
# SPDX-License-Identifier: GPL-2.0
# Makefile for nolibc tests
include ../../../scripts/Makefile.include
include ../../../scripts/utilities.mak
# We need this for the "cc-option" macro.
include ../../../build/Build.include
# we're in ".../tools/testing/selftests/nolibc"
ifeq ($(srctree),)
srctree := $(patsubst %/tools/testing/selftests/,%,$(dir $(CURDIR)))
endif
include $(srctree)/tools/scripts/utilities.mak
# We need this for the "__cc-option" macro.
include $(srctree)/scripts/Makefile.compiler
ifneq ($(O),)
ifneq ($(call is-absolute,$(O)),y)
$(error Only absolute O= parameters are supported)
endif
endif
# we're in ".../tools/testing/selftests/nolibc"
ifeq ($(srctree),)
srctree := $(patsubst %/tools/testing/selftests/,%,$(dir $(CURDIR)))
objtree := $(O)
else
objtree ?= $(srctree)
endif
ifeq ($(ARCH),)
@ -21,7 +23,7 @@ include $(srctree)/scripts/subarch.include
ARCH = $(SUBARCH)
endif
objtree ?= $(srctree)
cc-option = $(call __cc-option, $(CC),$(CLANG_CROSS_FLAGS),$(1),$(2))
# XARCH extends the kernel's ARCH with a few variants of the same
# architecture that only differ by the configuration, the toolchain
@ -155,9 +157,22 @@ CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 -W -Wall -Wex
$(CFLAGS_$(XARCH)) $(CFLAGS_STACKPROTECTOR) $(CFLAGS_EXTRA)
LDFLAGS :=
LIBGCC := -lgcc
ifneq ($(LLVM),)
# Not needed for clang
LIBGCC :=
endif
# Modify CFLAGS based on LLVM=
include $(srctree)/tools/scripts/Makefile.include
# GCC uses "s390", clang "systemz"
CLANG_CROSS_FLAGS := $(subst --target=s390-linux,--target=systemz-linux,$(CLANG_CROSS_FLAGS))
REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{if (!f) printf("\n"); f++; print;} /\[SKIPPED\][\r]*$$/{s++} \
END{ printf("\n%3d test(s): %3d passed, %3d skipped, %3d failed => status: ", p+s+f, p, s, f); \
if (f) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \
if (f || !p) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \
printf("\nSee all results in %s\n", ARGV[1]); }'
help:
@ -204,11 +219,11 @@ sysroot/$(ARCH)/include:
ifneq ($(NOLIBC_SYSROOT),0)
nolibc-test: nolibc-test.c nolibc-test-linkage.c sysroot/$(ARCH)/include
$(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \
-nostdlib -nostdinc -static -Isysroot/$(ARCH)/include nolibc-test.c nolibc-test-linkage.c -lgcc
-nostdlib -nostdinc -static -Isysroot/$(ARCH)/include nolibc-test.c nolibc-test-linkage.c $(LIBGCC)
else
nolibc-test: nolibc-test.c nolibc-test-linkage.c
$(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \
-nostdlib -static -include $(srctree)/tools/include/nolibc/nolibc.h nolibc-test.c nolibc-test-linkage.c -lgcc
-nostdlib -static -include $(srctree)/tools/include/nolibc/nolibc.h nolibc-test.c nolibc-test-linkage.c $(LIBGCC)
endif
libc-test: nolibc-test.c nolibc-test-linkage.c

View File

@ -542,7 +542,7 @@ int expect_strzr(const char *expr, int llen)
{
int ret = 0;
llen += printf(" = <%s> ", expr);
llen += printf(" = <%s> ", expr ? expr : "(null)");
if (expr) {
ret = 1;
result(llen, FAIL);
@ -561,7 +561,7 @@ int expect_strnz(const char *expr, int llen)
{
int ret = 0;
llen += printf(" = <%s> ", expr);
llen += printf(" = <%s> ", expr ? expr : "(null)");
if (!expr) {
ret = 1;
result(llen, FAIL);
@ -686,9 +686,10 @@ static void constructor1(void)
}
__attribute__((constructor))
static void constructor2(void)
static void constructor2(int argc, char **argv, char **envp)
{
constructor_test_value *= 2;
if (argc && argv && envp)
constructor_test_value *= 2;
}
int run_startup(int min, int max)

View File

@ -15,10 +15,11 @@ download_location="${cache_dir}/crosstools/"
build_location="$(realpath "${cache_dir}"/nolibc-tests/)"
perform_download=0
test_mode=system
CFLAGS_EXTRA="-Werror"
werror=1
llvm=
archs="i386 x86_64 arm64 arm mips32le mips32be ppc ppc64 ppc64le riscv s390 loongarch"
TEMP=$(getopt -o 'j:d:c:b:a:m:peh' -n "$0" -- "$@")
TEMP=$(getopt -o 'j:d:c:b:a:m:pelh' -n "$0" -- "$@")
eval set -- "$TEMP"
unset TEMP
@ -42,6 +43,7 @@ Options:
-b [DIR] Build location (default: ${build_location})
-m [MODE] Test mode user/system (default: ${test_mode})
-e Disable -Werror
-l Build with LLVM/clang
EOF
}
@ -69,7 +71,10 @@ while true; do
test_mode="$2"
shift 2; continue ;;
'-e')
CFLAGS_EXTRA=""
werror=0
shift; continue ;;
'-l')
llvm=1
shift; continue ;;
'-h')
print_usage
@ -140,7 +145,10 @@ test_arch() {
ct_abi=$(crosstool_abi "$1")
cross_compile=$(realpath "${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}/bin/${ct_arch}-${ct_abi}-")
build_dir="${build_location}/${arch}"
MAKE=(make -j"${nproc}" XARCH="${arch}" CROSS_COMPILE="${cross_compile}" O="${build_dir}")
if [ "$werror" -ne 0 ]; then
CFLAGS_EXTRA="$CFLAGS_EXTRA -Werror"
fi
MAKE=(make -j"${nproc}" XARCH="${arch}" CROSS_COMPILE="${cross_compile}" LLVM="${llvm}" O="${build_dir}")
mkdir -p "$build_dir"
if [ "$test_mode" = "system" ] && [ ! -f "${build_dir}/.config" ]; then