#!/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]*' } event_is_enabled() { # enable-file test -f $1 & grep -q "1" $1 } 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 if [ $GROUP_ENABLED -eq 0 ] && event_is_enabled $evdir/enable; then emit_kv $PREFIX.event.$group.$event.enable fi 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 ALL_ENABLED=0 if event_is_enabled $INSTANCE/events/enable; then emit_kv $PREFIX.event.enable ALL_ENABLED=1 fi for group in `ls $INSTANCE/events/` ; do [ ! -d $INSTANCE/events/$group ] && continue GROUP_ENABLED=$ALL_ENABLED if [ $ALL_ENABLED -eq 0 ] && \ event_is_enabled $INSTANCE/events/$group/enable ;then emit_kv $PREFIX.event.$group.enable GROUP_ENABLED=1 fi 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=`cat $INSTANCE/tracing_on` if [ `echo $val | sed -e s/f//g`x != x ]; then emit_kv $PREFIX.tracing_on = $val fi 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