Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When linking with lld, test suites are empty #269

Closed
maurer opened this issue Dec 20, 2024 · 7 comments
Closed

When linking with lld, test suites are empty #269

maurer opened this issue Dec 20, 2024 · 7 comments

Comments

@maurer
Copy link

maurer commented Dec 20, 2024

While trying to add a test, I noticed that it wasn't initially failing like it was supposed to. Eventually, I realized that none of the test suites thought they contained any tests.

Transcript of build with "passing" test suites because they don't exist

Switching CC to explicitly point at gcc causes the test suites to populate.

@lucasdemarchi
Copy link
Contributor

it works for me, but I pass clang in the CC variable. I wonder if the issue is related to the sanitizer or clang version.

$ CC=clang . ./scripts/sanitizer-env.sh
$ ./build/testsuite/test-dependencies -l 
Available tests:
	test_dependencies, test if kmod_module_get_dependencies works

what clang version are you using? Can you try without sanitizer? -Db_sanitize=

@evelikov any idea?

@lucasdemarchi
Copy link
Contributor

Another thing that would be useful:

$ readelf -t ./build/testsuite/test-dependencies  | grep -A3 kmod_tests
  [27] kmod_tests
       PROGBITS         000000000013ab00  000000000013ab00  0
       0000000000000080 0000000000000000  0                 8
       [0000000000000003]: WRITE, ALLOC

@maurer
Copy link
Author

maurer commented Jan 3, 2025

tl;dr: It's not actually clang, it's lld. It looks like you might be relying on the contents of GNU LD's default linker script in order to aggregate kmod_tests, and lld doesn't consider that behavior load bearing.

Additional information from the failing situation - I was using the Android prebuilt clang - the clangs available as system packages don't have sufficiently modern sanitizer support for what you're doing.

mmaurer@anyblade:~/kernel/kmod$ $CC --version
Android (12806354, +pgo, +bolt, +lto, +mlgo, based on r547379) clang version 20.0.0 (https://android.googlesource.com/toolchain/llvm-project b718bcaf8c198c82f3021447d943401e3ab5bd54)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/google/home/mmaurer/pore/android/platform/prebuilts/clang/host/linux-x86/clang-r547379/binI haven't tried
mmaurer@anyblade:~/kernel/kmod$

Your kmod_tests symbol doesn't appear at all.

mmaurer@anyblade:~/kernel/kmod$ readelf -t ./builddir/testsuite/test-dependencies  | grep -A3 kmod_tests
mmaurer@anyblade:~/kernel/kmod$ 

Setting -Db_sanitize= doesn't work (empty string not accepted), so I set it to none instead, which I assume is what you wanted thecked, e.g. meson setup --native-file build-dev.ini ./builddir -Db_sanitize=none. No differences in either test results, list of tests, or presence of kmod_tests.

If I set -Db_sanitize=none, the legacy clang on my machine,

mmaurer@anyblade:~/kernel/kmod$ cc --version
Debian clang version 16.0.6 (27+build1)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
mmaurer@anyblade:~/kernel/kmod$ 

successfully builds and executes the tests.

The main difference I could think of between these two compilers other than the age was that the modern, non-packaged clang uses lld as its linker by default. I tried setting LDFLAGS=-fuse-ld=lld, and sure enough, tests stop enumerating again.

The actual fix I was getting by switching to gcc or to a legacy packaged clang was that it was switching the linker back to ld. I'll edit the issue title to reflect this.

@maurer maurer changed the title When using clang, test suites are empty When linking with lld, test suites are empty Jan 3, 2025
@lucasdemarchi
Copy link
Contributor

Your kmod_tests symbol doesn't appear at all.

mmaurer@anyblade:~/kernel/kmod$ readelf -t ./builddir/testsuite/test-dependencies  | grep -A3 kmod_tests
mmaurer@anyblade:~/kernel/kmod$ 

if it were the _start/_end symbols, I would understand and possibly have to add a workaround for that. But here it seems you don't even have the elf section. How does that compiler build the kernel? Are we missing any flag here so it a) create the section and b) doesn't discard it when linking? The relevant code in kmod is this:

                __attribute__((used, section("kmod_tests"), aligned(8))) = { \
                        .name = #_name, .func = _func, ##__VA_ARGS__         \
                };

So we add them to a separate section, align it accordingly and instruct the linker that "this is used, trust me, do not discard".

Can you check if it's the linker discarding the section or the compiler not adding it?

$ readelf -t  build/testsuite/test-init.p/test-init.c.o  | grep -A3 kmod_tests
  [43] kmod_tests
       PROGBITS         0000000000000000  00000000000015a0  0
       0000000000000280 0000000000000000  0                 8
       [0000000000000003]: WRITE, ALLOC
  [44] .relakmod_tests
       RELA             0000000000000000  0000000000004c50  74
       0000000000000240 0000000000000018  43                8
       [0000000000000040]: INFO LINK

Android (12806354, +pgo, +bolt, +lto, +mlgo, based on r547379) clang version 20.0.0 (https://android.googlesource.com/toolchain/llvm-project b718bcaf8c198c82f3021447d943401e3ab5bd54)

I'm wondering if it's related to LTO

@lucasdemarchi
Copy link
Contributor

Now I can reproduce it with my distro's packages:

CC=clang CC_LD=lld meson setup --native-file build-dev.ini build-lto-clang/

and it's not related to lto as even passing -Db_lto=falses it still fails.

lucasdemarchi added a commit that referenced this issue Jan 3, 2025
When building with clang and linking with lld there is an issue with
keeping the kmod_tests sections: On ELF targets, __attribute__((used))
prevents compiler discarding, but does not affect linker --gc-sections,
according to https://lld.llvm.org/ELF/start-stop-gc.

Make sure the _start/_stop symbols are not weak and add the "retain"
attribute.

Closes: #269
Signed-off-by: Lucas De Marchi <[email protected]>
@lucasdemarchi
Copy link
Contributor

@maurer can you test with #274? I added the retain attribute and it fixed it for me.

@maurer
Copy link
Author

maurer commented Jan 3, 2025

I can confirm that this fixes it for me. I didn't know about retain, TIL!

lucasdemarchi added a commit that referenced this issue Jan 3, 2025
When building with clang and linking with lld there is an issue with
keeping the kmod_tests sections: On ELF targets, __attribute__((used))
prevents compiler discarding, but does not affect linker --gc-sections,
according to https://lld.llvm.org/ELF/start-stop-gc.

Make sure the _start/_stop symbols are not weak and add the "retain"
attribute.

Closes: #269
Signed-off-by: Lucas De Marchi <[email protected]>
lucasdemarchi added a commit that referenced this issue Jan 6, 2025
Avoid issues like #269
by asserting the test binary is non-empty:

Suggested-by: Emil Velikov <[email protected]>
Signed-off-by: Lucas De Marchi <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants