Uh oh!
There was an error while loading. Please reload this page.
Prevent bindgen from generating #[derive(Debug)] - #316
Conversation
Bindgen generates `#[derive(Debug)]` for all bindings by default. We never use these, and probably it didn't make sense to use them at all. But as we currently do not have LTO enabled, and all the bindings are exported via `pub mod bindings`, these `Debug` implementations take a lot of space. On my config this saves 400 KB of space: text data bss dec hex filename 6388276 2284324 292872 8965472 88cd60 vmlinux (with `Debug`) 6079475 2200836 292872 8573183 82d0ff vmlinux (without `Debug`) Signed-off-by: Gary Guo <gary@garyguo.net>
ksquirrel
commented
May 29, 2021
Review of
|
TheSven73
commented
May 29, 2021
What's the reason we don't have LTO enabled? I'm not saying it should be, just curious about the tradeoffs or difficulties regarding LTO. |
bjorn3
commented
May 29, 2021
Regular LTO won't work because |
TheSven73
commented
May 29, 2021
Interesting. And the linker (which I'm guessing is gcc's |
nbdd0121
commented
May 29, 2021
Only one .o file is created per crate. |
TheSven73
commented
May 29, 2021
Sorry, I meant the objects inside the |
nbdd0121
commented
May 29, 2021
Well, it's the same as C; without LTO or ffunction-sections + gc-sections, all functions with external linkage will be kept. |
TheSven73
commented
May 29, 2021
Ah I see. And there's no simple way have rustc generate function sections? Which are then gc'ed by |
bjorn3
commented
May 29, 2021
That is the default for rustc, but not for linux. |
TheSven73
commented
May 29, 2021
Thanks! So you're saying that rustc generates function sections by default, but |
bjorn3
commented
May 29, 2021
The target specs used by rust-for-linux disable function sections completely AFAIK. |
Kernel's --gc-sections support is behind config LD_DEAD_CODE_DATA_ELIMINATION which is marked experimental and hidden beind config EXPERT. |
Very interesting info, thanks! I noticed that the next kernel version ( Is the plan to simply piggy-back onto this, when we move to the next kernel version? Perhaps @ojeda has some insights too? Edited: ThinLTO worked, although slowly. Full LTO simply exhausted all memory on my 16 gig RAM laptop before it could finish. Holy smoke. Edit 2: ThinLTO kernel size is actually larger than no LTO kernel size on my builds. Seems like there are a few wrinkles to be ironed out upstream still. |
nbdd0121
commented
May 30, 2021
LTO is usually meant for performance improvement rather than size reduction. It could reduce the size if a lot of functions are unused, but obviously that's not the case for kernel's C code. To be able to LTO rust, you need to add |
wedsonaf
commented
Jun 1, 2021
FWIW, at Google we enable LTO when building android kernels. |
TheSven73
commented
Jun 1, 2021
Thanks! Why is this done? |
wedsonaf
commented
Jun 1, 2021
I wasn't directly involved in the work, but AFAIU, LTO improved performance and binary size. It was also required for control-flow integrity (CFI), which itself degrades performance but this degradation is offset by the improvements brought by LTO. I can confirm that building the kernel takes longer but we're willing to take the compilation time hit if the resulting binary is faster and/or harder to exploit. |
TheSven73
commented
Jun 1, 2021
I see, that sounds like a good tradeoff. I'm assuming not all of this stuff made it upstream? Because I noticed that ThinLTO has a bigger binary size compared to no LTO. And FullLTO ate all my laptop's memory :) For |
wedsonaf
commented
Jun 1, 2021
I'm not sure, it could be differences in other configurations too. I know the goal is to have everything upstream but I'm not sure if we're there yet. The kernels are all publicly available though, some details (including link to git repo) are available here: |
ojeda
commented
Jun 1, 2021
Related: LWN had an article on CFI a few days ago https://lwn.net/Articles/856514/ |
In case when is64 == 1 in emit(A64_REV32(is64, dst, dst), ctx) the generated insn reverses byte order for both high and low 32-bit words, resuling in an incorrect swap as indicated by the jit test: [ 9757.262607] test_bpf: Rust-for-Linux#312 BSWAP 16: 0x0123456789abcdef -> 0xefcd jited:1 8 PASS [ 9757.264435] test_bpf: Rust-for-Linux#313 BSWAP 32: 0x0123456789abcdef -> 0xefcdab89 jited:1 ret 1460850314 != -271733879 (0x5712ce8a != 0xefcdab89)FAIL (1 times) [ 9757.266260] test_bpf: Rust-for-Linux#314 BSWAP 64: 0x0123456789abcdef -> 0x67452301 jited:1 8 PASS [ 9757.268000] test_bpf: Rust-for-Linux#315 BSWAP 64: 0x0123456789abcdef >> 32 -> 0xefcdab89 jited:1 8 PASS [ 9757.269686] test_bpf: Rust-for-Linux#316 BSWAP 16: 0xfedcba9876543210 -> 0x1032 jited:1 8 PASS [ 9757.271380] test_bpf: Rust-for-Linux#317 BSWAP 32: 0xfedcba9876543210 -> 0x10325476 jited:1 ret -1460850316 != 271733878 (0xa8ed3174 != 0x10325476)FAIL (1 times) [ 9757.273022] test_bpf: Rust-for-Linux#318 BSWAP 64: 0xfedcba9876543210 -> 0x98badcfe jited:1 7 PASS [ 9757.274721] test_bpf: Rust-for-Linux#319 BSWAP 64: 0xfedcba9876543210 >> 32 -> 0x10325476 jited:1 9 PASS Fix this by forcing 32bit variant of rev32. Fixes: 1104247 ("bpf, arm64: Support unconditional bswap") Signed-off-by: Artem Savkov <asavkov@redhat.com> Tested-by: Puranjay Mohan <puranjay12@gmail.com> Acked-by: Puranjay Mohan <puranjay12@gmail.com> Acked-by: Xu Kuohai <xukuohai@huawei.com> Message-ID: <20240321081809.158803-1-asavkov@redhat.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Bindgen generates
#[derive(Debug)]for all bindings by default.We never use these, and probably it didn't make sense to use them
at all. But as we currently do not have LTO enabled, and all the
bindings are exported via
pub mod bindings, theseDebugimplementations take a lot of space.
On my config this saves 400 KB of space:
Discovered by a tiny static analysis tool that I am writing :)