Menglong reported issue where we can have function in BTF which has multiple addresses in kallsysm [1]. Rather than filtering this in runtime, let's teach pahole to remove such functions. Removing duplicate records from functions entries that have more at least one different address. This way btf_encoder__find_function won't find such functions and they won't be added in BTF. In my setup it removed 428 functions out of 77141. [1] https://lore.kernel.org/bpf/20250710070835.260831-1-dongml2@xxxxxxxxxxxxxxx/ Reported-by: Menglong Dong <menglong8.dong@xxxxxxxxx> Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx> --- Alan, I'd like to test this in the pahole CI, is there a way to manualy trigger it? thanks, jirka --- btf_encoder.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/btf_encoder.c b/btf_encoder.c index 16739066caae..a25fe2f8bfb1 100644 --- a/btf_encoder.c +++ b/btf_encoder.c @@ -99,6 +99,7 @@ struct elf_function { size_t prefixlen; bool kfunc; uint32_t kfunc_flags; + unsigned long addr; }; struct elf_secinfo { @@ -1469,6 +1470,7 @@ static void elf_functions__collect_function(struct elf_functions *functions, GEl func = &functions->entries[functions->cnt]; func->name = name; + func->addr = sym->st_value; if (strchr(name, '.')) { const char *suffix = strchr(name, '.'); @@ -2143,6 +2145,40 @@ int btf_encoder__encode(struct btf_encoder *encoder, struct conf_load *conf) return err; } +/* + * Remove name duplicates from functions->entries that have + * at least 2 different addresses. + */ +static void functions_remove_dups(struct elf_functions *functions) +{ + struct elf_function *n = &functions->entries[0]; + bool matched = false, diff = false; + int i, j; + + for (i = 0, j = 1; i < functions->cnt && j < functions->cnt; i++, j++) { + struct elf_function *a = &functions->entries[i]; + struct elf_function *b = &functions->entries[j]; + + if (!strcmp(a->name, b->name)) { + matched = true; + diff |= a->addr != b->addr; + continue; + } + + /* + * Keep only not-matched entries and last one of the matched/duplicates + * ones if all of the matched entries had the same address. + **/ + if (!matched || !diff) + *n++ = *a; + matched = diff = false; + } + + if (!matched || !diff) + *n++ = functions->entries[functions->cnt - 1]; + functions->cnt = n - &functions->entries[0]; +} + static int elf_functions__collect(struct elf_functions *functions) { uint32_t nr_symbols = elf_symtab__nr_symbols(functions->symtab); @@ -2168,6 +2204,7 @@ static int elf_functions__collect(struct elf_functions *functions) if (functions->cnt) { qsort(functions->entries, functions->cnt, sizeof(*functions->entries), functions_cmp); + functions_remove_dups(functions); } else { err = 0; goto out_free; -- 2.50.1