[PATCH] rust: Disallow BTF generation with Rust + LTO

Matthew Maurer posted 1 patch 11 months, 2 weeks ago
init/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Matthew Maurer 11 months, 2 weeks ago
The kernel cannot currently self-parse BTF containing Rust debug
information. pahole uses the language of the CU to determine whether to
filter out debug information when generating the BTF. When LTO is
enabled, Rust code can cross CU boundaries, resulting in Rust debug
information in CUs labeled as C. This results in a system which cannot
parse its own BTF.

Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
 init/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/init/Kconfig b/init/Kconfig
index c1f9eb3d5f2e892e977ba1425599502dc830f552..eb1076be6242cf349c12ef0f447696cb3a9976fa 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1962,7 +1962,7 @@ config RUST
 	depends on !MODVERSIONS
 	depends on !GCC_PLUGIN_RANDSTRUCT
 	depends on !RANDSTRUCT
-	depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE
+	depends on !DEBUG_INFO_BTF || (PAHOLE_HAS_LANG_EXCLUDE && !LTO)
 	depends on !CFI_CLANG || HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC
 	select CFI_ICALL_NORMALIZE_INTEGERS if CFI_CLANG
 	depends on !CALL_PADDING || RUSTC_VERSION >= 108100

---
base-commit: 4b90165c7d1173e0f65538d25aa718ec7ecdd5d6
change-id: 20250108-rust-btf-lto-incompat-0d258f1fb4eb

Best regards,
-- 
Matthew Maurer <mmaurer@google.com>
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Miguel Ojeda 9 months, 1 week ago
On Thu, Jan 9, 2025 at 12:35 AM Matthew Maurer <mmaurer@google.com> wrote:
>
> The kernel cannot currently self-parse BTF containing Rust debug
> information. pahole uses the language of the CU to determine whether to
> filter out debug information when generating the BTF. When LTO is
> enabled, Rust code can cross CU boundaries, resulting in Rust debug
> information in CUs labeled as C. This results in a system which cannot
> parse its own BTF.
>
> Signed-off-by: Matthew Maurer <mmaurer@google.com>

Applied to `rust-fixes` -- thanks everyone!

    Cc: stable@vger.kernel.org
    Fixes: c1177979af9c ("btf, scripts: Exclude Rust CUs with pahole")

If someone disagrees with those tags, please let me know.

Cheers,
Miguel
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Miguel Ojeda 11 months, 2 weeks ago
On Thu, Jan 9, 2025 at 12:35 AM Matthew Maurer <mmaurer@google.com> wrote:
>
> The kernel cannot currently self-parse BTF containing Rust debug
> information. pahole uses the language of the CU to determine whether to
> filter out debug information when generating the BTF. When LTO is
> enabled, Rust code can cross CU boundaries, resulting in Rust debug
> information in CUs labeled as C. This results in a system which cannot
> parse its own BTF.

Cc: Arnaldo Carvalho de Melo <acme@redhat.com>

as well as BPF/BTF, plus others that may be using or were involved
with the right-hand side of the condition.

Thanks!

Cheers,
Miguel
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Neal Gompa 11 months, 2 weeks ago
On Thu, Jan 9, 2025 at 8:17 AM Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
>
> On Thu, Jan 9, 2025 at 12:35 AM Matthew Maurer <mmaurer@google.com> wrote:
> >
> > The kernel cannot currently self-parse BTF containing Rust debug
> > information. pahole uses the language of the CU to determine whether to
> > filter out debug information when generating the BTF. When LTO is
> > enabled, Rust code can cross CU boundaries, resulting in Rust debug
> > information in CUs labeled as C. This results in a system which cannot
> > parse its own BTF.
>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
>
> as well as BPF/BTF, plus others that may be using or were involved
> with the right-hand side of the condition.
>

Do we have cases where something is a mix of C and Rust? I thought all
our Linux Rust code was self-contained?



-- 
真実はいつも一つ!/ Always, there's only one truth!
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Alice Ryhl 11 months, 2 weeks ago
On Thu, Jan 9, 2025 at 3:10 PM Neal Gompa <neal@gompa.dev> wrote:
>
> On Thu, Jan 9, 2025 at 8:17 AM Miguel Ojeda
> <miguel.ojeda.sandonis@gmail.com> wrote:
> >
> > On Thu, Jan 9, 2025 at 12:35 AM Matthew Maurer <mmaurer@google.com> wrote:
> > >
> > > The kernel cannot currently self-parse BTF containing Rust debug
> > > information. pahole uses the language of the CU to determine whether to
> > > filter out debug information when generating the BTF. When LTO is
> > > enabled, Rust code can cross CU boundaries, resulting in Rust debug
> > > information in CUs labeled as C. This results in a system which cannot
> > > parse its own BTF.
> >
> > Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> >
> > as well as BPF/BTF, plus others that may be using or were involved
> > with the right-hand side of the condition.
> >
>
> Do we have cases where something is a mix of C and Rust? I thought all
> our Linux Rust code was self-contained?

If LTO is used, then any time that Rust calls C or C calls Rust,
optimizations could move Rust code into a C object file and cause this
boot failure. For example, vsprintf calls the Rust function
rust_fmt_argument when using the %pA format specifier.

Alice
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Tamir Duberstein 11 months, 2 weeks ago
Cc: Alessandro Decina <alessandro.d@gmail.com>
Cc: Michal Rostecki <vadorovsky@protonmail.com>
Cc: Dave Tucker <dave@dtucker.co.uk>

> > > On Thu, Jan 9, 2025 at 12:35 AM Matthew Maurer <mmaurer@google.com> wrote:
> > > >
> > > > The kernel cannot currently self-parse BTF containing Rust debug
> > > > information. pahole uses the language of the CU to determine whether to
> > > > filter out debug information when generating the BTF.

In bpf-linker[0] we implemented "sanitization" to allow Rust DI to
produce functional BTF[1]. This is certainly outside the scope of this
change but: could pahole adopt a similar strategy rather than
employing such coarse heuristics?

