diff mbox series

[bpf-next,v2,4/5] selftests/bpf: Fix kprobe_multi_bench_attach test failure with LTO kernel

Message ID 20240321200119.2220027-1-yonghong.song@linux.dev (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series bpf: Fix a couple of test failures with LTO kernel | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for bpf-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 8 this patch: 8
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 16 maintainers not CCed: linux-kselftest@vger.kernel.org john.fastabend@gmail.com ndesaulniers@google.com jolsa@kernel.org mykolal@fb.com haoluo@google.com nathan@kernel.org eddyz87@gmail.com justinstitt@google.com sdf@google.com song@kernel.org kpsingh@kernel.org shuah@kernel.org morbo@google.com martin.lau@linux.dev llvm@lists.linux.dev
netdev/build_clang success Errors and warnings before: 8 this patch: 8
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 8 this patch: 8
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 24 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-33 success Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-21 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 success Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-30 success Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-31 success Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-32 success Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-14 success Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-37 success Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-38 success Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-39 success Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-40 success Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-41 success Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-12 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-15 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-18 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-11 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-17 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-34 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-35 success Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-42 success Logs for x86_64-llvm-18 / veristat
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-36 success Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-13 success Logs for s390x-gcc / test (test_maps, false, 360) / test_maps on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-16 success Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-7 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-10 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-8 success Logs for set-matrix

Commit Message

Yonghong Song March 21, 2024, 8:01 p.m. UTC
In my locally build clang LTO kernel (enabling CONFIG_LTO and
CONFIG_LTO_CLANG_THIN), kprobe_multi_bench_attach/kernel subtest
failed like:
  test_kprobe_multi_bench_attach:PASS:get_syms 0 nsec
  test_kprobe_multi_bench_attach:PASS:kprobe_multi_empty__open_and_load 0 nsec
  libbpf: prog 'test_kprobe_empty': failed to attach: No such process
  test_kprobe_multi_bench_attach:FAIL:bpf_program__attach_kprobe_multi_opts unexpected error: -3
  #117/1   kprobe_multi_bench_attach/kernel:FAIL

There are multiple symbols in /sys/kernel/debug/tracing/available_filter_functions
are renamed in /proc/kallsyms due to cross file inlining. One example is for
  static function __access_remote_vm in mm/memory.c.
In a non-LTO kernel, we have the following call stack:
  ptrace_access_vm (global, kernel/ptrace.c)
    access_remote_vm (global, mm/memory.c)
      __access_remote_vm (static, mm/memory.c)

With LTO kernel, it is possible that access_remote_vm() is inlined by
ptrace_access_vm(). So we end up with the following call stack:
  ptrace_access_vm (global, kernel/ptrace.c)
    __access_remote_vm (static, mm/memory.c)
The compiler renames __access_remote_vm to __access_remote_vm.llvm.<hash>
to prevent potential name collision.

The kernel bpf_kprobe_multi_link_attach() and ftrace_lookup_symbols() try
to find addresses based on /proc/kallsyms, hence the current test failed
with LTO kenrel.

This patch removed __access_remote_vm and other similar functions from
kprobe_multi_attach by checking if the symbol like __access_remote_vm
does not exist in kallsyms with LTO kernel. The test succeeded after this change:
  #117/1   kprobe_multi_bench_attach/kernel:OK

Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
---
 .../selftests/bpf/prog_tests/kprobe_multi_test.c     | 12 ++++++++++++
 1 file changed, 12 insertions(+)

Comments

Jiri Olsa March 22, 2024, 12:37 p.m. UTC | #1
On Thu, Mar 21, 2024 at 01:01:19PM -0700, Yonghong Song wrote:
> In my locally build clang LTO kernel (enabling CONFIG_LTO and
> CONFIG_LTO_CLANG_THIN), kprobe_multi_bench_attach/kernel subtest
> failed like:
>   test_kprobe_multi_bench_attach:PASS:get_syms 0 nsec
>   test_kprobe_multi_bench_attach:PASS:kprobe_multi_empty__open_and_load 0 nsec
>   libbpf: prog 'test_kprobe_empty': failed to attach: No such process
>   test_kprobe_multi_bench_attach:FAIL:bpf_program__attach_kprobe_multi_opts unexpected error: -3
>   #117/1   kprobe_multi_bench_attach/kernel:FAIL
> 
> There are multiple symbols in /sys/kernel/debug/tracing/available_filter_functions
> are renamed in /proc/kallsyms due to cross file inlining. One example is for
>   static function __access_remote_vm in mm/memory.c.
> In a non-LTO kernel, we have the following call stack:
>   ptrace_access_vm (global, kernel/ptrace.c)
>     access_remote_vm (global, mm/memory.c)
>       __access_remote_vm (static, mm/memory.c)
> 
> With LTO kernel, it is possible that access_remote_vm() is inlined by
> ptrace_access_vm(). So we end up with the following call stack:
>   ptrace_access_vm (global, kernel/ptrace.c)
>     __access_remote_vm (static, mm/memory.c)
> The compiler renames __access_remote_vm to __access_remote_vm.llvm.<hash>
> to prevent potential name collision.
> 
> The kernel bpf_kprobe_multi_link_attach() and ftrace_lookup_symbols() try
> to find addresses based on /proc/kallsyms, hence the current test failed
> with LTO kenrel.
> 
> This patch removed __access_remote_vm and other similar functions from
> kprobe_multi_attach by checking if the symbol like __access_remote_vm
> does not exist in kallsyms with LTO kernel. The test succeeded after this change:
>   #117/1   kprobe_multi_bench_attach/kernel:OK
> 
> Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
> ---
>  .../selftests/bpf/prog_tests/kprobe_multi_test.c     | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
> index 05000810e28e..f6130f4f3d88 100644
> --- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
> +++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
> @@ -345,6 +345,9 @@ static int get_syms(char ***symsp, size_t *cntp, bool kernel)
>  	FILE *f;
>  	int err = 0;
>  
> +	if (!ASSERT_OK(load_kallsyms(), "load_kallsyms"))
> +		return -EINVAL;
> +
>  	/*
>  	 * The available_filter_functions contains many duplicates,
>  	 * but other than that all symbols are usable in kprobe multi
> @@ -393,6 +396,15 @@ static int get_syms(char ***symsp, size_t *cntp, bool kernel)
>  		if (!strncmp(name, "__ftrace_invalid_address__",
>  			     sizeof("__ftrace_invalid_address__") - 1))
>  			continue;
> +		/*
> +		 * In certain cases, e.g., clang lto kernel, the 'name' here
> +		 * may be different from the one in /proc/kallsyms due to
> +		 * /proc/kallsyms name might be "<name>.llvm.<hash>" instead
> +		 * of "<name>". Exclude these 'name's since they will cause
> +		 * later kprobe_multi_attach failure.
> +		 */
> +		if (ksym_get_addr(name) == 0)
> +			continue;

curious how many symbols like that are there?

Acked-by: Jiri Olsa <jolsa@kernel.org>

jirka

>  
>  		err = hashmap__add(map, name, 0);
>  		if (err == -EEXIST) {
> -- 
> 2.43.0
> 
>
Yonghong Song March 22, 2024, 4:01 p.m. UTC | #2
On 3/22/24 5:37 AM, Jiri Olsa wrote:
> On Thu, Mar 21, 2024 at 01:01:19PM -0700, Yonghong Song wrote:
>> In my locally build clang LTO kernel (enabling CONFIG_LTO and
>> CONFIG_LTO_CLANG_THIN), kprobe_multi_bench_attach/kernel subtest
>> failed like:
>>    test_kprobe_multi_bench_attach:PASS:get_syms 0 nsec
>>    test_kprobe_multi_bench_attach:PASS:kprobe_multi_empty__open_and_load 0 nsec
>>    libbpf: prog 'test_kprobe_empty': failed to attach: No such process
>>    test_kprobe_multi_bench_attach:FAIL:bpf_program__attach_kprobe_multi_opts unexpected error: -3
>>    #117/1   kprobe_multi_bench_attach/kernel:FAIL
>>
>> There are multiple symbols in /sys/kernel/debug/tracing/available_filter_functions
>> are renamed in /proc/kallsyms due to cross file inlining. One example is for
>>    static function __access_remote_vm in mm/memory.c.
>> In a non-LTO kernel, we have the following call stack:
>>    ptrace_access_vm (global, kernel/ptrace.c)
>>      access_remote_vm (global, mm/memory.c)
>>        __access_remote_vm (static, mm/memory.c)
>>
>> With LTO kernel, it is possible that access_remote_vm() is inlined by
>> ptrace_access_vm(). So we end up with the following call stack:
>>    ptrace_access_vm (global, kernel/ptrace.c)
>>      __access_remote_vm (static, mm/memory.c)
>> The compiler renames __access_remote_vm to __access_remote_vm.llvm.<hash>
>> to prevent potential name collision.
>>
>> The kernel bpf_kprobe_multi_link_attach() and ftrace_lookup_symbols() try
>> to find addresses based on /proc/kallsyms, hence the current test failed
>> with LTO kenrel.
>>
>> This patch removed __access_remote_vm and other similar functions from
>> kprobe_multi_attach by checking if the symbol like __access_remote_vm
>> does not exist in kallsyms with LTO kernel. The test succeeded after this change:
>>    #117/1   kprobe_multi_bench_attach/kernel:OK
>>
>> Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
>> ---
>>   .../selftests/bpf/prog_tests/kprobe_multi_test.c     | 12 ++++++++++++
>>   1 file changed, 12 insertions(+)
>>
>> diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
>> index 05000810e28e..f6130f4f3d88 100644
>> --- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
>> +++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
>> @@ -345,6 +345,9 @@ static int get_syms(char ***symsp, size_t *cntp, bool kernel)
>>   	FILE *f;
>>   	int err = 0;
>>   
>> +	if (!ASSERT_OK(load_kallsyms(), "load_kallsyms"))
>> +		return -EINVAL;
>> +
>>   	/*
>>   	 * The available_filter_functions contains many duplicates,
>>   	 * but other than that all symbols are usable in kprobe multi
>> @@ -393,6 +396,15 @@ static int get_syms(char ***symsp, size_t *cntp, bool kernel)
>>   		if (!strncmp(name, "__ftrace_invalid_address__",
>>   			     sizeof("__ftrace_invalid_address__") - 1))
>>   			continue;
>> +		/*
>> +		 * In certain cases, e.g., clang lto kernel, the 'name' here
>> +		 * may be different from the one in /proc/kallsyms due to
>> +		 * /proc/kallsyms name might be "<name>.llvm.<hash>" instead
>> +		 * of "<name>". Exclude these 'name's since they will cause
>> +		 * later kprobe_multi_attach failure.
>> +		 */
>> +		if (ksym_get_addr(name) == 0)
>> +			continue;
> curious how many symbols like that are there?

The number of entries in /sys/kernel/tracing/available_filter_functions: 50654
After existing filtering ('arch_cpu_idle') etc: 50513 (filtering 141)
After above ksym_get_addr(name) check: 49437 (further filtering 1076)

>
> Acked-by: Jiri Olsa <jolsa@kernel.org>
>
> jirka
>
>>   
>>   		err = hashmap__add(map, name, 0);
>>   		if (err == -EEXIST) {
>> -- 
>> 2.43.0
>>
>>
Andrii Nakryiko March 22, 2024, 9:53 p.m. UTC | #3
On Fri, Mar 22, 2024 at 9:01 AM Yonghong Song <yonghong.song@linux.dev> wrote:
>
>
> On 3/22/24 5:37 AM, Jiri Olsa wrote:
> > On Thu, Mar 21, 2024 at 01:01:19PM -0700, Yonghong Song wrote:
> >> In my locally build clang LTO kernel (enabling CONFIG_LTO and
> >> CONFIG_LTO_CLANG_THIN), kprobe_multi_bench_attach/kernel subtest
> >> failed like:
> >>    test_kprobe_multi_bench_attach:PASS:get_syms 0 nsec
> >>    test_kprobe_multi_bench_attach:PASS:kprobe_multi_empty__open_and_load 0 nsec
> >>    libbpf: prog 'test_kprobe_empty': failed to attach: No such process
> >>    test_kprobe_multi_bench_attach:FAIL:bpf_program__attach_kprobe_multi_opts unexpected error: -3
> >>    #117/1   kprobe_multi_bench_attach/kernel:FAIL
> >>
> >> There are multiple symbols in /sys/kernel/debug/tracing/available_filter_functions
> >> are renamed in /proc/kallsyms due to cross file inlining. One example is for
> >>    static function __access_remote_vm in mm/memory.c.
> >> In a non-LTO kernel, we have the following call stack:
> >>    ptrace_access_vm (global, kernel/ptrace.c)
> >>      access_remote_vm (global, mm/memory.c)
> >>        __access_remote_vm (static, mm/memory.c)
> >>
> >> With LTO kernel, it is possible that access_remote_vm() is inlined by
> >> ptrace_access_vm(). So we end up with the following call stack:
> >>    ptrace_access_vm (global, kernel/ptrace.c)
> >>      __access_remote_vm (static, mm/memory.c)
> >> The compiler renames __access_remote_vm to __access_remote_vm.llvm.<hash>
> >> to prevent potential name collision.
> >>
> >> The kernel bpf_kprobe_multi_link_attach() and ftrace_lookup_symbols() try
> >> to find addresses based on /proc/kallsyms, hence the current test failed
> >> with LTO kenrel.
> >>
> >> This patch removed __access_remote_vm and other similar functions from
> >> kprobe_multi_attach by checking if the symbol like __access_remote_vm
> >> does not exist in kallsyms with LTO kernel. The test succeeded after this change:
> >>    #117/1   kprobe_multi_bench_attach/kernel:OK
> >>
> >> Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
> >> ---
> >>   .../selftests/bpf/prog_tests/kprobe_multi_test.c     | 12 ++++++++++++
> >>   1 file changed, 12 insertions(+)
> >>
> >> diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
> >> index 05000810e28e..f6130f4f3d88 100644
> >> --- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
> >> +++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
> >> @@ -345,6 +345,9 @@ static int get_syms(char ***symsp, size_t *cntp, bool kernel)
> >>      FILE *f;
> >>      int err = 0;
> >>
> >> +    if (!ASSERT_OK(load_kallsyms(), "load_kallsyms"))
> >> +            return -EINVAL;
> >> +
> >>      /*
> >>       * The available_filter_functions contains many duplicates,
> >>       * but other than that all symbols are usable in kprobe multi
> >> @@ -393,6 +396,15 @@ static int get_syms(char ***symsp, size_t *cntp, bool kernel)
> >>              if (!strncmp(name, "__ftrace_invalid_address__",
> >>                           sizeof("__ftrace_invalid_address__") - 1))
> >>                      continue;
> >> +            /*
> >> +             * In certain cases, e.g., clang lto kernel, the 'name' here
> >> +             * may be different from the one in /proc/kallsyms due to
> >> +             * /proc/kallsyms name might be "<name>.llvm.<hash>" instead
> >> +             * of "<name>". Exclude these 'name's since they will cause
> >> +             * later kprobe_multi_attach failure.
> >> +             */
> >> +            if (ksym_get_addr(name) == 0)
> >> +                    continue;
> > curious how many symbols like that are there?
>
> The number of entries in /sys/kernel/tracing/available_filter_functions: 50654
> After existing filtering ('arch_cpu_idle') etc: 50513 (filtering 141)
> After above ksym_get_addr(name) check: 49437 (further filtering 1076)
>

alternatively, you could have found matching func.llvm.* for any func
in available_filter_functions. Have you considered that?

> >
> > Acked-by: Jiri Olsa <jolsa@kernel.org>
> >
> > jirka
> >
> >>
> >>              err = hashmap__add(map, name, 0);
> >>              if (err == -EEXIST) {
> >> --
> >> 2.43.0
> >>
> >>
Yonghong Song March 22, 2024, 10:20 p.m. UTC | #4
On 3/22/24 2:53 PM, Andrii Nakryiko wrote:
> On Fri, Mar 22, 2024 at 9:01 AM Yonghong Song <yonghong.song@linux.dev> wrote:
>>
>> On 3/22/24 5:37 AM, Jiri Olsa wrote:
>>> On Thu, Mar 21, 2024 at 01:01:19PM -0700, Yonghong Song wrote:
>>>> In my locally build clang LTO kernel (enabling CONFIG_LTO and
>>>> CONFIG_LTO_CLANG_THIN), kprobe_multi_bench_attach/kernel subtest
>>>> failed like:
>>>>     test_kprobe_multi_bench_attach:PASS:get_syms 0 nsec
>>>>     test_kprobe_multi_bench_attach:PASS:kprobe_multi_empty__open_and_load 0 nsec
>>>>     libbpf: prog 'test_kprobe_empty': failed to attach: No such process
>>>>     test_kprobe_multi_bench_attach:FAIL:bpf_program__attach_kprobe_multi_opts unexpected error: -3
>>>>     #117/1   kprobe_multi_bench_attach/kernel:FAIL
>>>>
>>>> There are multiple symbols in /sys/kernel/debug/tracing/available_filter_functions
>>>> are renamed in /proc/kallsyms due to cross file inlining. One example is for
>>>>     static function __access_remote_vm in mm/memory.c.
>>>> In a non-LTO kernel, we have the following call stack:
>>>>     ptrace_access_vm (global, kernel/ptrace.c)
>>>>       access_remote_vm (global, mm/memory.c)
>>>>         __access_remote_vm (static, mm/memory.c)
>>>>
>>>> With LTO kernel, it is possible that access_remote_vm() is inlined by
>>>> ptrace_access_vm(). So we end up with the following call stack:
>>>>     ptrace_access_vm (global, kernel/ptrace.c)
>>>>       __access_remote_vm (static, mm/memory.c)
>>>> The compiler renames __access_remote_vm to __access_remote_vm.llvm.<hash>
>>>> to prevent potential name collision.
>>>>
>>>> The kernel bpf_kprobe_multi_link_attach() and ftrace_lookup_symbols() try
>>>> to find addresses based on /proc/kallsyms, hence the current test failed
>>>> with LTO kenrel.
>>>>
>>>> This patch removed __access_remote_vm and other similar functions from
>>>> kprobe_multi_attach by checking if the symbol like __access_remote_vm
>>>> does not exist in kallsyms with LTO kernel. The test succeeded after this change:
>>>>     #117/1   kprobe_multi_bench_attach/kernel:OK
>>>>
>>>> Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
>>>> ---
>>>>    .../selftests/bpf/prog_tests/kprobe_multi_test.c     | 12 ++++++++++++
>>>>    1 file changed, 12 insertions(+)
>>>>
>>>> diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
>>>> index 05000810e28e..f6130f4f3d88 100644
>>>> --- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
>>>> +++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
>>>> @@ -345,6 +345,9 @@ static int get_syms(char ***symsp, size_t *cntp, bool kernel)
>>>>       FILE *f;
>>>>       int err = 0;
>>>>
>>>> +    if (!ASSERT_OK(load_kallsyms(), "load_kallsyms"))
>>>> +            return -EINVAL;
>>>> +
>>>>       /*
>>>>        * The available_filter_functions contains many duplicates,
>>>>        * but other than that all symbols are usable in kprobe multi
>>>> @@ -393,6 +396,15 @@ static int get_syms(char ***symsp, size_t *cntp, bool kernel)
>>>>               if (!strncmp(name, "__ftrace_invalid_address__",
>>>>                            sizeof("__ftrace_invalid_address__") - 1))
>>>>                       continue;
>>>> +            /*
>>>> +             * In certain cases, e.g., clang lto kernel, the 'name' here
>>>> +             * may be different from the one in /proc/kallsyms due to
>>>> +             * /proc/kallsyms name might be "<name>.llvm.<hash>" instead
>>>> +             * of "<name>". Exclude these 'name's since they will cause
>>>> +             * later kprobe_multi_attach failure.
>>>> +             */
>>>> +            if (ksym_get_addr(name) == 0)
>>>> +                    continue;
>>> curious how many symbols like that are there?
>> The number of entries in /sys/kernel/tracing/available_filter_functions: 50654
>> After existing filtering ('arch_cpu_idle') etc: 50513 (filtering 141)
>> After above ksym_get_addr(name) check: 49437 (further filtering 1076)
>>
> alternatively, you could have found matching func.llvm.* for any func
> in available_filter_functions. Have you considered that?

Looks like you prefer not skipping those functions who have .llvm.* in
/proc/kallsyms in this patch set. Yes, I can do that.

>
>>> Acked-by: Jiri Olsa <jolsa@kernel.org>
>>>
>>> jirka
>>>
>>>>               err = hashmap__add(map, name, 0);
>>>>               if (err == -EEXIST) {
>>>> --
>>>> 2.43.0
>>>>
>>>>
diff mbox series

Patch

diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
index 05000810e28e..f6130f4f3d88 100644
--- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
+++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
@@ -345,6 +345,9 @@  static int get_syms(char ***symsp, size_t *cntp, bool kernel)
 	FILE *f;
 	int err = 0;
 
+	if (!ASSERT_OK(load_kallsyms(), "load_kallsyms"))
+		return -EINVAL;
+
 	/*
 	 * The available_filter_functions contains many duplicates,
 	 * but other than that all symbols are usable in kprobe multi
@@ -393,6 +396,15 @@  static int get_syms(char ***symsp, size_t *cntp, bool kernel)
 		if (!strncmp(name, "__ftrace_invalid_address__",
 			     sizeof("__ftrace_invalid_address__") - 1))
 			continue;
+		/*
+		 * In certain cases, e.g., clang lto kernel, the 'name' here
+		 * may be different from the one in /proc/kallsyms due to
+		 * /proc/kallsyms name might be "<name>.llvm.<hash>" instead
+		 * of "<name>". Exclude these 'name's since they will cause
+		 * later kprobe_multi_attach failure.
+		 */
+		if (ksym_get_addr(name) == 0)
+			continue;
 
 		err = hashmap__add(map, name, 0);
 		if (err == -EEXIST) {