Skip to content

Commit

Permalink
turn off x86 jump table optimization during jit compilation
Browse files Browse the repository at this point in the history
jump table optimization tries to optimize switch statements
into an array access. But such optimization will place certain
information, acted as the array, in the read-only section.
Currently, bcc does not support read-only section, so
jump table optimized code will fail during kernel verification.
This is what happened to biolatpcts.py in my environment with
latest llvm.

  -bash-4.4$ sudo ./biolatpcts.py console
  bpf: Failed to load program: Invalid argument
  unknown opcode 60
  processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0

  HINT: The 'unknown opcode' can happen if you reference a global or static variable,
  or data in read-only section. For example, 'char *p = "hello"' will result in p
  referencing a read-only section, and 'char p[] = "hello"' will have "hello" stored on the stack.

This patch disabled jump table optimization on x64. The jump table
optimization is guarded for llvm version 4 and above.
We can disable jump table on other architectures if needed.
A test case, developed based biolatpcts.py tool, is added
to ensure it pass the verifier.

Signed-off-by: Yonghong Song <yhs@fb.com>
  • Loading branch information
yonghong-song committed Jun 4, 2020
1 parent 5fed2a9 commit 8319d52
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/cc/frontends/clang/loader.cc
Expand Up @@ -316,6 +316,11 @@ int ClangLoader::do_compile(unique_ptr<llvm::Module> *mod, TableStorage &ts,
string target_triple = get_clang_target();
driver::Driver drv("", target_triple, diags);

#if LLVM_MAJOR_VERSION >= 4
if (target_triple == "x86_64-unknown-linux-gnu")
flags_cstr.push_back("-fno-jump-tables");
#endif

drv.setTitle("bcc-clang-driver");
drv.setCheckInputsExist(false);

Expand Down
48 changes: 48 additions & 0 deletions tests/python/test_clang.py
Expand Up @@ -1292,5 +1292,53 @@ def test_packed_structure(self):
self.assertEqual(st.a, 10)
self.assertEqual(st.b, 20)

@skipUnless(kernel_version_ge(4,14), "requires kernel >= 4.14")
def test_jump_table(self):
text = """
#include <linux/blk_types.h>
#include <linux/blkdev.h>
#include <linux/time64.h>
BPF_PERCPU_ARRAY(rwdf_100ms, u64, 400);
int do_request(struct pt_regs *ctx, struct request *rq) {
u32 cmd_flags;
u64 base, dur, slot, now = 100000;
if (!rq->start_time_ns)
return 0;
if (!rq->rq_disk || rq->rq_disk->major != 5 ||
rq->rq_disk->first_minor != 6)
return 0;
cmd_flags = rq->cmd_flags;
switch (cmd_flags & REQ_OP_MASK) {
case REQ_OP_READ:
base = 0;
break;
case REQ_OP_WRITE:
base = 100;
break;
case REQ_OP_DISCARD:
base = 200;
break;
case REQ_OP_FLUSH:
base = 300;
break;
default:
return 0;
}
dur = now - rq->start_time_ns;
slot = min_t(size_t, div_u64(dur, 100 * NSEC_PER_MSEC), 99);
rwdf_100ms.increment(base + slot);
return 0;
}
"""
b = BPF(text=text)
fns = b.load_funcs(BPF.KPROBE)

if __name__ == "__main__":
main()

0 comments on commit 8319d52

Please sign in to comment.