[0] https://github.com/aya-rs/bpf-linker
[1] https://github.com/aya-rs/bpf-linker/blob/e4a9267b0fee69ecb2550058d3c8e5233f946ebe/src/llvm/di.rs
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Arnaldo Carvalho de Melo 11 months, 2 weeks ago
On Thu, Jan 09, 2025 at 09:55:34AM -0500, Tamir Duberstein wrote:
> > > > On Thu, Jan 9, 2025 at 12:35 AM Matthew Maurer <mmaurer@google.com> wrote:
> > > > > The kernel cannot currently self-parse BTF containing Rust debug
> > > > > information. pahole uses the language of the CU to determine whether to
> > > > > filter out debug information when generating the BTF.
 
> In bpf-linker[0] we implemented "sanitization" to allow Rust DI to
> produce functional BTF[1]. This is certainly outside the scope of this
> change but: could pahole adopt a similar strategy rather than
> employing such coarse heuristics?

I was thinking about it after reading this thread yesterday, i.e. we
could encode constructs from Rust that can be represented in BTF and
skip the ones that can't, pruning types that depend on non BTF
representable types, etc.

This way we wouldn't care what language it was written on, as long as we
can represent the types in BTF.

I'll try to do some experimentation with this idea.

- Arnaldo
 
> [0] https://github.com/aya-rs/bpf-linker
> [1] https://github.com/aya-rs/bpf-linker/blob/e4a9267b0fee69ecb2550058d3c8e5233f946ebe/src/llvm/di.rs
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Tamir Duberstein 11 months, 2 weeks ago
On Thu, Jan 9, 2025 at 10:47 AM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> I was thinking about it after reading this thread yesterday, i.e. we
> could encode constructs from Rust that can be represented in BTF and
> skip the ones that can't, pruning types that depend on non BTF
> representable types, etc.

Yep, this is what bpf-linker does, along with some other things[0]. I
highly recommend reading the code I linked to avoid re-discovering
these things.

[0] https://github.com/aya-rs/bpf-linker/commit/1007ec7fed03562eb7d08f3e7521094a7e698b95
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Arnaldo Carvalho de Melo 11 months, 2 weeks ago
On Thu, Jan 09, 2025 at 10:49:49AM -0500, Tamir Duberstein wrote:
> On Thu, Jan 9, 2025 at 10:47 AM Arnaldo Carvalho de Melo <acme@kernel.org> wrote:

> > I was thinking about it after reading this thread yesterday, i.e. we
> > could encode constructs from Rust that can be represented in BTF and
> > skip the ones that can't, pruning types that depend on non BTF
> > representable types, etc.
 
> Yep, this is what bpf-linker does, along with some other things[0]. I
> highly recommend reading the code I linked to avoid re-discovering
> these things.

Sure, thanks for pointing it out and suggest I read it while
experimenting with having the same concept in pahole, I'll try a quick
hack and then look at it to see how close I got to what you guys came up
with :-)

- Arnaldo
 
> [0] https://github.com/aya-rs/bpf-linker/commit/1007ec7fed03562eb7d08f3e7521094a7e698b95
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Arnaldo Carvalho de Melo 11 months, 1 week ago
On Thu, Jan 09, 2025 at 01:29:47PM -0300, Arnaldo Carvalho de Melo wrote:
> On Thu, Jan 09, 2025 at 10:49:49AM -0500, Tamir Duberstein wrote:
> > On Thu, Jan 9, 2025 at 10:47 AM Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> > > I was thinking about it after reading this thread yesterday, i.e. we
> > > could encode constructs from Rust that can be represented in BTF and
> > > skip the ones that can't, pruning types that depend on non BTF
> > > representable types, etc.
>  
> > Yep, this is what bpf-linker does, along with some other things[0]. I
> > highly recommend reading the code I linked to avoid re-discovering
> > these things.
> 
> Sure, thanks for pointing it out and suggest I read it while
> experimenting with having the same concept in pahole, I'll try a quick
> hack and then look at it to see how close I got to what you guys came up
> with :-)

So I didn't manage to work on this today, just this quick hack:

⬢ [acme@toolbox pahole]$ git diff
diff --git a/btf_encoder.c b/btf_encoder.c
index 78efd705333e2e52..5610e0902f2cd347 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -1559,7 +1559,7 @@ static int btf_encoder__encode_tag(struct btf_encoder *encoder, struct tag *tag,
        default:
                fprintf(stderr, "Unsupported DW_TAG_%s(0x%x): type: 0x%x\n",
                        dwarf_tag_name(tag->tag), tag->tag, ref_type_id);
-               return -1;
+               return 0;
        }
 }
 
⬢ [acme@toolbox pahole]$

Which essentially encodes any DWARF tag that the BTF encoder doesn't
know about into 'void'.

Super quick hack, I still have to look at the implications, but some
results:

⬢ [acme@toolbox pahole]$ cp ../build/rust-kernel/vmlinux vmlinux.rust
⬢ [acme@toolbox pahole]$ pahole --btf_encode vmlinux.rust 
die__process_class: tag not supported 0x33 (variant_part) at <4c9c589>!
die__create_new_enumeration: DW_TAG_subprogram (0x2e) @ <0x4cb784b> not handled in a rust CU!
tag__recode_dwarf_type: couldn't find name for function 0x4cd72bf, abstract_origin=0, specification=0x4cb784b
⬢ [acme@toolbox pahole]$ 
⬢ [acme@toolbox pahole]$ pahole -F btf vmlinux.rust | less
⬢ [acme@toolbox pahole]$ 
⬢ [acme@toolbox pahole]$ 
⬢ [acme@toolbox pahole]$ pahole -F btf vmlinux.rust | less
⬢ [acme@toolbox pahole]$ 
⬢ [acme@toolbox pahole]$ bpftool btf dump file vmlinux.rust | less
⬢ [acme@toolbox pahole]$ bpftool btf dump file vmlinux.rust | head
[1] INT 'DW_ATE_signed_32' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
[2] INT 'DW_ATE_signed_64' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
[3] INT 'DW_ATE_unsigned_1' size=1 bits_offset=0 nr_bits=8 encoding=(none)
[4] INT 'DW_ATE_unsigned_8' size=1 bits_offset=0 nr_bits=8 encoding=(none)
[5] INT 'DW_ATE_unsigned_64' size=8 bits_offset=0 nr_bits=64 encoding=(none)
[6] INT 'DW_ATE_unsigned_32' size=4 bits_offset=0 nr_bits=32 encoding=(none)
[7] STRUCT 'tracepoint' size=80 vlen=9
	'name' type_id=8 bits_offset=0
	'key' type_id=12 bits_offset=64
	'static_call_key' type_id=23 bits_offset=192
