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