All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yonghong Song <yonghong.song@linux.dev>
To: Alan Maguire <alan.maguire@oracle.com>,
	Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com>,
	dwarves@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
	Andrii Nakryiko <andrii@kernel.org>,
	bpf@vger.kernel.org, kernel-team@fb.com
Subject: [PATCH dwarves] btf_encoder: Ensure the first same-name function has a non-zero address
Date: Mon, 27 Jul 2026 19:37:22 -0700	[thread overview]
Message-ID: <20260728023722.1978868-1-yonghong.song@linux.dev> (raw)

When true_signature is enabled, the same function can appear as two kinds
of saved states: an inlined (abstract) instance that carries the original
source signature with no address, and an out-of-line instance that carries
the reconstructed true signature. saved_functions_combine() compares every
same-name state in a group against the first (anchor) one and, when their
prototypes differ, marks the function as having an inconsistent prototype.

Without this patch, the first same-name function may be an inlined instance
whose prototype is the original source signature and thus differs from the
true signature. The two prototypes are then flagged as inconsistent and,
because --btf_features=+true_signature also enables the default
consistent_func feature (skip_encoding_btf_inconsistent_proto), which drops
functions flagged with an inconsistent prototype, the whole function is
dropped from BTF. This primarily affects clang: its signature-changed
functions keep their original name (no "." suffix), so state->sym is never
set and they bypass btf_encoder__add_true_signature(), falling through to
this canonical-state path.

With this patch, same-name functions are sorted so that, if any instance
has a non-zero address, such an instance becomes the first (anchor). That
addressed out-of-line instance is the one whose signature represents the
true signature, so the consistency check compares real instances against
each other and the function is retained in BTF with its true signature.

It is hard to create a test case where one function is inlined in one
place and not inlined in another place. So I built the latest bpf-next
kernel with
  make LLVM=1 -j
and then did
  with master branch:
    pahole -JV --btf_features=+true_signature vmlinux >& log.pahole.old
  with this patch on top of master branch:
    pahole -JV --btf_features=+true_signature vmlinux >& log.pahole.new
and then get warning messages:
  grep "skipping BTF encoding of function" log.pahole.old > log.old
  grep "skipping BTF encoding of function" log.pahole.new > log.new
and compare log.old and log.new
  diff log.old log.new > log.diff

The following are some results:
  --- log.old     2026-07-27 19:06:20.223881463 -0700
  +++ log.new     2026-07-27 19:06:28.874109831 -0700
  @@ -15,45 +15,28 @@
   ZSTD_getCParams_internal : skipping BTF encoding of function due to unexpected register usage for parameter
   ZSTD_getParams : skipping BTF encoding of function due to unexpected register usage for parameter
   __ata_sff_port_intr : skipping BTF encoding of function due to unexpected register usage for parameter
  -__build_flow_key : skipping BTF encoding of function due to param count mismatch; 9 params != 8 params
  -__build_flow_key : skipping BTF encoding of function due to inconsistet prototype
   __collect_tables : skipping BTF encoding of function due to ambiguous address
   __fl_lookup : skipping BTF encoding of function due to return type mismatch
   __fl_lookup : skipping BTF encoding of function due to ambiguous address
   __in6_dev_get : skipping BTF encoding of function due to ambiguous address
   __in_dev_get_rcu : skipping BTF encoding of function due to ambiguous address
  -__instance_destroy : skipping BTF encoding of function due to param type mismatch for param#1 inst != inst
  -__instance_destroy : skipping BTF encoding of function due to inconsistet prototype
   __ioremap_caller : skipping BTF encoding of function due to unexpected register usage for parameter
  -__ipmr_get_table : skipping BTF encoding of function due to param count mismatch; 2 params != 1 params
  -__ipmr_get_table : skipping BTF encoding of function due to inconsistet prototype
   __ipv6_neigh_lookup_noref : skipping BTF encoding of function due to ambiguous address
   __key_get : skipping BTF encoding of function due to ambiguous address
  -__kmem_cache_create : skipping BTF encoding of function due to param count mismatch; 5 params != 2 params
  -__kmem_cache_create : skipping BTF encoding of function due to inconsistet prototype
  -__kunmap_atomic : skipping BTF encoding of function due to param count mismatch; 1 params != 0 params
  -__kunmap_atomic : skipping BTF encoding of function due to inconsistet prototype
   __map_range : skipping BTF encoding of function due to ambiguous address
   __map_range_leaf : skipping BTF encoding of function due to ambiguous address
  -__map_single_page3 : skipping BTF encoding of function due to param count mismatch; 3 params != 4 params
  -__map_single_page3 : skipping BTF encoding of function due to inconsistet prototype
   __migrate_disable : skipping BTF encoding of function due to ambiguous address
   __migrate_enable : skipping BTF encoding of function due to ambiguous address
   __mod_tree_insert : skipping BTF encoding of function due to unexpected register usage for parameter
   __mptcp_pm_send_ack : skipping BTF encoding of function due to unexpected register usage for parameter
  +__neigh_lookup : skipping BTF encoding of function due to param count mismatch; 3 params != 2 params
   __neigh_lookup : skipping BTF encoding of function due to ambiguous address
  -__netdev_walk_all_lower_dev : skipping BTF encoding of function due to param count mismatch; 1 params != 3 params
  -__netdev_walk_all_lower_dev : skipping BTF encoding of function due to inconsistet prototype
   __pci_bus_set_current_state : skipping BTF encoding of function due to unexpected register usage for parameter
   __pskb_trim : skipping BTF encoding of function due to ambiguous address
   __release_region : skipping BTF encoding of function due to unexpected register usage for parameter
   __remove_hrtimer : skipping BTF encoding of function due to unexpected register usage for parameter
   __sk_dst_get : skipping BTF encoding of function due to ambiguous address
   __skb_complete_tx_timestamp : skipping BTF encoding of function due to unexpected register usage for parameter
  -__skb_gro_checksum_validate_complete : skipping BTF encoding of function due to param count mismatch; 2 params != 1 params
  -__skb_gro_checksum_validate_complete : skipping BTF encoding of function due to inconsistet prototype
  -__skb_gro_checksum_validate_needed : skipping BTF encoding of function due to param count mismatch; 3 params != 1 params
  -__skb_gro_checksum_validate_needed : skipping BTF encoding of function due to inconsistet prototype
   __task_rq_unlock : skipping BTF encoding of function due to unexpected register usage for parameter
   __tracing_open : skipping BTF encoding of function due to unexpected register usage for parameter
   __tty_buffer_request_room : skipping BTF encoding of function due to unexpected register usage for parameter
  @@ -63,44 +46,28 @@
  ...

With true signature enabled, this patch allows more BTF functions.

Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
---
 btf_encoder.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/btf_encoder.c b/btf_encoder.c
index 993a61c..fb2b5b0 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -1519,8 +1519,20 @@ static int saved_functions_cmp(const void *_a, const void *_b)
 {
 	const struct btf_encoder_func_state *a = _a;
 	const struct btf_encoder_func_state *b = _b;
-
-	return elf_function__name_cmp(a->elf, b->elf);
+	int ret;
+
+	ret = elf_function__name_cmp(a->elf, b->elf);
+	if (ret)
+		return ret;
+
+	/* For the same function, sort the out-of-line (real) instances, which
+	 * have a function address, before the inlined (abstract) ones, which do
+	 * not. saved_functions_combine() compares every state in a group against
+	 * the first (anchor) one, so keeping a real instance as the anchor
+	 * ensures real instances are still compared against each other for
+	 * prototype consistency.
+	 */
+	return (a->addr == 0) - (b->addr == 0);
 }
 
 static int saved_functions_combine(struct btf_encoder *encoder,
@@ -1536,7 +1548,9 @@ static int saved_functions_combine(struct btf_encoder *encoder,
 	inconsistent = a->inconsistent_proto | b->inconsistent_proto;
 	uncertain_parm_loc = a->uncertain_parm_loc | b->uncertain_parm_loc;
 	reordered_parm = a->reordered_parm | b->reordered_parm;
-	if (!unexpected && !inconsistent && !reordered_parm && !funcs__match(encoder, a, b))
+
+	if ((!encoder->true_signature || !!a->addr == !!b->addr) &&
+	    !unexpected && !inconsistent && !reordered_parm && !funcs__match(encoder, a, b))
 		inconsistent = 1;
 	a->unexpected_reg = b->unexpected_reg = unexpected;
 	a->inconsistent_proto = b->inconsistent_proto = inconsistent;
-- 
2.53.0-Meta


                 reply	other threads:[~2026-07-28  2:37 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260728023722.1978868-1-yonghong.song@linux.dev \
    --to=yonghong.song@linux.dev \
    --cc=alan.maguire@oracle.com \
    --cc=andrii@kernel.org \
    --cc=arnaldo.melo@gmail.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=dwarves@vger.kernel.org \
    --cc=kernel-team@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.