⬢ [acme@toolbox pahole]$ bpftool btf dump file vmlinux.rust | tail
	type_id=12300 offset=226816 size=24 (VAR 'cfd_data')
	type_id=12301 offset=226880 size=8 (VAR 'call_single_queue')
	type_id=12302 offset=226944 size=32 (VAR 'csd_data')
	type_id=51838 offset=227008 size=832 (VAR 'softnet_data')
	type_id=54492 offset=227840 size=24 (VAR 'rt_uncached_list')
	type_id=55984 offset=227904 size=24 (VAR 'rt6_uncached_list')
	type_id=8094 offset=229376 size=64 (VAR 'vmw_steal_time')
	type_id=8810 offset=229440 size=64 (VAR 'apf_reason')
	type_id=8811 offset=229504 size=64 (VAR 'steal_time')
	type_id=8813 offset=229568 size=8 (VAR 'kvm_apic_eoi')
⬢ [acme@toolbox pahole]$ readelf -wi vmlinux.rust | grep DW_AT_producer | head
    <d>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
    <1be5a>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
    <1ec5b>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
    <3bfd5>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
    <3d11c>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
    <4fcf0>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
    <503d5>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
    <5c067>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
    <5c42e>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
    <5efd9>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
⬢ [acme@toolbox pahole]$ readelf -wi vmlinux.rust | grep DW_AT_lang | grep -i rust
    <4c91de1>   DW_AT_language    : 28	(Rust)
    <4ce66ea>   DW_AT_language    : 28	(Rust)
    <4cf2cfa>   DW_AT_language    : 28	(Rust)
    <4cf71a8>   DW_AT_language    : 28	(Rust)
    <4d2797d>   DW_AT_language    : 28	(Rust)
    <4d50f34>   DW_AT_language    : 28	(Rust)
⬢ [acme@toolbox pahole]$

  Compilation Unit @ offset 0x4c91dd1:
   Length:        0x54905 (32-bit)
   Version:       4
   Abbrev Offset: 0x244258
   Pointer Size:  8
 <0><4c91ddc>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <4c91ddd>   DW_AT_producer    : (indirect string, offset: 0x282d41): clang LLVM (rustc version 1.80.0 (051478957 2024-07-21) (Fedora 1.80.0-1.fc40))
    <4c91de1>   DW_AT_language    : 28  (Rust)
    <4c91de3>   DW_AT_name        : (indirect string, offset: 0x282d91): /usr/lib/rustlib/src/rust/library/core/src/lib.rs/@/core.3f32dfd9e3bca37e-cgu.0
    <4c91de7>   DW_AT_stmt_list   : 0xa1d85f
    <4c91deb>   DW_AT_comp_dir    : (indirect string, offset: 0x2ebc6): /home/acme/git/build/rust-kernel
    <4c91def>   DW_AT_low_pc      : 0
    <4c91df7>   DW_AT_ranges      : 0x1e5f0
 <1><4c91dfb>: Abbrev Number: 2 (DW_TAG_variable)
    <4c91dfc>   DW_AT_name        : (indirect string, offset: 0x555b60): <usize as core::fmt::Debug>::{vtable}
    <4c91e00>   DW_AT_type        : <0x4c91e0e>
    <4c91e04>   DW_AT_location    : 9 byte block: 3 78 34 50 82 ff ff ff ff     (DW_OP_addr: ffffffff82503478)
 <1><4c91e0e>: Abbrev Number: 3 (DW_TAG_structure_type)
    <4c91e0f>   DW_AT_containing_type: <0x4c91e5a>
    <4c91e13>   DW_AT_name        : (indirect string, offset: 0x2b3380): <usize as core::fmt::Debug>::{vtable_type}
    <4c91e17>   DW_AT_byte_size   : 32
    <4c91e18>   DW_AT_alignment   : 8
 <2><4c91e19>: Abbrev Number: 4 (DW_TAG_member)
    <4c91e1a>   DW_AT_name        : (indirect string, offset: 0x313232): drop_in_place
    <4c91e1e>   DW_AT_type        : <0x4c91e46>
    <4c91e22>   DW_AT_alignment   : 8
    <4c91e23>   DW_AT_data_member_location: 0
 <2><4c91e24>: Abbrev Number: 4 (DW_TAG_member)
    <4c91e25>   DW_AT_name        : (indirect string, offset: 0x570b7e): size
    <4c91e29>   DW_AT_type        : <0x4c91e5a>

⬢ [acme@toolbox pahole]$ pahole -F btf -C "<usize as core::fmt::Debug>::{vtable_type}" vmlinux.rust 
struct <usize as core::fmt::Debug>::{vtable_type} {
	__SANITIZED_FAKE_INT__ *   drop_in_place;        /*     0     8 */
	usize                      size;                 /*     8     8 */
	usize                      align;                /*    16     8 */
	__SANITIZED_FAKE_INT__ *   __method3;            /*    24     8 */

	/* size: 32, cachelines: 1, members: 4 */
	/* last cacheline: 32 bytes */
};

⬢ [acme@toolbox pahole]$

⬢ [acme@toolbox pahole]$ pahole -F btf -C '<core::fmt::Error as core::fmt::Debug>::{vtable_type}' vmlinux.rust 
struct <core::fmt::Error as core::fmt::Debug>::{vtable_type} {
	__SANITIZED_FAKE_INT__ *   drop_in_place;        /*     0     8 */
	usize                      size;                 /*     8     8 */
	usize                      align;                /*    16     8 */
	__SANITIZED_FAKE_INT__ *   __method3;            /*    24     8 */

	/* size: 32, cachelines: 1, members: 4 */
	/* last cacheline: 32 bytes */
};

⬢ [acme@toolbox pahole]$

