Rust for Linux List
 help / color / mirror / Atom feed
* Re: [PATCHES 00/12] pahole: Support more rust tags and references to dwz alternate debug files
       [not found]   ` <anXTAComw6XAvnXU@x1>
@ 2026-08-07 17:34     ` Miguel Ojeda
  2026-08-07 18:53       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 4+ messages in thread
From: Miguel Ojeda @ 2026-08-07 17:34 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Alan Maguire, Jiri Olsa, Clark Williams, dwarves, bpf,
	Andrii Nakryiko, Yonghong Song, Mark Wieelard, rust-for-linux,
	Gary Guo

On Fri, Aug 7, 2026 at 2:43 PM Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
>
> Adding Miguel to the CC list, Miguel we're trying to improve BTF support
> for Rust, this series handles multiple enabling fixes/improvements that
> gets us to the next level, i.e. we can load everything from DWARF, now

Thanks for the Cc! Cc'ing rust-for-linux and Gary.

> its time to try to map it to existing BTF kinds and propose BTF
> extensions when we can't use existing encodings.

Sounds cool :)

> Inferring from "does any member have a niche layout" means
> reverse-engineering rustc's layout algorithm, which is explicitly
> unstable and unspecified. It'd break silently on a compiler bump, with
> no way to tell from the DWARF that you got it wrong.

Yeah, the LLM is correct here: the Rust compiler gives very few
guarantees for the default `repr`, i.e. in common cases it has the
freedom to use whatever layout it wants (i.e. even for essentially
equivalent types in the same compilation unit) -- the official docs
are at:

  https://doc.rust-lang.org/reference/type-layout.html

>     u8                  __discriminant;      /*  0  1 */

For the niche cases like `Option<NonZero<u32>>`, what would be printed?

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCHES 00/12] pahole: Support more rust tags and references to dwz alternate debug files
  2026-08-07 17:34     ` [PATCHES 00/12] pahole: Support more rust tags and references to dwz alternate debug files Miguel Ojeda
@ 2026-08-07 18:53       ` Arnaldo Carvalho de Melo
  2026-08-07 19:26         ` Gary Guo
  2026-08-07 20:30         ` Arnaldo Carvalho de Melo
  0 siblings, 2 replies; 4+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-08-07 18:53 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Alan Maguire, Jiri Olsa, Clark Williams, dwarves, bpf,
	Andrii Nakryiko, Yonghong Song, Mark Wieelard, rust-for-linux,
	Gary Guo

On Fri, Aug 07, 2026 at 07:34:10PM +0200, Miguel Ojeda wrote:
> On Fri, Aug 7, 2026 at 2:43 PM Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> >
> > Adding Miguel to the CC list, Miguel we're trying to improve BTF support
> > for Rust, this series handles multiple enabling fixes/improvements that
> > gets us to the next level, i.e. we can load everything from DWARF, now
> 
> Thanks for the Cc! Cc'ing rust-for-linux and Gary.
> 
> > its time to try to map it to existing BTF kinds and propose BTF
> > extensions when we can't use existing encodings.
> 
> Sounds cool :)
> 
> > Inferring from "does any member have a niche layout" means
> > reverse-engineering rustc's layout algorithm, which is explicitly
> > unstable and unspecified. It'd break silently on a compiler bump, with
> > no way to tell from the DWARF that you got it wrong.
> 
> Yeah, the LLM is correct here: the Rust compiler gives very few
> guarantees for the default `repr`, i.e. in common cases it has the
> freedom to use whatever layout it wants (i.e. even for essentially
> equivalent types in the same compilation unit) -- the official docs
> are at:
> 
>   https://doc.rust-lang.org/reference/type-layout.html
> 
> >     u8                  __discriminant;      /*  0  1 */
> 
> For the niche cases like `Option<NonZero<u32>>`, what would be printed?

Can you think about one such niche case that is present in the kernel
rust .o files right now? I tried finding the `Option<NonZero<u32>>` to
look at its DWARF but couldn't find one.

- Arnaldo

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCHES 00/12] pahole: Support more rust tags and references to dwz alternate debug files
  2026-08-07 18:53       ` Arnaldo Carvalho de Melo
@ 2026-08-07 19:26         ` Gary Guo
  2026-08-07 20:30         ` Arnaldo Carvalho de Melo
  1 sibling, 0 replies; 4+ messages in thread
From: Gary Guo @ 2026-08-07 19:26 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Miguel Ojeda
  Cc: Alan Maguire, Jiri Olsa, Clark Williams, dwarves, bpf,
	Andrii Nakryiko, Yonghong Song, Mark Wieelard, rust-for-linux,
	Gary Guo

On Fri Aug 7, 2026 at 7:53 PM BST, Arnaldo Carvalho de Melo wrote:
> On Fri, Aug 07, 2026 at 07:34:10PM +0200, Miguel Ojeda wrote:
>> On Fri, Aug 7, 2026 at 2:43 PM Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
>> >
>> > Adding Miguel to the CC list, Miguel we're trying to improve BTF support
>> > for Rust, this series handles multiple enabling fixes/improvements that
>> > gets us to the next level, i.e. we can load everything from DWARF, now
>> 
>> Thanks for the Cc! Cc'ing rust-for-linux and Gary.
>> 
>> > its time to try to map it to existing BTF kinds and propose BTF
>> > extensions when we can't use existing encodings.
>> 
>> Sounds cool :)
>> 
>> > Inferring from "does any member have a niche layout" means
>> > reverse-engineering rustc's layout algorithm, which is explicitly
>> > unstable and unspecified. It'd break silently on a compiler bump, with
>> > no way to tell from the DWARF that you got it wrong.
>> 
>> Yeah, the LLM is correct here: the Rust compiler gives very few
>> guarantees for the default `repr`, i.e. in common cases it has the
>> freedom to use whatever layout it wants (i.e. even for essentially
>> equivalent types in the same compilation unit) -- the official docs
>> are at:
>> 
>>   https://doc.rust-lang.org/reference/type-layout.html
>> 
>> >     u8                  __discriminant;      /*  0  1 */
>> 
>> For the niche cases like `Option<NonZero<u32>>`, what would be printed?
>
> Can you think about one such niche case that is present in the kernel
> rust .o files right now? I tried finding the `Option<NonZero<u32>>` to
> look at its DWARF but couldn't find one.

For direct use of `Option<NonZero<..>>` we only have `sriov_get_totalvfs` which
is `Option<NonZero<u16>>`.

However, we have many case of `Result<(), Error>` where `Error` is `NonZeroI32`,
so `Ok(())` is mapped to 0.

Best,
Gary

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCHES 00/12] pahole: Support more rust tags and references to dwz alternate debug files
  2026-08-07 18:53       ` Arnaldo Carvalho de Melo
  2026-08-07 19:26         ` Gary Guo
@ 2026-08-07 20:30         ` Arnaldo Carvalho de Melo
  1 sibling, 0 replies; 4+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-08-07 20:30 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Alan Maguire, Jiri Olsa, Clark Williams, dwarves, bpf,
	Andrii Nakryiko, Yonghong Song, Mark Wieelard, rust-for-linux,
	Gary Guo

On Fri, Aug 07, 2026 at 03:53:53PM -0300, Arnaldo Carvalho de Melo wrote:
> On Fri, Aug 07, 2026 at 07:34:10PM +0200, Miguel Ojeda wrote:
> > On Fri, Aug 7, 2026 at 2:43 PM Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> > > Adding Miguel to the CC list, Miguel we're trying to improve BTF support
> > > for Rust, this series handles multiple enabling fixes/improvements that
> > > gets us to the next level, i.e. we can load everything from DWARF, now

> > Thanks for the Cc! Cc'ing rust-for-linux and Gary.

> > > its time to try to map it to existing BTF kinds and propose BTF
> > > extensions when we can't use existing encodings.

> > Sounds cool :)

> > > Inferring from "does any member have a niche layout" means
> > > reverse-engineering rustc's layout algorithm, which is explicitly
> > > unstable and unspecified. It'd break silently on a compiler bump, with
> > > no way to tell from the DWARF that you got it wrong.

> > Yeah, the LLM is correct here: the Rust compiler gives very few
> > guarantees for the default `repr`, i.e. in common cases it has the
> > freedom to use whatever layout it wants (i.e. even for essentially
> > equivalent types in the same compilation unit) -- the official docs
> > are at:

> >   https://doc.rust-lang.org/reference/type-layout.html

> > >     u8                  __discriminant;      /*  0  1 */

> > For the niche cases like `Option<NonZero<u32>>`, what would be printed?
 
> Can you think about one such niche case that is present in the kernel
> rust .o files right now? I tried finding the `Option<NonZero<u32>>` to
> look at its DWARF but couldn't find one.

Good, so I went ahead and built the exact case, together with the
explicit `Option<u32>` one, so we can compare them.  The source,
containing the struct I dump below:

  use std::num::NonZeroU32;

  #[no_mangle]
  pub struct Container {
  	pub a: Option<NonZeroU32>,  // niche: 4 bytes, tag == payload
  	pub b: Option<u32>,        // explicit: tag at 0, payload at 4
  	pub c: Option<i32>,
  }

  #[no_mangle]
  pub fn consume(c: Container) -> u32 {
  	c.a.map(|x| x.get()).unwrap_or(0) + c.b.unwrap_or(0)
  }

  fn main() {
  	let c = Container { a: None, b: Some(3), c: Some(-1) };
  	let _ = consume(c);
  }

Compile (rustc 1.93.x here, don't link, just get an object file,
otherwise you'll debug 1M+ lines of std DWARF and the type will be
there but buried):

  acme@number:~/git/pahole$ rustc --edition 2021 --emit=obj -C debuginfo=2 \
  				  option_non_zero.rs -o option_non_zero.o

then dump the DWARF, note that the DW_AT_name has the expanded generic,
i.e. 'Option<core::num::nonzero::NonZero<u32>>', the NonZeroU32 alias
seems to be expanded at compile time and, thus, doesn't appear in DWARF:

  acme@number:~/git/pahole$ readelf --debug-dump=info option_non_zero.o \
  				  | grep -n 'nonzero::NonZero<u32>'
				  acme@number:~$ readelf --debug-dump=info option_non_zero.o | grep -n 'nonzero::NonZero<u32>'
  295: <2ca>   DW_AT_name  : (indirect string, offset: 0x213): Option<core::num::nonzero::NonZero<u32>>
  348: <32e>   DW_AT_name  : (indirect string, offset: 0x2ef): map<core::num::nonzero::NonZero<u32>, u32, option_non_zero::consume::{closure_env#0}>
  acme@number:~$

and you can see the niche case layout, size 4, the discriminant member
is the payload itself, same offset, same size, and the Some variant
doesn't even get a DW_AT_discr_value, it is just the default, so the
answer: nothing separate to print, the tag IS the payload.

Here is the full DIE for the niche case:

acme@number:~$ readelf --debug-dump=info option_non_zero.o | grep -B1 -A25 'Option<core::num::nonzero::NonZero<u32>>'
 <3><2c9>: Abbrev Number: 19 (DW_TAG_structure_type)
    <2ca>   DW_AT_name        : (indirect string, offset: 0x213): Option<core::num::nonzero::NonZero<u32>>
    <2ce>   DW_AT_byte_size   : 4
    <2cf>   DW_AT_accessibility: 1	(public)
    <2d0>   DW_AT_alignment   : 4
 <4><2d1>: Abbrev Number: 26 (DW_TAG_variant_part)
    <2d2>   DW_AT_discr       : <0x2d6>
 <5><2d6>: Abbrev Number: 27 (DW_TAG_member)
    <2d7>   DW_AT_type        : <0x5b2>
    <2db>   DW_AT_alignment   : 4
    <2dc>   DW_AT_data_member_location: 0
    <2dd>   DW_AT_artificial  : 1
 <5><2dd>: Abbrev Number: 28 (DW_TAG_variant)
    <2de>   DW_AT_discr_value : 0
 <6><2df>: Abbrev Number: 4 (DW_TAG_member)
    <2e0>   DW_AT_name        : (indirect string, offset: 0x1ce): None
    <2e4>   DW_AT_type        : <0x2f9>
    <2e8>   DW_AT_alignment   : 4
    <2e9>   DW_AT_data_member_location: 0
 <6><2ea>: Abbrev Number: 0
 <5><2eb>: Abbrev Number: 29 (DW_TAG_variant)
 <6><2ec>: Abbrev Number: 4 (DW_TAG_member)
    <2ed>   DW_AT_name        : (indirect string, offset: 0x20e): Some
    <2f1>   DW_AT_type        : <0x30b>
    <2f5>   DW_AT_alignment   : 4
    <2f6>   DW_AT_data_member_location: 0
 <6><2f7>: Abbrev Number: 0
acme@number:~$

On the explicit `Option<u32>` case the picture is different, the tag is
a real member at offset 0 with 4 bytes and Some.__0 moved to offset 4:

acme@number:~$ readelf --debug-dump=info option_non_zero.o | grep -B1 -A25 'Option<u32>'
 <3><360>: Abbrev Number: 19 (DW_TAG_structure_type)
    <361>   DW_AT_name        : (indirect string, offset: 0x345): Option<u32>
    <365>   DW_AT_byte_size   : 8
    <366>   DW_AT_accessibility: 1	(public)
    <367>   DW_AT_alignment   : 4
 <4><368>: Abbrev Number: 26 (DW_TAG_variant_part)
    <369>   DW_AT_discr       : <0x36d>
 <5><36d>: Abbrev Number: 27 (DW_TAG_member)
    <36e>   DW_AT_type        : <0x5b2>
    <372>   DW_AT_alignment   : 4
    <373>   DW_AT_data_member_location: 0
    <374>   DW_AT_artificial  : 1
 <5><374>: Abbrev Number: 28 (DW_TAG_variant)
    <375>   DW_AT_discr_value : 0
 <6><376>: Abbrev Number: 4 (DW_TAG_member)
    <377>   DW_AT_name        : (indirect string, offset: 0x1ce): None
    <37b>   DW_AT_type        : <0x391>
    <37f>   DW_AT_alignment   : 4
    <380>   DW_AT_data_member_location: 0
 <6><381>: Abbrev Number: 0
 <5><382>: Abbrev Number: 28 (DW_TAG_variant)
    <383>   DW_AT_discr_value : 1
 <6><384>: Abbrev Number: 4 (DW_TAG_member)
    <385>   DW_AT_name        : (indirect string, offset: 0x20e): Some
    <389>   DW_AT_type        : <0x3a3>
    <38d>   DW_AT_alignment   : 4
    <38e>   DW_AT_data_member_location: 0
acme@number:~$

So this is the one where we want a synthetic __discriminant member.

And what we do today for the niche one, with current pahole (built from
this series):

acme@number:~$ pahole -C 'Option<core::num::nonzero::NonZero<u32>>' option_non_zero.o
struct Option<core::num::nonzero::NonZero<u32>> {
	struct None {

		/* size: 4, cachelines: 1, members: 0 */
		/* padding: 4 */
		/* last cacheline: 4 bytes */
	} __attribute__((__aligned__(4)));

	struct Some {
	public:

		struct NonZero<u32>        __0 __attribute__((__aligned__(4))); /*     0     4 */

		/* size: 4, cachelines: 1, members: 1 */
		/* forced alignments: 1 */
		/* last cacheline: 4 bytes */
	} __attribute__((__aligned__(4)));

	struct Option<u32> map<core::num::nonzero::NonZero<u32>, u32, option_non_zero::consume::{closure_env#0}>(struct Option<core::num::nonzero::NonZero<u32>>, struct {closure_env#0});


	/* size: 4, cachelines: 1, members: 0 */
	/* padding: 4 */
	/* last cacheline: 4 bytes */
} __attribute__((__aligned__(4)));

acme@number:~$

and on the BTF side, also with this series:

acme@number:~$ pahole --btf_encode option_non_zero.o
acme@number:~$ pahole -F btf -C 'Option<core::num::nonzero::NonZero<u32>>' option_non_zero.o
union Option<core::num::nonzero::NonZero<u32>> {
	struct None                None;               /*     0     4 */
	struct Some                Some;               /*     0     4 */
};

acme@number:~$ pahole --expand_types -F btf -C 'Option<core::num::nonzero::NonZero<u32>>' option_non_zero.o
union Option<core::num::nonzero::NonZero<u32>> {
	struct None {
	} __attribute__((__aligned__(8))) None;                           /*     0     4 */
	struct Some {
		struct NonZero<u32> {
			struct NonZeroU32Inner {
				u32 __0;                                                 /*     0     4 */
			} __0; /*     0     4 */
		} __0; /*     0     4 */
	} Some; /*     0     4 */
};

acme@number:~$

matches the real in-memory layout, size 4, no extra member.

So for the future __discriminant work the rule should be: only emit it
when its location doesn't overlap with the payload, i.e. on the explicit
form; on the niche that field is the data itself, adding one would mean
two members covering the same bytes, and we'd be lying about the layout.

I'll add a test with both forms, pinning this behavior, so we don't
regress it, and then, when we improve support for the synthetic
discriminants, we can update it.

And yes, I used OpenCode + DeepSeek to iterate multiple times and
manually checked everything before hitting send, it helps me a lot and I
hope that if I missed something, you will correct me so that we can make
progress.

Regards,

- Arnaldo

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-08-07 20:30 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20260731193102.110693-1-acme@kernel.org>
     [not found] ` <18b557a8-e1ca-46cf-b03f-5e68490c9229@oracle.com>
     [not found]   ` <anXTAComw6XAvnXU@x1>
2026-08-07 17:34     ` [PATCHES 00/12] pahole: Support more rust tags and references to dwz alternate debug files Miguel Ojeda
2026-08-07 18:53       ` Arnaldo Carvalho de Melo
2026-08-07 19:26         ` Gary Guo
2026-08-07 20:30         ` Arnaldo Carvalho de Melo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox