xref: /linux/tools/bootconfig/scripts/ftrace2bconf.sh (revision 7d8d6ad659c02ed5d2387777194c22e8e81dbb2b)
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