⬢ [acme@toolbox pahole]$ pahole --show_decl_info -F dwarf -C Alignment vmlinux.rust 
die__process_class: tag not supported 0x33 (variant_part) at <4c9c589>!
die__create_new_enumeration: DW_TAG_subprogram (0x2e) @ <0x4cb784b> not handled in a rust CU!
tag__recode_dwarf_type: couldn't find name for function 0x4cd72bf, abstract_origin=0, specification=0x4cb784b
/* Used at: /usr/lib/rustlib/src/rust/library/core/src/lib.rs/@/core.3f32dfd9e3bca37e-cgu.0 */
/* <4c9c50c> (null):32530 */
enum Alignment {
	Left    = 0,
	Right   = 1,
	Center  = 2,
	Unknown = 3,
} __attribute__((__packed__));

⬢ [acme@toolbox pahole]$ pahole --show_decl_info -F btf -C Alignment vmlinux.rust 
/* Used at: vmlinux.rust */
/* <0> (null):0 */
enum Alignment {
	Left    = 0,
	Right   = 1,
	Center  = 2,
	Unknown = 3,
} __attribute__((__packed__));

⬢ [acme@toolbox pahole]$

I'll fixup those two:

die__create_new_enumeration: DW_TAG_subprogram (0x2e) @ <0x4cb784b> not handled in a rust CU!
tag__recode_dwarf_type: couldn't find name for function 0x4cd72bf, abstract_origin=0, specification=0x4cb784

I.e. support functions inside enumerations.

And sure this will be refused by the kernel, lots of stuff that have
invalid names, probably need to turn those into void as well as a
continuation of this hack, then prune, maybe that is it, we'll see.

Going AFK now.

- Arnaldo
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Dave Tucker 11 months, 1 week ago

