# Script for testing $$vars, $$parms, $$locals # # This works by grep'ing for the format strings produced in pass-3, then # comparing that $$vars is the same as $$parms + $$locals. # # NB: With PR3217 compiled-printf code, we can't tell as easily what was # generated. However, there's still the ifdef'ed STP_LEGACY_PRINT code which # has the format string we care about here. If that ever goes away, we'll # probably have to fall back to comparing pass-2 output instead. # # NB2: We FAIL if any of the functions tested have no locals or no # params to ensure we're not testing a null hypothesis. set test "vars" proc get_listings { probe_point } { if {![catch {exec stap -l ${probe_point} 2>@1} output]} { return [split $output "\n"] } } proc parse_lineno { function line } { if {[regexp "\[^:\]+:(\[0-9\]+)\"" $line dummy submatch]} { verbose -log "parsed lineno $submatch in line $line" return $submatch } else { verbose -log "can't parse lineno in $line" return 0 } } proc func_exists { function } { set probe_point "kernel.function\(\"$function\"\)" set line [get_listings $probe_point] if {$line == ""} { return 0 } else { return 1 } } proc get_first_valid_lineno { function } { set linenos "" set probe_point "kernel.statement\(\"$function:*\"\)" set line [lindex [get_listings $probe_point] 0] return [parse_lineno $function $line] } proc grab_C_statements { probe_point type } { set cmd [concat stap -p3 -e { "probe kernel.statement(\"$probe_point\") {print (\$\$$type)}" } \ | grep {"_stp_snprintf.*="} \ | head -n 1 \ | sed -e {"s/^.*MAXSTRINGLEN, \"//"} -e "s/\".*$//"] catch {eval exec $cmd} out if {$out == ""} { error "no output for $type" } else { verbose -log "output for $type: $out" } return $out } proc get_vars { probe_point } { set vars [grab_C_statements $probe_point vars] # syntax check of $$vars c statement set syntax_ok [regexp "(\[a-z_\]+=%#llx *)+" $vars] if {!$syntax_ok} { error "bad vars syntax" verbose -log "vars is $vars" } return $vars } proc get_parms { probe_point } { return [grab_C_statements $probe_point parms] } proc get_locals { probe_point } { return [grab_C_statements $probe_point locals] } proc test_function { function } { global test set subtest "$test - $function" if {! [func_exists $function]} { untested "$subtest - doesn't exist" return } set lineno [get_first_valid_lineno $function] if {$lineno == 0} { fail "$subtest (no first lineno)" return } else { pass "$subtest (first lineno is $lineno)" } if {[catch { set probe_point "$function:$lineno" set vars [get_vars $probe_point] set parms [get_parms $probe_point] set locals [get_locals $probe_point] } err]} { fail "$subtest ($err)" return } else { pass "$subtest" } # $$vars should be equivalent to $$parms + $$locals if {![string equal $vars "$parms $locals"]} { fail "$subtest (parms/locals)" verbose -log "vars=$vars=" verbose -log "rest=$parms $locals=" } else { pass "$subtest (parms/locals)" } } # Test a few different functions test_function {bio_copy_user@*/bio.c} test_function {bio_copy_user_iov@*/bio.c} test_function {vfs_read@fs/read_write.c}