forked from Minki/linux
tools/bootconfig: Add a script to generates bootconfig from ftrace
Add a ftrace2bconf.sh under tools/bootconfig/scripts which generates a bootconfig file from the current ftrace settings. To read the ftrace settings, ftrace2bconf.sh requires the root privilege (or sudo). The ftrace2bconf.sh will output the bootconfig to stdout and error messages to stderr, so usually you'll run it as # ftrace2bconf.sh > ftrace.bconf Note that some ftrace configurations are not supported. For example, function-call/callgraph trace/notrace settings are not supported because the wildcard has been expanded and lost in the ftrace anymore. Link: https://lkml.kernel.org/r/159704852163.175360.16738029520293360558.stgit@devnote2 Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
parent
7e66ef0046
commit
2b86062a34
244
tools/bootconfig/scripts/ftrace2bconf.sh
Executable file
244
tools/bootconfig/scripts/ftrace2bconf.sh
Executable file
@ -0,0 +1,244 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
usage() {
|
||||
echo "Dump boot-time tracing bootconfig from ftrace"
|
||||
echo "Usage: $0 [--debug] [ > BOOTCONFIG-FILE]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
DEBUG=
|
||||
while [ x"$1" != x ]; do
|
||||
case "$1" in
|
||||
"--debug")
|
||||
DEBUG=$1;;
|
||||
-*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
shift 1
|
||||
done
|
||||
|
||||
if [ x"$DEBUG" != x ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
TRACEFS=`grep -m 1 -w tracefs /proc/mounts | cut -f 2 -d " "`
|
||||
if [ -z "$TRACEFS" ]; then
|
||||
if ! grep -wq debugfs /proc/mounts; then
|
||||
echo "Error: No tracefs/debugfs was mounted."
|
||||
exit 1
|
||||
fi
|
||||
TRACEFS=`grep -m 1 -w debugfs /proc/mounts | cut -f 2 -d " "`/tracing
|
||||
if [ ! -d $TRACEFS ]; then
|
||||
echo "Error: ftrace is not enabled on this kernel." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
######## main #########
|
||||
|
||||
set -e
|
||||
|
||||
emit_kv() { # key =|+= value
|
||||
echo "$@"
|
||||
}
|
||||
|
||||
global_options() {
|
||||
val=`cat $TRACEFS/max_graph_depth`
|
||||
[ $val != 0 ] && emit_kv kernel.fgraph_max_depth = $val
|
||||
if grep -qv "^#" $TRACEFS/set_graph_function $TRACEFS/set_graph_notrace ; then
|
||||
cat 1>&2 << EOF
|
||||
# WARN: kernel.fgraph_filters and kernel.fgraph_notrace are not supported, since the wild card expression was expanded and lost from memory.
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
kprobe_event_options() {
|
||||
cat $TRACEFS/kprobe_events | while read p args; do
|
||||
case $p in
|
||||
r*)
|
||||
cat 1>&2 << EOF
|
||||
# WARN: A return probe found but it is not supported by bootconfig. Skip it.
|
||||
EOF
|
||||
continue;;
|
||||
esac
|
||||
p=${p#*:}
|
||||
event=${p#*/}
|
||||
group=${p%/*}
|
||||
if [ $group != "kprobes" ]; then
|
||||
cat 1>&2 << EOF
|
||||
# WARN: kprobes group name $group is changed to "kprobes" for bootconfig.
|
||||
EOF
|
||||
fi
|
||||
emit_kv $PREFIX.event.kprobes.$event.probes += $args
|
||||
done
|
||||
}
|
||||
|
||||
synth_event_options() {
|
||||
cat $TRACEFS/synthetic_events | while read event fields; do
|
||||
emit_kv $PREFIX.event.synthetic.$event.fields = `echo $fields | sed "s/;/,/g"`
|
||||
done
|
||||
}
|
||||
|
||||
# Variables resolver
|
||||
DEFINED_VARS=
|
||||
UNRESOLVED_EVENTS=
|
||||
|
||||
defined_vars() { # event-dir
|
||||
grep "^hist" $1/trigger | grep -o ':[a-zA-Z0-9]*='
|
||||
}
|
||||
referred_vars() {
|
||||
grep "^hist" $1/trigger | grep -o '$[a-zA-Z0-9]*'
|
||||
}
|
||||
|
||||
per_event_options() { # event-dir
|
||||
evdir=$1
|
||||
# Check the special event which has no filter and no trigger
|
||||
[ ! -f $evdir/filter ] && return
|
||||
|
||||
if grep -q "^hist:" $evdir/trigger; then
|
||||
# hist action can refer the undefined variables
|
||||
__vars=`defined_vars $evdir`
|
||||
for v in `referred_vars $evdir`; do
|
||||
if echo $DEFINED_VARS $__vars | grep -vqw ${v#$}; then
|
||||
# $v is not defined yet, defer it
|
||||
UNRESOLVED_EVENTS="$UNRESOLVED_EVENTS $evdir"
|
||||
return;
|
||||
fi
|
||||
done
|
||||
DEFINED_VARS="$DEFINED_VARS "`defined_vars $evdir`
|
||||
fi
|
||||
grep -v "^#" $evdir/trigger | while read action active; do
|
||||
emit_kv $PREFIX.event.$group.$event.actions += \'$action\'
|
||||
done
|
||||
|
||||
# enable is not checked; this is done by set_event in the instance.
|
||||
val=`cat $evdir/filter`
|
||||
if [ "$val" != "none" ]; then
|
||||
emit_kv $PREFIX.event.$group.$event.filter = "$val"
|
||||
fi
|
||||
}
|
||||
|
||||
retry_unresolved() {
|
||||
unresolved=$UNRESOLVED_EVENTS
|
||||
UNRESOLVED_EVENTS=
|
||||
for evdir in $unresolved; do
|
||||
event=${evdir##*/}
|
||||
group=${evdir%/*}; group=${group##*/}
|
||||
per_event_options $evdir
|
||||
done
|
||||
}
|
||||
|
||||
event_options() {
|
||||
# PREFIX and INSTANCE must be set
|
||||
if [ $PREFIX = "ftrace" ]; then
|
||||
# define the dynamic events
|
||||
kprobe_event_options
|
||||
synth_event_options
|
||||
fi
|
||||
for group in `ls $INSTANCE/events/` ; do
|
||||
[ ! -d $INSTANCE/events/$group ] && continue
|
||||
for event in `ls $INSTANCE/events/$group/` ;do
|
||||
[ ! -d $INSTANCE/events/$group/$event ] && continue
|
||||
per_event_options $INSTANCE/events/$group/$event
|
||||
done
|
||||
done
|
||||
retry=0
|
||||
while [ $retry -lt 3 ]; do
|
||||
retry_unresolved
|
||||
retry=$((retry + 1))
|
||||
done
|
||||
if [ "$UNRESOLVED_EVENTS" ]; then
|
||||
cat 1>&2 << EOF
|
||||
! ERROR: hist triggers in $UNRESOLVED_EVENTS use some undefined variables.
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
is_default_trace_option() { # option
|
||||
grep -qw $1 << EOF
|
||||
print-parent
|
||||
nosym-offset
|
||||
nosym-addr
|
||||
noverbose
|
||||
noraw
|
||||
nohex
|
||||
nobin
|
||||
noblock
|
||||
trace_printk
|
||||
annotate
|
||||
nouserstacktrace
|
||||
nosym-userobj
|
||||
noprintk-msg-only
|
||||
context-info
|
||||
nolatency-format
|
||||
record-cmd
|
||||
norecord-tgid
|
||||
overwrite
|
||||
nodisable_on_free
|
||||
irq-info
|
||||
markers
|
||||
noevent-fork
|
||||
nopause-on-trace
|
||||
function-trace
|
||||
nofunction-fork
|
||||
nodisplay-graph
|
||||
nostacktrace
|
||||
notest_nop_accept
|
||||
notest_nop_refuse
|
||||
EOF
|
||||
}
|
||||
|
||||
instance_options() { # [instance-name]
|
||||
if [ $# -eq 0 ]; then
|
||||
PREFIX="ftrace"
|
||||
INSTANCE=$TRACEFS
|
||||
else
|
||||
PREFIX="ftrace.instance.$1"
|
||||
INSTANCE=$TRACEFS/instances/$1
|
||||
fi
|
||||
val=
|
||||
for i in `cat $INSTANCE/trace_options`; do
|
||||
is_default_trace_option $i && continue
|
||||
val="$val, $i"
|
||||
done
|
||||
[ "$val" ] && emit_kv $PREFIX.options = "${val#,}"
|
||||
val="local"
|
||||
for i in `cat $INSTANCE/trace_clock` ; do
|
||||
[ "${i#*]}" ] && continue
|
||||
i=${i%]}; val=${i#[}
|
||||
done
|
||||
[ $val != "local" ] && emit_kv $PREFIX.trace_clock = $val
|
||||
val=`cat $INSTANCE/buffer_size_kb`
|
||||
if echo $val | grep -vq "expanded" ; then
|
||||
emit_kv $PREFIX.buffer_size = $val"KB"
|
||||
fi
|
||||
if grep -q "is allocated" $INSTANCE/snapshot ; then
|
||||
emit_kv $PREFIX.alloc_snapshot
|
||||
fi
|
||||
val=`cat $INSTANCE/tracing_cpumask`
|
||||
if [ `echo $val | sed -e s/f//g`x != x ]; then
|
||||
emit_kv $PREFIX.cpumask = $val
|
||||
fi
|
||||
|
||||
val=
|
||||
for i in `cat $INSTANCE/set_event`; do
|
||||
val="$val, $i"
|
||||
done
|
||||
[ "$val" ] && emit_kv $PREFIX.events = "${val#,}"
|
||||
val=`cat $INSTANCE/current_tracer`
|
||||
[ $val != nop ] && emit_kv $PREFIX.tracer = $val
|
||||
if grep -qv "^#" $INSTANCE/set_ftrace_filter $INSTANCE/set_ftrace_notrace; then
|
||||
cat 1>&2 << EOF
|
||||
# WARN: kernel.ftrace.filters and kernel.ftrace.notrace are not supported, since the wild card expression was expanded and lost from memory.
|
||||
EOF
|
||||
fi
|
||||
event_options
|
||||
}
|
||||
|
||||
global_options
|
||||
instance_options
|
||||
for i in `ls $TRACEFS/instances` ; do
|
||||
instance_options $i
|
||||
done
|
Loading…
Reference in New Issue
Block a user