> On 9 Jan 2025, at 22:39, Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> 
> On Thu, Jan 09, 2025 at 01:29:47PM -0300, Arnaldo Carvalho de Melo wrote:
>> On Thu, Jan 09, 2025 at 10:49:49AM -0500, Tamir Duberstein wrote:
>>> On Thu, Jan 9, 2025 at 10:47 AM Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
>>>> I was thinking about it after reading this thread yesterday, i.e. we
>>>> could encode constructs from Rust that can be represented in BTF and
>>>> skip the ones that can't, pruning types that depend on non BTF
>>>> representable types, etc.
>> 
>>> Yep, this is what bpf-linker does, along with some other things[0]. I
>>> highly recommend reading the code I linked to avoid re-discovering
>>> these things.
>> 
>> Sure, thanks for pointing it out and suggest I read it while
>> experimenting with having the same concept in pahole, I'll try a quick
>> hack and then look at it to see how close I got to what you guys came up
>> with :-)
> 
> So I didn't manage to work on this today, just this quick hack:
> 
> ⬢ [acme@toolbox pahole]$ git diff
> diff --git a/btf_encoder.c b/btf_encoder.c
> index 78efd705333e2e52..5610e0902f2cd347 100644
> --- a/btf_encoder.c
> +++ b/btf_encoder.c
> @@ -1559,7 +1559,7 @@ static int btf_encoder__encode_tag(struct btf_encoder *encoder, struct tag *tag,
>        default:
>                fprintf(stderr, "Unsupported DW_TAG_%s(0x%x): type: 0x%x\n",
>                        dwarf_tag_name(tag->tag), tag->tag, ref_type_id);
> -               return -1;
> +               return 0;
>        }
> }
> 
> ⬢ [acme@toolbox pahole]$
> 
> Which essentially encodes any DWARF tag that the BTF encoder doesn't
> know about into 'void'.
> 
> Super quick hack, I still have to look at the implications, but some
> results:
> 
> ⬢ [acme@toolbox pahole]$ cp ../build/rust-kernel/vmlinux vmlinux.rust
> ⬢ [acme@toolbox pahole]$ pahole --btf_encode vmlinux.rust 
> die__process_class: tag not supported 0x33 (variant_part) at <4c9c589>!
> die__create_new_enumeration: DW_TAG_subprogram (0x2e) @ <0x4cb784b> not handled in a rust CU!
> tag__recode_dwarf_type: couldn't find name for function 0x4cd72bf, abstract_origin=0, specification=0x4cb784b
> ⬢ [acme@toolbox pahole]$ 
> ⬢ [acme@toolbox pahole]$ pahole -F btf vmlinux.rust | less
> ⬢ [acme@toolbox pahole]$ 
> ⬢ [acme@toolbox pahole]$ 
> ⬢ [acme@toolbox pahole]$ pahole -F btf vmlinux.rust | less
> ⬢ [acme@toolbox pahole]$ 
> ⬢ [acme@toolbox pahole]$ bpftool btf dump file vmlinux.rust | less
> ⬢ [acme@toolbox pahole]$ bpftool btf dump file vmlinux.rust | head
> [1] INT 'DW_ATE_signed_32' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> [2] INT 'DW_ATE_signed_64' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> [3] INT 'DW_ATE_unsigned_1' size=1 bits_offset=0 nr_bits=8 encoding=(none)
> [4] INT 'DW_ATE_unsigned_8' size=1 bits_offset=0 nr_bits=8 encoding=(none)
> [5] INT 'DW_ATE_unsigned_64' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> [6] INT 'DW_ATE_unsigned_32' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> [7] STRUCT 'tracepoint' size=80 vlen=9
> 'name' type_id=8 bits_offset=0
> 'key' type_id=12 bits_offset=64
> 'static_call_key' type_id=23 bits_offset=192
> ⬢ [acme@toolbox pahole]$ bpftool btf dump file vmlinux.rust | tail
> type_id=12300 offset=226816 size=24 (VAR 'cfd_data')
> type_id=12301 offset=226880 size=8 (VAR 'call_single_queue')
> type_id=12302 offset=226944 size=32 (VAR 'csd_data')
> type_id=51838 offset=227008 size=832 (VAR 'softnet_data')
> type_id=54492 offset=227840 size=24 (VAR 'rt_uncached_list')
> type_id=55984 offset=227904 size=24 (VAR 'rt6_uncached_list')
> type_id=8094 offset=229376 size=64 (VAR 'vmw_steal_time')
> type_id=8810 offset=229440 size=64 (VAR 'apf_reason')
> type_id=8811 offset=229504 size=64 (VAR 'steal_time')
> type_id=8813 offset=229568 size=8 (VAR 'kvm_apic_eoi')
> ⬢ [acme@toolbox pahole]$ readelf -wi vmlinux.rust | grep DW_AT_producer | head
>    <d>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>    <1be5a>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>    <1ec5b>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>    <3bfd5>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>    <3d11c>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>    <4fcf0>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>    <503d5>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>    <5c067>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>    <5c42e>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>    <5efd9>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
> ⬢ [acme@toolbox pahole]$ readelf -wi vmlinux.rust | grep DW_AT_lang | grep -i rust
>    <4c91de1>   DW_AT_language    : 28 (Rust)
>    <4ce66ea>   DW_AT_language    : 28 (Rust)
>    <4cf2cfa>   DW_AT_language    : 28 (Rust)
>    <4cf71a8>   DW_AT_language    : 28 (Rust)
>    <4d2797d>   DW_AT_language    : 28 (Rust)
>    <4d50f34>   DW_AT_language    : 28 (Rust)
> ⬢ [acme@toolbox pahole]$
> 
>  Compilation Unit @ offset 0x4c91dd1:
>   Length:        0x54905 (32-bit)
>   Version:       4
>   Abbrev Offset: 0x244258
>   Pointer Size:  8
> <0><4c91ddc>: Abbrev Number: 1 (DW_TAG_compile_unit)
>    <4c91ddd>   DW_AT_producer    : (indirect string, offset: 0x282d41): clang LLVM (rustc version 1.80.0 (051478957 2024-07-21) (Fedora 1.80.0-1.fc40))
>    <4c91de1>   DW_AT_language    : 28  (Rust)
>    <4c91de3>   DW_AT_name        : (indirect string, offset: 0x282d91): /usr/lib/rustlib/src/rust/library/core/src/lib.rs/@/core.3f32dfd9e3bca37e-cgu.0
>    <4c91de7>   DW_AT_stmt_list   : 0xa1d85f
>    <4c91deb>   DW_AT_comp_dir    : (indirect string, offset: 0x2ebc6): /home/acme/git/build/rust-kernel
>    <4c91def>   DW_AT_low_pc      : 0
>    <4c91df7>   DW_AT_ranges      : 0x1e5f0
> <1><4c91dfb>: Abbrev Number: 2 (DW_TAG_variable)
>    <4c91dfc>   DW_AT_name        : (indirect string, offset: 0x555b60): <usize as core::fmt::Debug>::{vtable}
>    <4c91e00>   DW_AT_type        : <0x4c91e0e>
>    <4c91e04>   DW_AT_location    : 9 byte block: 3 78 34 50 82 ff ff ff ff     (DW_OP_addr: ffffffff82503478)
> <1><4c91e0e>: Abbrev Number: 3 (DW_TAG_structure_type)
>    <4c91e0f>   DW_AT_containing_type: <0x4c91e5a>
>    <4c91e13>   DW_AT_name        : (indirect string, offset: 0x2b3380): <usize as core::fmt::Debug>::{vtable_type}
>    <4c91e17>   DW_AT_byte_size   : 32
>    <4c91e18>   DW_AT_alignment   : 8
> <2><4c91e19>: Abbrev Number: 4 (DW_TAG_member)
>    <4c91e1a>   DW_AT_name        : (indirect string, offset: 0x313232): drop_in_place
>    <4c91e1e>   DW_AT_type        : <0x4c91e46>
>    <4c91e22>   DW_AT_alignment   : 8
>    <4c91e23>   DW_AT_data_member_location: 0
> <2><4c91e24>: Abbrev Number: 4 (DW_TAG_member)
>    <4c91e25>   DW_AT_name        : (indirect string, offset: 0x570b7e): size
>    <4c91e29>   DW_AT_type        : <0x4c91e5a>
> 
> ⬢ [acme@toolbox pahole]$ pahole -F btf -C "<usize as core::fmt::Debug>::{vtable_type}" vmlinux.rust 
> struct <usize as core::fmt::Debug>::{vtable_type} {
> __SANITIZED_FAKE_INT__ *   drop_in_place;        /*     0     8 */
> usize                      size;                 /*     8     8 */
> usize                      align;                /*    16     8 */
> __SANITIZED_FAKE_INT__ *   __method3;            /*    24     8 */
> 
> /* size: 32, cachelines: 1, members: 4 */
> /* last cacheline: 32 bytes */
> };
> 
> ⬢ [acme@toolbox pahole]$
> 
> ⬢ [acme@toolbox pahole]$ pahole -F btf -C '<core::fmt::Error as core::fmt::Debug>::{vtable_type}' vmlinux.rust 
> struct <core::fmt::Error as core::fmt::Debug>::{vtable_type} {
> __SANITIZED_FAKE_INT__ *   drop_in_place;        /*     0     8 */
> usize                      size;                 /*     8     8 */
> usize                      align;                /*    16     8 */
> __SANITIZED_FAKE_INT__ *   __method3;            /*    24     8 */
> 
> /* size: 32, cachelines: 1, members: 4 */
> /* last cacheline: 32 bytes */
> };
> 
> ⬢ [acme@toolbox pahole]$
> 
> ⬢ [acme@toolbox pahole]$ pahole --show_decl_info -F dwarf -C Alignment vmlinux.rust 
> die__process_class: tag not supported 0x33 (variant_part) at <4c9c589>!
> die__create_new_enumeration: DW_TAG_subprogram (0x2e) @ <0x4cb784b> not handled in a rust CU!
> tag__recode_dwarf_type: couldn't find name for function 0x4cd72bf, abstract_origin=0, specification=0x4cb784b
> /* Used at: /usr/lib/rustlib/src/rust/library/core/src/lib.rs/@/core.3f32dfd9e3bca37e-cgu.0 */
> /* <4c9c50c> (null):32530 */
> enum Alignment {
> Left    = 0,
> Right   = 1,
> Center  = 2,
> Unknown = 3,
> } __attribute__((__packed__));
> 
> ⬢ [acme@toolbox pahole]$ pahole --show_decl_info -F btf -C Alignment vmlinux.rust 
> /* Used at: vmlinux.rust */
> /* <0> (null):0 */
> enum Alignment {
> Left    = 0,
> Right   = 1,
> Center  = 2,
> Unknown = 3,
> } __attribute__((__packed__));
> 
> ⬢ [acme@toolbox pahole]$
> 
> I'll fixup those two:
> 
> die__create_new_enumeration: DW_TAG_subprogram (0x2e) @ <0x4cb784b> not handled in a rust CU!
> tag__recode_dwarf_type: couldn't find name for function 0x4cd72bf, abstract_origin=0, specification=0x4cb784
> 
> I.e. support functions inside enumerations.
> 
> And sure this will be refused by the kernel, lots of stuff that have
> invalid names, probably need to turn those into void as well as a
> continuation of this hack, then prune, maybe that is it, we'll see.

