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 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;