Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,3 @@
#!/bin/sh
# description: Basic trace file check
test -f README -a -f trace -a -f tracing_on -a -f trace_pipe
@@ -0,0 +1,9 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Basic test for tracers
# flags: instance
test -f available_tracers
for t in `cat available_tracers`; do
echo $t > current_tracer
done
echo nop > current_tracer
@@ -0,0 +1,10 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Basic trace clock test
# flags: instance
test -f trace_clock
for c in `cat trace_clock | tr -d \[\]`; do
echo $c > trace_clock
grep '\['$c'\]' trace_clock
done
echo local > trace_clock
@@ -0,0 +1,5 @@
#!/bin/sh
# description: Basic event tracing check
test -f available_events -a -f set_event -a -d events
# check scheduler events are available
grep -q sched available_events && exit_pass || exit_fail
@@ -0,0 +1,101 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test tracefs GID mount option
# requires: "[gid=<gid>]":README
fail() {
local msg="$1"
echo "FAILED: $msg"
exit_fail
}
find_alternate_gid() {
local original_gid="$1"
tac /etc/group | grep -v ":$original_gid:" | head -1 | cut -d: -f3
}
remount_tracefs_with_options() {
local mount_point="$1"
local options="$2"
mount -t tracefs -o "remount,$options" nodev "$mount_point"
setup
}
unmount_tracefs() {
local mount_point="$1"
# Need to make sure the mount isn't busy so that we can umount it
(cd $mount_point; finish_system;)
cleanup
}
create_instance() {
local mount_point="$1"
local instance="$mount_point/instances/$(mktemp -u test-XXXXXX)"
mkdir "$instance"
echo "$instance"
}
remove_instance() {
local instance="$1"
rmdir "$instance"
}
check_gid() {
local mount_point="$1"
local expected_gid="$2"
echo "Checking permission group ..."
cd "$mount_point"
for file in "." "events" "events/sched" "events/sched/sched_switch" "events/sched/sched_switch/enable"; do
local gid=`stat -c "%g" $file`
if [ "$gid" -ne "$expected_gid" ]; then
cd - # Return to the previous working directory (tracefs root)
fail "$(realpath $file): Expected group $expected_gid; Got group $gid"
fi
done
cd - # Return to the previous working directory (tracefs root)
}
test_gid_mount_option() {
local mount_point=$(get_mount_point)
local mount_options=$(get_mnt_options "$mount_point")
local original_group=$(stat -c "%g" .)
local other_group=$(find_alternate_gid "$original_group")
# Set up mount options with new GID for testing
local new_options=`echo "$mount_options" | sed -e "s/gid=[0-9]*/gid=$other_group/"`
if [ "$new_options" = "$mount_options" ]; then
new_options="$mount_options,gid=$other_group"
mount_options="$mount_options,gid=$original_group"
fi
# Unmount existing tracefs instance and mount with new GID
unmount_tracefs "$mount_point"
remount_tracefs_with_options "$mount_point" "$new_options"
check_gid "$mount_point" "$other_group"
# Check that files created after the mount inherit the GID
local instance=$(create_instance "$mount_point")
check_gid "$instance" "$other_group"
remove_instance "$instance"
# Unmount and remount with the original GID
unmount_tracefs "$mount_point"
remount_tracefs_with_options "$mount_point" "$mount_options"
check_gid "$mount_point" "$original_group"
}
test_gid_mount_option
exit 0
@@ -0,0 +1,22 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Change the ringbuffer size
# flags: instance
rb_size_test() {
ORIG=`cat buffer_size_kb`
expr $ORIG / 2 > buffer_size_kb
expr $ORIG \* 2 > buffer_size_kb
echo $ORIG > buffer_size_kb
}
rb_size_test
: "If per-cpu buffer is supported, imbalance it"
if [ -d per_cpu/cpu0 ]; then
cd per_cpu/cpu0
rb_size_test
fi
@@ -0,0 +1,95 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Change the ringbuffer sub-buffer size
# requires: buffer_subbuf_size_kb
# flags: instance
get_buffer_data_size() {
sed -ne 's/^.*data.*size:\([0-9][0-9]*\).*/\1/p' events/header_page
}
get_buffer_data_offset() {
sed -ne 's/^.*data.*offset:\([0-9][0-9]*\).*/\1/p' events/header_page
}
get_event_header_size() {
type_len=`sed -ne 's/^.*type_len.*:[^0-9]*\([0-9][0-9]*\).*/\1/p' events/header_event`
time_len=`sed -ne 's/^.*time_delta.*:[^0-9]*\([0-9][0-9]*\).*/\1/p' events/header_event`
array_len=`sed -ne 's/^.*array.*:[^0-9]*\([0-9][0-9]*\).*/\1/p' events/header_event`
total_bits=$((type_len+time_len+array_len))
total_bits=$((total_bits+7))
echo $((total_bits/8))
}
get_print_event_buf_offset() {
sed -ne 's/^.*buf.*offset:\([0-9][0-9]*\).*/\1/p' events/ftrace/print/format
}
event_header_size=`get_event_header_size`
print_header_size=`get_print_event_buf_offset`
data_offset=`get_buffer_data_offset`
marker_meta=$((event_header_size+print_header_size))
make_str() {
cnt=$1
printf -- 'X%.0s' $(seq $cnt)
}
write_buffer() {
size=$1
str=`make_str $size`
# clear the buffer
echo > trace
# write the string into the marker
echo $str > trace_marker
echo $str
}
test_buffer() {
size_kb=$1
page_size=$((size_kb*1024))
size=`get_buffer_data_size`
# the size must be greater than or equal to page_size - data_offset
page_size=$((page_size-data_offset))
if [ $size -lt $page_size ]; then
exit fail
fi
# Now add a little more the meta data overhead will overflow
str=`write_buffer $size`
# Make sure the line was broken
new_str=`awk ' /tracing_mark_write:/ { sub(/^.*tracing_mark_write: /,"");printf "%s", $0; exit}' trace`
if [ "$new_str" = "$str" ]; then
exit fail;
fi
# Make sure the entire line can be found
new_str=`awk ' /tracing_mark_write:/ { sub(/^.*tracing_mark_write: /,"");printf "%s", $0; }' trace`
if [ "$new_str" != "$str" ]; then
exit fail;
fi
}
ORIG=`cat buffer_subbuf_size_kb`
# Could test bigger sizes than 32K, but then creating the string
# to write into the ring buffer takes too long
for a in 4 8 16 32 ; do
echo $a > buffer_subbuf_size_kb
test_buffer $a
done
echo $ORIG > buffer_subbuf_size_kb
@@ -0,0 +1,27 @@
#!/bin/sh
# description: Snapshot and tracing setting
# requires: snapshot
# flags: instance
echo "Set tracing off"
echo 0 > tracing_on
echo "Allocate and take a snapshot"
echo 1 > snapshot
# Since trace buffer is empty, snapshot is also empty, but allocated
grep -q "Snapshot is allocated" snapshot
echo "Ensure keep tracing off"
test `cat tracing_on` -eq 0
echo "Set tracing on"
echo 1 > tracing_on
echo "Take a snapshot again"
echo 1 > snapshot
echo "Ensure keep tracing on"
test `cat tracing_on` -eq 1
exit 0
@@ -0,0 +1,31 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Snapshot and tracing_cpumask
# requires: trace_marker tracing_cpumask snapshot
# flags: instance
# This testcase is constrived to reproduce a problem that the cpu buffers
# become unavailable which is due to 'record_disabled' of array_buffer and
# max_buffer being messed up.
# Store origin cpumask
ORIG_CPUMASK=`cat tracing_cpumask`
# Stop tracing all cpu
echo 0 > tracing_cpumask
# Take a snapshot of the main buffer
echo 1 > snapshot
# Restore origin cpumask, note that there should be some cpus being traced
echo ${ORIG_CPUMASK} > tracing_cpumask
# Set tracing on
echo 1 > tracing_on
# Write a log into buffer
echo "test input 1" > trace_marker
# Ensure the log writed so that cpu buffers are still available
grep -q "test input 1" trace
exit 0
@@ -0,0 +1,122 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test file and directory ownership changes for eventfs
# requires: "[gid=<gid>]":README
original_group=`stat -c "%g" .`
original_owner=`stat -c "%u" .`
mount_point=$(get_mount_point)
mount_options=$(get_mnt_options "$mount_point")
# find another owner and group that is not the original
other_group=`tac /etc/group | grep -v ":$original_group:" | head -1 | cut -d: -f3`
other_owner=`tac /etc/passwd | grep -v ":$original_owner:" | head -1 | cut -d: -f3`
# Remove any group ownership already
new_options=`echo "$mount_options" | sed -e "s/gid=[0-9]*/gid=$other_group/"`
if [ "$new_options" = "$mount_options" ]; then
new_options="$mount_options,gid=$other_group"
mount_options="$mount_options,gid=$original_group"
fi
canary="events/timer events/timer/timer_cancel events/timer/timer_cancel/format"
test() {
file=$1
test_group=$2
owner=`stat -c "%u" $file`
group=`stat -c "%g" $file`
echo "testing $file $owner=$original_owner and $group=$test_group"
if [ $owner -ne $original_owner ]; then
exit_fail
fi
if [ $group -ne $test_group ]; then
exit_fail
fi
# Note, the remount does not update ownership so test going to and from owner
echo "test owner $file to $other_owner"
chown $other_owner $file
owner=`stat -c "%u" $file`
if [ $owner -ne $other_owner ]; then
exit_fail
fi
chown $original_owner $file
owner=`stat -c "%u" $file`
if [ $owner -ne $original_owner ]; then
exit_fail
fi
}
run_tests() {
for d in "." "events" "events/sched" "events/sched/sched_switch" "events/sched/sched_switch/enable" $canary; do
test "$d" $other_group
done
chgrp $original_group events
test "events" $original_group
for d in "." "events/sched" "events/sched/sched_switch" "events/sched/sched_switch/enable" $canary; do
test "$d" $other_group
done
chgrp $original_group events/sched
test "events/sched" $original_group
for d in "." "events/sched/sched_switch" "events/sched/sched_switch/enable" $canary; do
test "$d" $other_group
done
chgrp $original_group events/sched/sched_switch
test "events/sched/sched_switch" $original_group
for d in "." "events/sched/sched_switch/enable" $canary; do
test "$d" $other_group
done
chgrp $original_group events/sched/sched_switch/enable
test "events/sched/sched_switch/enable" $original_group
for d in "." $canary; do
test "$d" $other_group
done
}
# Run the tests twice as leftovers can cause issues
for loop in 1 2 ; do
echo "Running iteration $loop"
mount -o remount,"$new_options" .
run_tests
mount -o remount,"$mount_options" .
for d in "." "events" "events/sched" "events/sched/sched_switch" "events/sched/sched_switch/enable" $canary; do
test "$d" $original_group
done
# check instances as well
chgrp $other_group instances
instance="$(mktemp -u test-XXXXXX)"
mkdir instances/$instance
cd instances/$instance
run_tests
cd ../..
rmdir instances/$instance
chgrp $original_group instances
done
exit 0
@@ -0,0 +1,82 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Basic tests on writing to trace_marker
# requires: trace_marker
# flags: instance
get_buffer_data_size() {
sed -ne 's/^.*data.*size:\([0-9][0-9]*\).*/\1/p' events/header_page
}
get_buffer_data_offset() {
sed -ne 's/^.*data.*offset:\([0-9][0-9]*\).*/\1/p' events/header_page
}
get_event_header_size() {
type_len=`sed -ne 's/^.*type_len.*:[^0-9]*\([0-9][0-9]*\).*/\1/p' events/header_event`
time_len=`sed -ne 's/^.*time_delta.*:[^0-9]*\([0-9][0-9]*\).*/\1/p' events/header_event`
array_len=`sed -ne 's/^.*array.*:[^0-9]*\([0-9][0-9]*\).*/\1/p' events/header_event`
total_bits=$((type_len+time_len+array_len))
total_bits=$((total_bits+7))
echo $((total_bits/8))
}
get_print_event_buf_offset() {
sed -ne 's/^.*buf.*offset:\([0-9][0-9]*\).*/\1/p' events/ftrace/print/format
}
event_header_size=`get_event_header_size`
print_header_size=`get_print_event_buf_offset`
data_offset=`get_buffer_data_offset`
marker_meta=$((event_header_size+print_header_size))
make_str() {
cnt=$1
# subtract two for \n\0 as marker adds these
cnt=$((cnt-2))
printf -- 'X%.0s' $(seq $cnt)
}
write_buffer() {
size=$1
str=`make_str $size`
# clear the buffer
echo > trace
# write the string into the marker
echo -n $str > trace_marker
echo $str
}
test_buffer() {
size=`get_buffer_data_size`
oneline_size=$((size-marker_meta))
echo size = $size
echo meta size = $marker_meta
# Now add a little more the meta data overhead will overflow
str=`write_buffer $size`
# Make sure the line was broken
new_str=`awk ' /tracing_mark_write:/ { sub(/^.*tracing_mark_write: /,"");printf "%s", $0; exit}' trace`
if [ "$new_str" = "$str" ]; then
exit fail;
fi
# Make sure the entire line can be found
new_str=`awk ' /tracing_mark_write:/ { sub(/^.*tracing_mark_write: /,"");printf "%s", $0; }' trace`
if [ "$new_str" != "$str" ]; then
exit fail;
fi
}
test_buffer
@@ -0,0 +1,133 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Basic tests on writing to trace_marker_raw
# requires: trace_marker_raw
# flags: instance
check_awk_strtonum || exit_unresolved
is_little_endian() {
if lscpu | grep -q 'Little Endian'; then
echo 1;
else
echo 0;
fi
}
little=`is_little_endian`
make_str() {
id=$1
cnt=$2
if [ $little -eq 1 ]; then
val=`printf "\\%03o\\%03o\\%03o\\%03o" \
$(($id & 0xff)) \
$((($id >> 8) & 0xff)) \
$((($id >> 16) & 0xff)) \
$((($id >> 24) & 0xff))`
else
val=`printf "\\%03o\\%03o\\%03o\\%03o" \
$((($id >> 24) & 0xff)) \
$((($id >> 16) & 0xff)) \
$((($id >> 8) & 0xff)) \
$(($id & 0xff))`
fi
data=`printf -- 'X%.0s' $(seq $cnt)`
# Return escape-sequence text (e.g. "\003\000..."); the caller
# converts to binary. Shell command substitution strips NUL bytes,
# so the binary form cannot survive being captured into a variable.
printf '%s' "${val}${data}"
}
write_buffer() {
id=$1
size=$2
str=`make_str $id $size`
len=`printf "$str" | wc -c`
# Pipe through dd to ensure a single atomic write() syscall
# on architectures with 64K pages, where shell's printf builtin
# uses stdio buffering which may split the output into multiple
# writes.
printf "$str" | dd of=trace_marker_raw bs=$len iflag=fullblock
}
test_multiple_writes() {
# Write a bunch of data where the id is the count of
# data to write
for i in `seq 1 10` `seq 101 110` `seq 1001 1010`; do
write_buffer $i $i
done
# add a little buffer
echo stop > trace_marker
# Check to make sure the number of entries is the id (rounded up by 4)
awk '/.*: # [0-9a-f]* / {
print;
cnt = -1;
for (i = 0; i < NF; i++) {
# The counter is after the "#" marker
if ( $i == "#" ) {
i++;
cnt = strtonum("0x" $i);
num = NF - (i + 1);
# The number of items is always rounded up by 4
cnt2 = int((cnt + 3) / 4) * 4;
if (cnt2 != num) {
exit 1;
}
break;
}
}
}
// { if (NR > 30) { exit 0; } } ' trace_pipe;
}
get_buffer_data_size() {
sed -ne 's/^.*data.*size:\([0-9][0-9]*\).*/\1/p' events/header_page
}
test_buffer() {
# The id must be four bytes, test that 3 bytes fails a write
if echo -n abc > ./trace_marker_raw ; then
echo "Too small of write expected to fail but did not"
echo ${ORIG} > buffer_size_kb
exit_fail
fi
size=`get_buffer_data_size`
echo size = $size
# Now add a little more than what it can handle
if write_buffer 0xdeadbeef $size ; then
echo "Too big of write expected to fail but did not"
echo ${ORIG} > buffer_size_kb
exit_fail
fi
}
ORIG=`cat buffer_size_kb`
# test_multiple_writes test needs at least 12KB buffer
NEW_SIZE=12
if [ ${ORIG} -lt ${NEW_SIZE} ]; then
echo ${NEW_SIZE} > buffer_size_kb
fi
test_buffer
if ! test_multiple_writes; then
echo ${ORIG} > buffer_size_kb
exit_fail
fi
echo ${ORIG} > buffer_size_kb
@@ -0,0 +1,15 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: trace_pipe and trace_marker
# requires: trace_marker
# flags: instance
echo "test input 1" > trace_marker
: "trace interface never consume the ring buffer"
grep -q "test input 1" trace
grep -q "test input 1" trace
: "trace interface never consume the ring buffer"
head -n 1 trace_pipe | grep -q "test input 1"
! grep -q "test input 1" trace
@@ -0,0 +1,69 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test ftrace direct functions against tracers
rmmod ftrace-direct ||:
if ! modprobe ftrace-direct ; then
echo "No ftrace-direct sample module - please make CONFIG_SAMPLE_FTRACE_DIRECT=m"
exit_unresolved;
fi
echo "Let the module run a little"
sleep 1
grep -q "my_direct_func: waking up" trace
rmmod ftrace-direct
test_tracer() {
tracer=$1
# tracer -> direct -> no direct > no tracer
echo $tracer > current_tracer
modprobe ftrace-direct
rmmod ftrace-direct
echo nop > current_tracer
# tracer -> direct -> no tracer > no direct
echo $tracer > current_tracer
modprobe ftrace-direct
echo nop > current_tracer
rmmod ftrace-direct
# direct -> tracer -> no tracer > no direct
modprobe ftrace-direct
echo $tracer > current_tracer
echo nop > current_tracer
rmmod ftrace-direct
# direct -> tracer -> no direct > no notracer
modprobe ftrace-direct
echo $tracer > current_tracer
rmmod ftrace-direct
echo nop > current_tracer
}
for t in `cat available_tracers`; do
if [ "$t" != "nop" ]; then
test_tracer $t
fi
done
echo nop > current_tracer
rmmod ftrace-direct ||:
# Now do the same thing with another direct function registered
echo "Running with another ftrace direct function"
rmmod ftrace-direct-too ||:
modprobe ftrace-direct-too
for t in `cat available_tracers`; do
if [ "$t" != "nop" ]; then
test_tracer $t
fi
done
echo nop > current_tracer
rmmod ftrace-direct ||:
rmmod ftrace-direct-too ||:
@@ -0,0 +1,80 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test ftrace direct functions against kprobes
# requires: kprobe_events
rmmod ftrace-direct ||:
if ! modprobe ftrace-direct ; then
echo "No ftrace-direct sample module - please build with CONFIG_SAMPLE_FTRACE_DIRECT=m"
exit_unresolved;
fi
echo "Let the module run a little"
sleep 1
grep -q "my_direct_func: waking up" trace
rmmod ftrace-direct
echo 'p:kwake wake_up_process task=$arg1' > kprobe_events
start_direct() {
echo > trace
modprobe ftrace-direct
sleep 1
grep -q "my_direct_func: waking up" trace
}
stop_direct() {
rmmod ftrace-direct
}
enable_probe() {
echo > trace
echo 1 > events/kprobes/kwake/enable
sleep 1
grep -q "kwake:" trace
}
disable_probe() {
echo 0 > events/kprobes/kwake/enable
}
test_kprobes() {
# probe -> direct -> no direct > no probe
enable_probe
start_direct
stop_direct
disable_probe
# probe -> direct -> no probe > no direct
enable_probe
start_direct
disable_probe
stop_direct
# direct -> probe -> no probe > no direct
start_direct
enable_probe
disable_probe
stop_direct
# direct -> probe -> no direct > no noprobe
start_direct
enable_probe
stop_direct
disable_probe
}
test_kprobes
# Now do this with a second registered direct function
echo "Running with another ftrace direct function"
modprobe ftrace-direct-too
test_kprobes
rmmod ftrace-direct-too
echo > kprobe_events
@@ -0,0 +1,78 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - add/remove probes with BTF arguments
# requires: dynamic_events "<argname>":README
KPROBES=
FPROBES=
FIELDS=
if grep -qF "p[:[<group>/][<event>]] <place> [<args>]" README ; then
KPROBES=yes
fi
if grep -qF "f[:[<group>/][<event>]] <func-name>[%return] [<args>]" README ; then
FPROBES=yes
fi
if grep -qF "<argname>[->field[->field|.field...]]" README ; then
FIELDS=yes
fi
if [ -z "$KPROBES" -a -z "$FPROBES" ] ; then
exit_unsupported
fi
echo 0 > events/enable
echo > dynamic_events
TP=kfree
TP2=kmem_cache_alloc
TP3=getname_flags
TP4=sched_wakeup
if [ "$FPROBES" ] ; then
echo "f:fpevent $TP object" >> dynamic_events
echo "t:tpevent $TP ptr" >> dynamic_events
grep -q "fpevent.*object=object" dynamic_events
grep -q "tpevent.*ptr=ptr" dynamic_events
echo > dynamic_events
echo "f:fpevent $TP "'$arg1' >> dynamic_events
grep -q "fpevent.*object=object" dynamic_events
echo > dynamic_events
echo "f:fpevent $TP "'$arg*' >> dynamic_events
echo "t:tpevent $TP "'$arg*' >> dynamic_events
grep -q "fpevent.*object=object" dynamic_events
grep -q "tpevent.*ptr=ptr" dynamic_events
! grep -q "tpevent.*_data" dynamic_events
fi
echo > dynamic_events
if [ "$FIELDS" -a "$FPROBES" ] ; then
echo "t:tpevent ${TP2} obj_size=s->object_size" >> dynamic_events
echo "f:fpevent ${TP3}%return path=\$retval->name:string" >> dynamic_events
echo "t:tpevent2 ${TP4} p->se.group_node.next->prev" >> dynamic_events
grep -q "tpevent .*obj_size=s->object_size" dynamic_events
grep -q "fpevent.*path=\$retval->name:string" dynamic_events
grep -q 'tpevent2 .*p->se.group_node.next->prev' dynamic_events
echo > dynamic_events
fi
if [ "$KPROBES" ] ; then
echo "p:kpevent $TP object" >> dynamic_events
grep -q "kpevent.*object=object" dynamic_events
echo > dynamic_events
echo "p:kpevent $TP "'$arg*' >> dynamic_events
grep -q "kpevent.*object=object" dynamic_events
fi
clear_trace
@@ -0,0 +1,91 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - add/remove eprobe events
# requires: dynamic_events events/syscalls/sys_enter_chdir "<attached-group>.<attached-event> [<args>]":README
echo 0 > events/enable
clear_dynamic_events
SYSTEM="syscalls"
EVENT="sys_enter_chdir"
FIELD="filename"
EPROBE="eprobe_chdir"
OPTIONS="file=+0(\$filename):ustring"
echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
grep -q "$EPROBE" dynamic_events
test -d events/eprobes/$EPROBE
echo 1 > events/eprobes/$EPROBE/enable
cd /sys/kernel/tracing
echo 0 > events/eprobes/$EPROBE/enable
content=`grep -e 'file="/sys/kernel/tracing"\|(fault)' trace`
if [ -z "$content" ]; then
exit_fail
fi
echo "-:$EPROBE" >> dynamic_events
! grep -q "$EPROBE" dynamic_events
! test -d events/eprobes/$EPROBE
# test various ways to remove the probe (already tested with just event name)
# With group name
echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
grep -q "$EPROBE" dynamic_events
test -d events/eprobes/$EPROBE
echo "-:eprobes/$EPROBE" >> dynamic_events
! grep -q "$EPROBE" dynamic_events
! test -d events/eprobes/$EPROBE
# With group name and system/event
echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
grep -q "$EPROBE" dynamic_events
test -d events/eprobes/$EPROBE
echo "-:eprobes/$EPROBE $SYSTEM/$EVENT" >> dynamic_events
! grep -q "$EPROBE" dynamic_events
! test -d events/eprobes/$EPROBE
# With just event name and system/event
echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
grep -q "$EPROBE" dynamic_events
test -d events/eprobes/$EPROBE
echo "-:$EPROBE $SYSTEM/$EVENT" >> dynamic_events
! grep -q "$EPROBE" dynamic_events
! test -d events/eprobes/$EPROBE
# With just event name and system/event and options
echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
grep -q "$EPROBE" dynamic_events
test -d events/eprobes/$EPROBE
echo "-:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
! grep -q "$EPROBE" dynamic_events
! test -d events/eprobes/$EPROBE
# With group name and system/event and options
echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
grep -q "$EPROBE" dynamic_events
test -d events/eprobes/$EPROBE
echo "-:eprobes/$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
! grep -q "$EPROBE" dynamic_events
! test -d events/eprobes/$EPROBE
# Finally make sure what is in the dynamic_events file clears it too
echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
LINE=`sed -e '/$EPROBE/s/^e/-/' < dynamic_events`
test -d events/eprobes/$EPROBE
echo "-:eprobes/$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
! grep -q "$EPROBE" dynamic_events
! test -d events/eprobes/$EPROBE
if grep -q "e\[:\[<group>/]\[<event>]]" README; then
echo "e:mygroup/ $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
test -d events/mygroup
echo "-:mygroup/" >> dynamic_events
! test -d events/mygroup
fi
clear_trace
@@ -0,0 +1,82 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - add/remove fprobe events
# requires: dynamic_events "f[:[<group>/][<event>]] <func-name>[%return] [<args>]":README
echo 0 > events/enable
echo > dynamic_events
PLACE=$FUNCTION_FORK
PLACE2="kmem_cache_free"
PLACE3="schedule_timeout"
# Some functions may have BPF programs attached, therefore
# count already enabled_functions before tests start
ocnt=`cat enabled_functions | wc -l`
echo "f:myevent1 $PLACE" >> dynamic_events
echo "f:myevent2 $PLACE%return" >> dynamic_events
# add another event
echo "f:myevent3 $PLACE2" >> dynamic_events
grep -q myevent1 dynamic_events
grep -q myevent2 dynamic_events
grep -q myevent3 dynamic_events
test -d events/fprobes/myevent1
test -d events/fprobes/myevent2
echo 1 > events/fprobes/myevent1/enable
# Make sure the event is attached.
grep -q $PLACE enabled_functions
cnt=`cat enabled_functions | wc -l`
if [ $cnt -eq $ocnt ]; then
exit_fail
fi
echo 1 > events/fprobes/myevent2/enable
cnt2=`cat enabled_functions | wc -l`
echo 1 > events/fprobes/myevent3/enable
# If the function is different, the attached function should be increased
grep -q $PLACE2 enabled_functions
cnt=`cat enabled_functions | wc -l`
if [ $cnt -eq $cnt2 ]; then
exit_fail
fi
echo 0 > events/fprobes/myevent2/enable
echo "-:myevent2" >> dynamic_events
grep -q myevent1 dynamic_events
! grep -q myevent2 dynamic_events
echo 0 > events/fprobes/enable
echo > dynamic_events
# Should have none left
cnt=`cat enabled_functions | wc -l`
if [ $cnt -ne $ocnt ]; then
exit_fail
fi
echo "f:myevent4 $PLACE" >> dynamic_events
echo 1 > events/fprobes/myevent4/enable
# Should only have one enabled
cnt=`cat enabled_functions | wc -l`
if [ $cnt -ne $((ocnt + 1)) ]; then
exit_fail
fi
echo 0 > events/fprobes/enable
echo > dynamic_events
# Should have none left
cnt=`cat enabled_functions | wc -l`
if [ $cnt -ne $ocnt ]; then
exit_fail
fi
clear_trace
@@ -0,0 +1,96 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - add/remove fprobe events on module
# requires: dynamic_events "f[:[<group>/][<event>]] <func-name>[%return] [<args>]":README enabled_functions
rmmod trace-events-sample ||:
if ! modprobe trace-events-sample ; then
echo "No trace-events sample module - please make CONFIG_SAMPLE_TRACE_EVENTS=m"
exit_unresolved;
fi
trap "lsmod | grep -q trace_events_sample && rmmod trace-events-sample" EXIT
echo 0 > events/enable
echo > dynamic_events
FUNC1='foo_bar*'
FUNC2='vfs_read'
:;: "Save enabled functions count" ;:
ecount=`cat enabled_functions | wc -l`
count_enabled_functions() {
count=`cat enabled_functions | wc -l`
count=$(($count-$ecount))
echo $count
}
:;: "Add an event on the test module" ;:
echo "f:test1 $FUNC1" >> dynamic_events
echo 1 > events/fprobes/test1/enable
:;: "Ensure it is enabled" ;:
funcs=`count_enabled_functions`
test $funcs -ne 0
:;: "Check the enabled_functions is cleared on unloading" ;:
rmmod trace-events-sample
funcs=`count_enabled_functions`
test $funcs -eq 0
:;: "Check it is kept clean" ;:
modprobe trace-events-sample
echo 1 > events/fprobes/test1/enable || echo "OK"
funcs=`count_enabled_functions`
test $funcs -eq 0
:;: "Add another event not on the test module" ;:
echo "f:test2 $FUNC2" >> dynamic_events
echo 1 > events/fprobes/test2/enable
:;: "Ensure it is enabled" ;:
ofuncs=`count_enabled_functions`
test $ofuncs -ne 0
:;: "Disable and remove the first event"
echo 0 > events/fprobes/test1/enable
echo "-:fprobes/test1" >> dynamic_events
funcs=`count_enabled_functions`
test $ofuncs -eq $funcs
:;: "Disable and remove other events" ;:
echo 0 > events/fprobes/enable
echo > dynamic_events
funcs=`count_enabled_functions`
test $funcs -eq 0
rmmod trace-events-sample
:;: "Add events on kernel and test module" ;:
modprobe trace-events-sample
echo "f:test1 $FUNC1" >> dynamic_events
echo 1 > events/fprobes/test1/enable
echo "f:test2 $FUNC2" >> dynamic_events
echo 1 > events/fprobes/test2/enable
ofuncs=`count_enabled_functions`
test $ofuncs -ne 0
:;: "Unload module (ftrace entry should be removed)" ;:
rmmod trace-events-sample
funcs=`count_enabled_functions`
test $funcs -ne 0
test $ofuncs -ne $funcs
:;: "Disable and remove core-kernel fprobe event" ;:
echo 0 > events/fprobes/test2/enable
echo "-:fprobes/test2" >> dynamic_events
:;: "Ensure ftrace is disabled." ;:
funcs=`count_enabled_functions`
test $funcs -eq 0
echo 0 > events/fprobes/enable
echo > dynamic_events
trap "" EXIT
clear_trace
@@ -0,0 +1,19 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - Repeating add/remove fprobe events
# requires: dynamic_events "f[:[<group>/][<event>]] <func-name>[%return] [<args>]":README
echo 0 > events/enable
echo > dynamic_events
PLACE=$FUNCTION_FORK
REPEAT_TIMES=64
for i in `seq 1 $REPEAT_TIMES`; do
echo "f:myevent $PLACE" >> dynamic_events
grep -q myevent dynamic_events
test -d events/fprobes/myevent
echo > dynamic_events
done
clear_trace
@@ -0,0 +1,33 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - add/remove kprobe events
# requires: dynamic_events "place: [<module>:]<symbol>":README "place (kretprobe): [<module>:]<symbol>":README
echo 0 > events/enable
echo > dynamic_events
PLACE=$FUNCTION_FORK
echo "p:myevent1 $PLACE" >> dynamic_events
echo "r:myevent2 $PLACE" >> dynamic_events
grep -q myevent1 dynamic_events
grep -q myevent2 dynamic_events
test -d events/kprobes/myevent1
test -d events/kprobes/myevent2
echo "-:myevent2" >> dynamic_events
grep -q myevent1 dynamic_events
! grep -q myevent2 dynamic_events
echo > dynamic_events
if grep -q "p\[:\[<group>/]\[<event>]]" README; then
echo "p:mygroup/ $PLACE" >> dynamic_events
test -d events/mygroup
echo "-:mygroup/" >> dynamic_events
! test -d events/mygroup
fi
clear_trace
@@ -0,0 +1,69 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - add/remove multiple fprobe events on the same function
# requires: dynamic_events "f[:[<group>/][<event>]] <func-name>[%return] [<args>]":README enabled_functions
echo 0 > events/enable
echo > dynamic_events
PLACE=vfs_read
PLACE2=vfs_open
:;: 'Ensure no other ftrace user' ;:
test `cat enabled_functions | wc -l` -eq 0 || exit_unresolved
:;: 'Test case 1: leave entry event' ;:
:;: 'Add entry and exit events on the same place' ;:
echo "f:event1 ${PLACE}" >> dynamic_events
echo "f:event2 ${PLACE}%return" >> dynamic_events
:;: 'Enable both of them' ;:
echo 1 > events/fprobes/enable
test `cat enabled_functions | wc -l` -eq 1
:;: 'Disable and remove exit event' ;:
echo 0 > events/fprobes/event2/enable
echo -:event2 >> dynamic_events
:;: 'Disable and remove all events' ;:
echo 0 > events/fprobes/enable
echo > dynamic_events
:;: 'Add another event' ;:
echo "f:event3 ${PLACE2}%return" > dynamic_events
echo 1 > events/fprobes/enable
test `cat enabled_functions | wc -l` -eq 1
:;: 'No other ftrace user' ;:
echo 0 > events/fprobes/enable
echo > dynamic_events
test `cat enabled_functions | wc -l` -eq 0
:;: 'Test case 2: leave exit event' ;:
:;: 'Add entry and exit events on the same place' ;:
echo "f:event1 ${PLACE}" >> dynamic_events
echo "f:event2 ${PLACE}%return" >> dynamic_events
:;: 'Enable both of them' ;:
echo 1 > events/fprobes/enable
test `cat enabled_functions | wc -l` -eq 1
:;: 'Disable and remove entry event' ;:
echo 0 > events/fprobes/event1/enable
echo -:event1 >> dynamic_events
:;: 'Disable and remove all events' ;:
echo 0 > events/fprobes/enable
echo > dynamic_events
:;: 'Add another event' ;:
echo "f:event3 ${PLACE2}" > dynamic_events
echo 1 > events/fprobes/enable
test `cat enabled_functions | wc -l` -eq 1
:;: 'No other ftrace user' ;:
echo 0 > events/fprobes/enable
echo > dynamic_events
test `cat enabled_functions | wc -l` -eq 0
clear_trace
@@ -0,0 +1,24 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - add/remove synthetic events
# requires: dynamic_events "s:[synthetic/]":README
echo 0 > events/enable
echo > dynamic_events
echo "s:latency1 u64 lat; pid_t pid;" >> dynamic_events
echo "s:latency2 u64 lat; pid_t pid;" >> dynamic_events
grep -q latency1 dynamic_events
grep -q latency2 dynamic_events
test -d events/synthetic/latency1
test -d events/synthetic/latency2
echo "-:synthetic/latency2" >> dynamic_events
grep -q latency1 dynamic_events
! grep -q latency2 dynamic_events
echo > dynamic_events
clear_trace
@@ -0,0 +1,41 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - add/remove tracepoint probe events
# requires: dynamic_events "t[:[<group>/][<event>]] <tracepoint> [<args>]":README
echo 0 > events/enable
echo > dynamic_events
SUBSYSTEM=kmem
TRACEPOINT1=kmem_cache_alloc
TRACEPOINT2=kmem_cache_free
echo "t:myevent1 $TRACEPOINT1" >> dynamic_events
echo "t:myevent2 $TRACEPOINT2" >> dynamic_events
grep -q myevent1 dynamic_events
grep -q myevent2 dynamic_events
test -d events/tracepoints/myevent1
test -d events/tracepoints/myevent2
echo "-:myevent2" >> dynamic_events
grep -q myevent1 dynamic_events
! grep -q myevent2 dynamic_events
echo > dynamic_events
# auto naming check
echo "t $TRACEPOINT1" >> dynamic_events
test -d events/tracepoints/$TRACEPOINT1
echo > dynamic_events
# SUBSYSTEM is not supported
echo "t $SUBSYSTEM/$TRACEPOINT1" >> dynamic_events && exit_fail ||:
echo "t $SUBSYSTEM:$TRACEPOINT1" >> dynamic_events && exit_fail ||:
echo "t:myevent3 $SUBSYSTEM/$TRACEPOINT1" >> dynamic_events && exit_fail ||:
echo "t:myevent3 $SUBSYSTEM:$TRACEPOINT1" >> dynamic_events && exit_fail ||:
clear_trace
@@ -0,0 +1,61 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - add/remove tracepoint probe events on module
# requires: dynamic_events "t[:[<group>/][<event>]] <tracepoint> [<args>]":README
rmmod trace-events-sample ||:
if ! modprobe trace-events-sample ; then
echo "No trace-events sample module - please make CONFIG_SAMPLE_TRACE_EVENTS=m"
exit_unresolved;
fi
trap "rmmod trace-events-sample" EXIT
echo 0 > events/enable
echo > dynamic_events
TRACEPOINT1=foo_bar
TRACEPOINT2=foo_bar_with_cond
echo "t:myevent1 $TRACEPOINT1" >> dynamic_events
echo "t:myevent2 $TRACEPOINT2" >> dynamic_events
grep -q myevent1 dynamic_events
grep -q myevent2 dynamic_events
test -d events/tracepoints/myevent1
test -d events/tracepoints/myevent2
echo "-:myevent2" >> dynamic_events
grep -q myevent1 dynamic_events
! grep -q myevent2 dynamic_events
echo > dynamic_events
clear_trace
:;: "Try to put a probe on a tracepoint in non-loaded module" ;:
rmmod trace-events-sample
echo "t:myevent1 $TRACEPOINT1" >> dynamic_events
echo "t:myevent2 $TRACEPOINT2" >> dynamic_events
grep -q myevent1 dynamic_events
grep -q myevent2 dynamic_events
test -d events/tracepoints/myevent1
test -d events/tracepoints/myevent2
echo 1 > events/tracepoints/enable
modprobe trace-events-sample
sleep 2
grep -q "myevent1" trace
grep -q "myevent2" trace
rmmod trace-events-sample
trap "" EXIT
echo 0 > events/tracepoints/enable
echo > dynamic_events
clear_trace
@@ -0,0 +1,55 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - add/remove/test uprobe events
# requires: uprobe_events
if ! which readelf > /dev/null 2>&1 ; then
echo "No readelf found. skipped."
exit_unresolved
fi
echo 0 > events/enable
echo > dynamic_events
REALBIN=`readlink -f /bin/sh`
# Get the entry point virtual address from ELF header
ENTRY=`readelf -hW ${REALBIN} | grep "Entry point" | awk '{print $NF}'`
# Convert virtual address to file offset: find the LOAD segment containing
# the entry point, then compute file_offset = e_entry - p_vaddr + p_offset.
# For PIE binaries this is a no-op (vaddr == file offset), but for non-PIE
# executables the virtual address is much larger than the file size and
# must be converted, otherwise uprobe_register() rejects it with -EINVAL.
ENTRY_DEC=$(printf '%d' "$ENTRY")
OFFSET=$ENTRY
while IFS= read -r line; do
set -- $line
[ "$1" = "LOAD" ] || continue
VA_DEC=$(printf '%d' "$3")
OFF_DEC=$(printf '%d' "$2")
FSZ_DEC=$(printf '%d' "$5")
if [ "$ENTRY_DEC" -ge "$VA_DEC" ] && [ "$ENTRY_DEC" -lt "$((VA_DEC + FSZ_DEC))" ]; then
OFFSET=$(printf '0x%x' "$((ENTRY_DEC - VA_DEC + OFF_DEC))")
break
fi
done << EOF
$(readelf -lW ${REALBIN} | grep LOAD)
EOF
echo "p:myevent ${REALBIN}:${OFFSET}" >> uprobe_events
grep -q myevent uprobe_events
test -d events/uprobes/myevent
echo 1 > events/uprobes/myevent/enable
echo 'ls' | /bin/sh > /dev/null
echo 0 > events/uprobes/myevent/enable
grep -q myevent trace
echo "-:myevent" >> uprobe_events
! grep -q myevent uprobe_events
echo > uprobe_events
clear_trace
@@ -0,0 +1,41 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - selective clear (compatibility)
# requires: dynamic_events kprobe_events synthetic_events "place: [<module>:]<symbol>":README "place (kretprobe): [<module>:]<symbol>":README "s:[synthetic/]":README
echo 0 > events/enable
echo > dynamic_events
PLACE=$FUNCTION_FORK
setup_events() {
echo "p:myevent1 $PLACE" >> dynamic_events
echo "s:latency1 u64 lat; pid_t pid;" >> dynamic_events
echo "r:myevent2 $PLACE" >> dynamic_events
echo "s:latency2 u64 lat; pid_t pid;" >> dynamic_events
grep -q myevent1 dynamic_events
grep -q myevent2 dynamic_events
grep -q latency1 dynamic_events
grep -q latency2 dynamic_events
}
setup_events
echo > synthetic_events
grep -q myevent1 dynamic_events
grep -q myevent2 dynamic_events
! grep -q latency1 dynamic_events
! grep -q latency2 dynamic_events
echo > dynamic_events
setup_events
echo > kprobe_events
! grep -q myevent1 dynamic_events
! grep -q myevent2 dynamic_events
grep -q latency1 dynamic_events
grep -q latency2 dynamic_events
echo > dynamic_events
@@ -0,0 +1,63 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Checking dynamic events limitations
# requires: dynamic_events "imm-value":README
# Max arguments limitation
MAX_ARGS=128
EXCEED_ARGS=$((MAX_ARGS + 1))
# bash and dash evaluate variables differently.
# dash will evaluate '\\' every time it is read whereas bash does not.
#
# TEST_STRING="$TEST_STRING \\$i"
# echo $TEST_STRING
#
# With i=123
# On bash, that will print "\123"
# but on dash, that will print the escape sequence of \123 as the \ will
# be interpreted again in the echo.
#
# Set a variable "bs" to save a double backslash, then echo that
# to "ts" to see if $ts changed or not. If it changed, it's dash,
# if not, it's bash, and then bs can equal a single backslash.
bs='\\'
ts=`echo $bs`
if [ "$ts" = '\\' ]; then
# this is bash
bs='\'
fi
check_max_args() { # event_header
TEST_STRING=$1
# Acceptable
for i in `seq 1 $MAX_ARGS`; do
TEST_STRING="$TEST_STRING $bs$i"
done
echo "$TEST_STRING" >> dynamic_events
echo > dynamic_events
# Error
TEST_STRING="$TEST_STRING \\$EXCEED_ARGS"
! echo "$TEST_STRING" >> dynamic_events
return 0
}
# Kprobe max args limitation
if grep -q "kprobe_events" README; then
check_max_args "p vfs_read"
fi
# Fprobe max args limitation
if grep -q "f[:[<group>/][<event>]] <func-name>[%return] [<args>]" README; then
check_max_args "f vfs_read"
fi
# Tprobe max args limitation
if grep -q "t[:[<group>/][<event>]] <tracepoint> [<args>]" README; then
check_max_args "t kfree"
fi
# Uprobe max args limitation
if grep -q "uprobe_events" README; then
check_max_args "p /bin/sh:10"
fi
@@ -0,0 +1,40 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - enable/disable tracepoint probe events
# requires: dynamic_events "t[:[<group>/][<event>]] <tracepoint> [<args>]":README
echo 0 > events/enable
echo > dynamic_events
TRACEPOINT=sched_switch
ENABLEFILE=events/tracepoints/myprobe/enable
:;: "Add tracepoint event on $TRACEPOINT" ;:
echo "t:myprobe ${TRACEPOINT}" >> dynamic_events
:;: "Check enable/disable to ensure it works" ;:
echo 1 > $ENABLEFILE
grep -q $TRACEPOINT trace
echo 0 > $ENABLEFILE
echo > trace
! grep -q $TRACEPOINT trace
:;: "Repeat enable/disable to ensure it works" ;:
echo 1 > $ENABLEFILE
grep -q $TRACEPOINT trace
echo 0 > $ENABLEFILE
echo > trace
! grep -q $TRACEPOINT trace
exit 0
@@ -0,0 +1,29 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Event probe event parser error log check
# requires: dynamic_events events/syscalls/sys_enter_openat "<attached-group>.<attached-event> [<args>]":README error_log
check_error() { # command-with-error-pos-by-^
ftrace_errlog_check 'event_probe' "$1" 'dynamic_events'
}
check_error 'e ^a.' # NO_EVENT_INFO
check_error 'e ^.b' # NO_EVENT_INFO
check_error 'e ^a.b' # BAD_ATTACH_EVENT
check_error 'e syscalls/sys_enter_openat ^foo' # BAD_ATTACH_ARG
check_error 'e:^/bar syscalls/sys_enter_openat' # NO_GROUP_NAME
check_error 'e:^12345678901234567890123456789012345678901234567890123456789012345/bar syscalls/sys_enter_openat' # GROUP_TOO_LONG
check_error 'e:^foo.1/bar syscalls/sys_enter_openat' # BAD_GROUP_NAME
check_error 'e:^ syscalls/sys_enter_openat' # NO_EVENT_NAME
check_error 'e:foo/^12345678901234567890123456789012345678901234567890123456789012345 syscalls/sys_enter_openat' # EVENT_TOO_LONG
check_error 'e:foo/^bar.1 syscalls/sys_enter_openat' # BAD_EVENT_NAME
check_error 'e:foo/bar syscalls/sys_enter_openat arg=^dfd' # BAD_FETCH_ARG
check_error 'e:foo/bar syscalls/sys_enter_openat arg=^$foo' # BAD_ATTACH_ARG
if grep -q '<attached-group>\.<attached-event>.*\[if <filter>\]' README; then
check_error 'e:foo/bar syscalls/sys_enter_openat if ^' # NO_EP_FILTER
fi
exit 0
@@ -0,0 +1,41 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Fprobe event VFS type argument
# requires: dynamic_events "%pd/%pD":README "f[:[<group>/][<event>]] <func-name>[%return] [<args>]":README
: "Test argument %pd with name for fprobe"
echo 'f:testprobe dput name=$arg1:%pd' > dynamic_events
echo 1 > events/fprobes/testprobe/enable
grep -q "1" events/fprobes/testprobe/enable
echo 0 > events/fprobes/testprobe/enable
grep "dput" trace | grep -q "enable"
echo "" > dynamic_events
echo "" > trace
: "Test argument %pd without name for fprobe"
echo 'f:testprobe dput $arg1:%pd' > dynamic_events
echo 1 > events/fprobes/testprobe/enable
grep -q "1" events/fprobes/testprobe/enable
echo 0 > events/fprobes/testprobe/enable
grep "dput" trace | grep -q "enable"
echo "" > dynamic_events
echo "" > trace
: "Test argument %pD with name for fprobe"
echo 'f:testprobe vfs_read name=$arg1:%pD' > dynamic_events
echo 1 > events/fprobes/testprobe/enable
grep -q "1" events/fprobes/testprobe/enable
echo 0 > events/fprobes/testprobe/enable
grep "vfs_read" trace | grep -q "enable"
echo "" > dynamic_events
echo "" > trace
: "Test argument %pD without name for fprobe"
echo 'f:testprobe vfs_read $arg1:%pD' > dynamic_events
echo 1 > events/fprobes/testprobe/enable
grep -q "1" events/fprobes/testprobe/enable
echo 0 > events/fprobes/testprobe/enable
grep "vfs_read" trace | grep -q "enable"
echo "" > dynamic_events
echo "" > trace
@@ -0,0 +1,18 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Function return probe entry argument access
# requires: dynamic_events 'f[:[<group>/][<event>]] <func-name>':README 'kernel return probes support:':README
echo 'f:tests/myevent1 vfs_open arg=$arg1' >> dynamic_events
echo 'f:tests/myevent2 vfs_open%return arg=$arg1' >> dynamic_events
echo 1 > events/tests/enable
echo > trace
cat trace > /dev/null
streq() {
test $1 = $2
}
streq `grep -A 1 -m 1 myevent1 trace | sed -r 's/^.*(arg=.*)/\1/' `
@@ -0,0 +1,122 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Fprobe event parser error log check
# requires: dynamic_events "f[:[<group>/][<event>]] <func-name>[%return] [<args>]":README
check_error() { # command-with-error-pos-by-^
ftrace_errlog_check 'trace_fprobe' "$1" 'dynamic_events'
}
case `uname -m` in
x86_64|i[3456]86)
REG=%ax ;;
aarch64)
REG=%x0 ;;
*)
REG=%r0 ;;
esac
check_error 'f^100 vfs_read' # BAD_MAXACT
check_error 'f ^non_exist_func' # BAD_PROBE_ADDR (enoent)
check_error 'f ^vfs_read+10' # BAD_PROBE_ADDR
check_error 'f:^/bar vfs_read' # NO_GROUP_NAME
check_error 'f:^12345678901234567890123456789012345678901234567890123456789012345/bar vfs_read' # GROUP_TOO_LONG
check_error 'f:^foo.1/bar vfs_read' # BAD_GROUP_NAME
check_error 'f:^ vfs_read' # NO_EVENT_NAME
check_error 'f:foo/^12345678901234567890123456789012345678901234567890123456789012345 vfs_read' # EVENT_TOO_LONG
check_error 'f:foo/^bar.1 vfs_read' # BAD_EVENT_NAME
check_error 't kmem^/kfree' # BAD_TP_NAME
check_error 'f vfs_read ^$stack10000' # BAD_STACK_NUM
check_error 'f vfs_read ^$arg10000' # BAD_ARG_NUM
if !grep -q 'kernel return probes support:' README; then
check_error 'f vfs_read $retval ^$arg1' # BAD_VAR
fi
check_error 'f vfs_read ^$none_var' # BAD_VAR
check_error 'f vfs_read ^'$REG # BAD_VAR
check_error 'f vfs_read ^@12345678abcde' # BAD_MEM_ADDR
check_error 'f vfs_read ^@+10' # FILE_ON_KPROBE
grep -q "imm-value" README && \
check_error 'f vfs_read arg1=\^x' # BAD_IMM
grep -q "imm-string" README && \
check_error 'f vfs_read arg1=\"abcd^' # IMMSTR_NO_CLOSE
check_error 'f vfs_read ^+0@0)' # DEREF_NEED_BRACE
check_error 'f vfs_read ^+0ab1(@0)' # BAD_DEREF_OFFS
check_error 'f vfs_read +0(+0(@0^)' # DEREF_OPEN_BRACE
if grep -A1 "fetcharg:" README | grep -q '\$comm' ; then
check_error 'f vfs_read +0(^$comm)' # COMM_CANT_DEREF
fi
check_error 'f vfs_read ^&1' # BAD_FETCH_ARG
# We've introduced this limitation with array support
if grep -q ' <type>\\\[<array-size>\\\]' README; then
check_error 'f vfs_read +0(^+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(@0))))))))))))))' # TOO_MANY_OPS?
check_error 'f vfs_read +0(@11):u8[10^' # ARRAY_NO_CLOSE
check_error 'f vfs_read +0(@11):u8[10]^a' # BAD_ARRAY_SUFFIX
check_error 'f vfs_read +0(@11):u8[^10a]' # BAD_ARRAY_NUM
check_error 'f vfs_read +0(@11):u8[^256]' # ARRAY_TOO_BIG
fi
check_error 'f vfs_read @11:^unknown_type' # BAD_TYPE
check_error 'f vfs_read $stack0:^string' # BAD_STRING
check_error 'f vfs_read @11:^b10@a/16' # BAD_BITFIELD
check_error 'f vfs_read ^arg123456789012345678901234567890=@11' # ARG_NAME_TOO_LOG
check_error 'f vfs_read ^=@11' # NO_ARG_NAME
check_error 'f vfs_read ^var.1=@11' # BAD_ARG_NAME
check_error 'f vfs_read var1=@11 ^var1=@12' # USED_ARG_NAME
check_error 'f vfs_read ^+1234567(+1234567(+1234567(+1234567(+1234567(+1234567(@1234))))))' # ARG_TOO_LONG
check_error 'f vfs_read arg1=^' # NO_ARG_BODY
# multiprobe errors
if grep -q "Create/append/" README && grep -q "imm-value" README; then
echo "f:fprobes/testevent $FUNCTION_FORK" > dynamic_events
check_error '^f:fprobes/testevent do_exit%return' # DIFF_PROBE_TYPE
# Explicitly use printf "%s" to not interpret \1
printf "%s" "f:fprobes/testevent $FUNCTION_FORK abcd=\\1" > dynamic_events
check_error "f:fprobes/testevent $FUNCTION_FORK ^bcd=\\1" # DIFF_ARG_TYPE
check_error "f:fprobes/testevent $FUNCTION_FORK ^abcd=\\1:u8" # DIFF_ARG_TYPE
check_error "f:fprobes/testevent $FUNCTION_FORK ^abcd=\\\"foo\"" # DIFF_ARG_TYPE
check_error "^f:fprobes/testevent $FUNCTION_FORK abcd=\\1" # SAME_PROBE
fi
# %return suffix errors
check_error 'f vfs_read^%hoge' # BAD_ADDR_SUFFIX
# BTF arguments errors
if grep -q "<argname>" README; then
check_error 'f vfs_read args=^$arg*' # BAD_VAR_ARGS
check_error 'f vfs_read +0(^$arg*)' # BAD_VAR_ARGS
check_error 'f vfs_read $arg* ^$arg*' # DOUBLE_ARGS
if !grep -q 'kernel return probes support:' README; then
check_error 'f vfs_read%return ^$arg*' # NOFENTRY_ARGS
fi
check_error 'f vfs_read ^hoge' # NO_BTFARG
check_error 'f kfree ^$arg10' # NO_BTFARG (exceed the number of parameters)
check_error 'f kfree%return ^$retval' # NO_RETVAL
if grep -qF "<argname>[->field[->field|.field...]]" README ; then
check_error 'f vfs_read%return $retval->^foo' # NO_PTR_STRCT
check_error 'f vfs_read file->^foo' # NO_BTF_FIELD
check_error 'f vfs_read file^-.foo' # BAD_HYPHEN
check_error 'f vfs_read ^file:string' # BAD_TYPE4STR
fi
else
check_error 'f vfs_read ^$arg*' # NOSUP_BTFARG
check_error 't kfree ^$arg*' # NOSUP_BTFARG
fi
exit 0
@@ -0,0 +1,43 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - generic clear event
# requires: dynamic_events "place: [<module>:]<symbol>":README "place (kretprobe): [<module>:]<symbol>":README "s:[synthetic/]":README
echo 0 > events/enable
echo > dynamic_events
PLACE=$FUNCTION_FORK
setup_events() {
echo "p:myevent1 $PLACE" >> dynamic_events
echo "s:latency1 u64 lat; pid_t pid;" >> dynamic_events
echo "r:myevent2 $PLACE" >> dynamic_events
echo "s:latency2 u64 lat; pid_t pid;" >> dynamic_events
grep -q myevent1 dynamic_events
grep -q myevent2 dynamic_events
grep -q latency1 dynamic_events
grep -q latency2 dynamic_events
}
setup_events
echo "!p:myevent1 $PLACE" >> dynamic_events
! grep -q myevent1 dynamic_events
grep -q myevent2 dynamic_events
grep -q latency1 dynamic_events
grep -q latency2 dynamic_events
echo "!s:latency1 u64 lat; pid_t pid;" >> dynamic_events
grep -q myevent2 dynamic_events
! grep -q latency1 dynamic_events
grep -q latency2 dynamic_events
echo "!r:myevent2 $PLACE" >> dynamic_events
! grep -q myevent2 dynamic_events
grep -q latency2 dynamic_events
echo "!s:latency2 u64 lat; pid_t pid;" >> dynamic_events
! grep -q latency2 dynamic_events
echo > dynamic_events
@@ -0,0 +1,38 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Generic dynamic event - check if duplicate events are caught
# requires: dynamic_events "e[:[<group>/][<event>]] <attached-group>.<attached-event> [<args>]":README events/syscalls/sys_enter_openat
echo 0 > events/enable
HAVE_KPROBES=0
if [ -f kprobe_events ]; then
HAVE_KPROBES=1
fi
clear_dynamic_events
# first create dynamic events for eprobes and kprobes.
echo 'e:egroup/eevent syscalls/sys_enter_openat file=+0($filename):ustring' >> dynamic_events
# Test eprobe for same eprobe, existing kprobe and existing event
! echo 'e:egroup/eevent syscalls/sys_enter_openat file=+0($filename):ustring' >> dynamic_events
! echo 'e:syscalls/sys_enter_open syscalls/sys_enter_openat file=+0($filename):ustring' >> dynamic_events
if [ $HAVE_KPROBES -eq 1 ]; then
echo 'p:kgroup/kevent vfs_open file=+0($arg2)' >> dynamic_events
! echo 'e:kgroup/kevent syscalls/sys_enter_openat file=+0($filename):ustring' >> dynamic_events
# Test kprobe for same kprobe, existing eprobe and existing event
! echo 'p:kgroup/kevent vfs_open file=+0($arg2)' >> dynamic_events
! echo 'p:egroup/eevent vfs_open file=+0($arg2)' >> dynamic_events
! echo 'p:syscalls/sys_enter_open vfs_open file=+0($arg2)' >> dynamic_events
echo '-:kgroup/kevent' >> dynamic_events
fi
echo '-:egroup/eevent' >> dynamic_events
clear_trace
@@ -0,0 +1,81 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Tracepoint probe event parser error log check
# requires: dynamic_events "t[:[<group>/][<event>]] <tracepoint> [<args>]":README
check_error() { # command-with-error-pos-by-^
ftrace_errlog_check 'trace_fprobe' "$1" 'dynamic_events'
}
check_error 't^100 kfree' # BAD_MAXACT_TYPE
check_error 't:^/bar kfree' # NO_GROUP_NAME
check_error 't:^12345678901234567890123456789012345678901234567890123456789012345/bar kfree' # GROUP_TOO_LONG
check_error 't:^foo.1/bar kfree' # BAD_GROUP_NAME
check_error 't:^ kfree' # NO_EVENT_NAME
check_error 't:foo/^12345678901234567890123456789012345678901234567890123456789012345 kfree' # EVENT_TOO_LONG
check_error 't:foo/^bar.1 kfree' # BAD_EVENT_NAME
check_error 't kfree ^$retval' # RETVAL_ON_PROBE
check_error 't kfree ^$stack10000' # BAD_STACK_NUM
check_error 't kfree ^$arg10000' # BAD_ARG_NUM
check_error 't kfree ^$none_var' # BAD_VAR
check_error 't kfree ^%rax' # BAD_VAR
check_error 't kfree ^@12345678abcde' # BAD_MEM_ADDR
check_error 't kfree ^@+10' # FILE_ON_KPROBE
grep -q "imm-value" README && \
check_error 't kfree arg1=\^x' # BAD_IMM
grep -q "imm-string" README && \
check_error 't kfree arg1=\"abcd^' # IMMSTR_NO_CLOSE
check_error 't kfree ^+0@0)' # DEREF_NEED_BRACE
check_error 't kfree ^+0ab1(@0)' # BAD_DEREF_OFFS
check_error 't kfree +0(+0(@0^)' # DEREF_OPEN_BRACE
if grep -A1 "fetcharg:" README | grep -q '\$comm' ; then
check_error 't kfree +0(^$comm)' # COMM_CANT_DEREF
fi
check_error 't kfree ^&1' # BAD_FETCH_ARG
# We've introduced this limitation with array support
if grep -q ' <type>\\\[<array-size>\\\]' README; then
check_error 't kfree +0(^+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(@0))))))))))))))' # TOO_MANY_OPS?
check_error 't kfree +0(@11):u8[10^' # ARRAY_NO_CLOSE
check_error 't kfree +0(@11):u8[10]^a' # BAD_ARRAY_SUFFIX
check_error 't kfree +0(@11):u8[^10a]' # BAD_ARRAY_NUM
check_error 't kfree +0(@11):u8[^256]' # ARRAY_TOO_BIG
fi
check_error 't kfree @11:^unknown_type' # BAD_TYPE
check_error 't kfree $stack0:^string' # BAD_STRING
check_error 't kfree @11:^b10@a/16' # BAD_BITFIELD
check_error 't kfree ^arg123456789012345678901234567890=@11' # ARG_NAME_TOO_LOG
check_error 't kfree ^=@11' # NO_ARG_NAME
check_error 't kfree ^var.1=@11' # BAD_ARG_NAME
check_error 't kfree var1=@11 ^var1=@12' # USED_ARG_NAME
check_error 't kfree ^+1234567(+1234567(+1234567(+1234567(+1234567(+1234567(@1234))))))' # ARG_TOO_LONG
check_error 't kfree arg1=^' # NO_ARG_BODY
# multiprobe errors
if grep -q "Create/append/" README && grep -q "imm-value" README; then
echo "t:tracepoint/testevent kfree" > dynamic_events
check_error '^f:tracepoint/testevent kfree' # DIFF_PROBE_TYPE
# Explicitly use printf "%s" to not interpret \1
printf "%s" "t:tracepoints/testevent kfree abcd=\\1" > dynamic_events
check_error "t:tracepoints/testevent kfree ^bcd=\\1" # DIFF_ARG_TYPE
check_error "t:tracepoints/testevent kfree ^abcd=\\1:u8" # DIFF_ARG_TYPE
check_error "t:tracepoints/testevent kfree ^abcd=\\\"foo\"" # DIFF_ARG_TYPE
check_error "^t:tracepoints/testevent kfree abcd=\\1" # SAME_PROBE
fi
exit 0
@@ -0,0 +1,48 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: event tracing - enable/disable with event level files
# requires: set_event events/sched
# flags: instance
do_reset() {
echo > set_event
clear_trace
}
fail() { #msg
echo $1
exit_fail
}
echo 'sched:sched_switch' > set_event
yield
count=`cat trace | grep sched_switch | wc -l`
if [ $count -eq 0 ]; then
fail "sched_switch events are not recorded"
fi
do_reset
echo 1 > events/sched/sched_switch/enable
yield
count=`cat trace | grep sched_switch | wc -l`
if [ $count -eq 0 ]; then
fail "sched_switch events are not recorded"
fi
do_reset
echo 0 > events/sched/sched_switch/enable
yield
count=`cat trace | grep sched_switch | wc -l`
if [ $count -ne 0 ]; then
fail "sched_switch events should not be recorded"
fi
exit 0
@@ -0,0 +1,191 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: event tracing - enable/disable with module event
# requires: set_event "Can enable module events via: :mod:":README
# flags: instance
rmmod trace-events-sample ||:
if ! modprobe trace-events-sample ; then
echo "No trace-events sample module - please make CONFIG_SAMPLE_TRACE_EVENTS=m"
exit_unresolved;
fi
trap "rmmod trace-events-sample" EXIT
# Set events for the module
echo ":mod:trace-events-sample" > set_event
test_all_enabled() {
# Check if more than one is enabled
grep -q sample-trace:foo_bar set_event
grep -q sample-trace:foo_bar_with_cond set_event
grep -q sample-trace:foo_bar_with_fn set_event
# All of them should be enabled. Check via the enable file
val=`cat events/sample-trace/enable`
if [ $val -ne 1 ]; then
exit_fail
fi
}
clear_events() {
echo > set_event
val=`cat events/enable`
if [ "$val" != "0" ]; then
exit_fail
fi
count=`cat set_event | wc -l`
if [ $count -ne 0 ]; then
exit_fail
fi
}
test_all_enabled
echo clear all events
echo 0 > events/enable
echo Confirm the events are disabled
val=`cat events/sample-trace/enable`
if [ $val -ne 0 ]; then
exit_fail
fi
echo And the set_event file is empty
cnt=`wc -l set_event`
if [ $cnt -ne 0 ]; then
exit_fail
fi
echo now enable all events
echo 1 > events/enable
echo Confirm the events are enabled again
val=`cat events/sample-trace/enable`
if [ $val -ne 1 ]; then
exit_fail
fi
echo disable just the module events
echo '!:mod:trace-events-sample' >> set_event
echo Should have mix of events enabled
val=`cat events/enable`
if [ "$val" != "X" ]; then
exit_fail
fi
echo Confirm the module events are disabled
val=`cat events/sample-trace/enable`
if [ $val -ne 0 ]; then
exit_fail
fi
echo 0 > events/enable
echo now enable the system events
echo 'sample-trace:mod:trace-events-sample' > set_event
test_all_enabled
echo clear all events
echo 0 > events/enable
echo Confirm the events are disabled
val=`cat events/sample-trace/enable`
if [ $val -ne 0 ]; then
exit_fail
fi
echo Test enabling foo_bar only
echo 'foo_bar:mod:trace-events-sample' > set_event
grep -q sample-trace:foo_bar set_event
echo make sure nothing is found besides foo_bar
if grep -q -v sample-trace:foo_bar set_event ; then
exit_fail
fi
echo Append another using the system and event name
echo 'sample-trace:foo_bar_with_cond:mod:trace-events-sample' >> set_event
grep -q sample-trace:foo_bar set_event
grep -q sample-trace:foo_bar_with_cond set_event
count=`cat set_event | wc -l`
if [ $count -ne 2 ]; then
exit_fail
fi
clear_events
rmmod trace-events-sample
echo ':mod:trace-events-sample' > set_event
echo make sure that the module shows up, and '-' is converted to '_'
grep -q '\*:\*:mod:trace_events_sample' set_event
modprobe trace-events-sample
test_all_enabled
clear_events
rmmod trace-events-sample
echo Enable just the system events
echo 'sample-trace:mod:trace-events-sample' > set_event
grep -q 'sample-trace:mod:trace_events_sample' set_event
modprobe trace-events-sample
test_all_enabled
clear_events
rmmod trace-events-sample
echo Enable event with just event name
echo 'foo_bar:mod:trace-events-sample' > set_event
grep -q 'foo_bar:mod:trace_events_sample' set_event
echo Enable another event with both system and event name
echo 'sample-trace:foo_bar_with_cond:mod:trace-events-sample' >> set_event
grep -q 'sample-trace:foo_bar_with_cond:mod:trace_events_sample' set_event
echo Make sure the other event was still there
grep -q 'foo_bar:mod:trace_events_sample' set_event
modprobe trace-events-sample
echo There should be no :mod: cached events
if grep -q ':mod:' set_event; then
exit_fail
fi
echo two events should be enabled
count=`cat set_event | wc -l`
if [ $count -ne 2 ]; then
exit_fail
fi
echo only two events should be enabled
val=`cat events/sample-trace/enable`
if [ "$val" != "X" ]; then
exit_fail
fi
val=`cat events/sample-trace/foo_bar/enable`
if [ "$val" != "1" ]; then
exit_fail
fi
val=`cat events/sample-trace/foo_bar_with_cond/enable`
if [ "$val" != "1" ]; then
exit_fail
fi
clear_trace
@@ -0,0 +1,123 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: event tracing - restricts events based on pid notrace filtering
# requires: set_event events/sched set_event_pid set_event_notrace_pid
# flags: instance
do_reset() {
echo > set_event
echo > set_event_pid
echo > set_event_notrace_pid
echo 0 > options/event-fork
echo 0 > events/enable
clear_trace
echo 1 > tracing_on
}
fail() { #msg
cat trace
do_reset
echo $1
exit_fail
}
count_pid() {
pid=$@
cat trace | grep -v '^#' | sed -e 's/[^-]*-\([0-9]*\).*/\1/' | grep $pid | wc -l
}
count_no_pid() {
pid=$1
cat trace | grep -v '^#' | sed -e 's/[^-]*-\([0-9]*\).*/\1/' | grep -v $pid | wc -l
}
enable_system() {
system=$1
if [ -d events/$system ]; then
echo 1 > events/$system/enable
fi
}
enable_events() {
echo 0 > tracing_on
# Enable common groups of events, as all events can allow for
# events to be traced via scheduling that we don't care to test.
enable_system syscalls
enable_system rcu
enable_system block
enable_system exceptions
enable_system irq
enable_system net
enable_system power
enable_system signal
enable_system sock
enable_system timer
enable_system thermal
echo 1 > tracing_on
}
other_task() {
sleep .001 || usleep 1 || sleep 1
}
echo 0 > options/event-fork
do_reset
read mypid rest < /proc/self/stat
echo $mypid > set_event_notrace_pid
grep -q $mypid set_event_notrace_pid
enable_events
yield
echo 0 > tracing_on
cnt=`count_pid $mypid`
if [ $cnt -ne 0 ]; then
fail "Filtered out task has events"
fi
cnt=`count_no_pid $mypid`
if [ $cnt -eq 0 ]; then
fail "No other events were recorded"
fi
do_reset
echo $mypid > set_event_notrace_pid
echo 1 > options/event-fork
enable_events
yield &
child=$!
echo "child = $child"
wait $child
# Be sure some other events will happen for small systems (e.g. 1 core)
other_task
echo 0 > tracing_on
cnt=`count_pid $mypid`
if [ $cnt -ne 0 ]; then
fail "Filtered out task has events"
fi
cnt=`count_pid $child`
if [ $cnt -ne 0 ]; then
fail "Child of filtered out taskhas events"
fi
cnt=`count_no_pid $mypid`
if [ $cnt -eq 0 ]; then
fail "No other events were recorded"
fi
do_reset
exit 0
@@ -0,0 +1,61 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: event tracing - restricts events based on pid
# requires: set_event set_event_pid events/sched
# flags: instance
do_reset() {
echo > set_event
echo > set_event_pid
echo 0 > options/event-fork
clear_trace
}
fail() { #msg
do_reset
echo $1
exit_fail
}
echo 0 > options/event-fork
echo 1 > events/sched/sched_switch/enable
yield
count=`cat trace | grep sched_switch | wc -l`
if [ $count -eq 0 ]; then
fail "sched_switch events are not recorded"
fi
do_reset
read mypid rest < /proc/self/stat
echo $mypid > set_event_pid
grep -q $mypid set_event_pid
echo 'sched:sched_switch' > set_event
yield
count=`cat trace | grep sched_switch | grep -v "pid=$mypid" | wc -l`
if [ $count -ne 0 ]; then
fail "sched_switch events from other task are recorded"
fi
do_reset
echo $mypid > set_event_pid
echo 1 > options/event-fork
echo 1 > events/sched/sched_switch/enable
yield
count=`cat trace | grep sched_switch | grep -v "pid=$mypid" | wc -l`
if [ $count -eq 0 ]; then
fail "sched_switch events from other task are not recorded"
fi
do_reset
exit 0
@@ -0,0 +1,72 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: event tracing - enable/disable with subsystem level files
# requires: set_event events/sched/enable
# flags: instance
do_reset() {
echo > set_event
clear_trace
}
fail() { #msg
echo $1
exit_fail
}
# As reading trace can last forever, simply look for 3 different
# events then exit out of reading the file. If there's not 3 different
# events, then the test has failed.
check_unique() {
cat trace | grep -v '^#' | awk '
BEGIN { cnt = 0; }
{
for (i = 0; i < cnt; i++) {
if (event[i] == $5) {
break;
}
}
if (i == cnt) {
event[cnt++] = $5;
if (cnt > 2) {
exit;
}
}
}
END {
printf "%d", cnt;
}'
}
echo 'sched:*' > set_event
yield
count=`check_unique`
if [ $count -lt 3 ]; then
fail "at least fork, exec and exit events should be recorded"
fi
do_reset
echo 1 > events/sched/enable
yield
count=`check_unique`
if [ $count -lt 3 ]; then
fail "at least fork, exec and exit events should be recorded"
fi
do_reset
echo 0 > events/sched/enable
yield
count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
if [ $count -ne 0 ]; then
fail "any of scheduler events should not be recorded"
fi
exit 0
@@ -0,0 +1,52 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: event tracing - enable/disable with top level files
# requires: set_event events/enable
# flags: instance
do_reset() {
echo > set_event
clear_trace
}
fail() { #msg
echo $1
exit_fail
}
echo '*:*' > set_event
yield
echo 0 > tracing_on
count=`head -n 128 trace | grep -v ^# | wc -l`
if [ $count -eq 0 ]; then
fail "none of events are recorded"
fi
do_reset
echo 1 > events/enable
echo 1 > tracing_on
yield
echo 0 > tracing_on
count=`head -n 128 trace | grep -v ^# | wc -l`
if [ $count -eq 0 ]; then
fail "none of events are recorded"
fi
do_reset
echo 0 > events/enable
yield
count=`cat trace | grep -v ^# | wc -l`
if [ $count -ne 0 ]; then
fail "any of events should not be recorded"
fi
exit 0
@@ -0,0 +1,27 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test trace_printk from module
rmmod trace-printk ||:
if ! modprobe trace-printk ; then
echo "No trace-printk sample module - please make CONFIG_SAMPLE_TRACE_PRINTK=m"
exit_unresolved;
fi
echo "Waiting for irq work"
sleep 1
grep -q ": This .* trace_bputs" trace
grep -q ": This .* trace_puts" trace
grep -q ": This .* trace_bprintk" trace
grep -q ": This .* trace_printk" trace
grep -q ": (irq) .* trace_bputs" trace
grep -q ": (irq) .* trace_puts" trace
grep -q ": (irq) .* trace_bprintk" trace
grep -q ": (irq) .* trace_printk" trace
grep -q "This is a %s that will use trace_bprintk" printk_formats
grep -q "(irq) This is a static string that will use trace_bputs" printk_formats
rmmod trace-printk ||:
@@ -0,0 +1,109 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: event filter function - test event filtering on functions
# requires: set_event events/kmem/kmem_cache_free/filter
# flags: instance
fail() { #msg
echo $1
exit_fail
}
sample_events() {
echo 1 > events/kmem/kmem_cache_free/enable
echo 1 > tracing_on
ls > /dev/null
echo 0 > tracing_on
echo 0 > events/kmem/kmem_cache_free/enable
}
echo 0 > tracing_on
echo 0 > events/enable
# Clear functions caused by page cache; run sample_events twice
sample_events
sample_events
echo "Get the most frequently calling function"
echo > trace
sample_events
target_func=`cat trace | grep -o 'call_site=\([^+]*\)' | sed 's/call_site=//' | sort | uniq -c | sort | tail -n 1 | sed 's/^[ 0-9]*//'`
if [ -z "$target_func" ]; then
exit_fail
fi
echo > trace
echo "Test event filter function name"
echo "call_site.function == $target_func" > events/kmem/kmem_cache_free/filter
sample_events
max_retry=10
while [ `grep kmem_cache_free trace| wc -l` -eq 0 ]; do
sample_events
max_retry=$((max_retry - 1))
if [ $max_retry -eq 0 ]; then
exit_fail
fi
done
hitcnt=`grep kmem_cache_free trace| grep $target_func | wc -l`
misscnt=`grep kmem_cache_free trace| grep -v $target_func | wc -l`
if [ $hitcnt -eq 0 ]; then
exit_fail
fi
if [ $misscnt -gt 0 ]; then
exit_fail
fi
address=`grep " ${target_func}\$" /proc/kallsyms | cut -d' ' -f1`
echo "Test event filter function address"
echo "call_site.function == 0x$address" > events/kmem/kmem_cache_free/filter
echo > trace
sample_events
max_retry=10
while [ `grep kmem_cache_free trace| wc -l` -eq 0 ]; do
sample_events
max_retry=$((max_retry - 1))
if [ $max_retry -eq 0 ]; then
exit_fail
fi
done
hitcnt=`grep kmem_cache_free trace| grep $target_func | wc -l`
misscnt=`grep kmem_cache_free trace| grep -v $target_func | wc -l`
if [ $hitcnt -eq 0 ]; then
exit_fail
fi
if [ $misscnt -gt 0 ]; then
exit_fail
fi
# Check strings too
if [ -f events/syscalls/sys_enter_openat/filter ]; then
DIRNAME=`basename $TMPDIR`
echo "filename.ustring ~ \"*$DIRNAME*\"" > events/syscalls/sys_enter_openat/filter
echo 1 > events/syscalls/sys_enter_openat/enable
echo 1 > tracing_on
ls /bin/sh
nocnt=`grep openat trace | wc -l`
ls $TMPDIR
echo 0 > tracing_on
hitcnt=`grep openat trace | wc -l`;
echo 0 > events/syscalls/sys_enter_openat/enable
if [ $nocnt -gt 0 ]; then
exit_fail
fi
if [ $hitcnt -eq 0 ]; then
exit_fail
fi
fi
reset_events_filter
exit 0
@@ -0,0 +1,73 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function graph filters with stack tracer
# requires: stack_trace set_ftrace_filter function_graph:tracer
# Make sure that function graph filtering works, and is not
# affected by other tracers enabled (like stack tracer)
do_reset() {
if [ -e /proc/sys/kernel/stack_tracer_enabled ]; then
echo 0 > /proc/sys/kernel/stack_tracer_enabled
fi
}
fail() { # msg
do_reset
echo $1
exit_fail
}
disable_tracing
clear_trace;
# filter something, schedule is always good
if ! echo "schedule" > set_ftrace_filter; then
# test for powerpc 64
if ! echo ".schedule" > set_ftrace_filter; then
fail "can not enable schedule filter"
fi
fi
echo function_graph > current_tracer
echo "Now testing with stack tracer"
echo 1 > /proc/sys/kernel/stack_tracer_enabled
disable_tracing
clear_trace
enable_tracing
sleep 1
count=`cat trace | grep '()' | grep -v schedule | wc -l`
if [ $count -ne 0 ]; then
fail "Graph filtering not working with stack tracer?"
fi
# Make sure we did find something
count=`cat trace | grep 'schedule()' | wc -l`
if [ $count -eq 0 ]; then
fail "No schedule traces found?"
fi
echo 0 > /proc/sys/kernel/stack_tracer_enabled
clear_trace
sleep 1
count=`cat trace | grep '()' | grep -v schedule | wc -l`
if [ $count -ne 0 ]; then
fail "Graph filtering not working after stack tracer disabled?"
fi
count=`cat trace | grep 'schedule()' | wc -l`
if [ $count -eq 0 ]; then
fail "No schedule traces found?"
fi
do_reset
exit 0
@@ -0,0 +1,40 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function graph filters
# requires: set_ftrace_filter function_graph:tracer
# Make sure that function graph filtering works
fail() { # msg
echo $1
exit_fail
}
disable_tracing
clear_trace
# filter something, schedule is always good
if ! echo "schedule" > set_ftrace_filter; then
# test for powerpc 64
if ! echo ".schedule" > set_ftrace_filter; then
fail "can not enable schedule filter"
fi
fi
echo function_graph > current_tracer
enable_tracing
sleep 1
# search for functions (has "()" on the line), and make sure
# that only the schedule function was found
count=`cat trace | grep '()' | grep -v schedule | wc -l`
if [ $count -ne 0 ]; then
fail "Graph filtering not working by itself?"
fi
# Make sure we did find something
count=`cat trace | grep 'schedule()' | wc -l`
if [ $count -eq 0 ]; then
fail "No schedule traces found?"
fi
exit 0
@@ -0,0 +1,177 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function graph filters
# requires: set_ftrace_filter function_graph:tracer
# Make sure that function graph filtering works
INSTANCE1="instances/test1_$$"
INSTANCE2="instances/test2_$$"
WD=`pwd`
do_reset() {
cd $WD
if [ -d $INSTANCE1 ]; then
echo nop > $INSTANCE1/current_tracer
rmdir $INSTANCE1
fi
if [ -d $INSTANCE2 ]; then
echo nop > $INSTANCE2/current_tracer
rmdir $INSTANCE2
fi
}
mkdir $INSTANCE1
if ! grep -q function_graph $INSTANCE1/available_tracers; then
echo "function_graph not allowed with instances"
rmdir $INSTANCE1
exit_unsupported
fi
mkdir $INSTANCE2
fail() { # msg
do_reset
echo $1
exit_fail
}
disable_tracing
clear_trace
function_count() {
search=$1
vsearch=$2
if [ -z "$search" ]; then
cat enabled_functions | wc -l
elif [ -z "$vsearch" ]; then
grep $search enabled_functions | wc -l
else
grep $search enabled_functions | grep $vsearch| wc -l
fi
}
set_fgraph() {
instance=$1
filter="$2"
notrace="$3"
echo "$filter" > $instance/set_ftrace_filter
echo "$notrace" > $instance/set_ftrace_notrace
echo function_graph > $instance/current_tracer
}
check_functions() {
orig_cnt=$1
test=$2
cnt=`function_count $test`
if [ $cnt -gt $orig_cnt ]; then
fail
fi
}
check_cnt() {
orig_cnt=$1
search=$2
vsearch=$3
cnt=`function_count $search $vsearch`
if [ $cnt -gt $orig_cnt ]; then
fail
fi
}
reset_graph() {
instance=$1
echo nop > $instance/current_tracer
}
# get any functions that were enabled before the test
total_cnt=`function_count`
sched_cnt=`function_count sched`
lock_cnt=`function_count lock`
time_cnt=`function_count time`
clock_cnt=`function_count clock`
locks_clock_cnt=`function_count locks clock`
clock_locks_cnt=`function_count clock locks`
# Trace functions with "sched" but not "time"
set_fgraph $INSTANCE1 '*sched*' '*time*'
# Make sure "time" isn't listed
check_functions $time_cnt 'time'
instance1_cnt=`function_count`
# Trace functions with "lock" but not "clock"
set_fgraph $INSTANCE2 '*lock*' '*clock*'
instance1_2_cnt=`function_count`
# Turn off the first instance
reset_graph $INSTANCE1
# The second instance doesn't trace "clock" functions
check_functions $clock_cnt 'clock'
instance2_cnt=`function_count`
# Start from a clean slate
reset_graph $INSTANCE2
check_functions $total_cnt
# Trace functions with "lock" but not "clock"
set_fgraph $INSTANCE2 '*lock*' '*clock*'
# This should match the last time instance 2 was by itself
cnt=`function_count`
if [ $instance2_cnt -ne $cnt ]; then
fail
fi
# And it should not be tracing "clock" functions
check_functions $clock_cnt 'clock'
# Trace functions with "sched" but not "time"
set_fgraph $INSTANCE1 '*sched*' '*time*'
# This should match the last time both instances were enabled
cnt=`function_count`
if [ $instance1_2_cnt -ne $cnt ]; then
fail
fi
# Turn off the second instance
reset_graph $INSTANCE2
# This should match the last time instance 1 was by itself
cnt=`function_count`
if [ $instance1_cnt -ne $cnt ]; then
fail
fi
# And it should not be tracing "time" functions
check_functions $time_cnt 'time'
# Start from a clean slate
reset_graph $INSTANCE1
check_functions $total_cnt
# Enable all functions but those that have "locks"
set_fgraph $INSTANCE1 '' '*locks*'
# Enable all functions but those that have "clock"
set_fgraph $INSTANCE2 '' '*clock*'
# If a function has "locks" it should not have "clock"
check_cnt $locks_clock_cnt locks clock
# If a function has "clock" it should not have "locks"
check_cnt $clock_locks_cnt clock locks
reset_graph $INSTANCE1
reset_graph $INSTANCE2
do_reset
exit 0
@@ -0,0 +1,103 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function graph filters
# requires: set_ftrace_filter function_graph:tracer
# Make sure that function graph filtering works
INSTANCE1="instances/test1_$$"
INSTANCE2="instances/test2_$$"
INSTANCE3="instances/test3_$$"
WD=`pwd`
do_reset() {
cd $WD
if [ -d $INSTANCE1 ]; then
echo nop > $INSTANCE1/current_tracer
rmdir $INSTANCE1
fi
if [ -d $INSTANCE2 ]; then
echo nop > $INSTANCE2/current_tracer
rmdir $INSTANCE2
fi
if [ -d $INSTANCE3 ]; then
echo nop > $INSTANCE3/current_tracer
rmdir $INSTANCE3
fi
}
mkdir $INSTANCE1
if ! grep -q function_graph $INSTANCE1/available_tracers; then
echo "function_graph not allowed with instances"
rmdir $INSTANCE1
exit_unsupported
fi
mkdir $INSTANCE2
mkdir $INSTANCE3
fail() { # msg
do_reset
echo $1
exit_fail
}
disable_tracing
clear_trace
do_test() {
REGEX=$1
TEST=$2
# filter something, schedule is always good
if ! echo "$REGEX" > set_ftrace_filter; then
fail "can not enable filter $REGEX"
fi
echo > trace
echo function_graph > current_tracer
enable_tracing
sleep 1
# search for functions (has "{" or ";" on the line)
echo 0 > tracing_on
count=`cat trace | grep -v '^#' | grep -e '{' -e ';' | grep -v "$TEST" | wc -l`
echo 1 > tracing_on
if [ $count -ne 0 ]; then
fail "Graph filtering not working by itself against $TEST?"
fi
# Make sure we did find something
echo 0 > tracing_on
count=`cat trace | grep -v '^#' | grep -e '{' -e ';' | grep "$TEST" | wc -l`
echo 1 > tracing_on
if [ $count -eq 0 ]; then
fail "No traces found with $TEST?"
fi
}
do_test '*sched*' 'sched'
cd $INSTANCE1
do_test '*lock*' 'lock'
cd $WD
cd $INSTANCE2
do_test '*rcu*' 'rcu'
cd $WD
cd $INSTANCE3
echo function_graph > current_tracer
sleep 1
count=`cat trace | grep -v '^#' | grep -e '{' -e ';' | grep "$TEST" | wc -l`
if [ $count -eq 0 ]; then
fail "No traces found with all tracing?"
fi
cd $WD
echo nop > current_tracer
echo nop > $INSTANCE1/current_tracer
echo nop > $INSTANCE2/current_tracer
echo nop > $INSTANCE3/current_tracer
do_reset
exit 0
@@ -0,0 +1,31 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function profiler with function graph tracing
# requires: function_profile_enabled set_ftrace_filter function_graph:tracer
# The function graph tracer can now be run along side of the function
# profiler. But there was a bug that caused the combination of the two
# to crash. It also required the function graph tracer to be started
# first.
#
# This test triggers that bug
#
# We need both function_graph and profiling to run this test
fail() { # mesg
echo $1
exit_fail
}
echo "Enabling function graph tracer:"
echo function_graph > current_tracer
echo "enable profiler"
# Older kernels do not allow function_profile to be enabled with
# function graph tracer. If the below fails, mark it as unsupported
echo 1 > function_profile_enabled || exit_unsupported
# Let it run for a bit to make sure nothing explodes
sleep 1
exit 0
@@ -0,0 +1,44 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function graph print function return value
# requires: options/funcgraph-retval options/funcgraph-retval-hex function_graph:tracer
# Make sure that funcgraph-retval works
fail() { # msg
echo $1
exit_fail
}
disable_tracing
clear_trace
# get self PID, can not use $$, because it is PPID
read PID _ < /proc/self/stat
[ -f set_ftrace_filter ] && echo proc_reg_write > set_ftrace_filter
[ -f set_ftrace_pid ] && echo ${PID} > set_ftrace_pid
echo function_graph > current_tracer
echo 1 > options/funcgraph-retval
set +e
enable_tracing
echo > /proc/interrupts
disable_tracing
set -e
: "Test printing the error code in signed decimal format"
echo 0 > options/funcgraph-retval-hex
count=`cat trace | grep 'proc_reg_write' | grep -e '=-5 ' -e '= -5 ' | wc -l`
if [ $count -eq 0 ]; then
fail "Return value can not be printed in signed decimal format"
fi
: "Test printing the error code in hexadecimal format"
echo 1 > options/funcgraph-retval-hex
count=`cat trace | grep 'proc_reg_write' | grep 'fffffffb' | wc -l`
if [ $count -eq 0 ]; then
fail "Return value can not be printed in hexadecimal format"
fi
exit 0
@@ -0,0 +1,58 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function glob filters
# requires: set_ftrace_filter function:tracer
# Make sure that function glob matching filter works.
disable_tracing
clear_trace
ftrace_filter_check() { # glob grep
echo "$1" > set_ftrace_filter
cut -f1 -d" " set_ftrace_filter > $TMPDIR/actual
cut -f1 -d" " available_filter_functions | grep "$2" > $TMPDIR/expected
DIFF=`diff $TMPDIR/actual $TMPDIR/expected`
test -z "$DIFF"
}
# filter by *, front match
ftrace_filter_check '*schedule' '^.*schedule$'
# filter by *, middle match
ftrace_filter_check '*schedule*' '^.*schedule.*$'
# filter by *, end match
ftrace_filter_check 'schedule*' '^schedule.*$'
# filter by *mid*end
ftrace_filter_check '*pin*lock' '.*pin.*lock$'
# filter by start*mid*
ftrace_filter_check 'mutex*unl*' '^mutex.*unl.*'
# Advanced full-glob matching feature is recently supported.
# Skip the tests if we are sure the kernel does not support it.
if grep -q 'accepts: .* glob-matching-pattern' README ; then
# filter by *, both side match
ftrace_filter_check 'sch*ule' '^sch.*ule$'
# filter by char class.
ftrace_filter_check '[Ss]y[Ss]_*' '^[Ss]y[Ss]_.*$'
# filter by ?, schedule is always good
if ! echo "sch?dule" > set_ftrace_filter; then
# test for powerpc 64
if ! echo ".sch?dule" > set_ftrace_filter; then
fail "can not enable schedule filter"
fi
cat set_ftrace_filter | grep '^.schedule$'
else
cat set_ftrace_filter | grep '^schedule$'
fi
fi
echo > set_ftrace_filter
enable_tracing
@@ -0,0 +1,94 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function pid notrace filters
# requires: set_ftrace_notrace_pid set_ftrace_filter function:tracer
# flags: instance
# Make sure that function pid matching filter with notrace works.
do_function_fork=1
if [ ! -f options/function-fork ]; then
do_function_fork=0
echo "no option for function-fork found. Option will not be tested."
fi
read PID _ < /proc/self/stat
if [ $do_function_fork -eq 1 ]; then
# default value of function-fork option
orig_value=`grep function-fork trace_options`
fi
do_reset() {
if [ $do_function_fork -eq 0 ]; then
return
fi
echo > set_ftrace_notrace_pid
echo $orig_value > trace_options
}
fail() { # msg
do_reset
echo $1
exit_fail
}
do_test() {
disable_tracing
echo do_execve* > set_ftrace_filter
echo $FUNCTION_FORK >> set_ftrace_filter
echo $PID > set_ftrace_notrace_pid
echo function > current_tracer
if [ $do_function_fork -eq 1 ]; then
# don't allow children to be traced
echo nofunction-fork > trace_options
fi
enable_tracing
yield
count_pid=`cat trace | grep -v ^# | grep $PID | wc -l`
count_other=`cat trace | grep -v ^# | grep -v $PID | wc -l`
# count_pid should be 0
if [ $count_pid -ne 0 -o $count_other -eq 0 ]; then
fail "PID filtering not working? traced task = $count_pid; other tasks = $count_other "
fi
disable_tracing
clear_trace
if [ $do_function_fork -eq 0 ]; then
return
fi
# allow children to be traced
echo function-fork > trace_options
# With pid in both set_ftrace_pid and set_ftrace_notrace_pid
# there should not be any tasks traced.
echo $PID > set_ftrace_pid
enable_tracing
yield
count_pid=`cat trace | grep -v ^# | grep $PID | wc -l`
count_other=`cat trace | grep -v ^# | grep -v $PID | wc -l`
# both should be zero
if [ $count_pid -ne 0 -o $count_other -ne 0 ]; then
fail "PID filtering not following fork? traced task = $count_pid; other tasks = $count_other "
fi
}
do_test
do_reset
exit 0
@@ -0,0 +1,107 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function pid filters
# requires: set_ftrace_pid set_ftrace_filter function:tracer
# flags: instance
# Make sure that function pid matching filter works.
# Also test it on an instance directory
do_function_fork=1
do_funcgraph_proc=1
if [ ! -f options/function-fork ]; then
do_function_fork=0
echo "no option for function-fork found. Option will not be tested."
fi
if [ ! -f options/funcgraph-proc ]; then
do_funcgraph_proc=0
echo "no option for function-fork found. Option will not be tested."
fi
read PID _ < /proc/self/stat
if [ $do_function_fork -eq 1 ]; then
# default value of function-fork option
orig_value=`grep function-fork trace_options`
fi
if [ $do_funcgraph_proc -eq 1 ]; then
orig_value2=`cat options/funcgraph-proc`
echo 1 > options/funcgraph-proc
fi
do_reset() {
if [ $do_function_fork -eq 1 ]; then
echo $orig_value > trace_options
fi
if [ $do_funcgraph_proc -eq 1 ]; then
echo $orig_value2 > options/funcgraph-proc
fi
}
fail() { # msg
do_reset
echo $1
exit_fail
}
do_test() {
TRACER=$1
disable_tracing
echo do_execve* > set_ftrace_filter
echo $FUNCTION_FORK >> set_ftrace_filter
echo $PID > set_ftrace_pid
echo $TRACER > current_tracer
if [ $do_function_fork -eq 1 ]; then
# don't allow children to be traced
echo nofunction-fork > trace_options
fi
enable_tracing
yield
count_pid=`cat trace | grep -v ^# | grep $PID | wc -l`
count_other=`cat trace | grep -v ^# | grep -v $PID | wc -l`
# count_other should be 0
if [ $count_pid -eq 0 -o $count_other -ne 0 ]; then
fail "PID filtering not working?"
fi
disable_tracing
clear_trace
if [ $do_function_fork -eq 0 ]; then
return
fi
# allow children to be traced
echo function-fork > trace_options
enable_tracing
yield
count_pid=`cat trace | grep -v ^# | grep $PID | wc -l`
count_other=`cat trace | grep -v ^# | grep -v $PID | wc -l`
# count_other should NOT be 0
if [ $count_pid -eq 0 -o $count_other -eq 0 ]; then
fail "PID filtering not following fork?"
fi
}
do_test function
if grep -s function_graph available_tracers; then
do_test function_graph
fi
do_reset
exit 0
@@ -0,0 +1,13 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - stacktrace filter command
# requires: set_ftrace_filter
# flags: instance
echo $FUNCTION_FORK:stacktrace >> set_ftrace_filter
grep -q "$FUNCTION_FORK:stacktrace:unlimited" set_ftrace_filter
(echo "forked"; sleep 1)
grep -q "<stack trace>" trace
@@ -0,0 +1,43 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function trace with cpumask
# requires: function:tracer
if ! which nproc ; then
nproc() {
ls -d /sys/devices/system/cpu/cpu[0-9]* | wc -l
}
fi
NP=`nproc`
if [ $NP -eq 1 ] ;then
echo "We can not test cpumask on UP environment"
exit_unresolved
fi
ORIG_CPUMASK=`cat tracing_cpumask`
do_reset() {
echo $ORIG_CPUMASK > tracing_cpumask
}
echo 0 > tracing_on
echo > trace
: "Bitmask only record on CPU1"
echo 2 > tracing_cpumask
MASK=0x`cat tracing_cpumask`
test `printf "%d" $MASK` -eq 2 || do_reset
echo function > current_tracer
echo 1 > tracing_on
(echo "forked")
echo 0 > tracing_on
: "Check CPU1 events are recorded"
grep -q -e "\[001\]" trace || do_reset
: "There should be No other cpu events"
! grep -qv -e "\[001\]" -e "^#" trace || do_reset
do_reset
@@ -0,0 +1,123 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - test for function event triggers
# flags: instance
#
# The triggers are set within the set_ftrace_filter file
# requires: set_ftrace_filter
#
# Ftrace allows to add triggers to functions, such as enabling or disabling
# tracing, enabling or disabling trace events, or recording a stack trace
# within the ring buffer.
#
# This test is designed to test event triggers
do_reset() {
reset_ftrace_filter
reset_tracer
disable_events
clear_trace
enable_tracing
}
fail() { # mesg
echo $1
exit_fail
}
SLEEP_TIME=".1"
echo "Testing function probes with events:"
EVENT="sched:sched_switch"
EVENT_ENABLE="events/sched/sched_switch/enable"
cnt_trace() {
grep -v '^#' trace | wc -l
}
test_event_enabled() {
val=$1
check_times=10 # wait for 10 * SLEEP_TIME at most
while [ $check_times -ne 0 ]; do
e=`cat $EVENT_ENABLE`
if [ "$e" = $val ]; then
return 0
fi
sleep $SLEEP_TIME
check_times=$((check_times - 1))
done
fail "Expected $val but found $e"
}
run_enable_disable() {
enable=$1 # enable
Enable=$2 # Enable
check_disable=$3 # 0
check_enable_star=$4 # 1*
check_disable_star=$5 # 0*
cnt=`cnt_trace`
if [ $cnt -ne 0 ]; then
fail "Found junk in trace file"
fi
echo "$Enable event all the time"
echo $check_disable > $EVENT_ENABLE
sleep $SLEEP_TIME
test_event_enabled $check_disable
echo "schedule:${enable}_event:$EVENT" > set_ftrace_filter
if [ -d ../../instances ]; then # Check instances
cur=`cat set_ftrace_filter`
top=`cat ../../set_ftrace_filter`
if [ "$cur" = "$top" ]; then
echo "This kernel is too old to support per instance filter"
reset_ftrace_filter
exit_unsupported
fi
fi
echo " make sure it works 5 times"
for i in `seq 5`; do
sleep $SLEEP_TIME
echo " test $i"
test_event_enabled $check_enable_star
echo $check_disable > $EVENT_ENABLE
done
sleep $SLEEP_TIME
echo " make sure it still works"
test_event_enabled $check_enable_star
reset_ftrace_filter
echo " make sure it only works 3 times"
echo $check_disable > $EVENT_ENABLE
sleep $SLEEP_TIME
echo "schedule:${enable}_event:$EVENT:3" > set_ftrace_filter
for i in `seq 3`; do
sleep $SLEEP_TIME
echo " test $i"
test_event_enabled $check_enable_star
echo $check_disable > $EVENT_ENABLE
done
sleep $SLEEP_TIME
echo " make sure it stop working"
test_event_enabled $check_disable_star
do_reset
}
run_enable_disable enable Enable 0 "1*" "0*"
run_enable_disable disable Disable 1 "0*" "1*"
@@ -0,0 +1,42 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# description: ftrace - function trace across cpu hotplug
# requires: function:tracer
if ! which nproc ; then
nproc() {
ls -d /sys/devices/system/cpu/cpu[0-9]* | wc -l
}
fi
NP=`nproc`
if [ $NP -eq 1 ] ;then
echo "We cannot test cpu hotplug in UP environment"
exit_unresolved
fi
# Find online cpu
for i in /sys/devices/system/cpu/cpu[1-9]*; do
if [ -f $i/online ] && [ "$(cat $i/online)" = "1" ]; then
cpu=$i
break
fi
done
if [ -z "$cpu" ]; then
echo "We cannot test cpu hotplug with a single cpu online"
exit_unresolved
fi
echo 0 > tracing_on
echo > trace
: "Set $(basename $cpu) offline/online with function tracer enabled"
echo function > current_tracer
echo 1 > tracing_on
(echo 0 > $cpu/online)
(echo "forked"; sleep 1)
(echo 1 > $cpu/online)
echo 0 > tracing_on
echo nop > current_tracer
@@ -0,0 +1,23 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function trace on module
# requires: set_ftrace_filter
: "mod: allows to filter a non exist function"
echo 'non_exist_func:mod:non_exist_module' > set_ftrace_filter
grep -q "non_exist_func" set_ftrace_filter
: "mod: on exist module"
echo '*:mod:trace_printk' > set_ftrace_filter
if ! modprobe trace-printk ; then
echo "No trace-printk sample module - please make CONFIG_SAMPLE_TRACE_PRINTK=
m"
exit_unresolved;
fi
: "Wildcard should be resolved after loading module"
grep -q "trace_printk_irq_work" set_ftrace_filter
: "After removing the filter becomes empty"
rmmod trace_printk
test `cat set_ftrace_filter | wc -l` -eq 0
@@ -0,0 +1,21 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function profiling
# requires: function_profile_enabled
: "Enable function profile"
echo 1 > function_profile_enabled
: "Profile must be updated"
cp trace_stat/function0 $TMPDIR/
( echo "forked"; sleep 1 )
: "diff returns 0 if there is no difference"
! diff trace_stat/function0 $TMPDIR/function0
echo 0 > function_profile_enabled
: "Profile must NOT be updated"
cp trace_stat/function0 $TMPDIR/
( echo "forked"; sleep 1 )
: "diff returns 0 if there is no difference"
diff trace_stat/function0 $TMPDIR/function0
@@ -0,0 +1,64 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function profiler with function tracing
# requires: function_profile_enabled set_ftrace_filter function_graph:tracer
# There was a bug after a rewrite of the ftrace infrastructure that
# caused the function_profiler not to be able to run with the function
# tracer, because the function_profiler used the function_graph tracer
# and it was assumed the two could not run simultaneously.
#
# There was another related bug where the solution to the first bug
# broke the way filtering of the function tracer worked.
#
# This test triggers those bugs on those kernels.
#
# We need function_graph and profiling to to run this test
fail() { # mesg
echo $1
exit_fail
}
echo "Testing function tracer with profiler:"
echo "enable function tracer"
echo function > current_tracer
echo "enable profiler"
echo 1 > function_profile_enabled
sleep 1
echo "Now filter on just schedule"
echo '*schedule' > set_ftrace_filter
clear_trace
echo "Now disable function profiler"
echo 0 > function_profile_enabled
sleep 1
# make sure only schedule functions exist
echo "testing if only schedule is being traced"
if grep -v -e '^#' -e 'schedule' trace; then
fail "more than schedule was found"
fi
echo "Make sure schedule was traced"
if ! grep -e 'schedule' trace > /dev/null; then
cat trace
fail "can not find schedule in trace"
fi
echo > set_ftrace_filter
clear_trace
sleep 1
echo "make sure something other than scheduler is being traced"
if ! grep -v -e '^#' -e 'schedule' trace > /dev/null; then
cat trace
fail "no other functions besides schedule was found"
fi
exit 0
@@ -0,0 +1,161 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - test reading of set_ftrace_filter
#
# The triggers are set within the set_ftrace_filter file
# requires: set_ftrace_filter
#
# The set_ftrace_filter file of ftrace is used to list functions as well as
# triggers (probes) attached to functions. The code to read this file is not
# straight forward and has had various bugs in the past. This test is designed
# to add functions and triggers to that file in various ways and read that
# file in various ways (cat vs dd).
#
fail() { # mesg
echo $1
exit_fail
}
FILTER=set_ftrace_filter
FUNC1="schedule"
if grep '^sched_tick\b' available_filter_functions; then
FUNC2="sched_tick"
elif grep '^scheduler_tick\b' available_filter_functions; then
FUNC2="scheduler_tick"
else
exit_unresolved
fi
ALL_FUNCS="#### all functions enabled ####"
test_func() {
if ! echo "$1" | grep -q "^$2\$"; then
return 0
fi
echo "$1" | grep -v "^$2\$"
return 1
}
check_set_ftrace_filter() {
cat=`cat $FILTER`
dd1=`dd if=$FILTER bs=1 | grep -v -e 'records in' -e 'records out' -e 'bytes copied'`
dd100=`dd if=$FILTER bs=100 | grep -v -e 'records in' -e 'records out' -e 'bytes copied'`
echo "Testing '$@'"
while [ $# -gt 0 ]; do
echo "test $1"
if cat=`test_func "$cat" "$1"`; then
return 0
fi
if dd1=`test_func "$dd1" "$1"`; then
return 0
fi
if dd100=`test_func "$dd100" "$1"`; then
return 0
fi
shift
done
if [ -n "$cat" ]; then
return 0
fi
if [ -n "$dd1" ]; then
return 0
fi
if [ -n "$dd100" ]; then
return 0
fi
return 1;
}
if check_set_ftrace_filter "$ALL_FUNCS"; then
fail "Expected only $ALL_FUNCS"
fi
echo "$FUNC1:traceoff" > set_ftrace_filter
if check_set_ftrace_filter "$ALL_FUNCS" "$FUNC1:traceoff:unlimited"; then
fail "Expected $ALL_FUNCS and $FUNC1:traceoff:unlimited"
fi
echo "$FUNC1" > set_ftrace_filter
if check_set_ftrace_filter "$FUNC1" "$FUNC1:traceoff:unlimited"; then
fail "Expected $FUNC1 and $FUNC1:traceoff:unlimited"
fi
echo "$FUNC2" >> set_ftrace_filter
if check_set_ftrace_filter "$FUNC1" "$FUNC2" "$FUNC1:traceoff:unlimited"; then
fail "Expected $FUNC1 $FUNC2 and $FUNC1:traceoff:unlimited"
fi
echo "$FUNC2:traceoff" >> set_ftrace_filter
if check_set_ftrace_filter "$FUNC1" "$FUNC2" "$FUNC1:traceoff:unlimited" "$FUNC2:traceoff:unlimited"; then
fail "Expected $FUNC1 $FUNC2 $FUNC1:traceoff:unlimited and $FUNC2:traceoff:unlimited"
fi
echo "$FUNC1" > set_ftrace_filter
if check_set_ftrace_filter "$FUNC1" "$FUNC1:traceoff:unlimited" "$FUNC2:traceoff:unlimited"; then
fail "Expected $FUNC1 $FUNC1:traceoff:unlimited and $FUNC2:traceoff:unlimited"
fi
echo > set_ftrace_filter
if check_set_ftrace_filter "$ALL_FUNCS" "$FUNC1:traceoff:unlimited" "$FUNC2:traceoff:unlimited"; then
fail "Expected $ALL_FUNCS $FUNC1:traceoff:unlimited and $FUNC2:traceoff:unlimited"
fi
reset_ftrace_filter
if check_set_ftrace_filter "$ALL_FUNCS"; then
fail "Expected $ALL_FUNCS"
fi
echo "$FUNC1" > set_ftrace_filter
if check_set_ftrace_filter "$FUNC1" ; then
fail "Expected $FUNC1"
fi
echo "$FUNC2" >> set_ftrace_filter
if check_set_ftrace_filter "$FUNC1" "$FUNC2" ; then
fail "Expected $FUNC1 and $FUNC2"
fi
test_actual() { # Compares $TMPDIR/expected with set_ftrace_filter
cat set_ftrace_filter | grep -v '#' | cut -d' ' -f1 | cut -d':' -f1 | sort -u > $TMPDIR/actual
DIFF=`diff $TMPDIR/actual $TMPDIR/expected`
test -z "$DIFF"
}
# Set traceoff trigger for all fuctions with "lock" in their name
cat available_filter_functions | cut -d' ' -f1 | grep 'lock' | sort -u > $TMPDIR/expected
echo '*lock*:traceoff' > set_ftrace_filter
test_actual
# now remove all with 'try' in it, and end with lock
grep -v 'try.*lock$' $TMPDIR/expected > $TMPDIR/expected2
mv $TMPDIR/expected2 $TMPDIR/expected
echo '!*try*lock:traceoff' >> set_ftrace_filter
test_actual
# remove all that start with "m" and end with "lock"
grep -v '^m.*lock$' $TMPDIR/expected > $TMPDIR/expected2
mv $TMPDIR/expected2 $TMPDIR/expected
echo '!m*lock:traceoff' >> set_ftrace_filter
test_actual
# remove all that start with "c" and have "unlock"
grep -v '^c.*unlock' $TMPDIR/expected > $TMPDIR/expected2
mv $TMPDIR/expected2 $TMPDIR/expected
echo '!c*unlock*:traceoff' >> set_ftrace_filter
test_actual
# clear all the rest
> $TMPDIR/expected
echo '!*:traceoff' >> set_ftrace_filter
test_actual
rm $TMPDIR/expected
rm $TMPDIR/actual
exit 0
@@ -0,0 +1,35 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - Max stack tracer
# requires: stack_trace stack_trace_filter
# Test the basic function of max-stack usage tracing
echo > stack_trace_filter
echo 0 > stack_max_size
echo 1 > /proc/sys/kernel/stack_tracer_enabled
: "Fork and wait for the first entry become !lock"
timeout=10
while [ $timeout -ne 0 ]; do
( echo "forked" )
FL=`grep " 0)" stack_trace`
echo $FL | grep -q "lock" || break;
timeout=$((timeout - 1))
done
echo 0 > /proc/sys/kernel/stack_tracer_enabled
echo '*lock*' > stack_trace_filter
test `cat stack_trace_filter | wc -l` -eq `grep lock stack_trace_filter | wc -l`
echo 0 > stack_max_size
echo 1 > /proc/sys/kernel/stack_tracer_enabled
: "Fork and always the first entry including lock"
timeout=10
while [ $timeout -ne 0 ]; do
( echo "forked" )
FL=`grep " 0)" stack_trace`
echo $FL | grep -q "lock"
timeout=$((timeout - 1))
done
echo 0 > /proc/sys/kernel/stack_tracer_enabled
@@ -0,0 +1,173 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - test for function traceon/off triggers
# flags: instance
#
# The triggers are set within the set_ftrace_filter file
# requires: set_ftrace_filter
#
# Ftrace allows to add triggers to functions, such as enabling or disabling
# tracing, enabling or disabling trace events, or recording a stack trace
# within the ring buffer.
#
# This test is designed to test enabling and disabling tracing triggers
#
fail() { # mesg
echo $1
exit_fail
}
SLEEP_TIME=".1"
echo "Testing function probes with enabling disabling tracing:"
cnt_trace() {
grep -v '^#' trace | wc -l
}
echo '** DISABLE TRACING'
disable_tracing
clear_trace
cnt=`cnt_trace`
if [ $cnt -ne 0 ]; then
fail "Found junk in trace"
fi
echo '** ENABLE EVENTS'
echo 1 > events/sched/enable
echo '** ENABLE TRACING'
enable_tracing
cnt=`cnt_trace`
if [ $cnt -eq 0 ]; then
fail "Nothing found in trace"
fi
# powerpc uses .schedule
func="schedule"
available_file=available_filter_functions
if [ -d ../../instances -a -f ../../available_filter_functions ]; then
available_file=../../available_filter_functions
fi
x=`grep '^\.schedule$' available_filter_functions | wc -l`
if [ "$x" -eq 1 ]; then
func=".schedule"
fi
echo '** SET TRACEOFF'
echo "$func:traceoff" > set_ftrace_filter
if [ -d ../../instances ]; then # Check instances
cur=`cat set_ftrace_filter`
top=`cat ../../set_ftrace_filter`
if [ "$cur" = "$top" ]; then
echo "This kernel is too old to support per instance filter"
reset_ftrace_filter
exit_unsupported
fi
fi
cnt=`grep schedule set_ftrace_filter | wc -l`
if [ $cnt -ne 1 ]; then
fail "Did not find traceoff trigger"
fi
cnt=`cnt_trace`
sleep $SLEEP_TIME
cnt2=`cnt_trace`
if [ $cnt -ne $cnt2 ]; then
fail "Tracing is not stopped"
fi
on=`cat tracing_on`
if [ $on != "0" ]; then
fail "Tracing is not off"
fi
# Cannot rely on names being around as they are only cached, strip them
csum1=`cat trace | sed -e 's/^ *[^ ]*\(-[0-9][0-9]*\)/\1/' | md5sum`
sleep $SLEEP_TIME
csum2=`cat trace | sed -e 's/^ *[^ ]*\(-[0-9][0-9]*\)/\1/' | md5sum`
if [ "$csum1" != "$csum2" ]; then
fail "Tracing file is still changing"
fi
clear_trace
cnt=`cnt_trace`
if [ $cnt -ne 0 ]; then
fail "Tracing is still happeing"
fi
echo "!$func:traceoff" >> set_ftrace_filter
cnt=`grep schedule set_ftrace_filter | wc -l`
if [ $cnt -ne 0 ]; then
fail "traceoff trigger still exists"
fi
on=`cat tracing_on`
if [ $on != "0" ]; then
fail "Tracing is started again"
fi
echo "$func:traceon" > set_ftrace_filter
cnt=`grep schedule set_ftrace_filter | wc -l`
if [ $cnt -ne 1 ]; then
fail "traceon trigger not found"
fi
cnt=`cnt_trace`
if [ $cnt -eq 0 ]; then
fail "Tracing did not start"
fi
on=`cat tracing_on`
if [ $on != "1" ]; then
fail "Tracing was not enabled"
fi
echo "!$func:traceon" >> set_ftrace_filter
cnt=`grep schedule set_ftrace_filter | wc -l`
if [ $cnt -ne 0 ]; then
fail "traceon trigger still exists"
fi
check_sleep() {
val=$1
sleep $SLEEP_TIME
cat set_ftrace_filter
on=`cat tracing_on`
if [ $on != "$val" ]; then
fail "Expected tracing_on to be $val, but it was $on"
fi
}
echo "$func:traceoff:3" > set_ftrace_filter
check_sleep "0"
echo 1 > tracing_on
check_sleep "0"
echo 1 > tracing_on
check_sleep "0"
echo 1 > tracing_on
check_sleep "1"
echo "!$func:traceoff:0" > set_ftrace_filter
if grep -e traceon -e traceoff set_ftrace_filter; then
fail "Tracing on and off triggers still exist"
fi
disable_events
exit 0
@@ -0,0 +1,15 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - test tracing error log support
# event tracing is currently the only ftrace tracer that uses the
# tracing error_log, hence this check
# requires: set_event error_log
fail() { #msg
echo $1
exit_fail
}
ftrace_errlog_check 'event filter parse error' '((sig >= 10 && sig < 15) || dsig ^== 17) && comm != bash' 'events/signal/signal_generate/filter'
exit 0
@@ -0,0 +1,230 @@
clear_trace() { # reset trace output
echo > trace
}
disable_tracing() { # stop trace recording
echo 0 > tracing_on
}
enable_tracing() { # start trace recording
echo 1 > tracing_on
}
reset_tracer() { # reset the current tracer
echo nop > current_tracer
}
reset_trigger_file() {
# remove action triggers first
grep -H ':on[^:]*(' $@ |
while read line; do
cmd=`echo $line | cut -f2- -d: | cut -f1 -d"["`
file=`echo $line | cut -f1 -d:`
echo "!$cmd" >> $file
done
grep -Hv ^# $@ |
while read line; do
cmd=`echo $line | cut -f2- -d: | cut -f1 -d"["`
file=`echo $line | cut -f1 -d:`
echo "!$cmd" > $file
done
}
reset_trigger() { # reset all current setting triggers
if [ -d events/synthetic ]; then
reset_trigger_file events/synthetic/*/trigger
fi
reset_trigger_file events/*/*/trigger
}
reset_events_filter() { # reset all current setting filters
grep -v ^none events/*/*/filter |
while read line; do
echo 0 > `echo $line | cut -f1 -d:`
done
}
reset_ftrace_filter() { # reset all triggers in set_ftrace_filter
if [ ! -f set_ftrace_filter ]; then
return 0
fi
echo > set_ftrace_filter
grep -v '^#' set_ftrace_filter | while read t; do
tr=`echo $t | cut -d: -f2`
if [ "$tr" = "" ]; then
continue
fi
if ! grep -q "$t" set_ftrace_filter; then
continue;
fi
name=`echo $t | cut -d: -f1 | cut -d' ' -f1`
if [ $tr = "enable_event" -o $tr = "disable_event" ]; then
tr=`echo $t | cut -d: -f2-4`
limit=`echo $t | cut -d: -f5`
else
tr=`echo $t | cut -d: -f2`
limit=`echo $t | cut -d: -f3`
fi
if [ "$limit" != "unlimited" ]; then
tr="$tr:$limit"
fi
echo "!$name:$tr" > set_ftrace_filter
done
}
disable_events() {
echo 0 > events/enable
}
clear_synthetic_events() { # reset all current synthetic events
grep -v ^# synthetic_events |
while read line; do
echo "!$line" >> synthetic_events
done
}
clear_dynamic_events() { # reset all current dynamic events
again=1
stop=1
# loop mulitple times as some events require other to be removed first
while [ $again -eq 1 ]; do
stop=$((stop+1))
# Prevent infinite loops
if [ $stop -gt 10 ]; then
break;
fi
again=2
grep -v '^#' dynamic_events|
while read line; do
del=`echo $line | sed -e 's/^.\([^ ]*\).*/-\1/'`
if ! echo "$del" >> dynamic_events; then
again=1
fi
done
done
}
initialize_system() { # Reset ftrace to initial-state
# As the initial state, ftrace will be set to nop tracer,
# no events, no triggers, no filters, no function filters,
# no probes, and tracing on.
disable_tracing
reset_tracer
reset_trigger
reset_events_filter
reset_ftrace_filter
disable_events
clear_dynamic_events
[ -f set_event_pid ] && echo > set_event_pid
[ -f set_ftrace_pid ] && echo > set_ftrace_pid
[ -f set_ftrace_notrace ] && echo > set_ftrace_notrace
[ -f set_graph_function ] && echo | tee set_graph_*
[ -f stack_trace_filter ] && echo > stack_trace_filter
[ -f kprobe_events ] && echo > kprobe_events
[ -f uprobe_events ] && echo > uprobe_events
[ -f synthetic_events ] && echo > synthetic_events
[ -f snapshot ] && echo 0 > snapshot
# Stop tracing while reading the trace file by default, to prevent
# the test results while checking it and to avoid taking a long time
# to check the result.
[ -f options/pause-on-trace ] && echo 1 > options/pause-on-trace
clear_trace
enable_tracing
}
finish_system() {
initialize_system
# And recover it to default.
[ -f options/pause-on-trace ] && echo 0 > options/pause-on-trace
}
check_requires() { # Check required files and tracers
for i in "$@" ; do
p=${i%:program}
r=${i%:README}
t=${i%:tracer}
if [ "$p" != "$i" ]; then
if ! which "$p" ; then
echo "Required program $p is not found."
exit_unresolved
fi
elif [ "$t" != "$i" ]; then
if ! grep -wq "$t" available_tracers ; then
echo "Required tracer $t is not configured."
exit_unsupported
fi
elif [ "$r" != "$i" ]; then
# If this is an instance, check the top directory
if echo $TRACING_DIR | grep -q "/instances/"; then
test="$TRACING_DIR/../.."
else
test=$TRACING_DIR
fi
if ! grep -Fq "$r" "$test"/README ; then
echo "Required feature pattern \"$r\" is not in README."
exit_unsupported
fi
elif [ ! -e "$i" ]; then
echo "Required feature interface $i doesn't exist."
exit_unsupported
fi
done
}
check_awk_strtonum() { # strtonum is GNU awk extension
awk 'BEGIN{strtonum("0x1")}'
}
LOCALHOST=127.0.0.1
yield() {
ping $LOCALHOST -c 1 || sleep .001 || usleep 1 || sleep 1
}
# The fork function in the kernel was renamed from "_do_fork" to
# "kernel_fork". As older tests should still work with older kernels
# as well as newer kernels, check which version of fork is used on this
# kernel so that the tests can use the fork function for the running kernel.
FUNCTION_FORK=`(if grep '\bkernel_clone\b' /proc/kallsyms > /dev/null; then
echo kernel_clone; else echo '_do_fork'; fi)`
# Since probe event command may include backslash, explicitly use printf "%s"
# to NOT interpret it.
ftrace_errlog_check() { # err-prefix command-with-error-pos-by-^ command-file
pos=$(printf "%s" "${2%^*}" | wc -c) # error position
command=$(printf "%s" "$2" | tr -d ^)
echo "Test command: $command"
echo > error_log
(! printf "%s" "$command" >> "$3" ) 2> /dev/null
grep "$1: error:" -A 3 error_log
N=$(tail -n 1 error_log | wc -c)
# " Command: " and "^\n" => 13
test $(expr 13 + $pos) -eq $N
}
# Helper to get the tracefs mount point
get_mount_point() {
local mount_point=`stat -c '%m' .`
# If stat -c '%m' does not work (e.g. busybox) or failed, try to use the
# current working directory (which should be a tracefs) as the mount point.
if [ ! -d "$mount_point" ]; then
if mount | grep -qw "$PWD"; then
mount_point=$PWD
else
# If PWD doesn't work, that is an environmental problem.
exit_unresolved
fi
fi
echo "$mount_point"
}
# Helper function to retrieve mount options for a given mount point
get_mnt_options() {
local mnt_point="$1"
local opts=$(mount | grep -m1 "$mnt_point" | sed -e 's/.*(\(.*\)).*/\1/')
echo "$opts"
}
@@ -0,0 +1,142 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test creation and deletion of trace instances while setting an event
# requires: instances
fail() { # mesg
rmdir foo 2>/dev/null
echo $1
set -e
exit_fail
}
cd instances
# we don't want to fail on error
set +e
mkdir x
rmdir x
result=$?
if [ $result -ne 0 ]; then
echo "instance rmdir not supported"
exit_unsupported
fi
instance_slam() {
while :; do
mkdir foo 2> /dev/null
rmdir foo 2> /dev/null
done
}
instance_read() {
while :; do
cat foo/trace 1> /dev/null 2>&1
done
}
instance_set() {
while :; do
echo 1 > foo/events/sched/sched_switch/enable
done 2> /dev/null
}
instance_slam &
p1=$!
echo $p1
instance_set &
p2=$!
echo $p2
instance_read &
p3=$!
echo $p3
sleep 1
kill -1 $p3
kill -1 $p2
kill -1 $p1
echo "Wait for processes to finish"
wait $p1 $p2 $p3
echo "all processes finished, wait for cleanup"
sleep 1
mkdir foo
ls foo > /dev/null
rmdir foo
if [ -d foo ]; then
fail "foo still exists"
fi
mkdir foo
echo "schedule:enable_event:sched:sched_switch" > foo/set_ftrace_filter
rmdir foo
if [ -d foo ]; then
fail "foo still exists"
fi
if grep -q "schedule:enable_event:sched:sched_switch" ../set_ftrace_filter; then
echo "Older kernel detected. Cleanup filter"
echo '!schedule:enable_event:sched:sched_switch' > ../set_ftrace_filter
fi
instance_slam() {
while :; do
mkdir x
mkdir y
mkdir z
rmdir x
rmdir y
rmdir z
done 2>/dev/null
}
instance_slam &
p1=$!
echo $p1
instance_slam &
p2=$!
echo $p2
instance_slam &
p3=$!
echo $p3
instance_slam &
p4=$!
echo $p4
instance_slam &
p5=$!
echo $p5
ls -lR >/dev/null
sleep 1
kill -1 $p1
kill -1 $p2
kill -1 $p3
kill -1 $p4
kill -1 $p5
echo "Wait for processes to finish"
wait $p1 $p2 $p3 $p4 $p5
echo "all processes finished, wait for cleanup"
mkdir x y z
ls x y z
rmdir x y z
for d in x y z; do
if [ -d $d ]; then
fail "instance $d still exists"
fi
done
set -e
exit 0
@@ -0,0 +1,82 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test creation and deletion of trace instances
# requires: instances
fail() { # mesg
rmdir x y z 2>/dev/null
echo $1
set -e
exit_fail
}
cd instances
# we don't want to fail on error
set +e
mkdir x
rmdir x
result=$?
if [ $result -ne 0 ]; then
echo "instance rmdir not supported"
exit_unsupported
fi
instance_slam() {
while :; do
mkdir x
mkdir y
mkdir z
rmdir x
rmdir y
rmdir z
done 2>/dev/null
}
instance_slam &
p1=$!
echo $p1
instance_slam &
p2=$!
echo $p2
instance_slam &
p3=$!
echo $p3
instance_slam &
p4=$!
echo $p4
instance_slam &
p5=$!
echo $p5
ls -lR >/dev/null
sleep 1
kill -1 $p1
kill -1 $p2
kill -1 $p3
kill -1 $p4
kill -1 $p5
echo "Wait for processes to finish"
wait $p1 $p2 $p3 $p4 $p5
echo "all processes finished, wait for cleanup"
mkdir x y z
ls x y z
rmdir x y z
for d in x y z; do
if [ -d $d ]; then
fail "instance $d still exists"
fi
done
set -e
exit 0
@@ -0,0 +1,9 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe dynamic event - adding and removing
# requires: kprobe_events
echo p:myevent $FUNCTION_FORK > kprobe_events
grep myevent kprobe_events
test -d events/kprobes/myevent
echo > kprobe_events
@@ -0,0 +1,11 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe dynamic event - busy event check
# requires: kprobe_events
echo p:myevent $FUNCTION_FORK > kprobe_events
test -d events/kprobes/myevent
echo 1 > events/kprobes/myevent/enable
echo > kprobe_events && exit_fail # this must fail
echo 0 > events/kprobes/myevent/enable
echo > kprobe_events # this must succeed
@@ -0,0 +1,19 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe dynamic event with arguments
# requires: kprobe_events
echo "p:testprobe $FUNCTION_FORK \$stack \$stack0 +0(\$stack)" > kprobe_events
grep testprobe kprobe_events | grep -q 'arg1=\$stack arg2=\$stack0 arg3=+0(\$stack)'
test -d events/kprobes/testprobe
echo 1 > events/kprobes/testprobe/enable
( echo "forked")
grep testprobe trace | grep "$FUNCTION_FORK" | \
grep -q 'arg1=0x[[:xdigit:]]* arg2=0x[[:xdigit:]]* arg3=0x[[:xdigit:]]*$'
echo 0 > events/kprobes/testprobe/enable
echo "-:testprobe" >> kprobe_events
clear_trace
test -d events/kprobes/testprobe && exit_fail || exit_pass
@@ -0,0 +1,60 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe event char type argument
# requires: kprobe_events available_filter_functions
case `uname -m` in
x86_64)
ARG1=%di
;;
i[3456]86)
ARG1=%ax
;;
aarch64)
ARG1=%x0
;;
arm*)
ARG1=%r0
;;
ppc64*)
ARG1=%r3
;;
ppc*)
ARG1=%r3
;;
s390*)
ARG1=%r2
;;
mips*)
ARG1=%r4
;;
loongarch*)
ARG1=%r4
;;
riscv*)
ARG1=%a0
;;
*)
echo "Please implement other architecture here"
exit_untested
esac
: "Test get argument (1)"
if grep -q eventfs_create_dir available_filter_functions; then
DIR_NAME="eventfs_create_dir"
elif grep -q eventfs_add_dir available_filter_functions; then
DIR_NAME="eventfs_add_dir"
else
DIR_NAME="tracefs_create_dir"
fi
echo "p:testprobe ${DIR_NAME} arg1=+0(${ARG1}):char" > kprobe_events
echo 1 > events/kprobes/testprobe/enable
echo "p:test $FUNCTION_FORK" >> kprobe_events
grep -qe "testprobe.* arg1='t'" trace
echo 0 > events/kprobes/testprobe/enable
: "Test get argument (2)"
echo "p:testprobe ${DIR_NAME} arg1=+0(${ARG1}):char arg2=+0(${ARG1}):char[4]" > kprobe_events
echo 1 > events/kprobes/testprobe/enable
echo "p:test $FUNCTION_FORK" >> kprobe_events
grep -qe "testprobe.* arg1='t' arg2={'t','e','s','t'}" trace
@@ -0,0 +1,16 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe event with comm arguments
# requires: kprobe_events
grep -A1 "fetcharg:" README | grep -q "\$comm" || exit_unsupported # this is too old
echo "p:testprobe $FUNCTION_FORK comm=\$comm " > kprobe_events
grep testprobe kprobe_events | grep -q 'comm=$comm'
test -d events/kprobes/testprobe
echo 1 > events/kprobes/testprobe/enable
( echo "forked")
grep testprobe trace | grep -q 'comm=".*"'
exit 0
@@ -0,0 +1,61 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe event string type argument
# requires: kprobe_events available_filter_functions
case `uname -m` in
x86_64)
ARG1=%di
;;
i[3456]86)
ARG1=%ax
;;
aarch64)
ARG1=%x0
;;
arm*)
ARG1=%r0
;;
ppc64*)
ARG1=%r3
;;
ppc*)
ARG1=%r3
;;
s390*)
ARG1=%r2
;;
mips*)
ARG1=%r4
;;
loongarch*)
ARG1=%r4
;;
riscv*)
ARG1=%a0
;;
*)
echo "Please implement other architecture here"
exit_untested
esac
: "Test get argument (1)"
if grep -q eventfs_create_dir available_filter_functions; then
DIR_NAME="eventfs_create_dir"
elif grep -q eventfs_add_dir available_filter_functions; then
DIR_NAME="eventfs_add_dir"
else
DIR_NAME="tracefs_create_dir"
fi
echo "p:testprobe ${DIR_NAME} arg1=+0(${ARG1}):string" > kprobe_events
echo 1 > events/kprobes/testprobe/enable
echo "p:test $FUNCTION_FORK" >> kprobe_events
grep -qe "testprobe.* arg1=\"test\"" trace
echo 0 > events/kprobes/testprobe/enable
: "Test get argument (2)"
echo "p:testprobe ${DIR_NAME} arg1=+0(${ARG1}):string arg2=+0(${ARG1}):string" > kprobe_events
echo 1 > events/kprobes/testprobe/enable
echo "p:test $FUNCTION_FORK" >> kprobe_events
grep -qe "testprobe.* arg1=\"test\" arg2=\"test\"" trace
@@ -0,0 +1,38 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe event symbol argument
# requires: kprobe_events
SYMBOL="linux_proc_banner"
if [ ! -f /proc/kallsyms ]; then
echo "Can not check the target symbol - please enable CONFIG_KALLSYMS"
exit_unresolved
elif ! grep "$SYMBOL\$" /proc/kallsyms; then
echo "Linux banner is not exported - please enable CONFIG_KALLSYMS_ALL"
exit_unresolved
fi
: "Test get basic types symbol argument"
echo "p:testprobe_u $FUNCTION_FORK arg1=@linux_proc_banner:u64 arg2=@linux_proc_banner:u32 arg3=@linux_proc_banner:u16 arg4=@linux_proc_banner:u8" > kprobe_events
echo "p:testprobe_s $FUNCTION_FORK arg1=@linux_proc_banner:s64 arg2=@linux_proc_banner:s32 arg3=@linux_proc_banner:s16 arg4=@linux_proc_banner:s8" >> kprobe_events
if grep -q "x8/16/32/64" README; then
echo "p:testprobe_x $FUNCTION_FORK arg1=@linux_proc_banner:x64 arg2=@linux_proc_banner:x32 arg3=@linux_proc_banner:x16 arg4=@linux_proc_banner:x8" >> kprobe_events
fi
echo "p:testprobe_bf $FUNCTION_FORK arg1=@linux_proc_banner:b8@4/32" >> kprobe_events
echo 1 > events/kprobes/enable
(echo "forked")
echo 0 > events/kprobes/enable
grep "testprobe_[usx]:.* arg1=.* arg2=.* arg3=.* arg4=.*" trace
grep "testprobe_bf:.* arg1=.*" trace
: "Test get string symbol argument"
echo "p:testprobe_str $FUNCTION_FORK arg1=@linux_proc_banner:string" > kprobe_events
echo 1 > events/kprobes/enable
(echo "forked")
echo 0 > events/kprobes/enable
RESULT=`grep "testprobe_str" trace | sed -e 's/.* arg1=\(.*\)/\1/'`
RESULT=`echo $RESULT | sed -e 's/.* \((.*)\) \((.*)\) .*/\1 \2/'`
ORIG=`cat /proc/version | sed -e 's/.* \((.*)\) \((.*)\) .*/\1 \2/'`
test "$RESULT" = "$ORIG"
@@ -0,0 +1,115 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe event argument syntax
# requires: kprobe_events "x8/16/32/64":README
PROBEFUNC="vfs_read"
GOODREG=
BADREG=
GOODSYM="_sdata"
if ! grep -qw ${GOODSYM} /proc/kallsyms ; then
GOODSYM=$PROBEFUNC
fi
BADSYM="deaqswdefr"
SYMADDR=0x`grep -w ${GOODSYM} /proc/kallsyms | cut -f 1 -d " "`
GOODTYPE="x16"
BADTYPE="y16"
case `uname -m` in
x86_64|i[3456]86)
GOODREG=%ax
BADREG=%ex
;;
aarch64)
GOODREG=%x0
BADREG=%ax
;;
arm*)
GOODREG=%r0
BADREG=%ax
;;
ppc*)
GOODREG=%r3
BADREG=%msr
;;
s390*)
GOODREG=%r2
BADREG=%s2
;;
mips*)
GOODREG=%r4
BADREG=%r12
;;
loongarch*)
GOODREG=%r4
BADREG=%r12
;;
riscv*)
GOODREG=%a0
BADREG=%a8
;;
*)
echo "Please implement other architecture here"
exit_untested
esac
test_goodarg() # Good-args
{
while [ "$1" ]; do
echo "p ${PROBEFUNC} $1" > kprobe_events
shift 1
done;
}
test_badarg() # Bad-args
{
while [ "$1" ]; do
! echo "p ${PROBEFUNC} $1" > kprobe_events
shift 1
done;
}
echo > kprobe_events
: "Register access"
test_goodarg ${GOODREG}
test_badarg ${BADREG}
: "Symbol access"
test_goodarg "@${GOODSYM}" "@${SYMADDR}" "@${GOODSYM}+10" "@${GOODSYM}-10"
test_badarg "@" "@${BADSYM}" "@${GOODSYM}*10" "@${GOODSYM}/10" \
"@${GOODSYM}%10" "@${GOODSYM}&10" "@${GOODSYM}|10"
: "Stack access"
test_goodarg "\$stack" "\$stack0" "\$stack1"
test_badarg "\$stackp" "\$stack0+10" "\$stack1-10"
: "Retval access"
echo "r ${PROBEFUNC} \$retval" > kprobe_events
! echo "p ${PROBEFUNC} \$retval" > kprobe_events
# $comm was introduced in 4.8, older kernels reject it.
if grep -A1 "fetcharg:" README | grep -q '\$comm' ; then
: "Comm access"
test_goodarg "\$comm"
fi
: "Indirect memory access"
test_goodarg "+0(${GOODREG})" "-0(${GOODREG})" "+10(\$stack)" \
"+0(\$stack1)" "+10(@${GOODSYM}-10)" "+0(+10(+20(\$stack)))"
test_badarg "+(${GOODREG})" "(${GOODREG}+10)" "-(${GOODREG})" "(${GOODREG})" \
"+10(\$comm)" "+0(${GOODREG})+10"
: "Name assignment"
test_goodarg "varname=${GOODREG}"
test_badarg "varname=varname2=${GOODREG}"
: "Type syntax"
test_goodarg "${GOODREG}:${GOODTYPE}"
test_badarg "${GOODREG}::${GOODTYPE}" "${GOODREG}:${BADTYPE}" \
"${GOODTYPE}:${GOODREG}"
: "Combination check"
test_goodarg "\$comm:string" "+0(\$stack):string"
test_badarg "\$comm:x64" "\$stack:string" "${GOODREG}:string"
@@ -0,0 +1,47 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobes event arguments with types
# requires: kprobe_events "x8/16/32/64":README
gen_event() { # Bitsize
echo "p:testprobe $FUNCTION_FORK \$stack0:s$1 \$stack0:u$1 \$stack0:x$1 \$stack0:b4@4/$1"
}
check_types() { # s-type u-type x-type bf-type width
test $# -eq 5
CW=$5
CW=$((CW / 4))
X1=`printf "%x" $1 | tail -c ${CW}`
X2=`printf "%x" $2`
X3=`printf "%x" $3`
test $X1 = $X2
test $X2 = $X3
test 0x$X3 = $3
B4=`printf "%1x" $4`
B3=`printf "%03x" 0x$X3 | tail -c 2 | head -c 1`
test $B3 = $B4
}
for width in 64 32 16 8; do
: "Add new event with basic types"
gen_event $width > kprobe_events
grep testprobe kprobe_events
test -d events/kprobes/testprobe
: "Trace the event"
echo 1 > events/kprobes/testprobe/enable
( echo "forked")
echo 0 > events/kprobes/testprobe/enable
: "Confirm the arguments is recorded in given types correctly"
ARGS=`grep "testprobe" trace | head -n 1 | sed -e 's/.* arg1=\(.*\) arg2=\(.*\) arg3=\(.*\) arg4=\(.*\)/\1 \2 \3 \4/'`
check_types $ARGS $width
: "Clear event for next loop"
echo "-:testprobe" >> kprobe_events
clear_trace
done
exit_pass
@@ -0,0 +1,34 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe event user-memory access
# requires: kprobe_events '$arg<N>':README
grep -A10 "fetcharg:" README | grep -q 'ustring' || exit_unsupported
grep -A10 "fetcharg:" README | grep -q '\[u\]<offset>' || exit_unsupported
:;: "user-memory access syntax and ustring working on user memory";:
echo 'p:myevent do_sys_open path=+0($arg2):ustring path2=+u0($arg2):string' \
> kprobe_events
echo 'p:myevent2 do_sys_openat2 path=+0($arg2):ustring path2=+u0($arg2):string' \
>> kprobe_events
grep myevent kprobe_events | \
grep -q 'path=+0($arg2):ustring path2=+u0($arg2):string'
echo 1 > events/kprobes/myevent/enable
echo 1 > events/kprobes/myevent2/enable
echo > /dev/null
echo 0 > events/kprobes/myevent/enable
echo 0 > events/kprobes/myevent2/enable
grep myevent trace | grep -q 'path="/dev/null" path2="/dev/null"'
:;: "user-memory access syntax and ustring not working with kernel memory";:
echo 'p:myevent vfs_symlink path=+0($arg3):ustring path2=+u0($arg3):string' \
> kprobe_events
echo 1 > events/kprobes/myevent/enable
ln -s foo $TMPDIR/bar
echo 0 > events/kprobes/myevent/enable
grep myevent trace | grep -q 'path=(fault) path2=(fault)'
exit 0
@@ -0,0 +1,40 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe event VFS type argument
# requires: kprobe_events "%pd/%pD":README
: "Test argument %pd with name"
echo 'p:testprobe dput name=$arg1:%pd' > kprobe_events
echo 1 > events/kprobes/testprobe/enable
grep -q "1" events/kprobes/testprobe/enable
echo 0 > events/kprobes/testprobe/enable
grep "dput" trace | grep -q "enable"
echo "" > kprobe_events
echo "" > trace
: "Test argument %pd without name"
echo 'p:testprobe dput $arg1:%pd' > kprobe_events
echo 1 > events/kprobes/testprobe/enable
grep -q "1" events/kprobes/testprobe/enable
echo 0 > events/kprobes/testprobe/enable
grep "dput" trace | grep -q "enable"
echo "" > kprobe_events
echo "" > trace
: "Test argument %pD with name"
echo 'p:testprobe vfs_read name=$arg1:%pD' > kprobe_events
echo 1 > events/kprobes/testprobe/enable
grep -q "1" events/kprobes/testprobe/enable
echo 0 > events/kprobes/testprobe/enable
grep "vfs_read" trace | grep -q "enable"
echo "" > kprobe_events
echo "" > trace
: "Test argument %pD without name"
echo 'p:testprobe vfs_read $arg1:%pD' > kprobe_events
echo 1 > events/kprobes/testprobe/enable
grep -q "1" events/kprobes/testprobe/enable
echo 0 > events/kprobes/testprobe/enable
grep "vfs_read" trace | grep -q "enable"
echo "" > kprobe_events
echo "" > trace
@@ -0,0 +1,46 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe event auto/manual naming
# requires: kprobe_events
:;: "Add an event on function without name" ;:
FUNC=`grep " [tT] .*vfs_read$" /proc/kallsyms | tail -n 1 | cut -f 3 -d " "`
[ "x" != "x$FUNC" ] || exit_unresolved
echo "p $FUNC" > kprobe_events
PROBE_NAME=`echo $FUNC | tr ".:" "_"`
test -d events/kprobes/p_${PROBE_NAME}_0 || exit_failure
:;: "Add an event on function with new name" ;:
echo "p:event1 $FUNC" > kprobe_events
test -d events/kprobes/event1 || exit_failure
:;: "Add an event on function with new name and group" ;:
echo "p:kprobes2/event2 $FUNC" > kprobe_events
test -d events/kprobes2/event2 || exit_failure
:;: "Add an event on dot function without name" ;:
find_dot_func() {
if [ ! -f available_filter_functions ]; then
grep -m 10 " [tT] .*\.isra\..*$" /proc/kallsyms | tail -n 1 | cut -f 3 -d " "
return;
fi
grep " [tT] .*\.isra\..*" /proc/kallsyms | cut -f 3 -d " " | while read f; do
cnt=`grep -s $f available_filter_functions | wc -l`;
if [ $cnt -eq 1 ]; then
echo $f
break
fi
done
}
FUNC=`find_dot_func | tail -n 1`
[ "x" != "x$FUNC" ] || exit_unresolved
echo "p $FUNC" > kprobe_events
EVENT=`grep $FUNC kprobe_events | cut -f 1 -d " " | cut -f 2 -d:`
[ "x" != "x$EVENT" ] || exit_failure
test -d events/$EVENT || exit_failure
@@ -0,0 +1,45 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe dynamic event with function tracer
# requires: kprobe_events stack_trace_filter function:tracer
# prepare
echo nop > current_tracer
echo $FUNCTION_FORK > set_ftrace_filter
echo "p:testprobe $FUNCTION_FORK" > kprobe_events
# kprobe on / ftrace off
echo 1 > events/kprobes/testprobe/enable
echo > trace
( echo "forked")
grep testprobe trace
! grep "$FUNCTION_FORK <-" trace
# kprobe on / ftrace on
echo function > current_tracer
echo > trace
( echo "forked")
grep testprobe trace
grep "$FUNCTION_FORK <-" trace
# kprobe off / ftrace on
echo 0 > events/kprobes/testprobe/enable
echo > trace
( echo "forked")
! grep testprobe trace
grep "$FUNCTION_FORK <-" trace
# kprobe on / ftrace on
echo 1 > events/kprobes/testprobe/enable
echo function > current_tracer
echo > trace
( echo "forked")
grep testprobe trace
grep "$FUNCTION_FORK <-" trace
# kprobe on / ftrace off
echo nop > current_tracer
echo > trace
( echo "forked")
grep testprobe trace
! grep "$FUNCTION_FORK <-" trace
@@ -0,0 +1,19 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2023 Akanksha J N, IBM corporation
# description: Register multiple kprobe events in a function
# requires: kprobe_events
for i in `seq 0 255`; do
echo p $FUNCTION_FORK+${i} >> kprobe_events || continue
done
cat kprobe_events >> $testlog
echo 1 > events/kprobes/enable
( echo "forked" )
echo 0 > events/kprobes/enable
echo > kprobe_events
echo "Waiting for unoptimizing & freeing"
sleep 5
echo "Done"
@@ -0,0 +1,52 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe dynamic event - probing module
# requires: kprobe_events
rmmod trace-printk ||:
if ! modprobe trace-printk ; then
echo "No trace-printk sample module - please make CONFIG_SAMPLE_TRACE_PRINTK=
m"
exit_unresolved;
fi
MOD=trace_printk
FUNC=trace_printk_irq_work
:;: "Add an event on a module function without specifying event name" ;:
echo "p $MOD:$FUNC" > kprobe_events
PROBE_NAME=`echo $MOD:$FUNC | tr ".:" "_"`
test -d events/kprobes/p_${PROBE_NAME}_0 || exit_failure
:;: "Add an event on a module function with new event name" ;:
echo "p:event1 $MOD:$FUNC" > kprobe_events
test -d events/kprobes/event1 || exit_failure
:;: "Add an event on a module function with new event and group name" ;:
echo "p:kprobes1/event1 $MOD:$FUNC" > kprobe_events
test -d events/kprobes1/event1 || exit_failure
:;: "Remove target module, but event still be there" ;:
if ! rmmod trace-printk ; then
echo "Failed to unload module - please enable CONFIG_MODULE_UNLOAD"
exit_unresolved;
fi
test -d events/kprobes1/event1
:;: "Check posibility to defining events on unloaded module";:
echo "p:event2 $MOD:$FUNC" >> kprobe_events
:;: "Target is gone, but we can prepare for next time";:
echo 1 > events/kprobes1/event1/enable
:;: "Load module again, which means the event1 should be recorded";:
modprobe trace-printk
grep "event1:" trace
:;: "Remove the module again and check the event is not locked"
rmmod trace-printk
echo 0 > events/kprobes1/event1/enable
echo "-:kprobes1/event1" >> kprobe_events
@@ -0,0 +1,32 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Create/delete multiprobe on kprobe event
# requires: kprobe_events "Create/append/":README
# Choose 2 symbols for target
SYM1=$FUNCTION_FORK
SYM2=do_exit
EVENT_NAME=kprobes/testevent
DEF1="p:$EVENT_NAME $SYM1"
DEF2="p:$EVENT_NAME $SYM2"
:;: "Define an event which has 2 probes" ;:
echo $DEF1 >> kprobe_events
echo $DEF2 >> kprobe_events
cat kprobe_events | grep "$DEF1"
cat kprobe_events | grep "$DEF2"
:;: "Remove the event by name (should remove both)" ;:
echo "-:$EVENT_NAME" >> kprobe_events
test `cat kprobe_events | wc -l` -eq 0
:;: "Remove just 1 event" ;:
echo $DEF1 >> kprobe_events
echo $DEF2 >> kprobe_events
echo "-:$EVENT_NAME $SYM1" >> kprobe_events
! cat kprobe_events | grep "$DEF1"
cat kprobe_events | grep "$DEF2"
:;: "Appending different type must fail" ;:
! echo "$DEF1 \$stack" >> kprobe_events
@@ -0,0 +1,13 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test failure of registering kprobe on non unique symbol
# requires: kprobe_events
SYMBOL='name_show'
# We skip this test on kernel where SYMBOL is unique or does not exist.
if [ "$(grep -c -E "[[:alnum:]]+ t ${SYMBOL}" /proc/kallsyms)" -le '1' ]; then
exit_unsupported
fi
! echo "p:test_non_unique ${SYMBOL}" > kprobe_events
@@ -0,0 +1,34 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2023 Akanksha J N, IBM corporation
# description: Register/unregister optimized probe
# requires: kprobe_events
case `uname -m` in
x86_64)
;;
arm*)
;;
ppc*)
;;
*)
echo "Please implement other architecture here"
exit_unsupported
esac
DEFAULT=$(cat /proc/sys/debug/kprobes-optimization)
echo 1 > /proc/sys/debug/kprobes-optimization
for i in `seq 0 255`; do
echo "p:testprobe $FUNCTION_FORK+${i}" > kprobe_events || continue
echo 1 > events/kprobes/enable || continue
(echo "forked")
PROBE=$(grep $FUNCTION_FORK /sys/kernel/debug/kprobes/list)
echo 0 > events/kprobes/enable
echo > kprobe_events
if echo $PROBE | grep -q OPTIMIZED; then
echo "$DEFAULT" > /proc/sys/debug/kprobes-optimization
exit_pass
fi
done
echo "$DEFAULT" > /proc/sys/debug/kprobes-optimization
exit_unresolved
@@ -0,0 +1,122 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe event parser error log check
# requires: kprobe_events error_log
check_error() { # command-with-error-pos-by-^
ftrace_errlog_check 'trace_kprobe' "$1" 'kprobe_events'
}
if grep -q 'r\[maxactive\]' README; then
check_error 'p^100 vfs_read' # BAD_MAXACT_TYPE
check_error 'r^1a111 vfs_read' # BAD_MAXACT
check_error 'r^100000 vfs_read' # MAXACT_TOO_BIG
fi
check_error 'p ^non_exist_func' # BAD_PROBE_ADDR (enoent)
check_error 'p ^hoge-fuga' # BAD_PROBE_ADDR (bad syntax)
check_error 'p ^hoge+1000-1000' # BAD_PROBE_ADDR (bad syntax)
check_error 'r ^vfs_read+10' # BAD_RETPROBE
check_error 'p:^/bar vfs_read' # NO_GROUP_NAME
check_error 'p:^12345678901234567890123456789012345678901234567890123456789012345/bar vfs_read' # GROUP_TOO_LONG
check_error 'p:^foo.1/bar vfs_read' # BAD_GROUP_NAME
check_error 'p:^ vfs_read' # NO_EVENT_NAME
check_error 'p:foo/^12345678901234567890123456789012345678901234567890123456789012345 vfs_read' # EVENT_TOO_LONG
check_error 'p:foo/^bar.1 vfs_read' # BAD_EVENT_NAME
check_error 'p vfs_read ^$retval' # RETVAL_ON_PROBE
check_error 'p vfs_read ^$stack10000' # BAD_STACK_NUM
if grep -q '$arg<N>' README; then
check_error 'p vfs_read ^$arg10000' # BAD_ARG_NUM
fi
check_error 'p vfs_read ^$none_var' # BAD_VAR
check_error 'p vfs_read ^%none_reg' # BAD_REG_NAME
check_error 'p vfs_read ^@12345678abcde' # BAD_MEM_ADDR
check_error 'p vfs_read ^@+10' # FILE_ON_KPROBE
grep -q "imm-value" README && \
check_error 'p vfs_read arg1=\^x' # BAD_IMM
grep -q "imm-string" README && \
check_error 'p vfs_read arg1=\"abcd^' # IMMSTR_NO_CLOSE
check_error 'p vfs_read ^+0@0)' # DEREF_NEED_BRACE
check_error 'p vfs_read ^+0ab1(@0)' # BAD_DEREF_OFFS
check_error 'p vfs_read +0(+0(@0^)' # DEREF_OPEN_BRACE
if grep -A1 "fetcharg:" README | grep -q '\$comm' ; then
check_error 'p vfs_read +0(^$comm)' # COMM_CANT_DEREF
fi
check_error 'p vfs_read ^&1' # BAD_FETCH_ARG
# We've introduced this limitation with array support
if grep -q ' <type>\\\[<array-size>\\\]' README; then
check_error 'p vfs_read +0(^+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(@0))))))))))))))' # TOO_MANY_OPS?
check_error 'p vfs_read +0(@11):u8[10^' # ARRAY_NO_CLOSE
check_error 'p vfs_read +0(@11):u8[10]^a' # BAD_ARRAY_SUFFIX
check_error 'p vfs_read +0(@11):u8[^10a]' # BAD_ARRAY_NUM
check_error 'p vfs_read +0(@11):u8[^256]' # ARRAY_TOO_BIG
fi
check_error 'p vfs_read @11:^unknown_type' # BAD_TYPE
check_error 'p vfs_read $stack0:^string' # BAD_STRING
check_error 'p vfs_read @11:^b10@a/16' # BAD_BITFIELD
check_error 'p vfs_read ^arg123456789012345678901234567890=@11' # ARG_NAME_TOO_LOG
check_error 'p vfs_read ^=@11' # NO_ARG_NAME
check_error 'p vfs_read ^var.1=@11' # BAD_ARG_NAME
check_error 'p vfs_read var1=@11 ^var1=@12' # USED_ARG_NAME
check_error 'p vfs_read ^+1234567(+1234567(+1234567(+1234567(+1234567(+1234567(@1234))))))' # ARG_TOO_LONG
check_error 'p vfs_read arg1=^' # NO_ARG_BODY
# instruction boundary check is valid on x86 (at this moment)
case $(uname -m) in
x86_64|i[3456]86)
echo 'p vfs_read' > kprobe_events
if grep -q FTRACE ../kprobes/list ; then
check_error 'p ^vfs_read+3' # BAD_INSN_BNDRY (only if function-tracer is enabled)
fi
;;
esac
# multiprobe errors
if grep -q "Create/append/" README && grep -q "imm-value" README; then
echo "p:kprobes/testevent $FUNCTION_FORK" > kprobe_events
check_error '^r:kprobes/testevent do_exit' # DIFF_PROBE_TYPE
# Explicitly use printf "%s" to not interpret \1
printf "%s" "p:kprobes/testevent $FUNCTION_FORK abcd=\\1" > kprobe_events
check_error "p:kprobes/testevent $FUNCTION_FORK ^bcd=\\1" # DIFF_ARG_TYPE
check_error "p:kprobes/testevent $FUNCTION_FORK ^abcd=\\1:u8" # DIFF_ARG_TYPE
check_error "p:kprobes/testevent $FUNCTION_FORK ^abcd=\\\"foo\"" # DIFF_ARG_TYPE
check_error "^p:kprobes/testevent $FUNCTION_FORK abcd=\\1" # SAME_PROBE
fi
# %return suffix errors
if grep -q "place (kretprobe): .*%return.*" README; then
check_error 'p vfs_read^%hoge' # BAD_ADDR_SUFFIX
check_error 'p ^vfs_read+10%return' # BAD_RETPROBE
fi
# BTF arguments errors
if grep -q "<argname>" README; then
check_error 'p vfs_read args=^$arg*' # BAD_VAR_ARGS
check_error 'p vfs_read +0(^$arg*)' # BAD_VAR_ARGS
check_error 'p vfs_read $arg* ^$arg*' # DOUBLE_ARGS
if !grep -q 'kernel return probes support:' README; then
check_error 'r vfs_read ^$arg*' # NOFENTRY_ARGS
fi
check_error 'p vfs_read+20 ^$arg*' # NOFENTRY_ARGS
check_error 'p vfs_read ^hoge' # NO_BTFARG
check_error 'p kfree ^$arg10' # NO_BTFARG (exceed the number of parameters)
check_error 'r kfree ^$retval' # NO_RETVAL
else
check_error 'p vfs_read ^$arg*' # NOSUP_BTFARG
fi
exit 0
@@ -0,0 +1,19 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kretprobe dynamic event with arguments
# requires: kprobe_events
# Add new kretprobe event
echo "r:testprobe2 $FUNCTION_FORK \$retval" > kprobe_events
grep testprobe2 kprobe_events | grep -q 'arg1=\$retval'
test -d events/kprobes/testprobe2
echo 1 > events/kprobes/testprobe2/enable
( echo "forked")
cat trace | grep testprobe2 | grep -q "<- $FUNCTION_FORK"
echo 0 > events/kprobes/testprobe2/enable
echo '-:testprobe2' >> kprobe_events
clear_trace
test -d events/kprobes/testprobe2 && exit_fail || exit_pass
@@ -0,0 +1,18 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kretprobe entry argument access
# requires: kprobe_events 'kernel return probes support:':README
echo 'p:myevent1 vfs_open arg=$arg1' >> kprobe_events
echo 'r:myevent2 vfs_open arg=$arg1' >> kprobe_events
echo 1 > events/kprobes/enable
echo > trace
cat trace > /dev/null
streq() {
test $1 = $2
}
streq `grep -A 1 -m 1 myevent1 trace | sed -r 's/^.*(arg=.*)/\1/' `
@@ -0,0 +1,35 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kretprobe dynamic event with maxactive
# requires: kprobe_events 'r[maxactive]':README
# Test if we successfully reject unknown messages
if echo 'a:myprobeaccept inet_csk_accept' > kprobe_events; then false; else true; fi
# Test if we successfully reject too big maxactive
if echo 'r1000000:myprobeaccept inet_csk_accept' > kprobe_events; then false; else true; fi
# Test if we successfully reject unparsable numbers for maxactive
if echo 'r10fuzz:myprobeaccept inet_csk_accept' > kprobe_events; then false; else true; fi
# Test for kretprobe with event name without maxactive
echo 'r:myprobeaccept inet_csk_accept' > kprobe_events
grep myprobeaccept kprobe_events
test -d events/kprobes/myprobeaccept
echo '-:myprobeaccept' >> kprobe_events
# Test for kretprobe with event name with a small maxactive
echo 'r10:myprobeaccept inet_csk_accept' > kprobe_events
grep myprobeaccept kprobe_events
test -d events/kprobes/myprobeaccept
echo '-:myprobeaccept' >> kprobe_events
# Test for kretprobe without event name without maxactive
echo 'r inet_csk_accept' > kprobe_events
grep inet_csk_accept kprobe_events
echo > kprobe_events
# Test for kretprobe without event name with a small maxactive
echo 'r10 inet_csk_accept' > kprobe_events
grep inet_csk_accept kprobe_events
echo > kprobe_events
@@ -0,0 +1,21 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kretprobe %%return suffix test
# requires: kprobe_events '<symbol>[+<offset>]%return':README
# Test for kretprobe by "r"
echo 'r:myprobeaccept vfs_read' > kprobe_events
RESULT1=`cat kprobe_events`
# Test for kretprobe by "%return"
echo 'p:myprobeaccept vfs_read%return' > kprobe_events
RESULT2=`cat kprobe_events`
if [ "$RESULT1" != "$RESULT2" ]; then
echo "Error: %return suffix didn't make a return probe."
echo "r-command: $RESULT1"
echo "%return: $RESULT2"
exit_fail
fi
echo > kprobe_events
@@ -0,0 +1,35 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Register/unregister many kprobe events
# requires: kprobe_events
# ftrace fentry skip size depends on the machine architecture.
# Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc64le
case `uname -m` in
x86_64|i[3456]86) OFFS=5;;
ppc64le) OFFS=8;;
*) OFFS=0;;
esac
N=0
echo "Setup up kprobes on first available 256 text symbols"
grep -i " t " /proc/kallsyms | cut -f3 -d" " | grep -v .*\\..* | \
while read i; do
echo p ${i}+${OFFS} >> kprobe_events && N=$((N+1)) ||:
test $N -eq 256 && break
done
L=`cat kprobe_events | wc -l`
if [ $L -ne 256 ]; then
echo "The number of kprobes events ($L) is not 256"
exit_fail
fi
cat kprobe_events >> $testlog
echo 1 > events/kprobes/enable
echo 0 > events/kprobes/enable
echo > kprobe_events
echo "Waiting for unoptimizing & freeing"
sleep 5
echo "Done"
@@ -0,0 +1,38 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe events - probe points
# requires: kprobe_events
TARGET_FUNC=tracefs_create_dir
dec_addr() { # hexaddr
printf "%d" "0x"`echo $1 | tail -c 8`
}
set_offs() { # prev target next
A1=`dec_addr $1`
A2=`dec_addr $2`
A3=`dec_addr $3`
TARGET="0x$2" # an address
PREV=`expr $A1 - $A2` # offset to previous symbol
NEXT=+`expr $A3 - $A2` # offset to next symbol
OVERFLOW=+`printf "0x%x" ${PREV}` # overflow offset to previous symbol
}
# We have to decode symbol addresses to get correct offsets.
# If the offset is not an instruction boundary, it cause -EILSEQ.
set_offs `grep -v __pfx_ /proc/kallsyms | grep -A1 -B1 ${TARGET_FUNC} | cut -f 1 -d " " | xargs`
UINT_TEST=no
# printf "%x" -1 returns (unsigned long)-1.
if [ `printf "%x" -1 | wc -c` != 9 ]; then
UINT_TEST=yes
fi
echo "p:testprobe ${TARGET_FUNC}" > kprobe_events
echo "p:testprobe ${TARGET}" > kprobe_events
echo "p:testprobe ${TARGET_FUNC}${NEXT}" > kprobe_events
! echo "p:testprobe ${TARGET_FUNC}${PREV}" > kprobe_events
if [ "${UINT_TEST}" = yes ]; then
! echo "p:testprobe ${TARGET_FUNC}${OVERFLOW}" > kprobe_events
fi
@@ -0,0 +1,14 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Kprobe profile
# requires: kprobe_events
! grep -q 'myevent' kprobe_profile
echo "p:myevent $FUNCTION_FORK" > kprobe_events
grep -q 'myevent[[:space:]]*0[[:space:]]*0$' kprobe_profile
echo 1 > events/kprobes/myevent/enable
( echo "forked" )
grep -q 'myevent[[:space:]]*[[:digit:]]*[[:space:]]*0$' kprobe_profile
echo 0 > events/kprobes/myevent/enable
echo > kprobe_events
! grep -q 'myevent' kprobe_profile
@@ -0,0 +1,31 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Uprobe event parser error log check
# requires: uprobe_events error_log
check_error() { # command-with-error-pos-by-^
ftrace_errlog_check 'trace_uprobe' "$1" 'uprobe_events'
}
check_error 'p ^/non_exist_file:100' # FILE_NOT_FOUND
check_error 'p ^/sys:100' # NO_REGULAR_FILE
check_error 'p /bin/sh:^10a' # BAD_UPROBE_OFFS
check_error 'p /bin/sh:10(^1a)' # BAD_REFCNT
check_error 'p /bin/sh:10(10^' # REFCNT_OPEN_BRACE
check_error 'p /bin/sh:10(10)^a' # BAD_REFCNT_SUFFIX
check_error 'p /bin/sh:10 ^@+ab' # BAD_FILE_OFFS
check_error 'p /bin/sh:10 ^@symbol' # SYM_ON_UPROBE
# %return suffix error
if grep -q "place (uprobe): .*%return.*" README; then
check_error 'p /bin/sh:10^%hoge' # BAD_ADDR_SUFFIX
check_error 'p /bin/sh:10(10)^%return' # BAD_REFCNT_SUFFIX
fi
# symstr is not supported by uprobe
if grep -q ".*symstr.*" README; then
check_error 'p /bin/sh:10 $stack0:^symstr' # BAD_TYPE
fi
exit 0
@@ -0,0 +1,78 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: test for the preemptirqsoff tracer
# requires: preemptoff:tracer irqsoff:tracer
MOD=preemptirq_delay_test
fail() {
reset_tracer
rmmod $MOD || true
exit_fail
}
unsup() { #msg
reset_tracer
rmmod $MOD || true
echo $1
exit_unsupported
}
unres() { #msg
reset_tracer
rmmod $MOD || true
echo $1
exit_unresolved
}
modprobe $MOD || unres "$MOD module not available"
rmmod $MOD
reset_tracer
# Simulate preemptoff section for half a second couple of times
echo preemptoff > current_tracer
sleep 1
modprobe $MOD test_mode=preempt delay=500000 || fail
rmmod $MOD || fail
modprobe $MOD test_mode=preempt delay=500000 || fail
rmmod $MOD || fail
modprobe $MOD test_mode=preempt delay=500000 || fail
rmmod $MOD || fail
cat trace
# Confirm which tracer
grep -q "tracer: preemptoff" trace || fail
# Check the end of the section
grep -E -q "5.....us : <stack trace>" trace || fail
# Check for 500ms of latency
grep -E -q "latency: 5..... us" trace || fail
reset_tracer
# Simulate irqsoff section for half a second couple of times
echo irqsoff > current_tracer
sleep 1
modprobe $MOD test_mode=irq delay=500000 || fail
rmmod $MOD || fail
modprobe $MOD test_mode=irq delay=500000 || fail
rmmod $MOD || fail
modprobe $MOD test_mode=irq delay=500000 || fail
rmmod $MOD || fail
cat trace
# Confirm which tracer
grep -q "tracer: irqsoff" trace || fail
# Check the end of the section
grep -E -q "5.....us : <stack trace>" trace || fail
# Check for 500ms of latency
grep -E -q "latency: 5..... us" trace || fail
reset_tracer
exit 0
@@ -0,0 +1,25 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test trace remote buffer size
# requires: remotes/test
. $TEST_DIR/remotes/functions
test_buffer_size()
{
echo 0 > tracing_on
assert_unloaded
echo 4096 > buffer_size_kb
echo 1 > tracing_on
assert_loaded
echo 0 > tracing_on
echo 7 > buffer_size_kb
}
if [ -z "$SOURCE_REMOTE_TEST" ]; then
set -e
setup_remote_test
test_buffer_size
fi
@@ -0,0 +1,99 @@
# SPDX-License-Identifier: GPL-2.0
setup_remote()
{
local name=$1
[ -e $TRACING_DIR/remotes/$name/write_event ] || exit_unresolved
cd remotes/$name/
echo 0 > tracing_on
clear_trace
echo 7 > buffer_size_kb
echo 0 > events/enable
echo 1 > events/$name/selftest/enable
echo 1 > tracing_on
}
setup_remote_test()
{
[ -d $TRACING_DIR/remotes/test/ ] || modprobe remote_test || exit_unresolved
setup_remote "test"
}
assert_loaded()
{
grep -q "(loaded)" buffer_size_kb || return 1
}
assert_unloaded()
{
grep -q "(unloaded)" buffer_size_kb || return 1
}
reload_remote()
{
echo 0 > tracing_on
clear_trace
assert_unloaded
echo 1 > tracing_on
assert_loaded
}
dump_trace_pipe()
{
output=$(mktemp $TMPDIR/remote_test.XXXXXX)
cat trace_pipe > $output &
pid=$!
sleep 1
kill -1 $pid
echo $output
}
check_trace()
{
start_id="$1"
end_id="$2"
file="$3"
# Ensure the file is not empty
test -n "$(head $file)"
prev_ts=0
id=0
# Only keep <timestamp> <id>
tmp=$(mktemp $TMPDIR/remote_test.XXXXXX)
sed -e 's/\[[0-9]*\]\s*\([0-9]*.[0-9]*\): [a-z]* id=\([0-9]*\)/\1 \2/' $file > $tmp
while IFS= read -r line; do
ts=$(echo $line | cut -d ' ' -f 1)
id=$(echo $line | cut -d ' ' -f 2)
test $(echo "$ts>$prev_ts" | bc) -eq 1
test $id -eq $start_id
prev_ts=$ts
start_id=$((start_id + 1))
done < $tmp
test $id -eq $end_id
rm $tmp
}
get_cpu_ids()
{
sed -n 's/^processor\s*:\s*\([0-9]\+\).*/\1/p' /proc/cpuinfo
}
get_page_size()
{
sed -ne 's/^.*data.*size:\([0-9][0-9]*\).*/\1/p' events/header_page
}
get_selftest_event_size()
{
sed -ne 's/^.*field:.*;.*size:\([0-9][0-9]*\);.*/\1/p' events/*/selftest/format | awk '{s+=$1} END {print s}'
}
@@ -0,0 +1,88 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test trace remote read with an offline CPU
# requires: remotes/test
. $TEST_DIR/remotes/functions
hotunplug_one_cpu()
{
[ "$(get_cpu_ids | wc -l)" -ge 2 ] || return 1
for cpu in $(get_cpu_ids); do
echo 0 > /sys/devices/system/cpu/cpu$cpu/online || return 1
break
done
echo $cpu
}
# Check non-consuming and consuming read
check_read()
{
for i in $(seq 1 8); do
echo $i > write_event
done
check_trace 1 8 trace
output=$(dump_trace_pipe)
check_trace 1 8 $output
rm $output
}
test_hotplug()
{
echo 0 > trace
assert_loaded
#
# Test a trace buffer containing an offline CPU
#
cpu=$(hotunplug_one_cpu) || exit_unsupported
trap "echo 1 > /sys/devices/system/cpu/cpu$cpu/online" EXIT
check_read
#
# Test a trace buffer with a missing CPU
#
reload_remote
check_read
#
# Test a trace buffer with a CPU added later
#
echo 1 > /sys/devices/system/cpu/cpu$cpu/online
trap "" EXIT
assert_loaded
check_read
# Test if the ring-buffer for the newly added CPU is both writable and
# readable
for i in $(seq 1 8); do
taskset -c $cpu echo $i > write_event
done
cd per_cpu/cpu$cpu/
check_trace 1 8 trace
output=$(dump_trace_pipe)
check_trace 1 8 $output
rm $output
cd -
}
if [ -z "$SOURCE_REMOTE_TEST" ]; then
set -e
setup_remote_test
test_hotplug
fi
@@ -0,0 +1,11 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test hypervisor trace buffer size
# requires: remotes/hypervisor/write_event
SOURCE_REMOTE_TEST=1
. $TEST_DIR/remotes/buffer_size.tc
set -e
setup_remote "hypervisor"
test_buffer_size
@@ -0,0 +1,11 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test hypervisor trace read with an offline CPU
# requires: remotes/hypervisor/write_event
SOURCE_REMOTE_TEST=1
. $TEST_DIR/remotes/hotplug.tc
set -e
setup_remote "hypervisor"
test_hotplug

Some files were not shown because too many files have changed in this diff Show More