5
5
#
6
6
# This is a proof of concept using Linux ftrace capabilities on older kernels.
7
7
#
8
- # USAGE: functrace [-hH] [-p PID] [-d secs] funcstring
8
+ # USAGE: functrace [-hH] [-p PID] [-L TID] [- d secs] funcstring
9
9
# eg,
10
10
# functrace '*sleep' # trace all functions ending in "sleep"
11
11
#
59
59
# ## default variables
60
60
tracing=/sys/kernel/debug/tracing
61
61
flock=/var/tmp/.ftrace-lock
62
- opt_duration=0; duration=; opt_pid=0; pid=; pidtext=; opt_headers=0
62
+ opt_duration=0; duration=; opt_pid=0; pid=; opt_tid=0; tid=; pidtext=
63
+ opt_headers=0
63
64
trap ' :' INT QUIT TERM PIPE HUP # sends execution to end tracing section
64
65
65
66
function usage {
66
67
cat << -END >&2
67
- USAGE: functrace [-hH] [-p PID] [-d secs] funcstring
68
+ USAGE: functrace [-hH] [-p PID] [-L TID] [- d secs] funcstring
68
69
-d seconds # trace duration, and use buffers
69
70
-h # this usage message
70
71
-H # include column headers
71
72
-p PID # trace when this pid is on-CPU
73
+ -L TID # trace when this thread is on-CPU
72
74
eg,
73
75
functrace do_nanosleep # trace the do_nanosleep() function
74
76
functrace '*sleep' # trace functions ending in "sleep"
@@ -93,7 +95,7 @@ function end {
93
95
echo " Ending tracing..." 2> /dev/null
94
96
cd $tracing
95
97
warn " echo nop > current_tracer"
96
- (( opt_pid )) && warn " echo > set_ftrace_pid"
98
+ (( opt_pid || opt_tid )) && warn " echo > set_ftrace_pid"
97
99
warn " echo > set_ftrace_filter"
98
100
warn " echo > trace"
99
101
(( wroteflock )) && warn " rm $flock "
@@ -113,11 +115,12 @@ function edie {
113
115
}
114
116
115
117
# ## process options
116
- while getopts d:hHp: opt
118
+ while getopts d:hHp:L: opt
117
119
do
118
120
case $opt in
119
121
d) opt_duration=1; duration=$OPTARG ;;
120
122
p) opt_pid=1; pid=$OPTARG ;;
123
+ L) opt_tid=1; tid=$OPTARG ;;
121
124
H) opt_headers=1; ;;
122
125
h|? ) usage ;;
123
126
esac
@@ -126,8 +129,10 @@ shift $(( $OPTIND - 1 ))
126
129
127
130
# ## option logic
128
131
(( $# == 0 )) && usage
132
+ (( opt_pid && opt_tid )) && edie " ERROR: You can use -p or -L but not both."
129
133
funcs=" $1 "
130
134
(( opt_pid )) && pidtext=" for PID $pid "
135
+ (( opt_tid )) && pidtext=" for TID $pid "
131
136
if (( opt_duration )) ; then
132
137
echo " Tracing \" $funcs \" $pidtext for $duration seconds..."
133
138
else
@@ -148,9 +153,18 @@ sysctl -q kernel.ftrace_enabled=1 # doesn't set exit status
148
153
read mode < current_tracer
149
154
[[ " $mode " != " nop" ]] && edie " ERROR: ftrace active (current_tracer=$mode )"
150
155
if (( opt_pid )) ; then
151
- if ! echo $pid > set_ftrace_pid; then
152
- edie " ERROR: setting -p $pid (PID exist?). Exiting."
153
- fi
156
+ echo > set_ftrace_pid
157
+ # ftrace expects kernel pids, which are thread ids
158
+ for tid in /proc/$pid /task/* ; do
159
+ if ! echo ${tid##*/ } >> set_ftrace_pid; then
160
+ edie " ERROR: setting -p $pid (PID exist?). Exiting."
161
+ fi
162
+ done
163
+ fi
164
+ if (( opt_tid )) ; then
165
+ if ! echo $tid > set_ftrace_pid; then
166
+ edie " ERROR: setting -L $tid (TID exist?). Exiting."
167
+ fi
154
168
fi
155
169
if ! echo " $funcs " > set_ftrace_filter; then
156
170
edie " ERROR: enabling \" $funcs \" . Exiting."
0 commit comments