# Marker tests.  Note that we can't really run (pass 5) marker tests,
# since we have no idea where in the kernel they are (and what would
# trigger a specific marker).  So, we'll try to compile lots of tests
# to do as much as we can.

# Initialize variables
set kernel_markers_found 0
set kernel_marker_names {}
set kernel_marker_formats {}

set num_marker_found 0
set num_marker_name ""

set kernel_script {"probe kernel.mark(\"%s\") { }"}
set kernel_script_arg {"probe kernel.mark(\"%s\") { print(%s) print_backtrace() }"}
set kernel_script_arg2 {"probe kernel.mark(\"%s\") { %s = 0 }"}
set kernel_script_arg3 {"probe kernel.mark(\"%s\") { print(\$arg1%s) }"}
set kernel_format_script {"probe kernel.mark(\"%s\").format(\"%s\") { }"}

# Try to read in the marker list from the Module.markers file.
set uname [exec /bin/uname -r]
set path "/lib/modules/$uname/build/Module.markers"
if {! [catch {open $path RDONLY} fl]} {
    while {[gets $fl s] >= 0} {
	# This regexp only picks up markers that contain arguments.
	# This helps ensure that K_MARKER04 passes correctly.
	if [regexp {^([^ \t]+)\t[^ \t]+\t(.*%.+)$} $s match name fmt] {
	    set kernel_markers_found 1
	    lappend kernel_marker_names $name
	    lappend kernel_marker_formats $fmt
	    
	    # Look for a marker whose first argument is numeric
	    # (either '%d', '%u', or '%p').  If we find such a marker,
	    # we can run K_MARKER09, K_MARKER10, etc.
	    if {$num_marker_found == 0 && [regexp {^[^%]*%[dup]} $fmt]} {
		set num_marker_found 1
		set num_marker_name $name
	    }
	}
    }
    catch {close $fl}
}

#
# Do some marker tests.
#

set TEST_NAME "K_MARKER01"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that probes all kernel markers using a
    # wildcard.
    set script [format $kernel_script "*"]
    stap_compile $TEST_NAME 1 $script -u
}

set TEST_NAME "K_MARKER02"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that probes the first kernel marker
    # found.
    set script [format $kernel_script [lindex $kernel_marker_names 0]]
    stap_compile $TEST_NAME 1 $script
}

# We can go ahead and try this test even if the kernel doesn't have
# marker support, since we're probing a marker that doesn't exist.
set TEST_NAME "K_MARKER03"
# Try compiling a script that probes a kernel marker that doesn't
# exist.
set script [format $kernel_script "X_marker_that_does_not_exist_X"]
stap_compile $TEST_NAME 0 $script

set TEST_NAME "K_MARKER04"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that prints the first argument of a
    # marker.  This one might fail if the marker we pick doesn't have
    # any arguments (but hopefully our kernel marker list only
    # contains markers that have at least one argument).
    set script [format $kernel_script_arg \
		    [lindex $kernel_marker_names 0] {\$arg1}]
    stap_compile $TEST_NAME 1 $script
}

set TEST_NAME "K_MARKER05"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that prints an marker argument that
    # doesn't exist.  This one might fail if the marker we pick
    # has a 200th argument (which isn't likely).
    set script [format $kernel_script_arg \
		    [lindex $kernel_marker_names 0] {\$arg200}]
    stap_compile $TEST_NAME 0 $script
}

set TEST_NAME "K_MARKER06"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that prints marker argument $arg0
    # (which doesn't exist).
    set script [format $kernel_script_arg \
		    [lindex $kernel_marker_names 0] {\$arg0}]
    stap_compile $TEST_NAME 0 $script
}

set TEST_NAME "K_MARKER07"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that prints marker argument $foo1 (which
    # doesn't exist).
    set script [format $kernel_script_arg \
		    [lindex $kernel_marker_names 0] {\$foo1}]
    stap_compile $TEST_NAME 0 $script
}

set TEST_NAME "K_MARKER08"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that writes to marker argument $arg1 (which
    # isn't allowed).
    set script [format $kernel_script_arg2 \
		    [lindex $kernel_marker_names 0] {\$arg1}]
    stap_compile $TEST_NAME 0 $script
}

