public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 dwarves 0/5] Improve BTF concrete function accuracy
@ 2026-01-23 17:26 Alan Maguire
  2026-01-23 17:26 ` [PATCH v2 dwarves 1/5] dwarf_loader/btf_encoder: Detect reordered parameters Alan Maguire
                   ` (4 more replies)
  0 siblings, 5 replies; 20+ messages in thread
From: Alan Maguire @ 2026-01-23 17:26 UTC (permalink / raw)
  To: yonghong.song, mattbobrowski
  Cc: ihor.solodrai, eddyz87, jolsa, andrii, ast, david.faust, dwarves,
	bpf, Alan Maguire

This series brings together a few solutions to issues we have
with accuracy of BTF function representation at the binary level.

The first patch detects mismatches between concrete (binary)
and abstract (source-level) function signatures as a means
of either excluding them or providing a "true" function signature.

Patch 2 adds GCC true function signature support for optimized
functions; with that support, we use binary-level signatures
for .isra.0, .constprop.0 functions and represent them with
their "." suffixes as BTF_KIND_FUNC names.

This allows for fentry attach to such functions, and
the "." suffix is an indicator of signature modification.
The feature is guarded by a default-off BTF feature because
older kernels did not support a "." in a function name.

Patch 3 uses Yonghong's example program as a test; compiling
with -O2 we expect a parameter to "foo" to be optimized
out and the true function signature should reflect that.

Patch 4 documents the non-default "true_signature" feature.

Patch 5 is Matt's patch to favour the strong function
over the associated weak declaration.  The other patches
are important prerequisites for this as the patch selects
the binary-level function (with a lowpc value), and in
the case of optimized functions we were often selecting
the .isra function with optimized-out parameters.  Because
pahole did not previously detect this correctly we ended
up with functions with signatures having reordered parameters.

Patches 1-2 help avoid this by better detecting optimized-out
function parameters.

With these patches in place, ~20 functions are omitted from
vmlinux BTF; all these are "."-suffixed functions which
we were not noticing had optimized-out parameters.

Experimenting with adding true_signature to BTF features
we end up adding approximately 500 .isra and .constprop
functions to vmlinux BTF.

The true function signature support here will also hopefully
help pave the way for Yonghong's work on the LLVM side.

Changes since v1 [1]

- dropped Yonghong's patch (Ihor)
- fixed up issues Yonghong found in true signature encoding
  where we did not adjust the number of parameters and
  were not handling true function signature case correctly
  when adding saved functions (Yonghong, patch 2)
- added test using Yonghong's example (patch 3)

[1] https://lore.kernel.org/dwarves/20260113131352.2395024-1-alan.maguire@oracle.com/

Alan Maguire (4):
  dwarf_loader/btf_encoder: Detect reordered parameters
  btf_encoder: Add true_signature feature support for "."-suffixed
    functions
  test: add gcc true signature test
  man-pages: document true_signature btf_feature

Matt Bobrowski (1):
  btf_encoder: Prefer strong function definitions for BTF generation

 btf_encoder.c                | 139 +++++++++++++++++++++++++++++++----
 dwarf_loader.c               |   5 +-
 dwarves.h                    |   3 +
 man-pages/pahole.1           |   5 ++
 pahole.c                     |   1 +
 tests/gcc_true_signatures.sh |  92 +++++++++++++++++++++++
 6 files changed, 227 insertions(+), 18 deletions(-)
 create mode 100755 tests/gcc_true_signatures.sh

-- 
2.43.5


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

* [PATCH v2 dwarves 1/5] dwarf_loader/btf_encoder: Detect reordered parameters
  2026-01-23 17:26 [PATCH v2 dwarves 0/5] Improve BTF concrete function accuracy Alan Maguire
@ 2026-01-23 17:26 ` Alan Maguire
  2026-01-26  9:30   ` Matt Bobrowski
  2026-01-23 17:26 ` [PATCH v2 dwarves 2/5] btf_encoder: Add true_signature feature support for "."-suffixed functions Alan Maguire
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 20+ messages in thread
From: Alan Maguire @ 2026-01-23 17:26 UTC (permalink / raw)
  To: yonghong.song, mattbobrowski
  Cc: ihor.solodrai, eddyz87, jolsa, andrii, ast, david.faust, dwarves,
	bpf, Alan Maguire

When encoding concrete instances of optimized functions it is possible
parameters get reordered, often due to a parameter being optimized out;
in such cases the order of abstract origin references to the abstract
function is different, and the parameters that are optimized out
usually appear after all the non-optimized parameters with no
DW_AT_location information [1].

As an example consider

static void __blkcg_rstat_flush(struct blkcg *blkcg, int cpu);

It has - as expected - an abstract representation as follows:

 <1><6392a2d>: Abbrev Number: 47 (DW_TAG_subprogram)
    <6392a2e>   DW_AT_name        : (indirect string, offset: 0x261e25): __blkcg_rstat_flush
    <6392a32>   DW_AT_decl_file   : 1
    <6392a33>   DW_AT_decl_line   : 1043
    <6392a35>   DW_AT_decl_column : 13
    <6392a36>   DW_AT_prototyped  : 1
    <6392a36>   DW_AT_inline      : 1   (inlined)
    <6392a37>   DW_AT_sibling     : <0x6392bac>
 <2><6392a3b>: Abbrev Number: 38 (DW_TAG_formal_parameter)
    <6392a3c>   DW_AT_name        : (indirect string, offset: 0xa7a9f): blkcg
    <6392a40>   DW_AT_decl_file   : 1
    <6392a41>   DW_AT_decl_line   : 1043
    <6392a43>   DW_AT_decl_column : 47
    <6392a44>   DW_AT_type        : <0x638b611>
 <2><6392a48>: Abbrev Number: 20 (DW_TAG_formal_parameter)
    <6392a49>   DW_AT_name        : cpu
    <6392a4d>   DW_AT_decl_file   : 1
    <6392a4e>   DW_AT_decl_line   : 1043
    <6392a50>   DW_AT_decl_column : 58
    <6392a51>   DW_AT_type        : <0x6377f8f>

However the concrete representation after optimization becomes:

ffffffff8186d180 t __blkcg_rstat_flush.isra.0

and has a concrete representation with parameter order switched:

<1><6399661>: Abbrev Number: 110 (DW_TAG_subprogram)
    <6399662>   DW_AT_abstract_origin: <0x6392a2d>
    <6399666>   DW_AT_low_pc      : 0xffffffff8186d180
    <639966e>   DW_AT_high_pc     : 0x169
    <6399676>   DW_AT_frame_base  : 1 byte block: 9c    (DW_OP_call_frame_cfa)
    <6399678>   DW_AT_GNU_all_call_sites: 1
    <6399678>   DW_AT_sibling     : <0x6399a8a>
 <2><639967c>: Abbrev Number: 4 (DW_TAG_formal_parameter)
    <639967d>   DW_AT_abstract_origin: <0x6392a48>
    <6399681>   DW_AT_location    : 0x1fe21fb (location list)
    <6399685>   DW_AT_GNU_locviews: 0x1fe21f5
 <2><63996e4>: Abbrev Number: 4 (DW_TAG_formal_parameter)
    <63996e5>   DW_AT_abstract_origin: <0x6392a3b>
    <63996e9>   DW_AT_location    : 0x1fe2387 (location list)
    <63996ed>   DW_AT_GNU_locviews: 0x1fe2385

In other words we end up with

static void __blkcg_rstat_flush.isra(int cpu, struct blkcg *blkcg);

We are not detecting cases like this in pahole, so we need to
catch it to exclude such cases since they could lead to incorrect
fentry attachment.

Future work around true function signatures will allow such functions
with their "." suffixes, but even for such cases it is good to
detect the reordering.

In practice we just end up excluding a few more .isra/.constprop
functions which we cannot fentry-attach by name anyway; see [2] for an
example list from CI.

[1] https://lore.kernel.org/bpf/101b74c9-949a-4bf4-a766-a5343b70bdd2@oracle.com/
[2] https://github.com/alan-maguire/dwarves/actions/runs/20031993822

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Acked-by: Yonghong Song <yonghong.song@linux.dev>
---
 btf_encoder.c  | 29 ++++++++++++++++++++---------
 dwarf_loader.c |  5 +++--
 dwarves.h      |  2 ++
 3 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/btf_encoder.c b/btf_encoder.c
index ec6933e..9a567e4 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -87,6 +87,7 @@ struct btf_encoder_func_state {
 	uint8_t unexpected_reg:1;
 	uint8_t inconsistent_proto:1;
 	uint8_t uncertain_parm_loc:1;
+	uint8_t reordered_parm:1;
 	uint8_t ambiguous_addr:1;
 	int ret_type_id;
 	struct btf_encoder_func_parm *parms;
@@ -1273,6 +1274,7 @@ static int32_t btf_encoder__save_func(struct btf_encoder *encoder, struct functi
 	state->unexpected_reg = ftype->unexpected_reg;
 	state->optimized_parms = ftype->optimized_parms;
 	state->uncertain_parm_loc = ftype->uncertain_parm_loc;
+	state->reordered_parm = ftype->reordered_parm;
 	ftype__for_each_parameter(ftype, param) {
 		const char *name = parameter__name(param) ?: "";
 
@@ -1442,7 +1444,7 @@ static int saved_functions_combine(struct btf_encoder *encoder,
 				   struct btf_encoder_func_state *a,
 				   struct btf_encoder_func_state *b)
 {
-	uint8_t optimized, unexpected, inconsistent, uncertain_parm_loc;
+	uint8_t optimized, unexpected, inconsistent, uncertain_parm_loc, reordered_parm;
 
 	if (a->elf != b->elf)
 		return 1;
@@ -1451,12 +1453,14 @@ static int saved_functions_combine(struct btf_encoder *encoder,
 	unexpected = a->unexpected_reg | b->unexpected_reg;
 	inconsistent = a->inconsistent_proto | b->inconsistent_proto;
 	uncertain_parm_loc = a->uncertain_parm_loc | b->uncertain_parm_loc;
-	if (!unexpected && !inconsistent && !funcs__match(encoder, a, b))
+	reordered_parm = a->reordered_parm | b->reordered_parm;
+	if (!unexpected && !inconsistent && !reordered_parm && !funcs__match(encoder, a, b))
 		inconsistent = 1;
 	a->optimized_parms = b->optimized_parms = optimized;
 	a->unexpected_reg = b->unexpected_reg = unexpected;
 	a->inconsistent_proto = b->inconsistent_proto = inconsistent;
 	a->uncertain_parm_loc = b->uncertain_parm_loc = uncertain_parm_loc;
+	a->reordered_parm = b->reordered_parm = reordered_parm;
 
 	return 0;
 }
@@ -1494,7 +1498,7 @@ static int btf_encoder__add_saved_funcs(struct btf_encoder *encoder, bool skip_e
 
 	for (i = 0; i < nr_saved_fns; i = j) {
 		struct btf_encoder_func_state *state = &saved_fns[i];
-		bool add_to_btf = !skip_encoding_inconsistent_proto;
+		char *skip_reason = NULL;
 
 		/* Compare across sorted functions that match by name/prefix;
 		 * share inconsistent/unexpected reg state between them.
@@ -1510,14 +1514,21 @@ static int btf_encoder__add_saved_funcs(struct btf_encoder *encoder, bool skip_e
 		 * unexpected register use, multiple inconsistent prototypes or
 		 * uncertain parameters location
 		 */
-		add_to_btf |= !state->unexpected_reg && !state->inconsistent_proto && !state->uncertain_parm_loc && !state->elf->ambiguous_addr;
-
+		if (state->unexpected_reg)
+			skip_reason = "unexpected register usage for parameter\n";
+		if (skip_encoding_inconsistent_proto && state->inconsistent_proto)
+			skip_reason = "inconsistet prototype\n";
 		if (state->uncertain_parm_loc)
-			btf_encoder__log_func_skip(encoder, saved_fns[i].elf,
-					"uncertain parameter location\n",
-					0, 0);
+			skip_reason = "uncertain parameter location\n";
+		if (state->reordered_parm)
+			skip_reason = "reordered parameters\n";
+		if (state->elf->ambiguous_addr)
+			skip_reason = "ambiguous address\n";
 
-		if (add_to_btf) {
+		if (skip_reason) {
+			btf_encoder__log_func_skip(encoder, saved_fns[i].elf,
+						   skip_reason, 0, 0);
+		} else {
 			if (is_kfunc_state(state))
 				err = btf_encoder__add_bpf_kfunc(encoder, state);
 			else
diff --git a/dwarf_loader.c b/dwarf_loader.c
index 77aab8a..16fb7be 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -1262,7 +1262,7 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu,
 
 		tag__init(&parm->tag, cu, die);
 		parm->name = attr_string(die, DW_AT_name, conf);
-
+		parm->idx = param_idx;
 		if (param_idx >= cu->nr_register_params || param_idx < 0)
 			return parm;
 		/* Parameters which use DW_AT_abstract_origin to point at
@@ -2636,6 +2636,8 @@ static void ftype__recode_dwarf_types(struct tag *tag, struct cu *cu)
 			}
 			opos = tag__parameter(dtag__tag(dtype));
 			pos->name = opos->name;
+			if (pos->idx != opos->idx)
+				type->reordered_parm = 1;
 			pos->tag.type = dtag__tag(dtype)->type;
 			/* share location information between parameter and
 			 * abstract origin; if neither have location, we will
@@ -2838,7 +2840,6 @@ static int tag__recode_dwarf_type(struct tag *tag, struct cu *cu)
 		lexblock__recode_dwarf_types(&fn->lexblock, cu);
 	}
 		/* Fall thru */
-
 	case DW_TAG_subroutine_type:
 		ftype__recode_dwarf_types(tag, cu);
 		/* Fall thru, for the function return type */
diff --git a/dwarves.h b/dwarves.h
index 21d4166..78bedf5 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -944,6 +944,7 @@ struct parameter {
 	uint8_t optimized:1;
 	uint8_t unexpected_reg:1;
 	uint8_t has_loc:1;
+	uint8_t idx;
 };
 
 static inline struct parameter *tag__parameter(const struct tag *tag)
@@ -1023,6 +1024,7 @@ struct ftype {
 	uint8_t		 processed:1;
 	uint8_t		 inconsistent_proto:1;
 	uint8_t		 uncertain_parm_loc:1;
+	uint8_t		 reordered_parm:1;
 	struct list_head template_type_params;
 	struct list_head template_value_params;
 	struct template_parameter_pack *template_parameter_pack;
-- 
2.43.5


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

* [PATCH v2 dwarves 2/5] btf_encoder: Add true_signature feature support for "."-suffixed functions
  2026-01-23 17:26 [PATCH v2 dwarves 0/5] Improve BTF concrete function accuracy Alan Maguire
  2026-01-23 17:26 ` [PATCH v2 dwarves 1/5] dwarf_loader/btf_encoder: Detect reordered parameters Alan Maguire