Rather than voiding the names you can do something like this [0] to
coerce them into a format that the kernel is happy with. We initally
voided names but the resulting BTF was unusable since you couldn’t
lookup types by name.
 
A longer term fix is to relax the constraints in `__btf_name_char_ok`
which currently only allows characters that are valid in C
identifiers or part of a well-known section name like “.rodata”.

Even with relaxed constraints the kernel may still reject the BTF.
One example is the BTF PTR type since the kernel enforces that
name_offset = 0. When generating BTF for Rust code from LLVM IR
(and I assume from DWARF too) the name of PTR types is something
like `*const` or `*mut`.

- Dave

0: https://github.com/aya-rs/bpf-linker/blob/e4a9267b0fee69ecb2550058d3c8e5233f946ebe/src/llvm/di.rs#L34-L59


> Going AFK now.
> 
> - Arnaldo
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by vadorovsky@protonmail.com 11 months, 1 week ago
On Friday, January 10th, 2025 at 5:22 PM, Dave Tucker <dave@dtucker.co.uk> wrote:

> > On 9 Jan 2025, at 22:39, Arnaldo Carvalho de Melo acme@kernel.org wrote:
> > And sure this will be refused by the kernel, lots of stuff that have
> > invalid names, probably need to turn those into void as well as a
> > continuation of this hack, then prune, maybe that is it, we'll see.
> 
> 
> Rather than voiding the names you can do something like this [0] to
> coerce them into a format that the kernel is happy with. We initally
> voided names but the resulting BTF was unusable since you couldn’t
> lookup types by name.

Regarding the names, I would recommend to do exactly what we're doing in bpf-linker[0], which is converting each character not supported by C to `_[hex_representation]_`. This way, we make sure that two different types can't produce the same names in BTF.

An another important fixup we do is ignoring data-carrying enums[1], I think pahole could that do for now as well. That said, I think a long-term solution would be teaching the kernel to accept them.

Cheers,
Michal

