From 17e0a28b75e8a5961fcfae52b631eebf9e9fd118 Mon Sep 17 00:00:00 2001 From: Serhei Makarov Date: Wed, 24 Oct 2018 13:30:29 -0400 Subject: [PATCH 09/32] stapbpf assembler WIP #8 :: bpf-asm.exp driver and more testcases --- testsuite/systemtap.bpf/asm_tests/branch.stp | 14 ++- .../systemtap.bpf/asm_tests/err-printf_args.stp | 9 ++ testsuite/systemtap.bpf/asm_tests/err_numeric.stp | 1 - testsuite/systemtap.bpf/asm_tests/leniency.stp | 14 ++- testsuite/systemtap.bpf/asm_tests/printf-basic.stp | 9 ++ testsuite/systemtap.bpf/asm_tests/printf.stp | 16 ++++ testsuite/systemtap.bpf/asm_tests/simple.stp | 9 +- testsuite/systemtap.bpf/asm_tests/string.stp | 21 +++-- testsuite/systemtap.bpf/asm_tests/temporary.stp | 9 +- testsuite/systemtap.bpf/asm_tests/unreachable.stp | 17 ++++ testsuite/systemtap.bpf/bpf-asm.exp | 105 +++++++++++++++++++++ 11 files changed, 205 insertions(+), 19 deletions(-) create mode 100644 testsuite/systemtap.bpf/asm_tests/err-printf_args.stp create mode 100644 testsuite/systemtap.bpf/asm_tests/printf-basic.stp create mode 100644 testsuite/systemtap.bpf/asm_tests/printf.stp create mode 100644 testsuite/systemtap.bpf/asm_tests/unreachable.stp create mode 100644 testsuite/systemtap.bpf/bpf-asm.exp diff --git a/testsuite/systemtap.bpf/asm_tests/branch.stp b/testsuite/systemtap.bpf/asm_tests/branch.stp index aa22bf195..0e49213df 100644 --- a/testsuite/systemtap.bpf/asm_tests/branch.stp +++ b/testsuite/systemtap.bpf/asm_tests/branch.stp @@ -6,7 +6,6 @@ function foo:long (x:long) %{ /* bpf */ /* pure */ label, _bar; 0xb7, $$, -, -, 50; /* mov $$, 50 */ label, _done; - /* 0xbf, $$, $$, -, -; /* dummy op */ %} function bar:long (x:long) { @@ -14,9 +13,14 @@ function bar:long (x:long) { } probe begin { - printf("foo(1)=%d should be %d\n", foo(1), bar(1)) - printf("foo(8)=%d should be %d\n", foo(8), bar(8)) - printf("foo(15)=%d should be %d\n", foo(15), bar(15)) - exit() + printf("U foo(1)=%d should be %d\n", foo(1), bar(1)) + printf("U foo(8)=%d should be %d\n", foo(8), bar(8)) + printf("U foo(15)=%d should be %d\n", foo(15), bar(15)) } +probe kernel.function("vfs_read") { + printf("K foo(1)=%d should be %d\n", foo(1), bar(1)) + printf("K foo(8)=%d should be %d\n", foo(8), bar(8)) + printf("K foo(15)=%d should be %d\n", foo(15), bar(15)) + exit() +} diff --git a/testsuite/systemtap.bpf/asm_tests/err-printf_args.stp b/testsuite/systemtap.bpf/asm_tests/err-printf_args.stp new file mode 100644 index 000000000..eb4adc00f --- /dev/null +++ b/testsuite/systemtap.bpf/asm_tests/err-printf_args.stp @@ -0,0 +1,9 @@ +function foo:long (x:long) %{ /* bpf */ + call, -, printf, "x = 0x%p causing exit\n", $x, $x, $x, $x; + 0xb7, $$, -, -, 0x0; /* mov $$, 0 */ +%} + +probe begin { + printf("U x = 10 should print:\n"); foo(10) + exit() +} diff --git a/testsuite/systemtap.bpf/asm_tests/err_numeric.stp b/testsuite/systemtap.bpf/asm_tests/err_numeric.stp index 9428e5704..ed82b32a1 100644 --- a/testsuite/systemtap.bpf/asm_tests/err_numeric.stp +++ b/testsuite/systemtap.bpf/asm_tests/err_numeric.stp @@ -15,4 +15,3 @@ probe begin { printf("foo(15)=%d should be %d\n", foo(15), bar(15)) exit() } - diff --git a/testsuite/systemtap.bpf/asm_tests/leniency.stp b/testsuite/systemtap.bpf/asm_tests/leniency.stp index 939061158..1db1ec7fd 100644 --- a/testsuite/systemtap.bpf/asm_tests/leniency.stp +++ b/testsuite/systemtap.bpf/asm_tests/leniency.stp @@ -9,9 +9,17 @@ function foo:long (x:long) %{ /* bpf */ /* pure */ label, _done; %} +function bar:long (x:long) { + if (x < 10) return 17 else return 16 +} + probe begin { - printf("foo(1)=%d\n", foo(1)) - printf("foo(15)=%d\n", foo(15)) - exit() + printf("U foo(1)=%d should be %d\n", foo(1), bar(1)) + printf("U foo(15)=%d should be %d\n", foo(15), bar(15)) } +probe kernel.function("vfs_read") { + printf("K foo(1)=%d should be %d\n", foo(1), bar(1)) + printf("K foo(15)=%d should be %d\n", foo(15), bar(15)) + exit() +} diff --git a/testsuite/systemtap.bpf/asm_tests/printf-basic.stp b/testsuite/systemtap.bpf/asm_tests/printf-basic.stp new file mode 100644 index 000000000..ffa8e01eb --- /dev/null +++ b/testsuite/systemtap.bpf/asm_tests/printf-basic.stp @@ -0,0 +1,9 @@ +function foo:long (x:long) %{ /* bpf */ + call, -, printf, "x = %p \n", $x; + 0xb7, $$, -, -, 0x0; /* mov $$, 0 */ +%} + +probe begin { + printf("U 'x = 0xa' should print:\n"); foo(10) + exit() +} diff --git a/testsuite/systemtap.bpf/asm_tests/printf.stp b/testsuite/systemtap.bpf/asm_tests/printf.stp new file mode 100644 index 000000000..4bfa34648 --- /dev/null +++ b/testsuite/systemtap.bpf/asm_tests/printf.stp @@ -0,0 +1,16 @@ +function foo:long (x:long) %{ /* bpf */ /* calls:exit */ + 0xb5, $x, -, _skip, 20; /* jle n, 20, _skip */ + call, -, printf, "x = %d causing exit\n", $x; /* like error() */ + call, -, exit; + label, _skip; + call, -, printf, "x = %d not causing exit\n", $x; + 0xb7, $$, -, -, 0x0; /* mov $$, 0 */ +%} + +probe begin { + printf("U 'x = 10' should print:\n"); foo(10) +} + +probe kernel.function("vfs_read") { + printf("K 'x = 25' should print:\n"); foo(25) +} diff --git a/testsuite/systemtap.bpf/asm_tests/simple.stp b/testsuite/systemtap.bpf/asm_tests/simple.stp index 17184a139..f8dd693c5 100644 --- a/testsuite/systemtap.bpf/asm_tests/simple.stp +++ b/testsuite/systemtap.bpf/asm_tests/simple.stp @@ -5,7 +5,12 @@ function foo:long (x:long) %{ /* bpf */ /* pure */ %} probe begin { - printf("foo(1)=%d, should be 99\n", foo(1)) - printf("foo(15)=%d, should be 85\n", foo(15)) + printf("U foo(1)=%d, should be 99\n", foo(1)) + printf("U foo(15)=%d, should be 85\n", foo(15)) +} + +probe kernel.function("vfs_read") { + printf("K foo(1)=%d, should be 99\n", foo(1)) + printf("K foo(15)=%d, should be 85\n", foo(15)) exit() } diff --git a/testsuite/systemtap.bpf/asm_tests/string.stp b/testsuite/systemtap.bpf/asm_tests/string.stp index dce665c14..6ecbe08da 100644 --- a/testsuite/systemtap.bpf/asm_tests/string.stp +++ b/testsuite/systemtap.bpf/asm_tests/string.stp @@ -1,4 +1,4 @@ -function foo:long (x:long) %{ /* bpf */ /* pure */ +function foo:string (x:long) %{ /* bpf */ /* pure */ /* if x <= 10 then "fifty" else "one-hundred" */ 0xd5, $x, -, _bar, 10; /* jsle $x, 10, _bar */ 0xbf, $$, "one-hundred", -, -; /* mov $$, "one-hundred" */ @@ -9,14 +9,23 @@ function foo:long (x:long) %{ /* bpf */ /* pure */ /* 0xbf, $$, $$, -, -; /* dummy op */ %} -function bar:long (x:long) { - if (x <= 10) return 50 else return 100 +function bar:string (x:long) { + if (x <= 10) return "fifty" else return "one-hundred" } probe begin { - printf("foo(1)=%d should be %d\n", foo(1), bar(1)) - printf("foo(8)=%d should be %d\n", foo(8), bar(8)) - printf("foo(15)=%d should be %d\n", foo(15), bar(15)) + printf("U foo(1)=%s should be %s\n", foo(1), bar(1)) + printf("U foo(8)=%s should be %s\n", foo(8), bar(8)) + printf("U foo(15)=%s should be %s\n", foo(15), bar(15)) +} + +probe kernel.function("vfs_read") { + printf("K foo(1)=%s should be %s\n", bar(1), bar(1)) + printf("K foo(8)=%s should be %s\n", bar(8), bar(8)) + printf("K foo(15)=%s should be %s\n", bar(15), bar(15)) + # printf("K foo(1)=%s should be %s\n", foo(1), bar(1)) + # printf("K foo(8)=%s should be %s\n", foo(8), bar(8)) + # printf("K foo(15)=%s should be %s\n", foo(15), bar(15)) exit() } diff --git a/testsuite/systemtap.bpf/asm_tests/temporary.stp b/testsuite/systemtap.bpf/asm_tests/temporary.stp index 153c759ba..7cec89bb3 100644 --- a/testsuite/systemtap.bpf/asm_tests/temporary.stp +++ b/testsuite/systemtap.bpf/asm_tests/temporary.stp @@ -8,7 +8,12 @@ function foo:long (x:long) %{ /* bpf */ /* pure */ %} probe begin { - printf("foo(1)=%d, should be 99*3=297\n", foo(1)) - printf("foo(15)=%d, should be 85*18=1530\n", foo(15)) + printf("U foo(1)=%d, should be 99*3=297\n", foo(1)) + printf("U foo(15)=%d, should be 85*18=1530\n", foo(15)) +} + +probe kernel.function("vfs_read") { + printf("K foo(1)=%d, should be 99*3=297\n", foo(1)) + printf("K foo(15)=%d, should be 85*18=1530\n", foo(15)) exit() } diff --git a/testsuite/systemtap.bpf/asm_tests/unreachable.stp b/testsuite/systemtap.bpf/asm_tests/unreachable.stp new file mode 100644 index 000000000..b629fd5cb --- /dev/null +++ b/testsuite/systemtap.bpf/asm_tests/unreachable.stp @@ -0,0 +1,17 @@ +/* testcase for an early bug that would generate duplicate jump */ +function foo:long (x:long) %{ /* bpf */ + /* the code in the middle is unreachable */ + 0xd5, $x, -, _bar, 20; /* jsle $x, 20, _done */ + 0xb7, $$, -, -, 100; /* mov $$, 100 */ + 0x05, -, -, _done, -; + label, _bar; + 0xb7, $$, -, -, 50; /* mov $$, 50 */ + label, _done; +%} + +probe kernel.function("vfs_read") { + x = 10 + if (x > 12) printf("unreachable\n") + printf ("got %d (should be 50)\n", foo(x)) + exit() +} diff --git a/testsuite/systemtap.bpf/bpf-asm.exp b/testsuite/systemtap.bpf/bpf-asm.exp new file mode 100644 index 000000000..a53c7bcc4 --- /dev/null +++ b/testsuite/systemtap.bpf/bpf-asm.exp @@ -0,0 +1,105 @@ +# bpf-asm.exp +# +# TODO: Very basic test driver. Need to work out a way of signaling correctness. + +set testdir "$srcdir/$subdir/asm_tests" + +proc stapbpf_run { TEST_NAME args } { + global rc + set rc -1 + + # return codes + set pass 0 + #set fail 1 + #set bad_output 2 + set eof_start 3 + set eof_end 4 + set timeout_start 5 + set timeout_end 6 + set invalid_prog 7 + set comp_err 8 + + set cmd [concat stap -vg --runtime=bpf $args] + send_log "executing: $cmd\n" + eval spawn $cmd + set mypid [exp_pid -i $spawn_id] + expect { + -timeout 30 + -re {Pass 5: starting run} { + expect { + -timeout 20 + -re {Pass 5: run completed} { + set rc $pass + } + -re "bpf program load failed:" { set rc $invalid_prog } + default { + set rc $bad_output + } + timeout { + set rc $timeout_end + kill -INT -$mypid + } + eof { + set rc $eof_end + } + } + } + -re "semantic error:" { set rc $comp_err } + -re "bpf program load failed:" { set rc $invalid_prog } + timeout { + set rc $timeout_start + kill -INT -$mypid + } + eof { + set rc $eof_start + } + } + # again for good measure with KILL after 3s + kill -INT -$mypid 3 + catch close + wait + return $rc +} + +set stap_files [lsort [glob -nocomplain $testdir/*.stp]] + +foreach file $stap_files { + global mypid + set mypid 0 + set test [file tail $file] + if {! [installtest_p]} { untested $test; continue } + if {! [bpf_p]} { untested $test; continue } + + set errtest_p [regexp {^err} [file tail $file]] + verbose -log "Running $file" + switch [stapbpf_run $test $file] { + 0 { + if $errtest_p { + fail "$test unexpected success" + } else { + pass $test + } + } + 1 { fail "$test incorrect result" } + 2 { fail "$test unexpected output" } + 3 { fail "$test eof (startup)" } + 4 { fail "$test eof (shutdown)" } + 5 { fail "$test timeout (startup)" } + 6 { fail "$test timeout (startup)" } + 7 { fail "$test invalid bpf program" } + 8 { + if $errtest_p { + pass $test + } else { + fail "$test compilation" + } + } + default { fail "$test unknown return value" } + } + + if { $mypid > 0 } { + kill -INT -$mypid 3 + catch close + wait + } +} -- 2.14.5