forked from OSchip/llvm-project
2e94d8e67a
When investigating an issue with bcc tool inject.py, I found a verifier failure with latest clang. The portion of code can be illustrated as below: struct pid_struct { u64 curr_call; u64 conds_met; u64 stack[2]; }; struct pid_struct *bpf_map_lookup_elem(); int foo() { struct pid_struct *p = bpf_map_lookup_elem(); if (!p) return 0; p->curr_call--; if (p->conds_met < 1 || p->conds_met >= 3) return 0; if (p->stack[p->conds_met - 1] == p->curr_call) p->conds_met--; ... } The verifier failure looks like: ... 8: (79) r1 = *(u64 *)(r0 +0) R0_w=map_value(id=0,off=0,ks=4,vs=32,imm=0) R10=fp0 fp-8=mmmm???? 9: (07) r1 += -1 10: (7b) *(u64 *)(r0 +0) = r1 R0_w=map_value(id=0,off=0,ks=4,vs=32,imm=0) R1_w=inv(id=0) R10=fp0 fp-8=mmmm???? 11: (79) r2 = *(u64 *)(r0 +8) R0_w=map_value(id=0,off=0,ks=4,vs=32,imm=0) R1_w=inv(id=0) R10=fp0 fp-8=mmmm???? 12: (bf) r3 = r2 13: (07) r3 += -3 14: (b7) r4 = -2 15: (2d) if r4 > r3 goto pc+13 R0=map_value(id=0,off=0,ks=4,vs=32,imm=0) R1=inv(id=0) R2=inv(id=2) R3=inv(id=0,umin_value=18446744073709551614,var_off=(0xffffffff00000000; 0xffffffff)) R4=inv-2 R10=fp0 fp-8=mmmm???? 16: (07) r2 += -1 17: (bf) r3 = r2 18: (67) r3 <<= 3 19: (bf) r4 = r0 20: (0f) r4 += r3 math between map_value pointer and register with unbounded min value is not allowed Here the compiler optimized "p->conds_met < 1 || p->conds_met >= 3" to r2 = p->conds_met r3 = r2 r3 += -3 r4 = -2 if (r3 < r4) return 0 r2 += -1 r3 = r2 ... In the above, r3 is initially equal to r2, but is modified used by the comparison. But later on r2 is used again. This caused verification failure. BPF backend has a pass, AdjustOpt, to prevent such transformation, but only focused on signed integers since typical bpf helper returns signed integers. To fix this case, let us handle unsigned integers as well. Differential Revision: https://reviews.llvm.org/D121937 |
||
---|---|---|
.. | ||
BTF | ||
CORE | ||
32-bit-subreg-alu.ll | ||
32-bit-subreg-cond-select.ll | ||
32-bit-subreg-load-store.ll | ||
32-bit-subreg-peephole-phi-1.ll | ||
32-bit-subreg-peephole-phi-2.ll | ||
32-bit-subreg-peephole-phi-3.ll | ||
32-bit-subreg-peephole.ll | ||
32-bit-subreg-zext.ll | ||
adjust-opt-icmp1.ll | ||
adjust-opt-icmp2.ll | ||
adjust-opt-icmp3.ll | ||
adjust-opt-icmp4.ll | ||
adjust-opt-icmp5.ll | ||
adjust-opt-icmp6.ll | ||
adjust-opt-speculative1.ll | ||
adjust-opt-speculative2.ll | ||
alu8.ll | ||
atomics.ll | ||
atomics_2.ll | ||
basictest.ll | ||
byval.ll | ||
callx.ll | ||
cc_args.ll | ||
cc_args_be.ll | ||
cc_ret.ll | ||
cmp.ll | ||
dwarfdump.ll | ||
elf-symbol-information.ll | ||
ex1.ll | ||
fi_ri.ll | ||
i128.ll | ||
inline_asm.ll | ||
inlineasm-output-template.ll | ||
inlineasm-wreg.ll | ||
intrinsics.ll | ||
is_trunc_free.ll | ||
is_zext_free.ll | ||
lit.local.cfg | ||
load.ll | ||
loop-exit-cond.ll | ||
loops.ll | ||
many_args1.ll | ||
many_args2.ll | ||
mem_offset.ll | ||
mem_offset_be.ll | ||
memcpy-expand-in-order.ll | ||
objdump_atomics.ll | ||
objdump_cond_op.ll | ||
objdump_cond_op_2.ll | ||
objdump_dis_all.ll | ||
objdump_imm_hex.ll | ||
objdump_intrinsics.ll | ||
objdump_nop.ll | ||
objdump_static_var.ll | ||
objdump_trivial.ll | ||
objdump_two_funcs.ll | ||
optnone-1.ll | ||
optnone-2.ll | ||
reloc-2.ll | ||
reloc-3.ll | ||
reloc-btf-2.ll | ||
reloc-btf.ll | ||
reloc.ll | ||
remove_truncate_1.ll | ||
remove_truncate_2.ll | ||
remove_truncate_3.ll | ||
remove_truncate_4.ll | ||
remove_truncate_5.ll | ||
remove_truncate_6.ll | ||
remove_truncate_7.ll | ||
remove_truncate_8.ll | ||
rodata_1.ll | ||
rodata_2.ll | ||
rodata_3.ll | ||
rodata_4.ll | ||
rodata_5.ll | ||
rodata_6.ll | ||
rodata_7.ll | ||
sanity.ll | ||
sdiv_error.ll | ||
select_ri.ll | ||
selectiondag-bug.ll | ||
setcc.ll | ||
shifts.ll | ||
simplifycfg.ll | ||
sockex2.ll | ||
spill-alu32.ll | ||
struct_ret1.ll | ||
struct_ret2.ll | ||
undef.ll | ||
vararg1.ll | ||
vla.ll | ||
warn-call.ll | ||
warn-stack.ll | ||
xadd.ll | ||
xadd_legal.ll |