[0] https://github.com/aya-rs/bpf-linker/blob/v0.9.13/src/llvm/di.rs#L34-L60
[1] https://github.com/aya-rs/bpf-linker/blob/v0.9.13/src/llvm/di.rs#L129-L132
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Matthew Maurer 11 months, 1 week ago
On Thu, Jan 9, 2025 at 2:39 PM Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
>
> On Thu, Jan 09, 2025 at 01:29:47PM -0300, Arnaldo Carvalho de Melo wrote:
> > On Thu, Jan 09, 2025 at 10:49:49AM -0500, Tamir Duberstein wrote:
> > > On Thu, Jan 9, 2025 at 10:47 AM Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> > > > I was thinking about it after reading this thread yesterday, i.e. we
> > > > could encode constructs from Rust that can be represented in BTF and
> > > > skip the ones that can't, pruning types that depend on non BTF
> > > > representable types, etc.
> >
> > > Yep, this is what bpf-linker does, along with some other things[0]. I
> > > highly recommend reading the code I linked to avoid re-discovering
> > > these things.
> >
> > Sure, thanks for pointing it out and suggest I read it while
> > experimenting with having the same concept in pahole, I'll try a quick
> > hack and then look at it to see how close I got to what you guys came up
> > with :-)
>
> So I didn't manage to work on this today, just this quick hack:
>
> ⬢ [acme@toolbox pahole]$ git diff
> diff --git a/btf_encoder.c b/btf_encoder.c
> index 78efd705333e2e52..5610e0902f2cd347 100644
> --- a/btf_encoder.c
> +++ b/btf_encoder.c
> @@ -1559,7 +1559,7 @@ static int btf_encoder__encode_tag(struct btf_encoder *encoder, struct tag *tag,
>         default:
>                 fprintf(stderr, "Unsupported DW_TAG_%s(0x%x): type: 0x%x\n",
>                         dwarf_tag_name(tag->tag), tag->tag, ref_type_id);
> -               return -1;
> +               return 0;
>         }
>  }
>
> ⬢ [acme@toolbox pahole]$
>
> Which essentially encodes any DWARF tag that the BTF encoder doesn't
> know about into 'void'.
>
> Super quick hack, I still have to look at the implications, but some
> results:
>
> ⬢ [acme@toolbox pahole]$ cp ../build/rust-kernel/vmlinux vmlinux.rust
> ⬢ [acme@toolbox pahole]$ pahole --btf_encode vmlinux.rust
> die__process_class: tag not supported 0x33 (variant_part) at <4c9c589>!
> die__create_new_enumeration: DW_TAG_subprogram (0x2e) @ <0x4cb784b> not handled in a rust CU!
> tag__recode_dwarf_type: couldn't find name for function 0x4cd72bf, abstract_origin=0, specification=0x4cb784b
> ⬢ [acme@toolbox pahole]$
> ⬢ [acme@toolbox pahole]$ pahole -F btf vmlinux.rust | less
> ⬢ [acme@toolbox pahole]$
> ⬢ [acme@toolbox pahole]$
> ⬢ [acme@toolbox pahole]$ pahole -F btf vmlinux.rust | less
> ⬢ [acme@toolbox pahole]$
> ⬢ [acme@toolbox pahole]$ bpftool btf dump file vmlinux.rust | less
> ⬢ [acme@toolbox pahole]$ bpftool btf dump file vmlinux.rust | head
> [1] INT 'DW_ATE_signed_32' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> [2] INT 'DW_ATE_signed_64' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> [3] INT 'DW_ATE_unsigned_1' size=1 bits_offset=0 nr_bits=8 encoding=(none)
> [4] INT 'DW_ATE_unsigned_8' size=1 bits_offset=0 nr_bits=8 encoding=(none)
> [5] INT 'DW_ATE_unsigned_64' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> [6] INT 'DW_ATE_unsigned_32' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> [7] STRUCT 'tracepoint' size=80 vlen=9
>         'name' type_id=8 bits_offset=0
>         'key' type_id=12 bits_offset=64
>         'static_call_key' type_id=23 bits_offset=192
> ⬢ [acme@toolbox pahole]$ bpftool btf dump file vmlinux.rust | tail
>         type_id=12300 offset=226816 size=24 (VAR 'cfd_data')
>         type_id=12301 offset=226880 size=8 (VAR 'call_single_queue')
>         type_id=12302 offset=226944 size=32 (VAR 'csd_data')
>         type_id=51838 offset=227008 size=832 (VAR 'softnet_data')
>         type_id=54492 offset=227840 size=24 (VAR 'rt_uncached_list')
>         type_id=55984 offset=227904 size=24 (VAR 'rt6_uncached_list')
>         type_id=8094 offset=229376 size=64 (VAR 'vmw_steal_time')
>         type_id=8810 offset=229440 size=64 (VAR 'apf_reason')
>         type_id=8811 offset=229504 size=64 (VAR 'steal_time')
>         type_id=8813 offset=229568 size=8 (VAR 'kvm_apic_eoi')
> ⬢ [acme@toolbox pahole]$ readelf -wi vmlinux.rust | grep DW_AT_producer | head
>     <d>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>     <1be5a>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>     <1ec5b>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>     <3bfd5>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>     <3d11c>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>     <4fcf0>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>     <503d5>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>     <5c067>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>     <5c42e>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
>     <5efd9>   DW_AT_producer    : (indexed string: 0): clang version 18.1.6 (Fedora 18.1.6-3.fc40)
> ⬢ [acme@toolbox pahole]$ readelf -wi vmlinux.rust | grep DW_AT_lang | grep -i rust
>     <4c91de1>   DW_AT_language    : 28  (Rust)
>     <4ce66ea>   DW_AT_language    : 28  (Rust)
>     <4cf2cfa>   DW_AT_language    : 28  (Rust)
>     <4cf71a8>   DW_AT_language    : 28  (Rust)
>     <4d2797d>   DW_AT_language    : 28  (Rust)
>     <4d50f34>   DW_AT_language    : 28  (Rust)
> ⬢ [acme@toolbox pahole]$
>
>   Compilation Unit @ offset 0x4c91dd1:
>    Length:        0x54905 (32-bit)
>    Version:       4
>    Abbrev Offset: 0x244258
>    Pointer Size:  8
>  <0><4c91ddc>: Abbrev Number: 1 (DW_TAG_compile_unit)
>     <4c91ddd>   DW_AT_producer    : (indirect string, offset: 0x282d41): clang LLVM (rustc version 1.80.0 (051478957 2024-07-21) (Fedora 1.80.0-1.fc40))
>     <4c91de1>   DW_AT_language    : 28  (Rust)
>     <4c91de3>   DW_AT_name        : (indirect string, offset: 0x282d91): /usr/lib/rustlib/src/rust/library/core/src/lib.rs/@/core.3f32dfd9e3bca37e-cgu.0
>     <4c91de7>   DW_AT_stmt_list   : 0xa1d85f
>     <4c91deb>   DW_AT_comp_dir    : (indirect string, offset: 0x2ebc6): /home/acme/git/build/rust-kernel
>     <4c91def>   DW_AT_low_pc      : 0
>     <4c91df7>   DW_AT_ranges      : 0x1e5f0
>  <1><4c91dfb>: Abbrev Number: 2 (DW_TAG_variable)
>     <4c91dfc>   DW_AT_name        : (indirect string, offset: 0x555b60): <usize as core::fmt::Debug>::{vtable}
>     <4c91e00>   DW_AT_type        : <0x4c91e0e>
>     <4c91e04>   DW_AT_location    : 9 byte block: 3 78 34 50 82 ff ff ff ff     (DW_OP_addr: ffffffff82503478)
>  <1><4c91e0e>: Abbrev Number: 3 (DW_TAG_structure_type)
>     <4c91e0f>   DW_AT_containing_type: <0x4c91e5a>
>     <4c91e13>   DW_AT_name        : (indirect string, offset: 0x2b3380): <usize as core::fmt::Debug>::{vtable_type}
>     <4c91e17>   DW_AT_byte_size   : 32
>     <4c91e18>   DW_AT_alignment   : 8
>  <2><4c91e19>: Abbrev Number: 4 (DW_TAG_member)
>     <4c91e1a>   DW_AT_name        : (indirect string, offset: 0x313232): drop_in_place
>     <4c91e1e>   DW_AT_type        : <0x4c91e46>
>     <4c91e22>   DW_AT_alignment   : 8
>     <4c91e23>   DW_AT_data_member_location: 0
>  <2><4c91e24>: Abbrev Number: 4 (DW_TAG_member)
>     <4c91e25>   DW_AT_name        : (indirect string, offset: 0x570b7e): size
>     <4c91e29>   DW_AT_type        : <0x4c91e5a>
>
> ⬢ [acme@toolbox pahole]$ pahole -F btf -C "<usize as core::fmt::Debug>::{vtable_type}" vmlinux.rust
> struct <usize as core::fmt::Debug>::{vtable_type} {
>         __SANITIZED_FAKE_INT__ *   drop_in_place;        /*     0     8 */
>         usize                      size;                 /*     8     8 */
>         usize                      align;                /*    16     8 */
>         __SANITIZED_FAKE_INT__ *   __method3;            /*    24     8 */
>
>         /* size: 32, cachelines: 1, members: 4 */
>         /* last cacheline: 32 bytes */
> };
>
> ⬢ [acme@toolbox pahole]$
>
> ⬢ [acme@toolbox pahole]$ pahole -F btf -C '<core::fmt::Error as core::fmt::Debug>::{vtable_type}' vmlinux.rust
> struct <core::fmt::Error as core::fmt::Debug>::{vtable_type} {
>         __SANITIZED_FAKE_INT__ *   drop_in_place;        /*     0     8 */
>         usize                      size;                 /*     8     8 */
>         usize                      align;                /*    16     8 */
>         __SANITIZED_FAKE_INT__ *   __method3;            /*    24     8 */
>
>         /* size: 32, cachelines: 1, members: 4 */
>         /* last cacheline: 32 bytes */
> };
>
> ⬢ [acme@toolbox pahole]$
>
> ⬢ [acme@toolbox pahole]$ pahole --show_decl_info -F dwarf -C Alignment vmlinux.rust
> die__process_class: tag not supported 0x33 (variant_part) at <4c9c589>!
> die__create_new_enumeration: DW_TAG_subprogram (0x2e) @ <0x4cb784b> not handled in a rust CU!
> tag__recode_dwarf_type: couldn't find name for function 0x4cd72bf, abstract_origin=0, specification=0x4cb784b
> /* Used at: /usr/lib/rustlib/src/rust/library/core/src/lib.rs/@/core.3f32dfd9e3bca37e-cgu.0 */
> /* <4c9c50c> (null):32530 */
> enum Alignment {
>         Left    = 0,
>         Right   = 1,
>         Center  = 2,
>         Unknown = 3,
> } __attribute__((__packed__));
>
> ⬢ [acme@toolbox pahole]$ pahole --show_decl_info -F btf -C Alignment vmlinux.rust
> /* Used at: vmlinux.rust */
> /* <0> (null):0 */
> enum Alignment {
>         Left    = 0,
>         Right   = 1,
>         Center  = 2,
>         Unknown = 3,
> } __attribute__((__packed__));
>
> ⬢ [acme@toolbox pahole]$
>
> I'll fixup those two:
>
> die__create_new_enumeration: DW_TAG_subprogram (0x2e) @ <0x4cb784b> not handled in a rust CU!
> tag__recode_dwarf_type: couldn't find name for function 0x4cd72bf, abstract_origin=0, specification=0x4cb784
>
> I.e. support functions inside enumerations.
>
> And sure this will be refused by the kernel, lots of stuff that have
> invalid names, probably need to turn those into void as well as a
> continuation of this hack, then prune, maybe that is it, we'll see.
>
> Going AFK now.
>
> - Arnaldo

