[PATCH 08/16] encoders: Handle DW_TAG_subprogram in enumerations during BTF/CTF encoding
Arnaldo Carvalho de Melo <[email protected]> Mon, 22 Jun 2026 17:24:31 -0300
| Newsgroups | org.kernel.vger.dwarves |
|---|---|
| Message-ID | <[email protected]> |
From: Arnaldo Carvalho de Melo <[email protected]> Since commit 5c0162ee40f06c95 ("dwarf_loader: Initial support for DW_TAG_subprogram in DW_TAG_enumeration"), Rust enumerations with associated functions (impl blocks) are loaded with DW_TAG_subprogram children in their namespace. However, the BTF and CTF encoders were not aware of this and treated these subprogram tags as unexpected, producing noisy warnings: Unexpected DW_TAG_subprogram <0>, skipping it... This was problematic for real Rust binaries. For instance, BTF encoding the sashiko-cli Rust binary produced 653 such warnings from enumerations like Ordering (137), ChunkedState (106), TlsState (20), and others. Even the Rust standard library object produced 8 warnings. Since BTF and CTF have no representation for subprograms inside enumerations, we should skip them, but inform the user about it rather than warn about an unexpected tag. Switch the enumerator iteration in both encoders from an if/continue pattern to a proper switch statement: - DW_TAG_enumerator: processed normally - DW_TAG_subprogram: silently skipped (BTF logs it in verbose mode) - anything else: still warned about with the enumeration name for better diagnostics Before: $ pahole --btf_encode sashiko-cli 2>&1 | grep -c subprogram 653 After: $ pahole --btf_encode sashiko-cli 2>&1 | grep -c subprogram 0 $ pahole -V --btf_encode sashiko-cli 2>&1 | grep -c 'subprogram in enumeration' 653 Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Arnaldo Carvalho de Melo <[email protected]> --- btf_encoder.c | 22 +++++++++++++++------- ctf_encoder.c | 15 ++++++++++----- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/btf_encoder.c b/btf_encoder.c index 82dd5f27138c2949..dc1e18a986605d04 100644 --- a/btf_encoder.c +++ b/btf_encoder.c @@ -1798,14 +1798,22 @@ static int32_t btf_encoder__add_enum_type(struct btf_encoder *encoder, struct ta return type_id; type__for_each_enumerator(etype, pos) { - if (pos->tag.tag != DW_TAG_enumerator) { - fprintf(stderr, "Unexpected DW_TAG_%s <%llx>, skipping it...\n", - dwarf_tag_name(pos->tag.tag), tag__orig_id(&pos->tag, cu)); - continue; + switch (pos->tag.tag) { + case DW_TAG_enumerator: + name = enumerator__name(pos); + if (btf_encoder__add_enum_val(encoder, name, pos->value, etype, conf_load)) + return -1; + break; + case DW_TAG_subprogram: + if (encoder->verbose) + fprintf(stderr, "BTF: DW_TAG_subprogram in enumeration '%s' not supported, skipping\n", + type__name(etype) ?: "(anonymous)"); + break; + default: + fprintf(stderr, "BTF: unexpected DW_TAG_%s in enumeration '%s', skipping\n", + dwarf_tag_name(pos->tag.tag), type__name(etype) ?: "(anonymous)"); + break; } - name = enumerator__name(pos); - if (btf_encoder__add_enum_val(encoder, name, pos->value, etype, conf_load)) - return -1; } return type_id; diff --git a/ctf_encoder.c b/ctf_encoder.c index f2c63c2b039026f8..f9e75a5821ce4e83 100644 --- a/ctf_encoder.c +++ b/ctf_encoder.c @@ -155,12 +155,17 @@ static int enumeration_type__encode(struct tag *tag, const struct cu *cu, uint32 struct enumerator *pos; type__for_each_enumerator(etype, pos) { - if (pos->tag.tag != DW_TAG_enumerator) { - fprintf(stderr, "Unexpected DW_TAG_%s <%llx>, skipping it...\n", - dwarf_tag_name(pos->tag.tag), tag__orig_id(&pos->tag, cu)); - continue; + switch (pos->tag.tag) { + case DW_TAG_enumerator: + ctf__add_enumerator(ctf, pos->name, pos->value, &position); + break; + case DW_TAG_subprogram: + break; + default: + fprintf(stderr, "CTF: unexpected DW_TAG_%s in enumeration '%s', skipping\n", + dwarf_tag_name(pos->tag.tag), type__name(etype) ?: "(anonymous)"); + break; } - ctf__add_enumerator(ctf, pos->name, pos->value, &position); } return 0; -- 2.54.0