1#!/bin/sh 2# SPDX-License-Identifier: GPL-2.0-only 3 4usage() { 5 echo "Dump boot-time tracing bootconfig from ftrace" 6 echo "Usage: $0 [--debug] [ > BOOTCONFIG-FILE]" 7 exit 1 8} 9 10DEBUG= 11while [ x"$1" != x ]; do 12 case "$1" in 13 "--debug") 14 DEBUG=$1;; 15 -*) 16 usage 17 ;; 18 esac 19 shift 1 20done 21 22if [ x"$DEBUG" != x ]; then 23 set -x 24fi 25 26TRACEFS=`grep -m 1 -w tracefs /proc/mounts | cut -f 2 -d " "` 27if [ -z "$TRACEFS" ]; then 28 if ! grep -wq debugfs /proc/mounts; then 29 echo "Error: No tracefs/debugfs was mounted." 30 exit 1 31 fi 32 TRACEFS=`grep -m 1 -w debugfs /proc/mounts | cut -f 2 -d " "`/tracing 33 if [ ! -d $TRACEFS ]; then 34 echo "Error: ftrace is not enabled on this kernel." 1>&2 35 exit 1 36 fi 37fi 38 39######## main ######### 40 41set -e 42 43emit_kv() { # key =|+= value 44 echo "$@" 45} 46 47global_options() { 48 val=`cat $TRACEFS/max_graph_depth` 49 [ $val != 0 ] && emit_kv kernel.fgraph_max_depth = $val 50 if grep -qv "^#" $TRACEFS/set_graph_function $TRACEFS/set_graph_notrace ; then 51 cat 1>&2 << EOF 52# WARN: kernel.fgraph_filters and kernel.fgraph_notrace are not supported, since the wild card expression was expanded and lost from memory. 53EOF 54 fi 55} 56 57kprobe_event_options() { 58 cat $TRACEFS/kprobe_events | while read p args; do 59 case $p in 60 \#*) 61 continue;; 62 r*) 63 cat 1>&2 << EOF 64# WARN: A return probe found but it is not supported by bootconfig. Skip it. 65EOF 66 continue;; 67 esac 68 p=${p#*:} 69 event=${p#*/} 70 group=${p%/*} 71 if [ $group != "kprobes" ]; then 72 cat 1>&2 << EOF 73# WARN: kprobes group name $group is changed to "kprobes" for bootconfig. 74EOF 75 fi 76 emit_kv $PREFIX.event.kprobes.$event.probes += $args 77 done 78} 79 80synth_event_options() { 81 cat $TRACEFS/synthetic_events | while read event fields; do 82 emit_kv $PREFIX.event.synthetic.$event.fields = `echo $fields | sed "s/;/,/g"` 83 done 84} 85 86# Variables resolver 87DEFINED_VARS= 88UNRESOLVED_EVENTS= 89 90defined_vars() { # event-dir 91 grep "^hist" $1/trigger | grep -o ':[a-zA-Z0-9]*=' 92} 93referred_vars() { 94 grep "^hist" $1/trigger | grep -o '$[a-zA-Z0-9]*' 95} 96 97event_is_enabled() { # enable-file 98 test -f $1 && grep -q "1" $1 99} 100 101per_event_options() { # event-dir 102 evdir=$1 103 # Check the special event which has no filter and no trigger 104 [ ! -f $evdir/filter ] && return 105 106 if grep -q "^hist:" $evdir/trigger; then 107 # hist action can refer the undefined variables 108 __vars=`defined_vars $evdir` 109 for v in `referred_vars $evdir`; do 110 if echo $DEFINED_VARS $__vars | grep -vqw ${v#$}; then 111 # $v is not defined yet, defer it 112 UNRESOLVED_EVENTS="$UNRESOLVED_EVENTS $evdir" 113 return; 114 fi 115 done 116 DEFINED_VARS="$DEFINED_VARS "`defined_vars $evdir` 117 fi 118 grep -v "^#" $evdir/trigger | while read action active; do 119 emit_kv $PREFIX.event.$group.$event.actions += \'$action\' 120 done 121 122 if [ $GROUP_ENABLED -eq 0 ] && event_is_enabled $evdir/enable; then 123 emit_kv $PREFIX.event.$group.$event.enable 124 fi 125 val=`cat $evdir/filter` 126 if [ "$val" != "none" ]; then 127 emit_kv $PREFIX.event.$group.$event.filter = "$val" 128 fi 129} 130 131retry_unresolved() { 132 unresolved=$UNRESOLVED_EVENTS 133 UNRESOLVED_EVENTS= 134 for evdir in $unresolved; do 135 event=${evdir##*/} 136 group=${evdir%/*}; group=${group##*/} 137 per_event_options $evdir 138 done 139} 140 141event_options() { 142 # PREFIX and INSTANCE must be set 143 if [ $PREFIX = "ftrace" ]; then 144 # define the dynamic events 145 kprobe_event_options 146 synth_event_options 147 fi 148 ALL_ENABLED=0 149 if event_is_enabled $INSTANCE/events/enable; then 150 emit_kv $PREFIX.event.enable 151 ALL_ENABLED=1 152 fi 153 for group in `ls $INSTANCE/events/` ; do 154 [ ! -d $INSTANCE/events/$group ] && continue 155 GROUP_ENABLED=$ALL_ENABLED 156 if [ $ALL_ENABLED -eq 0 ] && \ 157 event_is_enabled $INSTANCE/events/$group/enable ;then 158 emit_kv $PREFIX.event.$group.enable 159 GROUP_ENABLED=1 160 fi 161 for event in `ls $INSTANCE/events/$group/` ;do 162 [ ! -d $INSTANCE/events/$group/$event ] && continue 163 per_event_options $INSTANCE/events/$group/$event 164 done 165 done 166 retry=0 167 while [ $retry -lt 3 ]; do 168 retry_unresolved 169 retry=$((retry + 1)) 170 done 171 if [ "$UNRESOLVED_EVENTS" ]; then 172 cat 1>&2 << EOF 173! ERROR: hist triggers in $UNRESOLVED_EVENTS use some undefined variables. 174EOF 175 fi 176} 177 178is_default_trace_option() { # option 179grep -qw $1 << EOF 180print-parent 181nosym-offset 182nosym-addr 183noverbose 184noraw 185nohex 186nobin 187noblock 188trace_printk 189annotate 190nouserstacktrace 191nosym-userobj 192noprintk-msg-only 193context-info 194nolatency-format 195record-cmd 196norecord-tgid 197overwrite 198nodisable_on_free 199irq-info 200markers 201noevent-fork 202nopause-on-trace 203function-trace 204nofunction-fork 205nodisplay-graph 206nostacktrace 207notest_nop_accept 208notest_nop_refuse 209EOF 210} 211 212instance_options() { # [instance-name] 213 if [ $# -eq 0 ]; then 214 PREFIX="ftrace" 215 INSTANCE=$TRACEFS 216 else 217 PREFIX="ftrace.instance.$1" 218 INSTANCE=$TRACEFS/instances/$1 219 fi 220 val= 221 for i in `cat $INSTANCE/trace_options`; do 222 is_default_trace_option $i && continue 223 val="$val, $i" 224 done 225 [ "$val" ] && emit_kv $PREFIX.options = "${val#,}" 226 val="local" 227 for i in `cat $INSTANCE/trace_clock` ; do 228 [ "${i#*]}" ] && continue 229 i=${i%]}; val=${i#[} 230 done 231 [ $val != "local" ] && emit_kv $PREFIX.trace_clock = $val 232 val=`cat $INSTANCE/buffer_size_kb` 233 if echo $val | grep -vq "expanded" ; then 234 emit_kv $PREFIX.buffer_size = $val"KB" 235 fi 236 if grep -q "is allocated" $INSTANCE/snapshot ; then 237 emit_kv $PREFIX.alloc_snapshot 238 fi 239 val=`cat $INSTANCE/tracing_cpumask` 240 if [ `echo $val | sed -e s/f//g`x != x ]; then 241 emit_kv $PREFIX.cpumask = $val 242 fi 243 val=`cat $INSTANCE/tracing_on` 244 if [ "$val" = "0" ]; then 245 emit_kv $PREFIX.tracing_on = 0 246 fi 247 248 val=`cat $INSTANCE/current_tracer` 249 [ $val != nop ] && emit_kv $PREFIX.tracer = $val 250 if grep -qv "^#" $INSTANCE/set_ftrace_filter $INSTANCE/set_ftrace_notrace; then 251 cat 1>&2 << EOF 252# WARN: kernel.ftrace.filters and kernel.ftrace.notrace are not supported, since the wild card expression was expanded and lost from memory. 253EOF 254 fi 255 event_options 256} 257 258global_options 259instance_options 260for i in `ls $TRACEFS/instances` ; do 261 instance_options $i 262done 263