set TEST_NAME "K_MARKER09"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} elseif {$num_marker_found == 0} {
    untested "$TEST_NAME : no kernel marker found with a numeric first argument"
} else {
    # Try compiling a script that treats its first marker argument
    # as a structure (which isn't allowed).
    set script [format $kernel_script_arg3 $num_marker_name "->foo"]
    stap_compile $TEST_NAME 0 $script
}

set TEST_NAME "K_MARKER10"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} elseif {$num_marker_found == 0} {
    untested "$TEST_NAME : no kernel marker found with a numeric first argument"
} else {
    # Try compiling a script that treats its first marker argument
    # like an array (which isn't allowed).
    set script [format $kernel_script_arg3 $num_marker_name {\[0\]}]
    stap_compile $TEST_NAME 0 $script
}

set TEST_NAME "K_MARKER11"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that prints the format string of a
    # marker.
    set script [format $kernel_script_arg \
		    [lindex $kernel_marker_names 0] {\$format}]
    stap_compile $TEST_NAME 1 $script
}

set TEST_NAME "K_MARKER12"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that writes to a marker format string
    # (which isn't allowed).
    set script [format $kernel_script_arg2 \
		    [lindex $kernel_marker_names 0] {\$format}]
    stap_compile $TEST_NAME 0 $script
}

set TEST_NAME "K_MARKER13"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that treats the marker format string as a
    # structure (which isn't allowed).
    set script [format $kernel_script_arg \
		    [lindex $kernel_marker_names 0] {\$format->foo}]
    stap_compile $TEST_NAME 0 $script
}

set TEST_NAME "K_MARKER14"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that treats the marker format string like
    # an array (which isn't allowed).
    set script [format $kernel_script_arg \
		    [lindex $kernel_marker_names 0] {\$format\[0\]}]
    stap_compile $TEST_NAME 0 $script
}

set TEST_NAME "K_MARKER15"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that specifies the marker format as a
    # wildcard.
    set script [format $kernel_format_script \
		    [lindex $kernel_marker_names 0] "*"]
    stap_compile $TEST_NAME 1 $script
}

set TEST_NAME "K_MARKER16"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that specifies the marker format.
    set script [format $kernel_format_script \
		    [lindex $kernel_marker_names 0] \
		    [lindex $kernel_marker_formats 0]]
    stap_compile $TEST_NAME 1 $script
}

set TEST_NAME "K_MARKER17"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that specifies the wrong marker format.
    set script [format $kernel_format_script \
		    [lindex $kernel_marker_names 0] "foo"]
    stap_compile $TEST_NAME 0 $script
}

set TEST_NAME "K_MARKER18"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that prints the name string of a
    # marker.
    set script [format $kernel_script_arg \
		    [lindex $kernel_marker_names 0] {\$name}]
    stap_compile $TEST_NAME 1 $script
}

set TEST_NAME "K_MARKER19"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that writes to a marker name string
    # (which isn't allowed).
    set script [format $kernel_script_arg2 \
		    [lindex $kernel_marker_names 0] {\$name}]
    stap_compile $TEST_NAME 0 $script
}

set TEST_NAME "K_MARKER20"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that treats the marker name string as a
    # structure (which isn't allowed).
    set script [format $kernel_script_arg \
		    [lindex $kernel_marker_names 0] {\$name->foo}]
    stap_compile $TEST_NAME 0 $script
}

set TEST_NAME "K_MARKER21"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that treats the marker name string like
    # an array (which isn't allowed).
    set script [format $kernel_script_arg \
		    [lindex $kernel_marker_names 0] {\$name\[0\]}]
    stap_compile $TEST_NAME 0 $script
}

set TEST_NAME "K_MARKER22"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that print $$parms.
    set script_vars {"probe kernel.mark(\"*\") { printf(\"%s\",\$\$parms) }"}
    stap_compile $TEST_NAME 1 $script_vars
}

set TEST_NAME "K_MARKER23"
if {$kernel_markers_found == 0} {
    untested "$TEST_NAME : no kernel markers present"
} else {
    # Try compiling a script that print $$vars.
    set script_parms {"probe kernel.mark(\"*\") { printf(\"%s\",\$\$vars) }"}
    stap_compile $TEST_NAME 1 $script_parms
}
