mirror of
https://github.com/brendangregg/perf-tools.git
synced 2025-12-01 07:26:04 +07:00
130 lines
4.0 KiB
Plaintext
130 lines
4.0 KiB
Plaintext
|
|
#!/bin/bash
|
||
|
|
#
|
||
|
|
# functrace - trace kernel function calls matching specified wildcards.
|
||
|
|
# A hack using Linux ftrace.
|
||
|
|
#
|
||
|
|
# This is a proof of concept using Linux ftrace capabilities circa Linux 3.2.
|
||
|
|
#
|
||
|
|
# USAGE: functrace [-h] [-d secs] funcstring
|
||
|
|
# eg,
|
||
|
|
# functrace '*sleep' # trace all functions ending in "sleep"
|
||
|
|
#
|
||
|
|
# Run "functrace -h" for full usage.
|
||
|
|
#
|
||
|
|
# The output format is the same as the ftrace function trace format, described
|
||
|
|
# in the kernel source under Documentation/trace/ftrace.txt.
|
||
|
|
#
|
||
|
|
# The "-d duration" mode leaves the trace data in the kernel buffer, and
|
||
|
|
# only reads it at the end. If the trace data is large, beware of exhausting
|
||
|
|
# buffer space (/sys/kernel/debug/tracing/buffer_size_kb) and losing data.
|
||
|
|
#
|
||
|
|
# Also beware of feedback loops: tracing tcp* functions over an ssh session,
|
||
|
|
# or writing ext4* functions to an ext4 file system. For the former, tcp
|
||
|
|
# trace data could be redirected to a file (as in the usage message). For
|
||
|
|
# the latter, trace to the screen or a different file system.
|
||
|
|
#
|
||
|
|
# WARNING: This uses dynamic tracing of kernel functions, and could cause
|
||
|
|
# kernel panics or freezes. Test, and know what you are doing, before use.
|
||
|
|
#
|
||
|
|
# OVERHEADS: This can generate a lot of trace data quickly, depending on the
|
||
|
|
# frequency of the traced events. Such data will cause performance overheads.
|
||
|
|
#
|
||
|
|
# From perf-tools: https://github.com/brendangregg/perf-tools
|
||
|
|
#
|
||
|
|
# COPYRIGHT: Copyright (c) 2014 Brendan Gregg.
|
||
|
|
#
|
||
|
|
# This program is free software; you can redistribute it and/or
|
||
|
|
# modify it under the terms of the GNU General Public License
|
||
|
|
# as published by the Free Software Foundation; either version 2
|
||
|
|
# of the License, or (at your option) any later version.
|
||
|
|
#
|
||
|
|
# This program is distributed in the hope that it will be useful,
|
||
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
# GNU General Public License for more details.
|
||
|
|
#
|
||
|
|
# You should have received a copy of the GNU General Public License
|
||
|
|
# along with this program; if not, write to the Free Software Foundation,
|
||
|
|
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
|
#
|
||
|
|
# (http://www.gnu.org/copyleft/gpl.html)
|
||
|
|
#
|
||
|
|
# 12-Jul-2014 Brendan Gregg Created this.
|
||
|
|
|
||
|
|
# default variables
|
||
|
|
tracing=/sys/kernel/debug/tracing
|
||
|
|
opt_duration=0; duration=
|
||
|
|
trap ':' SIGINT
|
||
|
|
|
||
|
|
function usage {
|
||
|
|
cat <<-END >&2
|
||
|
|
USAGE: functrace [-h] [-d secs] funcstring
|
||
|
|
-d seconds # total duration of trace; this mode
|
||
|
|
# buffers tracing for this duration
|
||
|
|
-h # this usage message
|
||
|
|
eg,
|
||
|
|
functrace do_nanosleep # trace the do_nanosleep() function
|
||
|
|
functrace '*sleep' # trace functions ending in "sleep"
|
||
|
|
functrace 'tcp*' > out # trace all "tcp*" funcs to out file
|
||
|
|
functrace -d 1 'tcp*' > out # trace 1 sec, then write out file
|
||
|
|
END
|
||
|
|
exit
|
||
|
|
}
|
||
|
|
|
||
|
|
function warn {
|
||
|
|
if ! eval "$@"; then
|
||
|
|
echo "WARNING: command failed \"$@\""
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# process options
|
||
|
|
while getopts d:h name
|
||
|
|
do
|
||
|
|
case $name in
|
||
|
|
d) opt_duration=1; duration=$OPTARG ;;
|
||
|
|
h|?) usage ;;
|
||
|
|
esac
|
||
|
|
done
|
||
|
|
shift $(( $OPTIND - 1 ))
|
||
|
|
|
||
|
|
# option logic
|
||
|
|
(( $# == 0 )) && usage
|
||
|
|
funcs="$1"
|
||
|
|
if (( opt_duration )); then
|
||
|
|
echo "Tracing \"$funcs\" for $duration seconds..."
|
||
|
|
else
|
||
|
|
echo "Tracing \"$funcs\"... Ctrl-C to end."
|
||
|
|
fi
|
||
|
|
|
||
|
|
# setup and commence tracing
|
||
|
|
if [[ ! -x $tracing ]]; then
|
||
|
|
echo "ERROR: accessing tracing. Root user? Kernel has FTRACE? Exiting."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
sysctl -q kernel.ftrace_enabled=1 # doesn't set exit status
|
||
|
|
if ! echo "$funcs" > $tracing/set_ftrace_filter; then
|
||
|
|
echo "ERROR: enabling \"$funcs\". Exiting."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
if ! echo function > $tracing/current_tracer; then
|
||
|
|
echo "ERROR: setting current_tracer to \"function\". Exiting."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# print trace buffer
|
||
|
|
end=0; secs=0
|
||
|
|
warn "echo > $tracing/trace"
|
||
|
|
if (( opt_duration )); then
|
||
|
|
sleep $duration
|
||
|
|
cat $tracing/trace
|
||
|
|
else
|
||
|
|
cat $tracing/trace_pipe
|
||
|
|
fi
|
||
|
|
|
||
|
|
# end tracing
|
||
|
|
echo
|
||
|
|
echo "Ending tracing..."
|
||
|
|
warn "echo nop > $tracing/current_tracer"
|
||
|
|
warn "echo > $tracing/set_ftrace_filter"
|
||
|
|
warn "echo > $tracing/trace"
|