The current support for LLVM and clang in nolibc and its testsuite is very limited.
* Various architectures plain do not compile * The user *has* to specify "-Os" otherwise the program crashes * Cross-compilation of the tests does not work * Using clang is not wired up in run-tests.sh
This series extends this support.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- Changes in v2: - Add support for all architectures - powerpc: "selftests/nolibc: don't use libgcc when building with clang" - mips: "tools/nolibc: mips: load current function to $t9" - s390: "selftests/nolibc: use correct clang target for s390/powerz" - Expand commit messages - Use __nolibc_ prefix for custom macros - Link to v1: https://lore.kernel.org/r/20240728-nolibc-llvm-v1-0-bc384269bc35@weissschuh....
--- Thomas Weißschuh (15): tools/nolibc: arm: use clang-compatible asm syntax tools/nolibc: mips: load current function to $t9 tools/nolibc: powerpc: limit stack-protector workaround to GCC tools/nolibc: compiler: introduce __nolibc_has_attribute() tools/nolibc: move entrypoint specifics to compiler.h tools/nolibc: compiler: use attribute((naked)) if available selftests/nolibc: report failure if no testcase passed selftests/nolibc: avoid passing NULL to printf("%s") selftests/nolibc: determine $(srctree) first selftests/nolibc: add support for LLVM= parameter selftests/nolibc: add cc-option compatible with clang cross builds selftests/nolibc: run-tests.sh: avoid overwriting CFLAGS_EXTRA selftests/nolibc: don't use libgcc when building with clang selftests/nolibc: use correct clang target for s390/powerz selftests/nolibc: run-tests.sh: allow building through LLVM
tools/include/nolibc/arch-aarch64.h | 4 +-- tools/include/nolibc/arch-arm.h | 8 +++--- tools/include/nolibc/arch-i386.h | 4 +-- tools/include/nolibc/arch-loongarch.h | 4 +-- tools/include/nolibc/arch-mips.h | 8 ++++-- tools/include/nolibc/arch-powerpc.h | 6 ++-- tools/include/nolibc/arch-riscv.h | 4 +-- tools/include/nolibc/arch-s390.h | 4 +-- tools/include/nolibc/arch-x86_64.h | 4 +-- tools/include/nolibc/compiler.h | 24 +++++++++++----- tools/testing/selftests/nolibc/Makefile | 41 +++++++++++++++++++--------- tools/testing/selftests/nolibc/nolibc-test.c | 4 +-- tools/testing/selftests/nolibc/run-tests.sh | 16 ++++++++--- 13 files changed, 83 insertions(+), 48 deletions(-) --- base-commit: ae1f550efc11eaf1496c431d9c6e784cb49124c5 change-id: 20240727-nolibc-llvm-3fad68590d4c
Best regards,
The clang assembler rejects the current syntax. Switch to a syntax accepted by both GCC and clang.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/arch-arm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/include/nolibc/arch-arm.h b/tools/include/nolibc/arch-arm.h index cae4afa7c1c7..d1c19d973e55 100644 --- a/tools/include/nolibc/arch-arm.h +++ b/tools/include/nolibc/arch-arm.h @@ -188,8 +188,8 @@ void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __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 */ );
The MIPS calling convention requires the address of the current function to be available in $t9. This was not done so far.
For GCC this seems to have worked, but when compiled with clang the executable segfault instantly. Properly load the address of _start_c() into $t9 before calling it.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/arch-mips.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h index 62cc50ef3288..a2ee77ed2fbb 100644 --- a/tools/include/nolibc/arch-mips.h +++ b/tools/include/nolibc/arch-mips.h @@ -194,7 +194,9 @@ 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" );
As mentioned in the comment, the workaround for __attribute__((no_stack_protector)) is only necessary on GCC. Avoid applying the workaround on clang, as clang does not recognize __attribute__((__optimize__)) and would fail.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/arch-powerpc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/include/nolibc/arch-powerpc.h b/tools/include/nolibc/arch-powerpc.h index ac212e6185b2..41ebd394b90c 100644 --- a/tools/include/nolibc/arch-powerpc.h +++ b/tools/include/nolibc/arch-powerpc.h @@ -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")))
Recent compilers support __has_attribute() to check if a certain compiler attribute is supported. Unfortunately we have to first check if __has_attribute is supported in the first place and then if a specific attribute is present. These two checks can't be folded into a single condition as that would lead to errors.
Nesting the two conditions like below works, but becomes ugly as soon as #else blocks are used as those need to be duplicated for both levels of #if.
#if defined __has_attribute # if __has_attribute (nonnull) # define ATTR_NONNULL __attribute__ ((nonnull)) # endif #endif
Introduce a new helper which makes the usage of __has_attribute() nicer and migrate the current user to it.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/compiler.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/tools/include/nolibc/compiler.h b/tools/include/nolibc/compiler.h index beddc3665d69..1730d0454a55 100644 --- a/tools/include/nolibc/compiler.h +++ b/tools/include/nolibc/compiler.h @@ -6,20 +6,22 @@ #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 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 */
The specific attributes for the _start entrypoint are duplicated for each architecture. Deduplicate it into a dedicated #define into compiler.h. The macros are similar to attribute((naked)), so adopt that naming. This make the code shorter and will make it easier to adapt for clang compatibility.
For clang compatibility, the epilogue will also need to be adapted, so move that one, too.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/arch-aarch64.h | 4 ++-- tools/include/nolibc/arch-arm.h | 4 ++-- tools/include/nolibc/arch-i386.h | 4 ++-- tools/include/nolibc/arch-loongarch.h | 4 ++-- tools/include/nolibc/arch-mips.h | 4 ++-- tools/include/nolibc/arch-powerpc.h | 4 ++-- tools/include/nolibc/arch-riscv.h | 4 ++-- tools/include/nolibc/arch-s390.h | 4 ++-- tools/include/nolibc/arch-x86_64.h | 4 ++-- tools/include/nolibc/compiler.h | 3 +++ 10 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/tools/include/nolibc/arch-aarch64.h b/tools/include/nolibc/arch-aarch64.h index b23ac1f04035..eb77de57e7ca 100644 --- a/tools/include/nolibc/arch-aarch64.h +++ b/tools/include/nolibc/arch-aarch64.h @@ -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_naked __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_naked_epilogue(); } #endif /* _NOLIBC_ARCH_AARCH64_H */ diff --git a/tools/include/nolibc/arch-arm.h b/tools/include/nolibc/arch-arm.h index d1c19d973e55..d22aa4d469d4 100644 --- a/tools/include/nolibc/arch-arm.h +++ b/tools/include/nolibc/arch-arm.h @@ -185,7 +185,7 @@ })
/* startup code */ -void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void) +void __attribute__((weak, noreturn)) __nolibc_naked __no_stack_protector _start(void) { __asm__ volatile ( "mov r0, sp\n" /* save stack pointer to %r0, as arg1 of _start_c */ @@ -193,7 +193,7 @@ void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_ "mov sp, ip\n" "bl _start_c\n" /* transfer to c runtime */ ); - __builtin_unreachable(); + __nolibc_naked_epilogue(); }
#endif /* _NOLIBC_ARCH_ARM_H */ diff --git a/tools/include/nolibc/arch-i386.h b/tools/include/nolibc/arch-i386.h index 28c26a00a762..054babfe41f8 100644 --- a/tools/include/nolibc/arch-i386.h +++ b/tools/include/nolibc/arch-i386.h @@ -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_naked __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_naked_epilogue(); }
#endif /* _NOLIBC_ARCH_I386_H */ diff --git a/tools/include/nolibc/arch-loongarch.h b/tools/include/nolibc/arch-loongarch.h index 3f8ef8f86c0f..8cacf03cbdf4 100644 --- a/tools/include/nolibc/arch-loongarch.h +++ b/tools/include/nolibc/arch-loongarch.h @@ -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_naked __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_naked_epilogue(); }
#endif /* _NOLIBC_ARCH_LOONGARCH_H */ diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h index a2ee77ed2fbb..cca3e325ef94 100644 --- a/tools/include/nolibc/arch-mips.h +++ b/tools/include/nolibc/arch-mips.h @@ -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_naked __no_stack_protector __start(void) { __asm__ volatile ( ".set push\n" @@ -200,7 +200,7 @@ void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_ " nop\n" /* delayed slot */ ".set pop\n" ); - __builtin_unreachable(); + __nolibc_naked_epilogue(); }
#endif /* _NOLIBC_ARCH_MIPS_H */ diff --git a/tools/include/nolibc/arch-powerpc.h b/tools/include/nolibc/arch-powerpc.h index 41ebd394b90c..a5b2a0403a80 100644 --- a/tools/include/nolibc/arch-powerpc.h +++ b/tools/include/nolibc/arch-powerpc.h @@ -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_naked __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_naked_epilogue(); }
#endif /* _NOLIBC_ARCH_POWERPC_H */ diff --git a/tools/include/nolibc/arch-riscv.h b/tools/include/nolibc/arch-riscv.h index 1927c643c739..3b0392353e4d 100644 --- a/tools/include/nolibc/arch-riscv.h +++ b/tools/include/nolibc/arch-riscv.h @@ -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_naked __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_naked_epilogue(); }
#endif /* _NOLIBC_ARCH_RISCV_H */ diff --git a/tools/include/nolibc/arch-s390.h b/tools/include/nolibc/arch-s390.h index 5d60fd43f883..cfb3956365d8 100644 --- a/tools/include/nolibc/arch-s390.h +++ b/tools/include/nolibc/arch-s390.h @@ -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_naked __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_naked_epilogue(); }
struct s390_mmap_arg_struct { diff --git a/tools/include/nolibc/arch-x86_64.h b/tools/include/nolibc/arch-x86_64.h index 68609f421934..3c3b703d9b0c 100644 --- a/tools/include/nolibc/arch-x86_64.h +++ b/tools/include/nolibc/arch-x86_64.h @@ -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_naked __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_naked_epilogue(); }
#define NOLIBC_ARCH_HAS_MEMMOVE diff --git a/tools/include/nolibc/compiler.h b/tools/include/nolibc/compiler.h index 1730d0454a55..14a854929910 100644 --- a/tools/include/nolibc/compiler.h +++ b/tools/include/nolibc/compiler.h @@ -12,6 +12,9 @@ # define __nolibc_has_attribute(attr) 0 #endif
+#define __nolibc_naked __attribute__((optimize("Os", "omit-frame-pointer"))) +#define __nolibc_naked_epilogue() __builtin_unreachable() + #if defined(__SSP__) || defined(__SSP_STRONG__) || defined(__SSP_ALL__) || defined(__SSP_EXPLICIT__)
#define _NOLIBC_STACKPROTECTOR
The current entrypoint attributes optimize("Os", "omit-frame-pointer") are intended to avoid all compiler generated code, like function porologue and epilogue. This is the exact usecase implemented by the attribute "naked".
Unfortunately this is not implemented by GCC for all targets, so only use it where available. This also provides compatibility with clang, which recognizes the "naked" attribute but not the previously used attribute "optimized".
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/compiler.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/tools/include/nolibc/compiler.h b/tools/include/nolibc/compiler.h index 14a854929910..e4cb5cf772ee 100644 --- a/tools/include/nolibc/compiler.h +++ b/tools/include/nolibc/compiler.h @@ -12,8 +12,13 @@ # define __nolibc_has_attribute(attr) 0 #endif
-#define __nolibc_naked __attribute__((optimize("Os", "omit-frame-pointer"))) -#define __nolibc_naked_epilogue() __builtin_unreachable() +#if __nolibc_has_attribute(naked) +# define __nolibc_naked __attribute__((naked)) +# define __nolibc_naked_epilogue() +#else +# define __nolibc_naked __attribute__((optimize("Os", "omit-frame-pointer"))) +# define __nolibc_naked_epilogue() __builtin_unreachable() +#endif /* __nolibc_has_attribute(naked) */
#if defined(__SSP__) || defined(__SSP_STRONG__) || defined(__SSP_ALL__) || defined(__SSP_EXPLICIT__)
When nolibc-test is so broken, it doesn't even start, don't report success.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net Reviewed-by: Shuah Khan skhan@linuxfoundation.org --- tools/testing/selftests/nolibc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index 3fbabab46958..46dfbb50fae5 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -157,7 +157,7 @@ LDFLAGS :=
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:
Clang on higher optimization levels detects that NULL is passed to printf("%s") and warns about it. While printf() from nolibc gracefully handles that NULL, it is undefined behavior as per POSIX, so the warning is reasonable. Avoid the warning by transforming NULL into a non-NULL placeholder.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net Reviewed-by: Shuah Khan skhan@linuxfoundation.org --- tools/testing/selftests/nolibc/nolibc-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 093d0512f4c5..8cbb51dca0cd 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -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);
The nolibc-test Makefile includes various other Makefiles from the tree. At first these are included with relative paths like "../../../build/Build.include" but as soon as $(srctree) is set up, the inclusions use that instead to build full paths.
To keep the style of inclusions consistent, perform the setup $(srctree) as early as possible and use it for all inclusions.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net Reviewed-by: Shuah Khan skhan@linuxfoundation.org --- tools/testing/selftests/nolibc/Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index 46dfbb50fae5..803a4e1bbe24 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -1,9 +1,14 @@ # SPDX-License-Identifier: GPL-2.0 # Makefile for nolibc tests -include ../../../scripts/Makefile.include -include ../../../scripts/utilities.mak +# we're in ".../tools/testing/selftests/nolibc" +ifeq ($(srctree),) +srctree := $(patsubst %/tools/testing/selftests/,%,$(dir $(CURDIR))) +endif + +include $(srctree)/tools/scripts/Makefile.include +include $(srctree)/tools/scripts/utilities.mak # We need this for the "cc-option" macro. -include ../../../build/Build.include +include $(srctree)/tools/build/Build.include
ifneq ($(O),) ifneq ($(call is-absolute,$(O)),y) @@ -11,11 +16,6 @@ $(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))) -endif - ifeq ($(ARCH),) include $(srctree)/scripts/subarch.include ARCH = $(SUBARCH)
Makefile.include can modify CC and CFLAGS for usage with clang. Make use of it.
Makefile.include is currently used to handle the O= variable. This is incompatible with the LLVM= handling as for O= it has to be included as early as possible, while for LLVM= it needs to be included after CFLAGS are set up.
To avoid this incompatibility, switch the O= handling to custom logic.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net Reviewed-by: Shuah Khan skhan@linuxfoundation.org --- tools/testing/selftests/nolibc/Makefile | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index 803a4e1bbe24..cdff317c35f2 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -5,7 +5,6 @@ ifeq ($(srctree),) srctree := $(patsubst %/tools/testing/selftests/,%,$(dir $(CURDIR))) endif
-include $(srctree)/tools/scripts/Makefile.include include $(srctree)/tools/scripts/utilities.mak # We need this for the "cc-option" macro. include $(srctree)/tools/build/Build.include @@ -14,6 +13,9 @@ ifneq ($(O),) ifneq ($(call is-absolute,$(O)),y) $(error Only absolute O= parameters are supported) endif +objtree := $(O) +else +objtree ?= $(srctree) endif
ifeq ($(ARCH),) @@ -21,8 +23,6 @@ include $(srctree)/scripts/subarch.include ARCH = $(SUBARCH) endif
-objtree ?= $(srctree) - # XARCH extends the kernel's ARCH with a few variants of the same # architecture that only differ by the configuration, the toolchain # and the Qemu program used. It is copied as-is into ARCH except for @@ -155,6 +155,9 @@ CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 -W -Wall -Wex $(CFLAGS_$(XARCH)) $(CFLAGS_STACKPROTECTOR) $(CFLAGS_EXTRA) LDFLAGS :=
+# Modify CFLAGS based on LLVM= +include $(srctree)/tools/scripts/Makefile.include + 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 || !p) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \
If the user specified their own CFLAGS_EXTRA these should not be overwritten by `-e`.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net Reviewed-by: Shuah Khan skhan@linuxfoundation.org --- tools/testing/selftests/nolibc/run-tests.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/nolibc/run-tests.sh b/tools/testing/selftests/nolibc/run-tests.sh index 0446e6326a40..324509b99e2c 100755 --- a/tools/testing/selftests/nolibc/run-tests.sh +++ b/tools/testing/selftests/nolibc/run-tests.sh @@ -15,7 +15,7 @@ download_location="${cache_dir}/crosstools/" build_location="$(realpath "${cache_dir}"/nolibc-tests/)" perform_download=0 test_mode=system -CFLAGS_EXTRA="-Werror" +werror=1 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" -- "$@") @@ -69,7 +69,7 @@ while true; do test_mode="$2" shift 2; continue ;; '-e') - CFLAGS_EXTRA="" + werror=0 shift; continue ;; '-h') print_usage @@ -140,6 +140,9 @@ 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}" + if [ "$werror" -ne 0 ]; then + CFLAGS_EXTRA="$CFLAGS_EXTRA -Werror" + fi MAKE=(make -j"${nproc}" XARCH="${arch}" CROSS_COMPILE="${cross_compile}" O="${build_dir}")
mkdir -p "$build_dir"
The logic in clang to find the libgcc.a from a GCC toolchain for a specific ABI does not work reliably and can lead to errors. Instead disable libgcc when building with clang, as it's not needed anyways.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/testing/selftests/nolibc/Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index b8577086e008..f0ce8264baac 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -157,6 +157,13 @@ 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
@@ -209,11 +216,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
The target names between GCC and clang differ for s390. While GCC uses "s390", clang uses "powerz". This mapping is not handled by tools/scripts/Makefile.include, so do it in the nolibc-test Makefile.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/testing/selftests/nolibc/Makefile | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index f0ce8264baac..8de98ea7af80 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -167,6 +167,9 @@ 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 || !p) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \
On Wed, Aug 07, 2024 at 11:51:50PM +0200, Thomas Weißschuh wrote:
The target names between GCC and clang differ for s390. While GCC uses "s390", clang uses "powerz".
(...)
+# GCC uses "s390", clang "systemz" +CLANG_CROSS_FLAGS := $(subst --target=s390-linux,--target=systemz-linux,$(CLANG_CROSS_FLAGS))
Based on your successful tests, I think the "powerz" in the commit message is the one to change here ;-)
Willy
The nolibc tests can now be properly built with LLVM. Expose this through run-tests.sh.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net Reviewed-by: Shuah Khan skhan@linuxfoundation.org --- tools/testing/selftests/nolibc/run-tests.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/nolibc/run-tests.sh b/tools/testing/selftests/nolibc/run-tests.sh index 324509b99e2c..e7ecda4ae796 100755 --- a/tools/testing/selftests/nolibc/run-tests.sh +++ b/tools/testing/selftests/nolibc/run-tests.sh @@ -16,9 +16,10 @@ build_location="$(realpath "${cache_dir}"/nolibc-tests/)" perform_download=0 test_mode=system 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 }
@@ -71,6 +73,9 @@ while true; do '-e') werror=0 shift; continue ;; + '-l') + llvm=1 + shift; continue ;; '-h') print_usage exit 0 @@ -143,7 +148,7 @@ test_arch() { if [ "$werror" -ne 0 ]; then CFLAGS_EXTRA="$CFLAGS_EXTRA -Werror" fi - MAKE=(make -j"${nproc}" XARCH="${arch}" CROSS_COMPILE="${cross_compile}" O="${build_dir}") + 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
On 8/7/24 15:51, Thomas Weißschuh wrote:
The current support for LLVM and clang in nolibc and its testsuite is very limited.
- Various architectures plain do not compile
- The user *has* to specify "-Os" otherwise the program crashes
- Cross-compilation of the tests does not work
- Using clang is not wired up in run-tests.sh
This series extends this support.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net
Changes in v2:
- Add support for all architectures
- powerpc: "selftests/nolibc: don't use libgcc when building with clang"
- mips: "tools/nolibc: mips: load current function to $t9"
- s390: "selftests/nolibc: use correct clang target for s390/powerz"
- Expand commit messages
- Use __nolibc_ prefix for custom macros
- Link to v1: https://lore.kernel.org/r/20240728-nolibc-llvm-v1-0-bc384269bc35@weissschuh....
Thomas Weißschuh (15): tools/nolibc: arm: use clang-compatible asm syntax tools/nolibc: mips: load current function to $t9 tools/nolibc: powerpc: limit stack-protector workaround to GCC tools/nolibc: compiler: introduce __nolibc_has_attribute() tools/nolibc: move entrypoint specifics to compiler.h tools/nolibc: compiler: use attribute((naked)) if available selftests/nolibc: report failure if no testcase passed selftests/nolibc: avoid passing NULL to printf("%s") selftests/nolibc: determine $(srctree) first selftests/nolibc: add support for LLVM= parameter selftests/nolibc: add cc-option compatible with clang cross builds selftests/nolibc: run-tests.sh: avoid overwriting CFLAGS_EXTRA selftests/nolibc: don't use libgcc when building with clang selftests/nolibc: use correct clang target for s390/powerz selftests/nolibc: run-tests.sh: allow building through LLVM
tools/include/nolibc/arch-aarch64.h | 4 +-- tools/include/nolibc/arch-arm.h | 8 +++--- tools/include/nolibc/arch-i386.h | 4 +-- tools/include/nolibc/arch-loongarch.h | 4 +-- tools/include/nolibc/arch-mips.h | 8 ++++-- tools/include/nolibc/arch-powerpc.h | 6 ++-- tools/include/nolibc/arch-riscv.h | 4 +-- tools/include/nolibc/arch-s390.h | 4 +-- tools/include/nolibc/arch-x86_64.h | 4 +-- tools/include/nolibc/compiler.h | 24 +++++++++++----- tools/testing/selftests/nolibc/Makefile | 41 +++++++++++++++++++--------- tools/testing/selftests/nolibc/nolibc-test.c | 4 +-- tools/testing/selftests/nolibc/run-tests.sh | 16 ++++++++--- 13 files changed, 83 insertions(+), 48 deletions(-)
base-commit: ae1f550efc11eaf1496c431d9c6e784cb49124c5 change-id: 20240727-nolibc-llvm-3fad68590d4c
Best regards,
Looks good to me. For selftests patches:
Reviewed-by: Shuah Khan skhan@linuxfoundation.org
thanks, -- Shuah
On Wed, Aug 07, 2024 at 04:09:41PM -0600, Shuah Khan wrote:
On 8/7/24 15:51, Thomas Weißschuh wrote:
The current support for LLVM and clang in nolibc and its testsuite is very limited.
- Various architectures plain do not compile
- The user *has* to specify "-Os" otherwise the program crashes
- Cross-compilation of the tests does not work
- Using clang is not wired up in run-tests.sh
This series extends this support.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net
Changes in v2:
- Add support for all architectures
- powerpc: "selftests/nolibc: don't use libgcc when building with clang"
- mips: "tools/nolibc: mips: load current function to $t9"
- s390: "selftests/nolibc: use correct clang target for s390/powerz"
- Expand commit messages
- Use __nolibc_ prefix for custom macros
- Link to v1: https://lore.kernel.org/r/20240728-nolibc-llvm-v1-0-bc384269bc35@weissschuh....
Thomas Weißschuh (15): tools/nolibc: arm: use clang-compatible asm syntax tools/nolibc: mips: load current function to $t9 tools/nolibc: powerpc: limit stack-protector workaround to GCC tools/nolibc: compiler: introduce __nolibc_has_attribute() tools/nolibc: move entrypoint specifics to compiler.h tools/nolibc: compiler: use attribute((naked)) if available selftests/nolibc: report failure if no testcase passed selftests/nolibc: avoid passing NULL to printf("%s") selftests/nolibc: determine $(srctree) first selftests/nolibc: add support for LLVM= parameter selftests/nolibc: add cc-option compatible with clang cross builds selftests/nolibc: run-tests.sh: avoid overwriting CFLAGS_EXTRA selftests/nolibc: don't use libgcc when building with clang selftests/nolibc: use correct clang target for s390/powerz selftests/nolibc: run-tests.sh: allow building through LLVM
tools/include/nolibc/arch-aarch64.h | 4 +-- tools/include/nolibc/arch-arm.h | 8 +++--- tools/include/nolibc/arch-i386.h | 4 +-- tools/include/nolibc/arch-loongarch.h | 4 +-- tools/include/nolibc/arch-mips.h | 8 ++++-- tools/include/nolibc/arch-powerpc.h | 6 ++-- tools/include/nolibc/arch-riscv.h | 4 +-- tools/include/nolibc/arch-s390.h | 4 +-- tools/include/nolibc/arch-x86_64.h | 4 +-- tools/include/nolibc/compiler.h | 24 +++++++++++----- tools/testing/selftests/nolibc/Makefile | 41 +++++++++++++++++++--------- tools/testing/selftests/nolibc/nolibc-test.c | 4 +-- tools/testing/selftests/nolibc/run-tests.sh | 16 ++++++++--- 13 files changed, 83 insertions(+), 48 deletions(-)
base-commit: ae1f550efc11eaf1496c431d9c6e784cb49124c5 change-id: 20240727-nolibc-llvm-3fad68590d4c
Best regards,
Looks good to me. For selftests patches:
Reviewed-by: Shuah Khan skhan@linuxfoundation.org
And all the series looks good to me as well (modulo that tiny "powerz" vs "systemz" mentioned in the 14th patch's commit message). The commit messages are now way more detailed and more pleasant to go through, thanks for that!
Acked-by: Willy Tarreau w@1wt.eu
Willy
linux-kselftest-mirror@lists.linaro.org