* 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