Re: [PATCH dwarves 1/2] btf_encoder: Only skip optimized parms when ABI changed

Alan Maguire <[email protected]> Wed, 22 Jul 2026 13:20:45 +0100
Newsgroups org.kernel.vger.dwarves,org.kernel.vger.bpf
Message-ID <[email protected]>
On 21/07/2026 14:39, Jiri Olsa wrote:
> On Tue, Jul 14, 2026 at 02:50:34PM +0100, Alan Maguire wrote:
>> The true-signature series made optimized-parameter state more visible to
>> the BTF encoder.  Skipping every function with optimized parameters is too
>> broad, though: an unused parameter can still be part of the real calling
>> ABI, so default BTF should continue to encode that function.
>> 
>> Limit the optimized-parameter skip to cases where default BTF cannot
>> represent the concrete ABI safely:
>>  - clang functions marked as signature-changed via DW_CC_nocall
>>  - GCC optimized clones with ELF suffixes such as .isra or .constprop
>> 
>> When multiple saved states share the same base ELF function, prefer a
>> canonical state that does not require this optimized-parameter skip, so a
>> usable concrete instance is not dropped just because another optimized clone
>> exists.
>> 
>> Signed-off-by: Alan Maguire <[email protected]>
>> ---
>>  btf_encoder.c | 97 ++++++++++++++++++++++++++++++++++++++-------------
>>  1 file changed, 73 insertions(+), 24 deletions(-)
>> 
>> diff --git a/btf_encoder.c b/btf_encoder.c
>> index 38455a4..2e6eab0 100644
>> --- a/btf_encoder.c
>> +++ b/btf_encoder.c
>> @@ -95,6 +95,8 @@ struct btf_encoder_func_state {
>>  	uint8_t inconsistent_proto:1;
>>  	uint8_t uncertain_parm_loc:1;
>>  	uint8_t reordered_parm:1;
>> +	uint8_t signature_changed:1;
>> +	uint8_t optimized_symbol:1;
>>  	uint8_t ambiguous_addr:1;
>>  	int ret_type_id;
>>  	struct btf_encoder_func_parm *parms;
>> @@ -1209,27 +1211,44 @@ static struct btf_encoder_func_state *btf_encoder__alloc_func_state(struct btf_e
>>  	return state;
>>  }
>>  
>> -/* some "." suffixes do not correspond to real functions;
>> - * - .part for partial inline
>> - * - .cold for rarely-used codepath extracted for better code locality
>> - */
>> -static bool str_contains_non_fn_suffix(const char *str) {
>> -	static const char *skip[] = {
>> -		".cold",
>> -		".part"
>> -	};
>> +static bool str_contains_suffix(const char *str, const char * const *suffixes, int nr_suffixes)
>> +{
>>  	const char *suffix = strchr(str, '.');
>>  	int i;
>>  
>>  	if (!suffix)
>>  		return false;
>> -	for (i = 0; i < ARRAY_SIZE(skip); i++) {
>> -		if (strstr(suffix, skip[i]))
>> +	for (i = 0; i < nr_suffixes; i++) {
>> +		if (strstr(suffix, suffixes[i]))
>>  			return true;
>>  	}
>>  	return false;
>>  }
>>  
>> +/* some "." suffixes do not correspond to real functions;
>> + * - .part for partial inline
>> + * - .cold for rarely-used codepath extracted for better code locality
>> + */
>> +static bool str_contains_non_fn_suffix(const char *str)
>> +{
>> +	static const char * const skip[] = {
>> +		".cold",
>> +		".part"
>> +	};
>> +
>> +	return str_contains_suffix(str, skip, ARRAY_SIZE(skip));
>> +}
>> +
>> +static bool str_contains_optimized_fn_suffix(const char *str)
>> +{
>> +	static const char * const suffixes[] = {
>> +		".constprop",
>> +		".isra",
>> +	};
>> +
>> +	return str_contains_suffix(str, suffixes, ARRAY_SIZE(suffixes));
>> +}
>> +
>>  static bool elf_function__has_ambiguous_address(struct elf_function *func)
>>  {
>>  	struct elf_function_sym *sym;
>> @@ -1295,6 +1314,17 @@ static int32_t btf_encoder__save_func(struct btf_encoder *encoder, struct functi
>>  	state->optimized_parms = ftype->optimized_parms;
>>  	state->uncertain_parm_loc = ftype->uncertain_parm_loc;
>>  	state->reordered_parm = ftype->reordered_parm;
>> +	state->signature_changed = ftype->signature_changed;
>> +	if (state->addr) {
>> +		for (int i = 0; i < func->sym_cnt; i++) {
>> +			if (state->addr != func->syms[i].addr)
>> +				continue;
>> +			if (str_contains_optimized_fn_suffix(func->syms[i].name)) {
>> +				state->optimized_symbol = 1;
>> +				break;
>> +			}
>> +		}
>> +	}
>>  	ftype__for_each_parameter(ftype, param) {
>>  		const char *name;
>>  		char *final_name = NULL;
>> @@ -1497,19 +1527,17 @@ 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, reordered_parm;
>> +	uint8_t unexpected, inconsistent, uncertain_parm_loc, reordered_parm;
>>  
>>  	if (a->elf != b->elf)
>>  		return 1;
>>  
>> -	optimized = a->optimized_parms | b->optimized_parms;
>>  	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;
>>  	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;
>> @@ -1574,7 +1602,16 @@ static int btf_encoder__add_true_signature(struct btf_encoder *encoder,
>>  	return 0;
>>  }
>>  
>> -static struct btf_encoder_func_state *btf_encoder__select_canonical_state(struct btf_encoder_func_state *combined_states,
>> +static bool btf_encoder_func_state__skip_optimized_parms(struct btf_encoder *encoder,
>> +							 struct btf_encoder_func_state *state)
>> +{
>> +	return !encoder->true_signature &&
>> +	       state->optimized_parms &&
>> +	       (state->signature_changed || state->optimized_symbol);
>> +}
> 
> so this take effect only when true_signatues are disabled?
> 

Yep; when true signature is enabled we are basically saying "give me
the actual representation even if it doesn't match source-level expectations";
this includes clang nocall and dot-suffixed gcc-optimized functions. With true 
signature disabled we skip such cases.

> ---
> 
> hi,
> sorry for delay, I checked this patchset on top of your pahole branch: 
>   alan-maguire/dwarves-inline-on-true-sig-v10
> 
> true signatues in that branch gives me different stats (than before)
> in generated functions:
> 
>    279 added, 94 removed (diff attached below)
> 

Ah, sorry that's the wrong branch; that has the work-in-progress v2 BTF inline 
stuff on top rather than just Yonghong's patches. Probably not a huge amount
of change in this area though, so I think the testing should still be valid
(those changes would have simply added inline encoding if the APIs were available
in libbpf which they weren't). Thanks for testing!

Alan