aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
diff options
context:
space:
mode:
authoryonghong-song <yhs@fb.com>2025-05-27 13:34:15 -0700
committerGitHub <noreply@github.com>2025-05-27 13:34:15 -0700
commitab391beb11f733b526b86f9df23734a34657d876 (patch)
treeb7d69efa24d5cdd26db84b44e74a763b725885e2 /llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
parenta8edb6a5484964a399f6a297b02338e053d276c7 (diff)
downloadllvm-ab391beb11f733b526b86f9df23734a34657d876.zip
llvm-ab391beb11f733b526b86f9df23734a34657d876.tar.gz
llvm-ab391beb11f733b526b86f9df23734a34657d876.tar.bz2
[BPF] Handle traps with kfunc call __bpf_trap (#131731)
Currently, middle-end generates 'unreachable' insn if the compiler feels the code is indeed unreachable or the code becomes invalid due to some optimizaiton (e.g. code optimization with uninitialized variables). Right now BPF backend ignores 'unreachable' insn during selectiondag lowering. For cases where 'unreachable' is due to invalid code transformation, such a signal will be missed. Later on, users needs some effort to debug it which impacts developer productivity. This patch enabled selectiondag lowering for 'unreachable' insn. Previous attempt ([1]) tries to have a backend IR pass to filter out 'unreachable' insns in a number of cases. But such pattern matching may misalign with future middle-end optimization with 'unreachable' insns. This patch takes a different approach. The 'unreachable' insn is lowered with special encoding in bpf object file and verifier will do proper verification for the bpf prog. More specifically, the 'unreachable' insn is replaced by a __bpf_trap() function. This function will be a kfunc (in ".ksyms" section) with a weak attribute, but does not have definition. The actual kfunc definition is expected to be in kernel. The __bpf_trap() extern function is also encoded in BTF. The name __bpf_trap() is chosen to satisfy reserved identifier requirement. Besides the uninitialized variable case, the builtin function '__builtin_trap' can also generate kfunc __bpf_trap(). For example in [3], we have ``` # define __bpf_unreachable() __builtin_trap() ``` If the compiler didn't remove __builtin_trap() during middle-end optimization, compilation will fail. With this patch, compilation will not fail and __builtin_trap() is converted to __bpf_trap() kfunc. The eventual failure will be in verifier instead of llvm compilation. To keep compilation time failure, user can add an option like `-ftrap-function=<something>`. I tested this patch on bpf selftests and all tests are passed. I also tried original example in [2] and the code looks like below: ``` ; { 0: bf 16 00 00 00 00 00 00 r6 = r1 ; bpf_printk("Start"); 1: 18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0x0 ll 0000000000000008: R_BPF_64_64 .rodata 3: b4 02 00 00 06 00 00 00 w2 = 0x6 4: 85 00 00 00 06 00 00 00 call 0x6 ; DEFINE_FUNC_CTX_POINTER(data) 5: 61 61 4c 00 00 00 00 00 w1 = *(u32 *)(r6 + 0x4c) ; bpf_printk("pre ipv6_hdrlen_offset"); 6: 18 01 00 00 06 00 00 00 00 00 00 00 00 00 00 00 r1 = 0x6 ll 0000000000000030: R_BPF_64_64 .rodata 8: b4 02 00 00 17 00 00 00 w2 = 0x17 9: 85 00 00 00 06 00 00 00 call 0x6 10: 85 10 00 00 ff ff ff ff call -0x1 0000000000000050: R_BPF_64_32 __bpf_trap 11: 95 00 00 00 00 00 00 00 exit <END> ``` Eventually kernel verifier will emit the following logs: ``` 10: (85) call __bpf_trap#74479 unexpected __bpf_trap() due to uninitialized variable? ``` In another internal sched-ext bpf prog, with the patch we have bpf code: ``` Disassembly of section .text: 0000000000000000 <scx_storage_init_single>: ; { 0: bc 13 00 00 00 00 00 00 w3 = w1 1: b4 01 00 00 00 00 00 00 w1 = 0x0 ; const u32 zero = 0; ... 0000000000003a80 <create_dom>: ; { 1872: bc 16 00 00 00 00 00 00 w6 = w1 ; bpf_printk("dom_id %d", dom_id); 1873: 18 01 00 00 3f 00 00 00 00 00 00 00 00 00 00 00 r1 = 0x3f ll 0000000000003a88: R_BPF_64_64 .rodata 1875: b4 02 00 00 0a 00 00 00 w2 = 0xa 1876: bc 63 00 00 00 00 00 00 w3 = w6 1877: 85 00 00 00 06 00 00 00 call 0x6 ; ret = scx_bpf_create_dsq(dom_id, 0); 1878: bc 61 00 00 00 00 00 00 w1 = w6 1879: b4 02 00 00 00 00 00 00 w2 = 0x0 1880: 85 10 00 00 ff ff ff ff call -0x1 0000000000003ac0: R_BPF_64_32 scx_bpf_create_dsq ; domc->node_cpumask = node_data[node_id]; 1881: 85 10 00 00 ff ff ff ff call -0x1 0000000000003ac8: R_BPF_64_32 __bpf_trap 1882: 95 00 00 00 00 00 00 00 exit <END> ``` The verifier can easily report the error too. A bpf flag `-bpf-disable-trap-unreachable` is introduced to disable trapping for 'unreachable' or __builtin_trap. [1] https://github.com/llvm/llvm-project/pull/126858 [2] https://github.com/msune/clang_bpf/blob/main/Makefile#L3 [3] https://github.com/libbpf/libbpf/blob/master/src/bpf_helpers.h
Diffstat (limited to 'llvm/lib/Analysis/ModuleSummaryAnalysis.cpp')
0 files changed, 0 insertions, 0 deletions