On Fri, Jul 11, 2025 at 7:23 PM Jiri Olsa <olsajiri@xxxxxxxxx> wrote: > > On Fri, Jul 11, 2025 at 01:51:31PM +0800, Menglong Dong wrote: > > On Fri, Jul 11, 2025 at 11:46 AM Yonghong Song <yonghong.song@xxxxxxxxx> wrote: > > > > > > > > > > > > On 7/10/25 8:10 PM, Yonghong Song wrote: > > > > > > > > > > > > On 7/10/25 12:08 AM, Menglong Dong wrote: > > > >> For now, we lookup the address of the attach target in > > > >> bpf_check_attach_target() with find_kallsyms_symbol_value or > > > >> kallsyms_lookup_name, which is not accurate in some cases. > > > >> > > > >> For example, we want to attach to the target "t_next", but there are > > > >> multiple symbols with the name "t_next" exist in the kallsyms, which > > > >> makes > > > >> the attach target ambiguous, and the attach should fail. > > > >> > > > >> Introduce the function bpf_lookup_attach_addr() to do the address > > > >> lookup, > > > >> which will return -EADDRNOTAVAIL when the symbol is not unique. > > > >> > > > >> We can do the testing with following shell: > > > >> > > > >> for s in $(cat /proc/kallsyms | awk '{print $3}' | sort | uniq -d) > > > >> do > > > >> if grep -q "^$s\$" > > > >> /sys/kernel/debug/tracing/available_filter_functions > > > >> then > > > >> bpftrace -e "fentry:$s {printf(\"1\");}" -v > > > >> fi > > > >> done > > > >> > > > >> The script will find all the duplicated symbols in /proc/kallsyms, which > > > >> is also in /sys/kernel/debug/tracing/available_filter_functions, and > > > >> attach them with bpftrace. > > > >> > > > >> After this patch, all the attaching fail with the error: > > > >> > > > >> The address of function xxx cannot be found > > > >> or > > > >> No BTF found for xxx > > > >> > > > >> Signed-off-by: Menglong Dong <dongml2@xxxxxxxxxxxxxxx> > > > > > > > > Maybe we should prevent vmlinux BTF generation for such symbols > > > > which are static and have more than one instances? This can > > > > be done in pahole and downstream libbpf/kernel do not > > > > need to do anything. This can avoid libbpf/kernel runtime overhead > > > > since bpf_lookup_attach_addr() could be expensive as it needs > > > > to go through ALL symbols, even for unique symbols. > > > > Hi, yonghong. You are right, the best solution is to solve > > this problem in the pahole, just like what Jiri said in the V2: > > https://lore.kernel.org/bpf/aG5hzvaqXi7uI4GL@krava/ > > > > I wonder will we focus the users to use the latest pahole > > that supports duplicate symbols filter after we fix this problem > > in pahole? If so, this patch is useless, and just ignore it. If > > not, the only usage of this patch is for the users that build > > the kernel with an old pahole. > > > > > > > > There is a multi-link effort: > > > https://lore.kernel.org/bpf/20250703121521.1874196-1-dongml2@xxxxxxxxxxxxxxx/ > > > which tries to do similar thing for multi-kprobe. For example, for fentry, > > > multi-link may pass an array of btf_id's to the kernel. For such cases, > > > this patch may cause significant performance overhead. > > > > For the symbol in the vmlinux, there will be no additional overhead, > > as the logic is the same as previous. If the symbol is in the > > modules, it does have additional overhead. Following is the > > testing that hooks all the symbols with fentry-multi. > > > > Without this patch, the time to attach all the symbols: > > kernel: 0.372660s for 48857 symbols > > modules: 0.135543s for 8631 symbols > > > > And with this patch, the time is: > > kernel: 0.380087s for 48857 symbols > > modules: 0.176904s for 8631 symbols > > > > One more thing, is there anyone to fix the problem in pahole? > > I mean, I'm not good at pahole. But if there is nobody, I still can > > do this job, but I need to learn it first :/ > > I'm testing change below, I'll send the patch after some more testing Awesome, thank you :/ > > jirka > > > --- > diff --git a/btf_encoder.c b/btf_encoder.c > index 16739066caae..29ff86bac7de 100644 > --- a/btf_encoder.c > +++ b/btf_encoder.c > @@ -2143,6 +2143,31 @@ int btf_encoder__encode(struct btf_encoder *encoder, struct conf_load *conf) > return err; > } > > +static void remove_dups(struct elf_functions *functions) > +{ > + struct elf_function *n = &functions->entries[0]; > + bool matched = 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; > + continue; > + } > + > + if (!matched) > + *n++ = *a; > + matched = false; > + } > + > + if (!matched) > + *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 +2193,7 @@ static int elf_functions__collect(struct elf_functions *functions) > > if (functions->cnt) { > qsort(functions->entries, functions->cnt, sizeof(*functions->entries), functions_cmp); > + remove_dups(functions); > } else { > err = 0; > goto out_free;