@ 2026-01-23 17:26 ` Alan Maguire
  2026-01-23 19:05   ` Yonghong Song
  2026-01-26  9:52   ` Matt Bobrowski
  2026-01-23 17:26 ` [PATCH v2 dwarves 3/5] test: add gcc true signature test Alan Maguire
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 20+ messages in thread
From: Alan Maguire @ 2026-01-23 17:26 UTC (permalink / raw)
  To: yonghong.song, mattbobrowski
  Cc: ihor.solodrai, eddyz87, jolsa, andrii, ast, david.faust, dwarves,
	bpf, Alan Maguire

Currently we collate function information by name and add functions
provided there are no inconsistencies across various representations.

For true_signature support - where we wish to add the real signature
of a function even if it differs from source level - we need to do
a few things:

1. For "."-suffixed functions, we need to match from DWARF->ELF;
   we can do this via the address associated with the function.
   In doing this, we can then be confident that the debug info
   for foo.isra.0 is the right info for the function at that
   address.

2. When adding saved functions we need to look for such cases
   and provided they do not violate other constraints around BTF
   representation - unexpected reg usage for function, uncertain
   parameter location or ambiguous address - we add them with
   their "."-suffixed name.  The latter can be used as a signal
   that the function is transformed from the original.

Doing this adds 500 functions to BTF.  These are traceable with
their "."-suffix names and because we have excluded ambiguous
address cases we know exactly which function address they refer
to.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
 btf_encoder.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++-----
 dwarves.h     |  1 +
 pahole.c      |  1 +
 3 files changed, 71 insertions(+), 7 deletions(-)

diff --git a/btf_encoder.c b/btf_encoder.c
index 9a567e4..c1002c3 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -77,9 +77,16 @@ struct btf_encoder_func_annot {
 	int16_t component_idx;
 };
 
+struct elf_function_sym {
+	const char *name;
+	uint64_t addr;
+};
+
 /* state used to do later encoding of saved functions */
 struct btf_encoder_func_state {
 	struct elf_function *elf;
+	struct elf_function_sym *sym;
+	uint64_t addr;
 	uint32_t type_id_off;
 	uint16_t nr_parms;
 	uint16_t nr_annots;
@@ -94,11 +101,6 @@ struct btf_encoder_func_state {
 	struct btf_encoder_func_annot *annots;
 };
 
-struct elf_function_sym {
-	const char *name;
-	uint64_t addr;
-};
-
 struct elf_function {
 	char		*name;
 	struct elf_function_sym *syms;
@@ -145,7 +147,8 @@ struct btf_encoder {
 			  skip_encoding_decl_tag,
 			  tag_kfuncs,
 			  gen_distilled_base,
-			  encode_attributes;
+			  encode_attributes,
+			  true_signature;
 	uint32_t	  array_index_id;
 	struct elf_secinfo *secinfo;
 	size_t             seccnt;
@@ -1270,14 +1273,36 @@ static int32_t btf_encoder__save_func(struct btf_encoder *encoder, struct functi
 			goto out;
 		}
 	}
+	if (encoder->true_signature && fn->lexblock.ip.addr) {
+		int i;
+
+		for (i = 0; i < func->sym_cnt; i++) {
+			if (fn->lexblock.ip.addr != func->syms[i].addr)
+				continue;
+			/* Only need to record address for '.'-suffixed
+			 * functions, since we only currently need true
+			 * signatures for them.
+			 */
+			if (!strchr(func->syms[i].name, '.'))
+				continue;
+			state->sym = &func->syms[i];
+			break;
+		}
+	}
 	state->inconsistent_proto = ftype->inconsistent_proto;
 	state->unexpected_reg = ftype->unexpected_reg;
 	state->optimized_parms = ftype->optimized_parms;
 	state->uncertain_parm_loc = ftype->uncertain_parm_loc;
 	state->reordered_parm = ftype->reordered_parm;
 	ftype__for_each_parameter(ftype, param) {
-		const char *name = parameter__name(param) ?: "";
+		const char *name;
 
+		/* No location info/optimized + reordered means optimized out. */
+		if (ftype->reordered_parm && (!param->has_loc || param->optimized)) {
+			state->nr_parms--;
+			continue;
+		}
+		name = parameter__name(param) ?: "";
 		str_off = btf__add_str(btf, name);
 		if (str_off < 0) {
 			err = str_off;
@@ -1366,6 +1391,9 @@ static int32_t btf_encoder__add_func(struct btf_encoder *encoder,
 
 	btf_fnproto_id = btf_encoder__add_func_proto_for_state(encoder, state);
 	name = func->name;
+	if (encoder->true_signature && state->sym)
+		name = state->sym->name;
+
 	if (btf_fnproto_id >= 0)
 		btf_fn_id = btf_encoder__add_ref_type(encoder, BTF_KIND_FUNC, btf_fnproto_id,
 						      name, false);
@@ -1508,6 +1536,39 @@ static int btf_encoder__add_saved_funcs(struct btf_encoder *encoder, bool skip_e
 		while (j < nr_saved_fns && saved_functions_combine(encoder, &saved_fns[i], &saved_fns[j]) == 0)
 			j++;
 
+		/* Add true signatures for case where we have an exact
+		 * symbol match by address from DWARF->ELF and have a
+		 * "." suffixed name.
+		 */
+		if (encoder->true_signature) {
+			bool true_added = false;
+			int k;
+
+			for (k = i; k < nr_saved_fns; k++) {
+				struct btf_encoder_func_state *true_state = &saved_fns[k];
+
+				if (state->elf != true_state->elf)
+					break;
+				if (!true_state->sym)
+					continue;
+				/* Unexpected reg, uncertain parm loc and
+				 * ambiguous address mean we cannot trust fentry.
+				 */
+				if (true_state->unexpected_reg ||
+				    true_state->uncertain_parm_loc ||
+				    true_state->ambiguous_addr)
+					continue;
+				err = btf_encoder__add_func(encoder, true_state);
+				if (err < 0)
+					goto out;
+				true_added = true;
+				break;
+			}
+			/* If true symbol was added, skip the below. */
+			if (true_added)
+				continue;
+		}
+
 		/* do not exclude functions with optimized-out parameters; they
 		 * may still be _called_ with the right parameter values, they
 		 * just do not _use_ them.  Only exclude functions with
@@ -2584,6 +2645,7 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam
 		encoder->tag_kfuncs	 = conf_load->btf_decl_tag_kfuncs;
 		encoder->gen_distilled_base = conf_load->btf_gen_distilled_base;
 		encoder->encode_attributes = conf_load->btf_attributes;
+		encoder->true_signature = conf_load->true_signature;
 		encoder->verbose	 = verbose;
 		encoder->has_index_type  = false;
 		encoder->need_index_type = false;
diff --git a/dwarves.h b/dwarves.h
index 78bedf5..d7c6474 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -101,6 +101,7 @@ struct conf_load {
 	bool			btf_decl_tag_kfuncs;
 	bool			btf_gen_distilled_base;
 	bool			btf_attributes;
+	bool			true_signature;
 	uint8_t			hashtable_bits;
 	uint8_t			max_hashtable_bits;
 	uint16_t		kabi_prefix_len;
diff --git a/pahole.c b/pahole.c
index ef01e58..02a0d19 100644
--- a/pahole.c
+++ b/pahole.c
@@ -1234,6 +1234,7 @@ struct btf_feature {
 	BTF_NON_DEFAULT_FEATURE(global_var, encode_btf_global_vars, false),
 	BTF_NON_DEFAULT_FEATURE_CHECK(attributes, btf_attributes, false,
 				      attributes_check),
+	BTF_NON_DEFAULT_FEATURE(true_signature, true_signature, false),
 };
 
 #define BTF_MAX_FEATURE_STR	1024
-- 
2.43.5


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

* [PATCH v2 dwarves 3/5] test: add gcc true signature test
  2026-01-23 17:26 [PATCH v2 dwarves 0/5] Improve BTF concrete function accuracy Alan Maguire
  2026-01-23 17:26 ` [PATCH v2 dwarves 1/5] dwarf_loader/btf_encoder: Detect reordered parameters Alan Maguire
  2026-01-23 17:26 ` [PATCH v2 dwarves 2/5] btf_encoder: Add true_signature feature support for "."-suffixed functions Alan Maguire
@ 2026-01-23 17:26 ` Alan Maguire
  2026-01-23 19:06   ` Yonghong Song
  2026-01-23 17:26 ` [PATCH v2 dwarves 4/5] man-pages: document true_signature btf_feature Alan Maguire
  2026-01-23 17:26 ` [PATCH v2 dwarves 5/5] btf_encoder: Prefer strong function definitions for BTF generation Alan Maguire
  4 siblings, 1 reply; 20+ messages in thread
From: Alan Maguire @ 2026-01-23 17:26 UTC (permalink / raw)
  To: yonghong.song, mattbobrowski
  Cc: ihor.solodrai, eddyz87, jolsa, andrii, ast, david.faust, dwarves,
	bpf, Alan Maguire

Use Yonghong's true signature test program to verify signatures
differ for function "foo" with optimized-out parameter.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
 tests/gcc_true_signatures.sh | 92 ++++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)
 create mode 100755 tests/gcc_true_signatures.sh

diff --git a/tests/gcc_true_signatures.sh b/tests/gcc_true_signatures.sh
new file mode 100755
index 0000000..57cbe3f
--- /dev/null
+++ b/tests/gcc_true_signatures.sh
@@ -0,0 +1,92 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
+
+outdir=
+
+fail()
+{
+	# Do not remove test dir; might be useful for analysis
+	trap - EXIT
+	if [[ -d "$outdir" ]]; then
+		echo "Test data is in $outdir"
+	fi
+	exit 1
+}
+
+cleanup()
+{
+	rm ${outdir}/*
+	rmdir $outdir
+}
+
+outdir=$(mktemp -d /tmp/gcc_true.sh.XXXXXX)
+
+trap cleanup EXIT
+
+echo -n "Validation of BTF encoding of true_signatures: "
+
+gcc_true="${outdir}/gcc_true"
+CC=$(which gcc 2>/dev/null)
+
+if [[ -z "$CC" ]]; then
+	echo "skip: gcc not available"
+	exit 2
+fi
+
+cat > ${gcc_true}.c << EOF
+struct t { int a; };
+__attribute__((noinline)) char *tar(struct t *a, struct t *d)
+{
+	if (a->a == d->a)
+		return (char *)10;
+	else
+		return (char *)0;
+}
+
+__attribute__((noinline)) static char * foo(struct t *a, int b, struct t *d)
+{
+	return tar(a, d);
+}
+
+__attribute__((noinline)) char *bar(struct t *a, struct t *d)
+{
+	return foo(a, 1, d);
+}
+
+struct t p1, p2;
+int main()
+{
+	return !!bar(&p1, &p2);
+}
+EOF
+
+CFLAGS="$CFLAGS -g -O2"
+${CC} ${CFLAGS} -o $gcc_true ${gcc_true}.c
+if [[ $? -ne 0 ]]; then
+	echo "Could not compile ${gcc_true}.c" >& 2
+	exit 1
+fi
+LLVM_OBJCOPY=objcopy pahole -J --btf_features=+true_signature $gcc_true
+if [[ $? -ne 0 ]]; then
+	echo "Could not encode BTF for $gcc_true"
+	exit 1
+fi
+
+btf_optimized=$(pfunct --all --format_path=btf $gcc_true |grep "foo\.")
+if [[ -z "$btf_optimized" ]]; then
+	echo "skip: no optimizations applied."
+	exit 2
+fi
+# Convert foo.[constprop|isra].0 to foo to allow comparison.
+btf_cmp="$(echo $btf_optimized \
+	awk '/foo/ {sub(/\.constprop.0/,""); sub(/\.isra.0/,""); print $0 }')"
+dwarf=$(pfunct --all $gcc_true |grep "foo")
+
+test -n "$VERBOSE" && printf "\nBTF: $btf_optimized  DWARF: $dwarf \n"
+
+if [[ "$btf_cmp" == "$dwarf" ]]; then
+	echo "BTF and DWARF signatures should be different and they are not: BTF: $btf_optimized ; DWARF $dwarf"
+	exit 1
+fi
+echo "Ok"
+exit 0
-- 
2.43.5


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

* [PATCH v2 dwarves 4/5] man-pages: document true_signature btf_feature
  2026-01-23 17:26 [PATCH v2 dwarves 0/5] Improve BTF concrete function accuracy Alan Maguire
                   ` (2 preceding siblings ...)
  2026-01-23 17:26 ` [PATCH v2 dwarves 3/5] test: add gcc true signature test Alan Maguire
@ 2026-01-23 17:26 ` Alan Maguire
  2026-01-23 19:07   ` Yonghong Song
  2026-01-26 10:02   ` Matt Bobrowski
  2026-01-23 17:26 ` [PATCH v2 dwarves 5/5] btf_encoder: Prefer strong function definitions for BTF generation Alan Maguire
  4 siblings, 2 replies; 20+ messages in thread
From: Alan Maguire @ 2026-01-23 17:26 UTC (permalink / raw)
  To: yonghong.song, mattbobrowski
  Cc: ihor.solodrai, eddyz87, jolsa, andrii, ast, david.faust, dwarves,
	bpf, Alan Maguire

Ensure non-default "true_signature" feature is documented in
the manual page.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
 man-pages/pahole.1 | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/man-pages/pahole.1 b/man-pages/pahole.1
index 3125de3..90a8f45 100644
--- a/man-pages/pahole.1
+++ b/man-pages/pahole.1
@@ -337,6 +337,11 @@ Supported non-standard features (not enabled for 'default')
 	                   of split BTF with a possibly changed base, storing
 	                   it in a .BTF.base ELF section.
 	global_var         Encode all global variables using BTF_KIND_VAR in BTF.
+	true_signature     Encode functions ensuring that binary-level
+	                   (rather than source-level) signatures are used;
+                           for gcc these are ".isra.0" and ".costprop.0"
+                           optimized functions
+
 .fi
 
 So for example, specifying \-\-btf_encode=var,enum64 will result in a BTF encoding that (as well as encoding basic BTF information) will contain variables and enum64 values.
-- 
2.43.5


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

* [PATCH v2 dwarves 5/5] btf_encoder: Prefer strong function definitions for BTF generation
  2026-01-23 17:26 [PATCH v2 dwarves 0/5] Improve BTF concrete function accuracy Alan Maguire
                   ` (3 preceding siblings ...)
  2026-01-23 17:26 ` [PATCH v2 dwarves 4/5] man-pages: document true_signature btf_feature Alan Maguire
@ 2026-01-23 17:26 ` Alan Maguire
  2026-01-23 19:09   ` Yonghong Song
  4 siblings, 1 reply; 20+ messages in thread
From: Alan Maguire @ 2026-01-23 17:26 UTC (permalink / raw)
  To: yonghong.song, mattbobrowski
  Cc: ihor.solodrai, eddyz87, jolsa, andrii, ast, david.faust, dwarves,
	bpf

From: Matt Bobrowski <mattbobrowski@google.com>

Currently, when a function has both a weak and a strong definition
across different compilation units (CUs), the BTF encoder arbitrarily
selects one to generate the BTF entry. This selection fundamentally is
dependent on the order in which pahole processes the CUs.

This indifference often leads to a mismatch where the generated BTF
reflects the weak definition's prototype, even though the linker
selected the strong definition for the final vmlinux binary.

A notable example described in [0] involving function
bpf_lsm_mmap_file(). Both weak and strong definitions exist,
distinguished only by parameter names (e.g., file vs
file__nullable). While the strong definition is linked into the
vmlinux object, the generated BTF contained the prototype for the weak
definition. This causes issues for BPF verifier (e.g., __nullable
annotation semantics), or tools relying on accurate type information.

To fix this, ensure the BTF encoder selects the function definition
corresponding to the actual code linked into the binary. This is
achieved by comparing the DWARF function address (DW_AT_low_pc) with
the ELF symbol address (st_value). Only the DWARF entry for the strong
definition will match the final resolved ELF symbol address.

[0] https://lore.kernel.org/all/aVJY9H-e83T7ivT4@google.com/

Link: https://lore.kernel.org/all/aVJY9H-e83T7ivT4@google.com/
Signed-off-by: Matt Bobrowski <mattbobrowski@google.com>
---
 btf_encoder.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/btf_encoder.c b/btf_encoder.c
index c1002c3..4264f36 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -1263,6 +1263,7 @@ static int32_t btf_encoder__save_func(struct btf_encoder *encoder, struct functi
 	if (!state)
 		return -ENOMEM;
 
+	state->addr = function__addr(fn);
 	state->elf = func;
 	state->nr_parms = ftype->nr_parms + (ftype->unspec_parms ? 1 : 0);
 	state->ret_type_id = ftype->tag.type == 0 ? 0 : encoder->type_id_off + ftype->tag.type;
@@ -1510,6 +1511,29 @@ static void btf_encoder__delete_saved_funcs(struct btf_encoder *encoder)
 	encoder->func_states.cap = 0;
 }
 
+static struct btf_encoder_func_state *btf_encoder__select_canonical_state(struct btf_encoder_func_state *combined_states,
+									  int combined_cnt)
+{
+	int i, j;
+
+	/*
+	 * The same elf_function is shared amongst combined functions,
+	 * as per saved_functions_combine().
+	 */
+	struct elf_function *elf = combined_states[0].elf;
+
+	for (i = 0; i < combined_cnt; i++) {
+		struct btf_encoder_func_state *state = &combined_states[i];
+
+		for (j = 0; j < elf->sym_cnt; j++) {
+			if (state->addr == elf->syms[j].addr)
+				return state;
+		}
+	}
+
+	return &combined_states[0];
+}
+
 static int btf_encoder__add_saved_funcs(struct btf_encoder *encoder, bool skip_encoding_inconsistent_proto)
 {
 	struct btf_encoder_func_state *saved_fns = encoder->func_states.array;
@@ -1590,6 +1614,16 @@ static int btf_encoder__add_saved_funcs(struct btf_encoder *encoder, bool skip_e
 			btf_encoder__log_func_skip(encoder, saved_fns[i].elf,
 						   skip_reason, 0, 0);
 		} else {
+			/*
+			 * We're to add the current function within
+			 * BTF. Although, from all functions that have
+			 * possibly been combined via
+			 * saved_functions_combine(), ensure to only
+			 * select and emit BTF for the most canonical
+			 * function definition.
+			 */
+			if (j - i > 1)
+				state = btf_encoder__select_canonical_state(state, j - i);
 			if (is_kfunc_state(state))
 				err = btf_encoder__add_bpf_kfunc(encoder, state);
 			else
-- 
2.43.5


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

* Re: [PATCH v2 dwarves 2/5] btf_encoder: Add true_signature feature support for "."-suffixed functions
  2026-01-23 17:26 ` [PATCH v2 dwarves 2/5] btf_encoder: Add true_signature feature support for "."-suffixed functions Alan Maguire
@ 2026-01-23 19:05   ` Yonghong Song
  2026-01-26  9:52   ` Matt Bobrowski
  1 sibling, 0 replies; 20+ messages in thread
From: Yonghong Song @ 2026-01-23 19:05 UTC (permalink / raw)
  To: Alan Maguire, mattbobrowski
  Cc: ihor.solodrai, eddyz87, jolsa, andrii, ast, david.faust, dwarves,
	bpf



On 1/23/26 9:26 AM, Alan Maguire wrote:
> Currently we collate function information by name and add functions
> provided there are no inconsistencies across various representations.
>
> For true_signature support - where we wish to add the real signature
> of a function even if it differs from source level - we need to do
> a few things:
>
> 1. For "."-suffixed functions, we need to match from DWARF->ELF;
>     we can do this via the address associated with the function.
>     In doing this, we can then be confident that the debug info
>     for foo.isra.0 is the right info for the function at that
>     address.
>
> 2. When adding saved functions we need to look for such cases
>     and provided they do not violate other constraints around BTF
>     representation - unexpected reg usage for function, uncertain
>     parameter location or ambiguous address - we add them with
>     their "."-suffixed name.  The latter can be used as a signal
>     that the function is transformed from the original.
>
> Doing this adds 500 functions to BTF.  These are traceable with
> their "."-suffix names and because we have excluded ambiguous
> address cases we know exactly which function address they refer
> to.
>
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>

Acked-by: Yonghong Song <yonghong.song@linux.dev>


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

* Re: [PATCH v2 dwarves 3/5] test: add gcc true signature test
  2026-01-23 17:26 ` [PATCH v2 dwarves 3/5] test: add gcc true signature test Alan Maguire
@ 2026-01-23 19:06   ` Yonghong Song
  0 siblings, 0 replies; 20+ messages in thread
From: Yonghong Song @ 2026-01-23 19:06 UTC (permalink / raw)
  To: Alan Maguire, mattbobrowski
  Cc: ihor.solodrai, eddyz87, jolsa, andrii, ast, david.faust, dwarves,
	bpf



On 1/23/26 9:26 AM, Alan Maguire wrote:
> Use Yonghong's true signature test program to verify signatures
> differ for function "foo" with optimized-out parameter.
>
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>

Tested and it works fine to me.

Acked-by: Yonghong Song <yonghong.song@linux.dev>


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

* Re: [PATCH v2 dwarves 4/5] man-pages: document true_signature btf_feature
  2026-01-23 17:26 ` [PATCH v2 dwarves 4/5] man-pages: document true_signature btf_feature Alan Maguire
@ 2026-01-23 19:07   ` Yonghong Song
  2026-01-26 10:02   ` Matt Bobrowski
  1 sibling, 0 replies; 20+ messages in thread
From: Yonghong Song @ 2026-01-23 19:07 UTC (permalink / raw)
  To: Alan Maguire, mattbobrowski
  Cc: ihor.solodrai, eddyz87, jolsa, andrii, ast, david.faust, dwarves,
	bpf



On 1/23/26 9:26 AM, Alan Maguire wrote:
> Ensure non-default "true_signature" feature is documented in
> the manual page.
>
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>

Acked-by: Yonghong Song <yonghong.song@linux.dev>


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

* Re: [PATCH v2 dwarves 5/5] btf_encoder: Prefer strong function definitions for BTF generation
  2026-01-23 17:26 ` [PATCH v2 dwarves 5/5] btf_encoder: Prefer strong function definitions for BTF generation Alan Maguire
@ 2026-01-23 19:09   ` Yonghong Song
  0 siblings, 0 replies; 20+ messages in thread
From: Yonghong Song @ 2026-01-23 19:09 UTC (permalink / raw)
  To: Alan Maguire, mattbobrowski
  Cc: ihor.solodrai, eddyz87, jolsa, andrii, ast, david.faust, dwarves,
	bpf



On 1/23/26 9:26 AM, Alan Maguire wrote:
> From: Matt Bobrowski <mattbobrowski@google.com>
>
> Currently, when a function has both a weak and a strong definition
> across different compilation units (CUs), the BTF encoder arbitrarily
> selects one to generate the BTF entry. This selection fundamentally is
> dependent on the order in which pahole processes the CUs.
>
> This indifference often leads to a mismatch where the generated BTF
> reflects the weak definition's prototype, even though the linker
> selected the strong definition for the final vmlinux binary.
>
> A notable example described in [0] involving function
> bpf_lsm_mmap_file(). Both weak and strong definitions exist,
> distinguished only by parameter names (e.g., file vs
> file__nullable). While the strong definition is linked into the
> vmlinux object, the generated BTF contained the prototype for the weak
> definition. This causes issues for BPF verifier (e.g., __nullable
> annotation semantics), or tools relying on accurate type information.
>
> To fix this, ensure the BTF encoder selects the function definition
> corresponding to the actual code linked into the binary. This is
> achieved by comparing the DWARF function address (DW_AT_low_pc) with
> the ELF symbol address (st_value). Only the DWARF entry for the strong
> definition will match the final resolved ELF symbol address.
>
> [0] https://lore.kernel.org/all/aVJY9H-e83T7ivT4@google.com/
>
> Link: https://lore.kernel.org/all/aVJY9H-e83T7ivT4@google.com/
> Signed-off-by: Matt Bobrowski <mattbobrowski@google.com>

I have checked and verified that the logic is sound.

Acked-by: Yonghong Song <yonghong.song@linux.dev>


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

* Re: [PATCH v2 dwarves 1/5] dwarf_loader/btf_encoder: Detect reordered parameters
  2026-01-23 17:26 ` [PATCH v2 dwarves 1/5] dwarf_loader/btf_encoder: Detect reordered parameters Alan Maguire
@ 2026-01-26  9:30   ` Matt Bobrowski
  0 siblings, 0 replies; 20+ messages in thread
From: Matt Bobrowski @ 2026-01-26  9:30 UTC (permalink / raw)
  To: Alan Maguire
  Cc: yonghong.song, ihor.solodrai, eddyz87, jolsa, andrii, ast,
	david.faust, dwarves, bpf

On Fri, Jan 23, 2026 at 05:26:46PM +0000, Alan Maguire wrote:
> When encoding concrete instances of optimized functions it is possible
> parameters get reordered, often due to a parameter being optimized out;
> in such cases the order of abstract origin references to the abstract
> function is different, and the parameters that are optimized out
> usually appear after all the non-optimized parameters with no
> DW_AT_location information [1].
> 
> As an example consider
> 
> static void __blkcg_rstat_flush(struct blkcg *blkcg, int cpu);
> 
> It has - as expected - an abstract representation as follows:
> 
>  <1><6392a2d>: Abbrev Number: 47 (DW_TAG_subprogram)
>     <6392a2e>   DW_AT_name        : (indirect string, offset: 0x261e25): __blkcg_rstat_flush
>     <6392a32>   DW_AT_decl_file   : 1
>     <6392a33>   DW_AT_decl_line   : 1043
>     <6392a35>   DW_AT_decl_column : 13
>     <6392a36>   DW_AT_prototyped  : 1
>     <6392a36>   DW_AT_inline      : 1   (inlined)
>     <6392a37>   DW_AT_sibling     : <0x6392bac>
>  <2><6392a3b>: Abbrev Number: 38 (DW_TAG_formal_parameter)
>     <6392a3c>   DW_AT_name        : (indirect string, offset: 0xa7a9f): blkcg
>     <6392a40>   DW_AT_decl_file   : 1
>     <6392a41>   DW_AT_decl_line   : 1043
>     <6392a43>   DW_AT_decl_column : 47
>     <6392a44>   DW_AT_type        : <0x638b611>
>  <2><6392a48>: Abbrev Number: 20 (DW_TAG_formal_parameter)
>     <6392a49>   DW_AT_name        : cpu
>     <6392a4d>   DW_AT_decl_file   : 1
>     <6392a4e>   DW_AT_decl_line   : 1043
>     <6392a50>   DW_AT_decl_column : 58
>     <6392a51>   DW_AT_type        : <0x6377f8f>
> 
> However the concrete representation after optimization becomes:
> 
> ffffffff8186d180 t __blkcg_rstat_flush.isra.0
> 
> and has a concrete representation with parameter order switched:
> 
> <1><6399661>: Abbrev Number: 110 (DW_TAG_subprogram)
>     <6399662>   DW_AT_abstract_origin: <0x6392a2d>
>     <6399666>   DW_AT_low_pc      : 0xffffffff8186d180
>     <639966e>   DW_AT_high_pc     : 0x169
>     <6399676>   DW_AT_frame_base  : 1 byte block: 9c    (DW_OP_call_frame_cfa)
>     <6399678>   DW_AT_GNU_all_call_sites: 1
>     <6399678>   DW_AT_sibling     : <0x6399a8a>
>  <2><639967c>: Abbrev Number: 4 (DW_TAG_formal_parameter)
>     <639967d>   DW_AT_abstract_origin: <0x6392a48>
>     <6399681>   DW_AT_location    : 0x1fe21fb (location list)
>     <6399685>   DW_AT_GNU_locviews: 0x1fe21f5
>  <2><63996e4>: Abbrev Number: 4 (DW_TAG_formal_parameter)
>     <63996e5>   DW_AT_abstract_origin: <0x6392a3b>
>     <63996e9>   DW_AT_location    : 0x1fe2387 (location list)
>     <63996ed>   DW_AT_GNU_locviews: 0x1fe2385
> 
> In other words we end up with
> 
> static void __blkcg_rstat_flush.isra(int cpu, struct blkcg *blkcg);
> 
> We are not detecting cases like this in pahole, so we need to
> catch it to exclude such cases since they could lead to incorrect
> fentry attachment.
> 
> Future work around true function signatures will allow such functions
> with their "." suffixes, but even for such cases it is good to
> detect the reordering.
> 
> In practice we just end up excluding a few more .isra/.constprop
> functions which we cannot fentry-attach by name anyway; see [2] for an
> example list from CI.
> 
> [1] https://lore.kernel.org/bpf/101b74c9-949a-4bf4-a766-a5343b70bdd2@oracle.com/
> [2] https://github.com/alan-maguire/dwarves/actions/runs/20031993822
> 
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> Acked-by: Yonghong Song <yonghong.song@linux.dev>

Looks good.

Acked-by: Matt Bobrowski <mattbobrowski@google.com>

> ---
>  btf_encoder.c  | 29 ++++++++++++++++++++---------
>  dwarf_loader.c |  5 +++--
>  dwarves.h      |  2 ++
>  3 files changed, 25 insertions(+), 11 deletions(-)
> 
> diff --git a/btf_encoder.c b/btf_encoder.c
> index ec6933e..9a567e4 100644
> --- a/btf_encoder.c
> +++ b/btf_encoder.c
> @@ -87,6 +87,7 @@ struct btf_encoder_func_state {
>  	uint8_t unexpected_reg:1;
>  	uint8_t inconsistent_proto:1;
>  	uint8_t uncertain_parm_loc:1;
> +	uint8_t reordered_parm:1;
>  	uint8_t ambiguous_addr:1;
>  	int ret_type_id;
>  	struct btf_encoder_func_parm *parms;
> @@ -1273,6 +1274,7 @@ static int32_t btf_encoder__save_func(struct btf_encoder *encoder, struct functi
>  	state->unexpected_reg = ftype->unexpected_reg;
>  	state->optimized_parms = ftype->optimized_parms;
>  	state->uncertain_parm_loc = ftype->uncertain_parm_loc;
> +	state->reordered_parm = ftype->reordered_parm;
>  	ftype__for_each_parameter(ftype, param) {
>  		const char *name = parameter__name(param) ?: "";
>  
> @@ -1442,7 +1444,7 @@ static int saved_functions_combine(struct btf_encoder *encoder,
>  				   struct btf_encoder_func_state *a,
>  				   struct btf_encoder_func_state *b)
>  {
> -	uint8_t optimized, unexpected, inconsistent, uncertain_parm_loc;
> +	uint8_t optimized, unexpected, inconsistent, uncertain_parm_loc, reordered_parm;
>  
>  	if (a->elf != b->elf)
>  		return 1;
> @@ -1451,12 +1453,14 @@ static int saved_functions_combine(struct btf_encoder *encoder,
>  	unexpected = a->unexpected_reg | b->unexpected_reg;
>  	inconsistent = a->inconsistent_proto | b->inconsistent_proto;
>  	uncertain_parm_loc = a->uncertain_parm_loc | b->uncertain_parm_loc;
> -	if (!unexpected && !inconsistent && !funcs__match(encoder, a, b))
> +	reordered_parm = a->reordered_parm | b->reordered_parm;
> +	if (!unexpected && !inconsistent && !reordered_parm && !funcs__match(encoder, a, b))
>  		inconsistent = 1;
>  	a->optimized_parms = b->optimized_parms = optimized;
>  	a->unexpected_reg = b->unexpected_reg = unexpected;
>  	a->inconsistent_proto = b->inconsistent_proto = inconsistent;
>  	a->uncertain_parm_loc = b->uncertain_parm_loc = uncertain_parm_loc;
> +	a->reordered_parm = b->reordered_parm = reordered_parm;
>  
>  	return 0;
>  }
> @@ -1494,7 +1498,7 @@ static int btf_encoder__add_saved_funcs(struct btf_encoder *encoder, bool skip_e
>  
>  	for (i = 0; i < nr_saved_fns; i = j) {
>  		struct btf_encoder_func_state *state = &saved_fns[i];
> -		bool add_to_btf = !skip_encoding_inconsistent_proto;
> +		char *skip_reason = NULL;
>  
>  		/* Compare across sorted functions that match by name/prefix;
>  		 * share inconsistent/unexpected reg state between them.
> @@ -1510,14 +1514,21 @@ static int btf_encoder__add_saved_funcs(struct btf_encoder *encoder, bool skip_e
>  		 * unexpected register use, multiple inconsistent prototypes or
>  		 * uncertain parameters location
>  		 */
> -		add_to_btf |= !state->unexpected_reg && !state->inconsistent_proto && !state->uncertain_parm_loc && !state->elf->ambiguous_addr;
> -
> +		if (state->unexpected_reg)
> +			skip_reason = "unexpected register usage for parameter\n";
> +		if (skip_encoding_inconsistent_proto && state->inconsistent_proto)
> +			skip_reason = "inconsistet prototype\n";
>  		if (state->uncertain_parm_loc)
> -			btf_encoder__log_func_skip(encoder, saved_fns[i].elf,
> -					"uncertain parameter location\n",
> -					0, 0);
> +			skip_reason = "uncertain parameter location\n";
> +		if (state->reordered_parm)
> +			skip_reason = "reordered parameters\n";
> +		if (state->elf->ambiguous_addr)
> +			skip_reason = "ambiguous address\n";
>  
> -		if (add_to_btf) {
> +		if (skip_reason) {
> +			btf_encoder__log_func_skip(encoder, saved_fns[i].elf,
> +						   skip_reason, 0, 0);
> +		} else {
>  			if (is_kfunc_state(state))
>  				err = btf_encoder__add_bpf_kfunc(encoder, state);
>  			else

Oh, I like how you've split up the various skip reasonings.

> diff --git a/dwarf_loader.c b/dwarf_loader.c
> index 77aab8a..16fb7be 100644
> --- a/dwarf_loader.c
> +++ b/dwarf_loader.c
> @@ -1262,7 +1262,7 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu,
>  
>  		tag__init(&parm->tag, cu, die);
>  		parm->name = attr_string(die, DW_AT_name, conf);
> -
> +		parm->idx = param_idx;
>  		if (param_idx >= cu->nr_register_params || param_idx < 0)
>  			return parm;
>  		/* Parameters which use DW_AT_abstract_origin to point at
> @@ -2636,6 +2636,8 @@ static void ftype__recode_dwarf_types(struct tag *tag, struct cu *cu)
>  			}
>  			opos = tag__parameter(dtag__tag(dtype));
>  			pos->name = opos->name;
> +			if (pos->idx != opos->idx)
> +				type->reordered_parm = 1;
>  			pos->tag.type = dtag__tag(dtype)->type;
>  			/* share location information between parameter and
>  			 * abstract origin; if neither have location, we will
> @@ -2838,7 +2840,6 @@ static int tag__recode_dwarf_type(struct tag *tag, struct cu *cu)
>  		lexblock__recode_dwarf_types(&fn->lexblock, cu);
>  	}
>  		/* Fall thru */
> -
>  	case DW_TAG_subroutine_type:
>  		ftype__recode_dwarf_types(tag, cu);
>  		/* Fall thru, for the function return type */
> diff --git a/dwarves.h b/dwarves.h
> index 21d4166..78bedf5 100644
> --- a/dwarves.h
> +++ b/dwarves.h
> @@ -944,6 +944,7 @@ struct parameter {
>  	uint8_t optimized:1;
>  	uint8_t unexpected_reg:1;
>  	uint8_t has_loc:1;
> +	uint8_t idx;
>  };
>  
>  static inline struct parameter *tag__parameter(const struct tag *tag)
> @@ -1023,6 +1024,7 @@ struct ftype {
>  	uint8_t		 processed:1;
>  	uint8_t		 inconsistent_proto:1;
>  	uint8_t		 uncertain_parm_loc:1;
> +	uint8_t		 reordered_parm:1;
>  	struct list_head template_type_params;
>  	struct list_head template_value_params;
>  	struct template_parameter_pack *template_parameter_pack;
> -- 
> 2.43.5
> 

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

* Re: [PATCH v2 dwarves 2/5] btf_encoder: Add true_signature feature support for "."-suffixed functions
  2026-01-23 17:26 ` [PATCH v2 dwarves 2/5] btf_encoder: Add true_signature feature support for "."-suffixed functions Alan Maguire
  2026-01-23 19:05   ` Yonghong Song
@ 2026-01-26  9:52   ` Matt Bobrowski
  2026-01-26 10:49     ` Alan Maguire
  1 sibling, 1 reply; 20+ messages in thread
From: Matt Bobrowski @ 2026-01-26  9:52 UTC (permalink / raw)
  To: Alan Maguire
  Cc: yonghong.song, ihor.solodrai, eddyz87, jolsa, andrii, ast,
	david.faust, dwarves, bpf

On Fri, Jan 23, 2026 at 05:26:47PM +0000, Alan Maguire wrote:
> Currently we collate function information by name and add functions
> provided there are no inconsistencies across various representations.
> 
> For true_signature support - where we wish to add the real signature
> of a function even if it differs from source level - we need to do
> a few things:
> 
> 1. For "."-suffixed functions, we need to match from DWARF->ELF;
>    we can do this via the address associated with the function.
>    In doing this, we can then be confident that the debug info
>    for foo.isra.0 is the right info for the function at that
>    address.
> 
> 2. When adding saved functions we need to look for such cases
>    and provided they do not violate other constraints around BTF
>    representation - unexpected reg usage for function, uncertain
>    parameter location or ambiguous address - we add them with
>    their "."-suffixed name.  The latter can be used as a signal
>    that the function is transformed from the original.
> 
> Doing this adds 500 functions to BTF.  These are traceable with
> their "."-suffix names and because we have excluded ambiguous
> address cases we know exactly which function address they refer
> to.
> 
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>

Some minor nits, but apart from that it looks OK to me.

Acked-by: Matt Bobrowski <mattbobrowski@google.com>

> ---
>  btf_encoder.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++-----
>  dwarves.h     |  1 +
>  pahole.c      |  1 +
>  3 files changed, 71 insertions(+), 7 deletions(-)
> 
> diff --git a/btf_encoder.c b/btf_encoder.c
> index 9a567e4..c1002c3 100644
> --- a/btf_encoder.c
> +++ b/btf_encoder.c
> @@ -77,9 +77,16 @@ struct btf_encoder_func_annot {
>  	int16_t component_idx;
>  };
>  
> +struct elf_function_sym {
> +	const char *name;
> +	uint64_t addr;
> +};
> +
>  /* state used to do later encoding of saved functions */
>  struct btf_encoder_func_state {
>  	struct elf_function *elf;
> +	struct elf_function_sym *sym;
> +	uint64_t addr;
  		 ^
		 This appears to have leaked into wrong commit?
		 This member should've been introduced within patch
		 5/5.
		 
>  	uint32_t type_id_off;
>  	uint16_t nr_parms;
>  	uint16_t nr_annots;
> @@ -94,11 +101,6 @@ struct btf_encoder_func_state {
>  	struct btf_encoder_func_annot *annots;
>  };
>  
> -struct elf_function_sym {
> -	const char *name;
> -	uint64_t addr;
> -};
> -
>  struct elf_function {
>  	char		*name;
>  	struct elf_function_sym *syms;
> @@ -145,7 +147,8 @@ struct btf_encoder {
>  			  skip_encoding_decl_tag,
>  			  tag_kfuncs,
>  			  gen_distilled_base,
> -			  encode_attributes;
> +			  encode_attributes,
> +			  true_signature;
>  	uint32_t	  array_index_id;
>  	struct elf_secinfo *secinfo;
>  	size_t             seccnt;
> @@ -1270,14 +1273,36 @@ static int32_t btf_encoder__save_func(struct btf_encoder *encoder, struct functi
>  			goto out;
>  		}
>  	}
> +	if (encoder->true_signature && fn->lexblock.ip.addr) {
> +		int i;
> +
> +		for (i = 0; i < func->sym_cnt; i++) {
> +			if (fn->lexblock.ip.addr != func->syms[i].addr)
> +				continue;
> +			/* Only need to record address for '.'-suffixed
> +			 * functions, since we only currently need true
> +			 * signatures for them.
> +			 */
> +			if (!strchr(func->syms[i].name, '.'))
> +				continue;
> +			state->sym = &func->syms[i];
> +			break;
> +		}
> +	}
>  	state->inconsistent_proto = ftype->inconsistent_proto;
>  	state->unexpected_reg = ftype->unexpected_reg;
>  	state->optimized_parms = ftype->optimized_parms;
>  	state->uncertain_parm_loc = ftype->uncertain_parm_loc;
>  	state->reordered_parm = ftype->reordered_parm;
>  	ftype__for_each_parameter(ftype, param) {
> -		const char *name = parameter__name(param) ?: "";
> +		const char *name;
>  
> +		/* No location info/optimized + reordered means optimized out. */
> +		if (ftype->reordered_parm && (!param->has_loc || param->optimized)) {
> +			state->nr_parms--;
> +			continue;
> +		}
> +		name = parameter__name(param) ?: "";
>  		str_off = btf__add_str(btf, name);
>  		if (str_off < 0) {
>  			err = str_off;
> @@ -1366,6 +1391,9 @@ static int32_t btf_encoder__add_func(struct btf_encoder *encoder,
>  
>  	btf_fnproto_id = btf_encoder__add_func_proto_for_state(encoder, state);
>  	name = func->name;
> +	if (encoder->true_signature && state->sym)
> +		name = state->sym->name;
> +
>  	if (btf_fnproto_id >= 0)
>  		btf_fn_id = btf_encoder__add_ref_type(encoder, BTF_KIND_FUNC, btf_fnproto_id,
>  						      name, false);
> @@ -1508,6 +1536,39 @@ static int btf_encoder__add_saved_funcs(struct btf_encoder *encoder, bool skip_e
>  		while (j < nr_saved_fns && saved_functions_combine(encoder, &saved_fns[i], &saved_fns[j]) == 0)
>  			j++;
>  
> +		/* Add true signatures for case where we have an exact
> +		 * symbol match by address from DWARF->ELF and have a
> +		 * "." suffixed name.
> +		 */
> +		if (encoder->true_signature) {
> +			bool true_added = false;
> +			int k;
> +
> +			for (k = i; k < nr_saved_fns; k++) {
> +				struct btf_encoder_func_state *true_state = &saved_fns[k];
> +
> +				if (state->elf != true_state->elf)
> +					break;
> +				if (!true_state->sym)
> +					continue;
> +				/* Unexpected reg, uncertain parm loc and
> +				 * ambiguous address mean we cannot trust fentry.
> +				 */
> +				if (true_state->unexpected_reg ||
> +				    true_state->uncertain_parm_loc ||
> +				    true_state->ambiguous_addr)
> +					continue;
> +				err = btf_encoder__add_func(encoder, true_state);
> +				if (err < 0)
> +					goto out;
> +				true_added = true;
> +				break;
> +			}
> +			/* If true symbol was added, skip the below. */
> +			if (true_added)
> +				continue;
> +		}
> +

I think this hunk should be factored out into a
helper. btf_encoder__add_saved_funcs() is starting to get hairy IMO.

>  		/* do not exclude functions with optimized-out parameters; they
>  		 * may still be _called_ with the right parameter values, they
>  		 * just do not _use_ them.  Only exclude functions with
> @@ -2584,6 +2645,7 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam
>  		encoder->tag_kfuncs	 = conf_load->btf_decl_tag_kfuncs;
>  		encoder->gen_distilled_base = conf_load->btf_gen_distilled_base;
>  		encoder->encode_attributes = conf_load->btf_attributes;
> +		encoder->true_signature = conf_load->true_signature;
>  		encoder->verbose	 = verbose;
>  		encoder->has_index_type  = false;
>  		encoder->need_index_type = false;
> diff --git a/dwarves.h b/dwarves.h
> index 78bedf5..d7c6474 100644
> --- a/dwarves.h
> +++ b/dwarves.h
> @@ -101,6 +101,7 @@ struct conf_load {
>  	bool			btf_decl_tag_kfuncs;
>  	bool			btf_gen_distilled_base;
>  	bool			btf_attributes;
> +	bool			true_signature;
>  	uint8_t			hashtable_bits;
>  	uint8_t			max_hashtable_bits;
>  	uint16_t		kabi_prefix_len;
> diff --git a/pahole.c b/pahole.c
> index ef01e58..02a0d19 100644
> --- a/pahole.c
> +++ b/pahole.c
> @@ -1234,6 +1234,7 @@ struct btf_feature {
>  	BTF_NON_DEFAULT_FEATURE(global_var, encode_btf_global_vars, false),
>  	BTF_NON_DEFAULT_FEATURE_CHECK(attributes, btf_attributes, false,
>  				      attributes_check),
> +	BTF_NON_DEFAULT_FEATURE(true_signature, true_signature, false),
>  };
>  
>  #define BTF_MAX_FEATURE_STR	1024
> -- 
> 2.43.5
> 

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

* Re: [PATCH v2 dwarves 4/5] man-pages: document true_signature btf_feature
  2026-01-23 17:26 ` [PATCH v2 dwarves 4/5] man-pages: document true_signature btf_feature Alan Maguire
  2026-01-23 19:07   ` Yonghong Song
@ 2026-01-26 10:02   ` Matt Bobrowski
  2026-01-26 10:51     ` Alan Maguire
  1 sibling, 1 reply; 20+ messages in thread
From: Matt Bobrowski @ 2026-01-26 10:02 UTC (permalink / raw)
  To: Alan Maguire
  Cc: yonghong.song, ihor.solodrai, eddyz87, jolsa, andrii, ast,
	david.faust, dwarves, bpf

On Fri, Jan 23, 2026 at 05:26:49PM +0000, Alan Maguire wrote:
> Ensure non-default "true_signature" feature is documented in
> the manual page.
> 
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>

Acked-by: Matt Bobrowski <mattbobrowski@google.com>

> ---
>  man-pages/pahole.1 | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/man-pages/pahole.1 b/man-pages/pahole.1
> index 3125de3..90a8f45 100644
> --- a/man-pages/pahole.1
> +++ b/man-pages/pahole.1
> @@ -337,6 +337,11 @@ Supported non-standard features (not enabled for 'default')
>  	                   of split BTF with a possibly changed base, storing
>  	                   it in a .BTF.base ELF section.
>  	global_var         Encode all global variables using BTF_KIND_VAR in BTF.
> +	true_signature     Encode functions ensuring that binary-level
> +	                   (rather than source-level) signatures are used;
									 ^
									 within the generated BTF.
									 
> +                           for gcc these are ".isra.0" and ".costprop.0"
> +                           optimized functions

For BTF generation, would there ever be a situation whereby we
wouldn't want true signature support? I'm just trying to understand
why this isn't defaulted to true.

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

* Re: [PATCH v2 dwarves 2/5] btf_encoder: Add true_signature feature support for "."-suffixed functions
  2026-01-26  9:52   ` Matt Bobrowski
@ 2026-01-26 10:49     ` Alan Maguire
  2026-01-26 11:18       ` Matt Bobrowski
  0 siblings, 1 reply; 20+ messages in thread
From: Alan Maguire @ 2026-01-26 10:49 UTC (permalink / raw)
  To: Matt Bobrowski
  Cc: yonghong.song, ihor.solodrai, eddyz87, jolsa, andrii, ast,
	david.faust, dwarves, bpf

On 26/01/2026 09:52, Matt Bobrowski wrote:
> On Fri, Jan 23, 2026 at 05:26:47PM +0000, Alan Maguire wrote:
>> Currently we collate function information by name and add functions
>> provided there are no inconsistencies across various representations.
>>
>> For true_signature support - where we wish to add the real signature
>> of a function even if it differs from source level - we need to do
>> a few things:
>>
>> 1. For "."-suffixed functions, we need to match from DWARF->ELF;
>>    we can do this via the address associated with the function.
>>    In doing this, we can then be confident that the debug info
>>    for foo.isra.0 is the right info for the function at that
>>    address.
>>
>> 2. When adding saved functions we need to look for such cases
>>    and provided they do not violate other constraints around BTF
>>    representation - unexpected reg usage for function, uncertain
>>    parameter location or ambiguous address - we add them with
>>    their "."-suffixed name.  The latter can be used as a signal
>>    that the function is transformed from the original.
>>
>> Doing this adds 500 functions to BTF.  These are traceable with
>> their "."-suffix names and because we have excluded ambiguous
>> address cases we know exactly which function address they refer
>> to.
>>
>> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> 
> Some minor nits, but apart from that it looks OK to me.
> 
> Acked-by: Matt Bobrowski <mattbobrowski@google.com>
> 
>> ---
>>  btf_encoder.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++-----
>>  dwarves.h     |  1 +
>>  pahole.c      |  1 +
>>  3 files changed, 71 insertions(+), 7 deletions(-)
>>
>> diff --git a/btf_encoder.c b/btf_encoder.c
>> index 9a567e4..c1002c3 100644
>> --- a/btf_encoder.c
>> +++ b/btf_encoder.c
>> @@ -77,9 +77,16 @@ struct btf_encoder_func_annot {
>>  	int16_t component_idx;
>>  };
>>  
>> +struct elf_function_sym {
>> +	const char *name;
>> +	uint64_t addr;
>> +};
>> +
>>  /* state used to do later encoding of saved functions */
>>  struct btf_encoder_func_state {
>>  	struct elf_function *elf;
>> +	struct elf_function_sym *sym;
>> +	uint64_t addr;
>   		 ^
> 		 This appears to have leaked into wrong commit?
> 		 This member should've been introduced within patch
> 		 5/5.
>

It's used here too though; specifically in btf_encoder__save_func()
below. We need to use addresses to map between a DWARF representation
and the associated ELF function to ensure we're using debug info
for the correct "."-suffixed function. We need to do this because
the late DWARF generated after optimizations are applied uses
the original name ("foo" rather than "foo.isra.0"). 
 		 
>>  	uint32_t type_id_off;
>>  	uint16_t nr_parms;
>>  	uint16_t nr_annots;
>> @@ -94,11 +101,6 @@ struct btf_encoder_func_state {
>>  	struct btf_encoder_func_annot *annots;
>>  };
>>  
>> -struct elf_function_sym {
>> -	const char *name;
>> -	uint64_t addr;
>> -};
>> -
>>  struct elf_function {
>>  	char		*name;
>>  	struct elf_function_sym *syms;
>> @@ -145,7 +147,8 @@ struct btf_encoder {
>>  			  skip_encoding_decl_tag,
>>  			  tag_kfuncs,
>>  			  gen_distilled_base,
>> -			  encode_attributes;
>> +			  encode_attributes,
>> +			  true_signature;
>>  	uint32_t	  array_index_id;
>>  	struct elf_secinfo *secinfo;
>>  	size_t             seccnt;
>> @@ -1270,14 +1273,36 @@ static int32_t btf_encoder__save_func(struct btf_encoder *encoder, struct functi
>>  			goto out;
>>  		}
>>  	}
>> +	if (encoder->true_signature && fn->lexblock.ip.addr) {
>> +		int i;
>> +
>> +		for (i = 0; i < func->sym_cnt; i++) {
>> +			if (fn->lexblock.ip.addr != func->syms[i].addr)
>> +				continue;
>> +			/* Only need to record address for '.'-suffixed
>> +			 * functions, since we only currently need true
>> +			 * signatures for them.
>> +			 */
>> +			if (!strchr(func->syms[i].name, '.'))
>> +				continue;
>> +			state->sym = &func->syms[i];
>> +			break;
>> +		}
>> +	}
>>  	state->inconsistent_proto = ftype->inconsistent_proto;
>>  	state->unexpected_reg = ftype->unexpected_reg;
>>  	state->optimized_parms = ftype->optimized_parms;
>>  	state->uncertain_parm_loc = ftype->uncertain_parm_loc;
>>  	state->reordered_parm = ftype->reordered_parm;
>>  	ftype__for_each_parameter(ftype, param) {
>> -		const char *name = parameter__name(param) ?: "";
>> +		const char *name;
>>  
>> +		/* No location info/optimized + reordered means optimized out. */
>> +		if (ftype->reordered_parm && (!param->has_loc || param->optimized)) {
>> +			state->nr_parms--;
>> +			continue;
>> +		}
>> +		name = parameter__name(param) ?: "";
>>  		str_off = btf__add_str(btf, name);
>>  		if (str_off < 0) {
>>  			err = str_off;
>> @@ -1366,6 +1391,9 @@ static int32_t btf_encoder__add_func(struct btf_encoder *encoder,
>>  
>>  	btf_fnproto_id = btf_encoder__add_func_proto_for_state(encoder, state);
>>  	name = func->name;
>> +	if (encoder->true_signature && state->sym)
>> +		name = state->sym->name;
>> +
>>  	if (btf_fnproto_id >= 0)
>>  		btf_fn_id = btf_encoder__add_ref_type(encoder, BTF_KIND_FUNC, btf_fnproto_id,
>>  						      name, false);
>> @@ -1508,6 +1536,39 @@ static int btf_encoder__add_saved_funcs(struct btf_encoder *encoder, bool skip_e
>>  		while (j < nr_saved_fns && saved_functions_combine(encoder, &saved_fns[i], &saved_fns[j]) == 0)
>>  			j++;
>>  
>> +		/* Add true signatures for case where we have an exact
>> +		 * symbol match by address from DWARF->ELF and have a
>> +		 * "." suffixed name.
>> +		 */
>> +		if (encoder->true_signature) {
>> +			bool true_added = false;
>> +			int k;
>> +
>> +			for (k = i; k < nr_saved_fns; k++) {
>> +				struct btf_encoder_func_state *true_state = &saved_fns[k];
>> +
>> +				if (state->elf != true_state->elf)
>> +					break;
>> +				if (!true_state->sym)
>> +					continue;
>> +				/* Unexpected reg, uncertain parm loc and
>> +				 * ambiguous address mean we cannot trust fentry.
>> +				 */
>> +				if (true_state->unexpected_reg ||
>> +				    true_state->uncertain_parm_loc ||
>> +				    true_state->ambiguous_addr)
>> +					continue;
>> +				err = btf_encoder__add_func(encoder, true_state);
>> +				if (err < 0)
>> +					goto out;
>> +				true_added = true;
>> +				break;
>> +			}
>> +			/* If true symbol was added, skip the below. */
>> +			if (true_added)
>> +				continue;
>> +		}
>> +
> 
> I think this hunk should be factored out into a
> helper. btf_encoder__add_saved_funcs() is starting to get hairy IMO.
> 

Yeah, I think that's reasonable. The combination of loops within loops,
breaks and continues is getting hard to follow. I'll respin with a
btf_encoder__add_true_signature() function replicating this logic.


>>  		/* do not exclude functions with optimized-out parameters; they
>>  		 * may still be _called_ with the right parameter values, they
>>  		 * just do not _use_ them.  Only exclude functions with
>> @@ -2584,6 +2645,7 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam
>>  		encoder->tag_kfuncs	 = conf_load->btf_decl_tag_kfuncs;
>>  		encoder->gen_distilled_base = conf_load->btf_gen_distilled_base;
>>  		encoder->encode_attributes = conf_load->btf_attributes;
>> +		encoder->true_signature = conf_load->true_signature;
>>  		encoder->verbose	 = verbose;
>>  		encoder->has_index_type  = false;
>>  		encoder->need_index_type = false;
>> diff --git a/dwarves.h b/dwarves.h
>> index 78bedf5..d7c6474 100644
>> --- a/dwarves.h
>> +++ b/dwarves.h
>> @@ -101,6 +101,7 @@ struct conf_load {
>>  	bool			btf_decl_tag_kfuncs;
>>  	bool			btf_gen_distilled_base;
>>  	bool			btf_attributes;
>> +	bool			true_signature;
>>  	uint8_t			hashtable_bits;
>>  	uint8_t			max_hashtable_bits;
>>  	uint16_t		kabi_prefix_len;
>> diff --git a/pahole.c b/pahole.c
>> index ef01e58..02a0d19 100644
>> --- a/pahole.c
>> +++ b/pahole.c
>> @@ -1234,6 +1234,7 @@ struct btf_feature {
>>  	BTF_NON_DEFAULT_FEATURE(global_var, encode_btf_global_vars, false),
>>  	BTF_NON_DEFAULT_FEATURE_CHECK(attributes, btf_attributes, false,
>>  				      attributes_check),
>> +	BTF_NON_DEFAULT_FEATURE(true_signature, true_signature, false),
>>  };
>>  
>>  #define BTF_MAX_FEATURE_STR	1024
>> -- 
>> 2.43.5
>>


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

* Re: [PATCH v2 dwarves 4/5] man-pages: document true_signature btf_feature
  2026-01-26 10:02   ` Matt Bobrowski
@ 2026-01-26 10:51     ` Alan Maguire
  2026-01-26 11:21       ` Matt Bobrowski
  0 siblings, 1 reply; 20+ messages in thread
From: Alan Maguire @ 2026-01-26 10:51 UTC (permalink / raw)
  To: Matt Bobrowski
  Cc: yonghong.song, ihor.solodrai, eddyz87, jolsa, andrii, ast,
	david.faust, dwarves, bpf

On 26/01/2026 10:02, Matt Bobrowski wrote:
> On Fri, Jan 23, 2026 at 05:26:49PM +0000, Alan Maguire wrote:
>> Ensure non-default "true_signature" feature is documented in
>> the manual page.
>>
>> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> 
> Acked-by: Matt Bobrowski <mattbobrowski@google.com>
> 
>> ---
>>  man-pages/pahole.1 | 5 +++++
>>  1 file changed, 5 insertions(+)
>>
>> diff --git a/man-pages/pahole.1 b/man-pages/pahole.1
>> index 3125de3..90a8f45 100644
>> --- a/man-pages/pahole.1
>> +++ b/man-pages/pahole.1
>> @@ -337,6 +337,11 @@ Supported non-standard features (not enabled for 'default')
>>  	                   of split BTF with a possibly changed base, storing
>>  	                   it in a .BTF.base ELF section.
>>  	global_var         Encode all global variables using BTF_KIND_VAR in BTF.
>> +	true_signature     Encode functions ensuring that binary-level
>> +	                   (rather than source-level) signatures are used;
> 									 ^
> 									 within the generated BTF.
> 									 
>> +                           for gcc these are ".isra.0" and ".costprop.0"
>> +                           optimized functions
> 
> For BTF generation, would there ever be a situation whereby we
> wouldn't want true signature support? I'm just trying to understand
> why this isn't defaulted to true.

The key reason is the "." in the name for gcc-optimized functions
"function.isra.0" ; older kernels will reject BTF function names with 
a "." in them, so we have to guard against new pahole with the feature
enabled by default being run on older kernels. So by having the newer
kernels request the feature only we avoid this.

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

* Re: [PATCH v2 dwarves 2/5] btf_encoder: Add true_signature feature support for "."-suffixed functions
  2026-01-26 10:49     ` Alan Maguire
@ 2026-01-26 11:18       ` Matt Bobrowski
  2026-01-27 12:18         ` Alan Maguire
  0 siblings, 1 reply; 20+ messages in thread
From: Matt Bobrowski @ 2026-01-26 11:18 UTC (permalink / raw)
  To: Alan Maguire
  Cc: yonghong.song, ihor.solodrai, eddyz87, jolsa, andrii, ast,
	david.faust, dwarves, bpf

On Mon, Jan 26, 2026 at 10:49:00AM +0000, Alan Maguire wrote:
> On 26/01/2026 09:52, Matt Bobrowski wrote:
> > On Fri, Jan 23, 2026 at 05:26:47PM +0000, Alan Maguire wrote:
> >> Currently we collate function information by name and add functions
> >> provided there are no inconsistencies across various representations.
> >>
> >> For true_signature support - where we wish to add the real signature
> >> of a function even if it differs from source level - we need to do
> >> a few things:
> >>
> >> 1. For "."-suffixed functions, we need to match from DWARF->ELF;
> >>    we can do this via the address associated with the function.
> >>    In doing this, we can then be confident that the debug info
> >>    for foo.isra.0 is the right info for the function at that
> >>    address.
> >>
> >> 2. When adding saved functions we need to look for such cases
> >>    and provided they do not violate other constraints around BTF
> >>    representation - unexpected reg usage for function, uncertain
> >>    parameter location or ambiguous address - we add them with
> >>    their "."-suffixed name.  The latter can be used as a signal
> >>    that the function is transformed from the original.
> >>
> >> Doing this adds 500 functions to BTF.  These are traceable with
> >> their "."-suffix names and because we have excluded ambiguous
> >> address cases we know exactly which function address they refer
> >> to.
> >>
> >> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> > 
> > Some minor nits, but apart from that it looks OK to me.
> > 
> > Acked-by: Matt Bobrowski <mattbobrowski@google.com>
> > 
> >> ---
> >>  btf_encoder.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++-----
> >>  dwarves.h     |  1 +
> >>  pahole.c      |  1 +
> >>  3 files changed, 71 insertions(+), 7 deletions(-)
> >>
> >> diff --git a/btf_encoder.c b/btf_encoder.c
> >> index 9a567e4..c1002c3 100644
> >> --- a/btf_encoder.c
> >> +++ b/btf_encoder.c
> >> @@ -77,9 +77,16 @@ struct btf_encoder_func_annot {
> >>  	int16_t component_idx;
> >>  };
> >>  
> >> +struct elf_function_sym {
> >> +	const char *name;
> >> +	uint64_t addr;
> >> +};
> >> +
> >>  /* state used to do later encoding of saved functions */
> >>  struct btf_encoder_func_state {
> >>  	struct elf_function *elf;
> >> +	struct elf_function_sym *sym;
> >> +	uint64_t addr;
> >   		 ^
> > 		 This appears to have leaked into wrong commit?
> > 		 This member should've been introduced within patch
> > 		 5/5.
> >
> 
> It's used here too though; specifically in btf_encoder__save_func()
> below. We need to use addresses to map between a DWARF representation
> and the associated ELF function to ensure we're using debug info
> for the correct "."-suffixed function. We need to do this because
> the late DWARF generated after optimizations are applied uses
> the original name ("foo" rather than "foo.isra.0").

Sorry, I thought I only saw usage of member "addr" within
btf_encoder__save_func() against fn->lenblock.ip.addr which maps to
member "addr" within struct ip_tag and func->syms[i].addr which maps
to member "addr" within struct elf_function_sym. Member "addr" within
struct btf_encoder_func_state remains unused until patch 5/5 where we
assign it the value returned from function__addr().

With that said, within btf_encoder__save_func() why don't you do the
following instead:

state->addr = function__addr(fn);

...

if (encoder->true_signature && state->addr) {
	if (state->addr != func->syms[i].addr) {
		...
	}
}

There's no need to open code fn->lexblock.ip.addr everywhere as it
deminishes readability.

> >>  	uint32_t type_id_off;
> >>  	uint16_t nr_parms;
> >>  	uint16_t nr_annots;
> >> @@ -94,11 +101,6 @@ struct btf_encoder_func_state {
> >>  	struct btf_encoder_func_annot *annots;
> >>  };
> >>  
> >> -struct elf_function_sym {
> >> -	const char *name;
> >> -	uint64_t addr;
> >> -};
> >> -
> >>  struct elf_function {
> >>  	char		*name;
> >>  	struct elf_function_sym *syms;
> >> @@ -145,7 +147,8 @@ struct btf_encoder {
> >>  			  skip_encoding_decl_tag,
> >>  			  tag_kfuncs,
> >>  			  gen_distilled_base,
> >> -			  encode_attributes;
> >> +			  encode_attributes,
> >> +			  true_signature;
> >>  	uint32_t	  array_index_id;
> >>  	struct elf_secinfo *secinfo;
> >>  	size_t             seccnt;
> >> @@ -1270,14 +1273,36 @@ static int32_t btf_encoder__save_func(struct btf_encoder *encoder, struct functi
> >>  			goto out;
> >>  		}
> >>  	}
> >> +	if (encoder->true_signature && fn->lexblock.ip.addr) {
> >> +		int i;
> >> +
> >> +		for (i = 0; i < func->sym_cnt; i++) {
> >> +			if (fn->lexblock.ip.addr != func->syms[i].addr)
> >> +				continue;
> >> +			/* Only need to record address for '.'-suffixed
> >> +			 * functions, since we only currently need true
> >> +			 * signatures for them.
> >> +			 */
> >> +			if (!strchr(func->syms[i].name, '.'))
> >> +				continue;
> >> +			state->sym = &func->syms[i];
> >> +			break;
> >> +		}
> >> +	}
> >>  	state->inconsistent_proto = ftype->inconsistent_proto;
> >>  	state->unexpected_reg = ftype->unexpected_reg;
> >>  	state->optimized_parms = ftype->optimized_parms;
> >>  	state->uncertain_parm_loc = ftype->uncertain_parm_loc;
> >>  	state->reordered_parm = ftype->reordered_parm;
> >>  	ftype__for_each_parameter(ftype, param) {
> >> -		const char *name = parameter__name(param) ?: "";
> >> +		const char *name;
> >>  
> >> +		/* No location info/optimized + reordered means optimized out. */
> >> +		if (ftype->reordered_parm && (!param->has_loc || param->optimized)) {
> >> +			state->nr_parms--;
> >> +			continue;
> >> +		}
> >> +		name = parameter__name(param) ?: "";
> >>  		str_off = btf__add_str(btf, name);
> >>  		if (str_off < 0) {
> >>  			err = str_off;
> >> @@ -1366,6 +1391,9 @@ static int32_t btf_encoder__add_func(struct btf_encoder *encoder,
> >>  
> >>  	btf_fnproto_id = btf_encoder__add_func_proto_for_state(encoder, state);
> >>  	name = func->name;
> >> +	if (encoder->true_signature && state->sym)
> >> +		name = state->sym->name;
> >> +
> >>  	if (btf_fnproto_id >= 0)
> >>  		btf_fn_id = btf_encoder__add_ref_type(encoder, BTF_KIND_FUNC, btf_fnproto_id,
> >>  						      name, false);
> >> @@ -1508,6 +1536,39 @@ static int btf_encoder__add_saved_funcs(struct btf_encoder *encoder, bool skip_e
> >>  		while (j < nr_saved_fns && saved_functions_combine(encoder, &saved_fns[i], &saved_fns[j]) == 0)
> >>  			j++;
> >>  
> >> +		/* Add true signatures for case where we have an exact
> >> +		 * symbol match by address from DWARF->ELF and have a
> >> +		 * "." suffixed name.
> >> +		 */
> >> +		if (encoder->true_signature) {
> >> +			bool true_added = false;
> >> +			int k;
> >> +
> >> +			for (k = i; k < nr_saved_fns; k++) {
> >> +				struct btf_encoder_func_state *true_state = &saved_fns[k];
> >> +
> >> +				if (state->elf != true_state->elf)
> >> +					break;
> >> +				if (!true_state->sym)
> >> +					continue;
> >> +				/* Unexpected reg, uncertain parm loc and
> >> +				 * ambiguous address mean we cannot trust fentry.
> >> +				 */
> >> +				if (true_state->unexpected_reg ||
> >> +				    true_state->uncertain_parm_loc ||
> >> +				    true_state->ambiguous_addr)
> >> +					continue;
> >> +				err = btf_encoder__add_func(encoder, true_state);
> >> +				if (err < 0)
> >> +					goto out;
> >> +				true_added = true;
> >> +				break;
> >> +			}
> >> +			/* If true symbol was added, skip the below. */
> >> +			if (true_added)
> >> +				continue;
> >> +		}
> >> +
> > 
> > I think this hunk should be factored out into a
> > helper. btf_encoder__add_saved_funcs() is starting to get hairy IMO.
> > 
> 
> Yeah, I think that's reasonable. The combination of loops within loops,
> breaks and continues is getting hard to follow. I'll respin with a
> btf_encoder__add_true_signature() function replicating this logic.
> 
> 
> >>  		/* do not exclude functions with optimized-out parameters; they
> >>  		 * may still be _called_ with the right parameter values, they
> >>  		 * just do not _use_ them.  Only exclude functions with
> >> @@ -2584,6 +2645,7 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam
> >>  		encoder->tag_kfuncs	 = conf_load->btf_decl_tag_kfuncs;
> >>  		encoder->gen_distilled_base = conf_load->btf_gen_distilled_base;
> >>  		encoder->encode_attributes = conf_load->btf_attributes;
> >> +		encoder->true_signature = conf_load->true_signature;
> >>  		encoder->verbose	 = verbose;
> >>  		encoder->has_index_type  = false;
> >>  		encoder->need_index_type = false;
> >> diff --git a/dwarves.h b/dwarves.h
> >> index 78bedf5..d7c6474 100644
> >> --- a/dwarves.h
> >> +++ b/dwarves.h
> >> @@ -101,6 +101,7 @@ struct conf_load {
> >>  	bool			btf_decl_tag_kfuncs;
> >>  	bool			btf_gen_distilled_base;
> >>  	bool			btf_attributes;
> >> +	bool			true_signature;
> >>  	uint8_t			hashtable_bits;
> >>  	uint8_t			max_hashtable_bits;
> >>  	uint16_t		kabi_prefix_len;
> >> diff --git a/pahole.c b/pahole.c
> >> index ef01e58..02a0d19 100644
> >> --- a/pahole.c
> >> +++ b/pahole.c
> >> @@ -1234,6 +1234,7 @@ struct btf_feature {
> >>  	BTF_NON_DEFAULT_FEATURE(global_var, encode_btf_global_vars, false),
> >>  	BTF_NON_DEFAULT_FEATURE_CHECK(attributes, btf_attributes, false,
> >>  				      attributes_check),
> >> +	BTF_NON_DEFAULT_FEATURE(true_signature, true_signature, false),
> >>  };
> >>  
> >>  #define BTF_MAX_FEATURE_STR	1024
> >> -- 
> >> 2.43.5
> >>
> 

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

* Re: [PATCH v2 dwarves 4/5] man-pages: document true_signature btf_feature
  2026-01-26 10:51     ` Alan Maguire
@ 2026-01-26 11:21       ` Matt Bobrowski
  2026-01-26 17:10         ` Alan Maguire
  0 siblings, 1 reply; 20+ messages in thread
From: Matt Bobrowski @ 2026-01-26 11:21 UTC (permalink / raw)
  To: Alan Maguire
  Cc: yonghong.song, ihor.solodrai, eddyz87, jolsa, andrii, ast,
	david.faust, dwarves, bpf

On Mon, Jan 26, 2026 at 10:51:31AM +0000, Alan Maguire wrote:
> On 26/01/2026 10:02, Matt Bobrowski wrote:
> > On Fri, Jan 23, 2026 at 05:26:49PM +0000, Alan Maguire wrote:
> >> Ensure non-default "true_signature" feature is documented in
> >> the manual page.
> >>
> >> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> > 
> > Acked-by: Matt Bobrowski <mattbobrowski@google.com>
> > 
> >> ---
> >>  man-pages/pahole.1 | 5 +++++
> >>  1 file changed, 5 insertions(+)
> >>
> >> diff --git a/man-pages/pahole.1 b/man-pages/pahole.1
> >> index 3125de3..90a8f45 100644
> >> --- a/man-pages/pahole.1
> >> +++ b/man-pages/pahole.1
> >> @@ -337,6 +337,11 @@ Supported non-standard features (not enabled for 'default')
> >>  	                   of split BTF with a possibly changed base, storing
> >>  	                   it in a .BTF.base ELF section.
> >>  	global_var         Encode all global variables using BTF_KIND_VAR in BTF.
> >> +	true_signature     Encode functions ensuring that binary-level
> >> +	                   (rather than source-level) signatures are used;
> > 									 ^
> > 									 within the generated BTF.
> > 									 
> >> +                           for gcc these are ".isra.0" and ".costprop.0"
> >> +                           optimized functions
> > 
> > For BTF generation, would there ever be a situation whereby we
> > wouldn't want true signature support? I'm just trying to understand
> > why this isn't defaulted to true.
> 
> The key reason is the "." in the name for gcc-optimized functions
> "function.isra.0" ; older kernels will reject BTF function names with 
> a "." in them, so we have to guard against new pahole with the feature
> enabled by default being run on older kernels. So by having the newer
> kernels request the feature only we avoid this.

Oh, yes, that makes sense. Once a new pahole version is released with
true_signature support available, will you also be looking to update
scripts/Makefile.btf and conditionally enable it based on
availability?

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

* Re: [PATCH v2 dwarves 4/5] man-pages: document true_signature btf_feature
  2026-01-26 11:21       ` Matt Bobrowski
@ 2026-01-26 17:10         ` Alan Maguire
  2026-01-26 18:13           ` Yonghong Song
  0 siblings, 1 reply; 20+ messages in thread
From: Alan Maguire @ 2026-01-26 17:10 UTC (permalink / raw)
  To: Matt Bobrowski
  Cc: yonghong.song, ihor.solodrai, eddyz87, jolsa, andrii, ast,
	david.faust, dwarves, bpf

On 26/01/2026 11:21, Matt Bobrowski wrote:
> On Mon, Jan 26, 2026 at 10:51:31AM +0000, Alan Maguire wrote:
>> On 26/01/2026 10:02, Matt Bobrowski wrote:
>>> On Fri, Jan 23, 2026 at 05:26:49PM +0000, Alan Maguire wrote:
>>>> Ensure non-default "true_signature" feature is documented in
>>>> the manual page.
>>>>
>>>> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
>>>
>>> Acked-by: Matt Bobrowski <mattbobrowski@google.com>
>>>
>>>> ---
>>>>  man-pages/pahole.1 | 5 +++++
>>>>  1 file changed, 5 insertions(+)
>>>>
>>>> diff --git a/man-pages/pahole.1 b/man-pages/pahole.1
>>>> index 3125de3..90a8f45 100644
>>>> --- a/man-pages/pahole.1
>>>> +++ b/man-pages/pahole.1
>>>> @@ -337,6 +337,11 @@ Supported non-standard features (not enabled for 'default')
>>>>  	                   of split BTF with a possibly changed base, storing
>>>>  	                   it in a .BTF.base ELF section.
>>>>  	global_var         Encode all global variables using BTF_KIND_VAR in BTF.
>>>> +	true_signature     Encode functions ensuring that binary-level
>>>> +	                   (rather than source-level) signatures are used;
>>> 									 ^
>>> 									 within the generated BTF.
>>> 									 
>>>> +                           for gcc these are ".isra.0" and ".costprop.0"
>>>> +                           optimized functions
>>>
>>> For BTF generation, would there ever be a situation whereby we
>>> wouldn't want true signature support? I'm just trying to understand
>>> why this isn't defaulted to true.
>>
>> The key reason is the "." in the name for gcc-optimized functions
>> "function.isra.0" ; older kernels will reject BTF function names with 
>> a "." in them, so we have to guard against new pahole with the feature
>> enabled by default being run on older kernels. So by having the newer
>> kernels request the feature only we avoid this.
> 
> Oh, yes, that makes sense. Once a new pahole version is released with
> true_signature support available, will you also be looking to update
> scripts/Makefile.btf and conditionally enable it based on
> availability?

Yep, we're hoping to get some support on the LLVM side for true signatures, but
absolutely, that's the plan. Because the --btf_features option will simply
ignore features that it does not know about, this approach works with older
pahole too without erroring out.


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

* Re: [PATCH v2 dwarves 4/5] man-pages: document true_signature btf_feature
  2026-01-26 17:10         ` Alan Maguire
@ 2026-01-26 18:13           ` Yonghong Song
  0 siblings, 0 replies; 20+ messages in thread
From: Yonghong Song @ 2026-01-26 18:13 UTC (permalink / raw)
  To: Alan Maguire, Matt Bobrowski
  Cc: ihor.solodrai, eddyz87, jolsa, andrii, ast, david.faust, dwarves,
	bpf



On 1/26/26 9:10 AM, Alan Maguire wrote:
> On 26/01/2026 11:21, Matt Bobrowski wrote:
>> On Mon, Jan 26, 2026 at 10:51:31AM +0000, Alan Maguire wrote:
>>> On 26/01/2026 10:02, Matt Bobrowski wrote:
>>>> On Fri, Jan 23, 2026 at 05:26:49PM +0000, Alan Maguire wrote:
>>>>> Ensure non-default "true_signature" feature is documented in
>>>>> the manual page.
>>>>>
>>>>> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
>>>> Acked-by: Matt Bobrowski <mattbobrowski@google.com>
>>>>
>>>>> ---
>>>>>   man-pages/pahole.1 | 5 +++++
>>>>>   1 file changed, 5 insertions(+)
>>>>>
>>>>> diff --git a/man-pages/pahole.1 b/man-pages/pahole.1
>>>>> index 3125de3..90a8f45 100644
>>>>> --- a/man-pages/pahole.1
>>>>> +++ b/man-pages/pahole.1
>>>>> @@ -337,6 +337,11 @@ Supported non-standard features (not enabled for 'default')
>>>>>   	                   of split BTF with a possibly changed base, storing
>>>>>   	                   it in a .BTF.base ELF section.
>>>>>   	global_var         Encode all global variables using BTF_KIND_VAR in BTF.
>>>>> +	true_signature     Encode functions ensuring that binary-level
>>>>> +	                   (rather than source-level) signatures are used;
>>>> 									 ^
>>>> 									 within the generated BTF.
>>>> 									
>>>>> +                           for gcc these are ".isra.0" and ".costprop.0"
>>>>> +                           optimized functions
>>>> For BTF generation, would there ever be a situation whereby we
>>>> wouldn't want true signature support? I'm just trying to understand
>>>> why this isn't defaulted to true.
>>> The key reason is the "." in the name for gcc-optimized functions
>>> "function.isra.0" ; older kernels will reject BTF function names with
>>> a "." in them, so we have to guard against new pahole with the feature
>>> enabled by default being run on older kernels. So by having the newer
>>> kernels request the feature only we avoid this.
>> Oh, yes, that makes sense. Once a new pahole version is released with
>> true_signature support available, will you also be looking to update
>> scripts/Makefile.btf and conditionally enable it based on
>> availability?
> Yep, we're hoping to get some support on the LLVM side for true signatures, but
> absolutely, that's the plan. Because the --btf_features option will simply
> ignore features that it does not know about, this approach works with older
> pahole too without erroring out.

I actually have started to work on this from llvm side. Once Alan's patch
lands (which has true_signature infrastructure implemented), I should be
able to send some patch to address true_signature for llvm-built kernel.


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

* Re: [PATCH v2 dwarves 2/5] btf_encoder: Add true_signature feature support for "."-suffixed functions
  2026-01-26 11:18       ` Matt Bobrowski
@ 2026-01-27 12:18         ` Alan Maguire
  0 siblings, 0 replies; 20+ messages in thread
From: Alan Maguire @ 2026-01-27 12:18 UTC (permalink / raw)
  To: Matt Bobrowski
  Cc: yonghong.song, ihor.solodrai, eddyz87, jolsa, andrii, ast,
	david.faust, dwarves, bpf

On 26/01/2026 11:18, Matt Bobrowski wrote:
> On Mon, Jan 26, 2026 at 10:49:00AM +0000, Alan Maguire wrote:
>> On 26/01/2026 09:52, Matt Bobrowski wrote:
>>> On Fri, Jan 23, 2026 at 05:26:47PM +0000, Alan Maguire wrote:
>>>> Currently we collate function information by name and add functions
>>>> provided there are no inconsistencies across various representations.
>>>>
>>>> For true_signature support - where we wish to add the real signature
>>>> of a function even if it differs from source level - we need to do
>>>> a few things:
>>>>
>>>> 1. For "."-suffixed functions, we need to match from DWARF->ELF;
>>>>    we can do this via the address associated with the function.
>>>>    In doing this, we can then be confident that the debug info
>>>>    for foo.isra.0 is the right info for the function at that
>>>>    address.
>>>>
>>>> 2. When adding saved functions we need to look for such cases
>>>>    and provided they do not violate other constraints around BTF
>>>>    representation - unexpected reg usage for function, uncertain
>>>>    parameter location or ambiguous address - we add them with
>>>>    their "."-suffixed name.  The latter can be used as a signal
>>>>    that the function is transformed from the original.
>>>>
>>>> Doing this adds 500 functions to BTF.  These are traceable with
>>>> their "."-suffix names and because we have excluded ambiguous
>>>> address cases we know exactly which function address they refer
>>>> to.
>>>>
>>>> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
>>>
>>> Some minor nits, but apart from that it looks OK to me.
>>>
>>> Acked-by: Matt Bobrowski <mattbobrowski@google.com>
>>>
>>>> ---
>>>>  btf_encoder.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++-----
>>>>  dwarves.h     |  1 +
>>>>  pahole.c      |  1 +
>>>>  3 files changed, 71 insertions(+), 7 deletions(-)
>>>>
>>>> diff --git a/btf_encoder.c b/btf_encoder.c
>>>> index 9a567e4..c1002c3 100644
>>>> --- a/btf_encoder.c
>>>> +++ b/btf_encoder.c
>>>> @@ -77,9 +77,16 @@ struct btf_encoder_func_annot {
>>>>  	int16_t component_idx;
>>>>  };
>>>>  
>>>> +struct elf_function_sym {
>>>> +	const char *name;
>>>> +	uint64_t addr;
>>>> +};
>>>> +
>>>>  /* state used to do later encoding of saved functions */
>>>>  struct btf_encoder_func_state {
>>>>  	struct elf_function *elf;
>>>> +	struct elf_function_sym *sym;
>>>> +	uint64_t addr;
>>>   		 ^
>>> 		 This appears to have leaked into wrong commit?
>>> 		 This member should've been introduced within patch
>>> 		 5/5.
>>>
>>
>> It's used here too though; specifically in btf_encoder__save_func()
>> below. We need to use addresses to map between a DWARF representation
>> and the associated ELF function to ensure we're using debug info
>> for the correct "."-suffixed function. We need to do this because
>> the late DWARF generated after optimizations are applied uses
>> the original name ("foo" rather than "foo.isra.0").
> 
> Sorry, I thought I only saw usage of member "addr" within
> btf_encoder__save_func() against fn->lenblock.ip.addr which maps to
> member "addr" within struct ip_tag and func->syms[i].addr which maps
> to member "addr" within struct elf_function_sym. Member "addr" within
> struct btf_encoder_func_state remains unused until patch 5/5 where we
> assign it the value returned from function__addr().
> 
> With that said, within btf_encoder__save_func() why don't you do the
> following instead:
> 
> state->addr = function__addr(fn);
> 
> ...
> 
> if (encoder->true_signature && state->addr) {
> 	if (state->addr != func->syms[i].addr) {
> 		...
> 	}
> }
> 
> There's no need to open code fn->lexblock.ip.addr everywhere as it
> deminishes readability.
>

yep, good suggestion, will do this for v3 which should be ready shortly..

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

end of thread, other threads:[~2026-01-27 12:19 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-23 17:26 [PATCH v2 dwarves 0/5] Improve BTF concrete function accuracy Alan Maguire
2026-01-23 17:26 ` [PATCH v2 dwarves 1/5] dwarf_loader/btf_encoder: Detect reordered parameters Alan Maguire
2026-01-26  9:30   ` Matt Bobrowski
2026-01-23 17:26 ` [PATCH v2 dwarves 2/5] btf_encoder: Add true_signature feature support for "."-suffixed functions Alan Maguire
2026-01-23 19:05   ` Yonghong Song
2026-01-26  9:52   ` Matt Bobrowski
2026-01-26 10:49     ` Alan Maguire
2026-01-26 11:18       ` Matt Bobrowski
2026-01-27 12:18         ` Alan Maguire
2026-01-23 17:26 ` [PATCH v2 dwarves 3/5] test: add gcc true signature test Alan Maguire
2026-01-23 19:06   ` Yonghong Song
2026-01-23 17:26 ` [PATCH v2 dwarves 4/5] man-pages: document true_signature btf_feature Alan Maguire
2026-01-23 19:07   ` Yonghong Song
2026-01-26 10:02   ` Matt Bobrowski
2026-01-26 10:51     ` Alan Maguire
2026-01-26 11:21       ` Matt Bobrowski
2026-01-26 17:10         ` Alan Maguire
2026-01-26 18:13           ` Yonghong Song
2026-01-23 17:26 ` [PATCH v2 dwarves 5/5] btf_encoder: Prefer strong function definitions for BTF generation Alan Maguire
2026-01-23 19:09   ` Yonghong Song

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