Doing a little more digging, I've also found that the latest version
of `pahole` doesn't seem to conflict with LTO in my test builds - it
seems to successfully filter out the Rust types. Version 1.25 was
causing the errors that got reported to me and I was able to
reproduce.
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Arnaldo Carvalho de Melo 11 months, 1 week ago
On Thu, Jan 09, 2025 at 02:41:50PM -0800, Matthew Maurer wrote:
> Doing a little more digging, I've also found that the latest version
> of `pahole` doesn't seem to conflict with LTO in my test builds - it
> seems to successfully filter out the Rust types. Version 1.25 was
> causing the errors that got reported to me and I was able to
> reproduce.

Right, I recall now that this multi-lang mixup of DWARF tags theory came
up in the past and IIRC were fixed by:

commit b98565e7b17ec24daeb0b17f8f403c263dfcbd36
Author: Arnaldo Carvalho de Melo <acme@redhat.com>
Date:   Tue Oct 1 14:57:25 2024 -0300

    dwarf_loader: Honour --lang_exclude when merging LTO built CUs
    
    When building kernels with clang, thin-LTO, the Rust DWARF tags were
    being added, which causes confusion as there has not been a concerted
    effort to check if what is being generated is useful/valid.
    
    At least the Rust DWARF tags, when converted to BTF, were not causing
    crashes, which is a good signal.
    
    Fix it by passing a 'struct cu' with all fields zeroed except for the
    CU name and its language code. This is enough for the existing filter,
    in pahole (cu__filter) and will also allow us to, in verbose mode, show
    the CU names being filtered.
    
    Reported-by: Tom Stellard <tstellar@redhat.com>
    Cc: Alan Maguire <alan.maguire@oracle.com>
    Cc: Don Zickus <dzickus@redhat.com>
    Cc: Josh Stone <jistone@redhat.com>
    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

So there was a mixup, but not in the DWARF data, but in the way pahole
processes LTO built CUs, combining then into one to resolve inter CU tag
references, by not filtering the Rust CUs.

But as the message there mentions, it would be good to process tags that
are valid as BTF while "voiding", i.e. filtering the ones that are not,
I'll try to continue experimenting with it as reported in this thread,
this way we could stop using lang_exclude and have some degree of Rust
BTF support that could maybe be useful to some use cases, who knows.

- Arnaldo
Re: [PATCH] rust: Disallow BTF generation with Rust + LTO
Posted by Arnaldo Carvalho de Melo 11 months, 2 weeks ago
On Thu, Jan 09, 2025 at 01:29:47PM -0300, Arnaldo Carvalho de Melo wrote:
> On Thu, Jan 09, 2025 at 10:49:49AM -0500, Tamir Duberstein wrote:
> > On Thu, Jan 9, 2025 at 10:47 AM Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
 
> > > I was thinking about it after reading this thread yesterday, i.e. we
> > > could encode constructs from Rust that can be represented in BTF and
> > > skip the ones that can't, pruning types that depend on non BTF
> > > representable types, etc.
  
> > Yep, this is what bpf-linker does, along with some other things[0]. I
> > highly recommend reading the code I linked to avoid re-discovering
> > these things.
 
> Sure, thanks for pointing it out and suggest I read it while
> experimenting with having the same concept in pahole, I'll try a quick
> hack and then look at it to see how close I got to what you guys came up
> with :-)

BTW, its "funny" how the DWARF loader can get things from Rust, golang,
fortran and end up with things like:

Rust:

https://git.kernel.org/pub/scm/devel/pahole/pahole.git/commit/?id=d744d859768d6951cacd146604891c108b39f6a1
https://git.kernel.org/pub/scm/devel/pahole/pahole.git/commit/?id=c4eb1897d1f3841d291ee39dc969c4212750cf2c
https://git.kernel.org/pub/scm/devel/pahole/pahole.git/commit/?id=2e8cd6a435d96335c4794794147019369b6a7b6a

FORTRAN:

https://git.kernel.org/pub/scm/devel/pahole/pahole.git/commit/?id=f5847773d94d4875e04e47de9b677098f34c6510

Go:

https://git.kernel.org/pub/scm/devel/pahole/pahole.git/commit/?id=31bc0d7410572f6e03e3ed9da7c8c6f0d8df23c8

Now its a matter of making the BTF encoder be more permissive and just
skip things it can't express in BTF.

:-)

- Arnaldo