fluent-plugin-perf-tools 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rubocop.yml +26 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +5 -0
  6. data/CODE_OF_CONDUCT.md +84 -0
  7. data/Gemfile +5 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +43 -0
  10. data/Rakefile +17 -0
  11. data/bin/console +15 -0
  12. data/bin/setup +8 -0
  13. data/fluent-plugin-perf-tools.gemspec +48 -0
  14. data/lib/fluent/plugin/in_perf_tools.rb +42 -0
  15. data/lib/fluent/plugin/perf_tools/cachestat.rb +65 -0
  16. data/lib/fluent/plugin/perf_tools/command.rb +30 -0
  17. data/lib/fluent/plugin/perf_tools/version.rb +9 -0
  18. data/lib/fluent/plugin/perf_tools.rb +11 -0
  19. data/perf-tools/LICENSE +339 -0
  20. data/perf-tools/README.md +205 -0
  21. data/perf-tools/bin/bitesize +1 -0
  22. data/perf-tools/bin/cachestat +1 -0
  23. data/perf-tools/bin/execsnoop +1 -0
  24. data/perf-tools/bin/funccount +1 -0
  25. data/perf-tools/bin/funcgraph +1 -0
  26. data/perf-tools/bin/funcslower +1 -0
  27. data/perf-tools/bin/functrace +1 -0
  28. data/perf-tools/bin/iolatency +1 -0
  29. data/perf-tools/bin/iosnoop +1 -0
  30. data/perf-tools/bin/killsnoop +1 -0
  31. data/perf-tools/bin/kprobe +1 -0
  32. data/perf-tools/bin/opensnoop +1 -0
  33. data/perf-tools/bin/perf-stat-hist +1 -0
  34. data/perf-tools/bin/reset-ftrace +1 -0
  35. data/perf-tools/bin/syscount +1 -0
  36. data/perf-tools/bin/tcpretrans +1 -0
  37. data/perf-tools/bin/tpoint +1 -0
  38. data/perf-tools/bin/uprobe +1 -0
  39. data/perf-tools/deprecated/README.md +1 -0
  40. data/perf-tools/deprecated/execsnoop-proc +150 -0
  41. data/perf-tools/deprecated/execsnoop-proc.8 +80 -0
  42. data/perf-tools/deprecated/execsnoop-proc_example.txt +46 -0
  43. data/perf-tools/disk/bitesize +175 -0
  44. data/perf-tools/examples/bitesize_example.txt +63 -0
  45. data/perf-tools/examples/cachestat_example.txt +58 -0
  46. data/perf-tools/examples/execsnoop_example.txt +153 -0
  47. data/perf-tools/examples/funccount_example.txt +126 -0
  48. data/perf-tools/examples/funcgraph_example.txt +2178 -0
  49. data/perf-tools/examples/funcslower_example.txt +110 -0
  50. data/perf-tools/examples/functrace_example.txt +341 -0
  51. data/perf-tools/examples/iolatency_example.txt +350 -0
  52. data/perf-tools/examples/iosnoop_example.txt +302 -0
  53. data/perf-tools/examples/killsnoop_example.txt +62 -0
  54. data/perf-tools/examples/kprobe_example.txt +379 -0
  55. data/perf-tools/examples/opensnoop_example.txt +47 -0
  56. data/perf-tools/examples/perf-stat-hist_example.txt +149 -0
  57. data/perf-tools/examples/reset-ftrace_example.txt +88 -0
  58. data/perf-tools/examples/syscount_example.txt +297 -0
  59. data/perf-tools/examples/tcpretrans_example.txt +93 -0
  60. data/perf-tools/examples/tpoint_example.txt +210 -0
  61. data/perf-tools/examples/uprobe_example.txt +321 -0
  62. data/perf-tools/execsnoop +292 -0
  63. data/perf-tools/fs/cachestat +167 -0
  64. data/perf-tools/images/perf-tools_2016.png +0 -0
  65. data/perf-tools/iolatency +296 -0
  66. data/perf-tools/iosnoop +296 -0
  67. data/perf-tools/kernel/funccount +146 -0
  68. data/perf-tools/kernel/funcgraph +259 -0
  69. data/perf-tools/kernel/funcslower +248 -0
  70. data/perf-tools/kernel/functrace +192 -0
  71. data/perf-tools/kernel/kprobe +270 -0
  72. data/perf-tools/killsnoop +263 -0
  73. data/perf-tools/man/man8/bitesize.8 +70 -0
  74. data/perf-tools/man/man8/cachestat.8 +111 -0
  75. data/perf-tools/man/man8/execsnoop.8 +104 -0
  76. data/perf-tools/man/man8/funccount.8 +76 -0
  77. data/perf-tools/man/man8/funcgraph.8 +166 -0
  78. data/perf-tools/man/man8/funcslower.8 +129 -0
  79. data/perf-tools/man/man8/functrace.8 +123 -0
  80. data/perf-tools/man/man8/iolatency.8 +116 -0
  81. data/perf-tools/man/man8/iosnoop.8 +169 -0
  82. data/perf-tools/man/man8/killsnoop.8 +100 -0
  83. data/perf-tools/man/man8/kprobe.8 +162 -0
  84. data/perf-tools/man/man8/opensnoop.8 +113 -0
  85. data/perf-tools/man/man8/perf-stat-hist.8 +111 -0
  86. data/perf-tools/man/man8/reset-ftrace.8 +49 -0
  87. data/perf-tools/man/man8/syscount.8 +96 -0
  88. data/perf-tools/man/man8/tcpretrans.8 +93 -0
  89. data/perf-tools/man/man8/tpoint.8 +140 -0
  90. data/perf-tools/man/man8/uprobe.8 +168 -0
  91. data/perf-tools/misc/perf-stat-hist +223 -0
  92. data/perf-tools/net/tcpretrans +311 -0
  93. data/perf-tools/opensnoop +280 -0
  94. data/perf-tools/syscount +192 -0
  95. data/perf-tools/system/tpoint +232 -0
  96. data/perf-tools/tools/reset-ftrace +123 -0
  97. data/perf-tools/user/uprobe +390 -0
  98. metadata +349 -0
@@ -0,0 +1,248 @@
1
+ #!/bin/bash
2
+ #
3
+ # funcslower - trace kernel functions slower than a threshold (microseconds).
4
+ # Uses Linux ftrace.
5
+ #
6
+ # This uses the Linux ftrace function graph profiler to time kernel functions
7
+ # and filter them based on a latency threshold. This is a proof of concept using
8
+ # Linux ftrace capabilities on older kernels.
9
+ #
10
+ # USAGE: funcslower [-aChHPt] [-p PID] [-d secs] funcstring latency_us
11
+ #
12
+ # Run "funcslower -h" for full usage.
13
+ #
14
+ # REQUIREMENTS: FTRACE function graph, which you may already have available
15
+ # and enabled in recent kernels. And awk.
16
+ #
17
+ # The output format is the same as the ftrace function graph trace format,
18
+ # described in the kernel source under Documentation/trace/ftrace.txt.
19
+ # Note that the output may be shuffled when different CPU buffers are read;
20
+ # check the CPU column for changes, or include timestamps (-t) and post sort.
21
+ #
22
+ # WARNING: This uses dynamic tracing of kernel functions, and could cause
23
+ # kernel panics or freezes. Test, and know what you are doing, before use.
24
+ #
25
+ # OVERHEADS: Timing and filtering is performed in-kernel context, costing
26
+ # lower overheads than post-processing in user space. If you trace frequent
27
+ # events (eg, pick a common function and a low threshold), you might want to
28
+ # try the "-d secs" option, which buffers events in-kernel instead of printing
29
+ # them live.
30
+ #
31
+ # From perf-tools: https://github.com/brendangregg/perf-tools
32
+ #
33
+ # COPYRIGHT: Copyright (c) 2014 Brendan Gregg.
34
+ #
35
+ # This program is free software; you can redistribute it and/or
36
+ # modify it under the terms of the GNU General Public License
37
+ # as published by the Free Software Foundation; either version 2
38
+ # of the License, or (at your option) any later version.
39
+ #
40
+ # This program is distributed in the hope that it will be useful,
41
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
42
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43
+ # GNU General Public License for more details.
44
+ #
45
+ # You should have received a copy of the GNU General Public License
46
+ # along with this program; if not, write to the Free Software Foundation,
47
+ # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
48
+ #
49
+ # (http://www.gnu.org/copyleft/gpl.html)
50
+ #
51
+ # 12-Jul-2014 Brendan Gregg Created this.
52
+
53
+ ### default variables
54
+ tracing=/sys/kernel/debug/tracing
55
+ flock=/var/tmp/.ftrace-lock
56
+ opt_duration=0; duration=; opt_pid=0; pid=; opt_tid=0; tid=
57
+ pidtext=; opt_headers=0; opt_proc=0; opt_time=0; opt_cpu=0
58
+ trap ':' INT QUIT TERM PIPE HUP # sends execution to end tracing section
59
+
60
+ function usage {
61
+ cat <<-END >&2
62
+ USAGE: funcslower [-aChHPt] [-p PID] [-L TID] [-d secs] funcstring latency_us
63
+ -a # all info (same as -HPt)
64
+ -C # measure on-CPU time only
65
+ -d seconds # trace duration, and use buffers
66
+ -h # this usage message
67
+ -H # include column headers
68
+ -p PID # trace when this pid is on-CPU
69
+ -L TID # trace when this thread is on-CPU
70
+ -P # show process names & PIDs
71
+ -t # show timestamps
72
+ eg,
73
+ funcslower vfs_read 10000 # trace vfs_read() slower than 10 ms
74
+
75
+ See the man page and example file for more info.
76
+ END
77
+ exit
78
+ }
79
+
80
+ function warn {
81
+ if ! eval "$@"; then
82
+ echo >&2 "WARNING: command failed \"$@\""
83
+ fi
84
+ }
85
+
86
+ function end {
87
+ # disable tracing
88
+ echo 2>/dev/null
89
+ echo "Ending tracing..." 2>/dev/null
90
+ cd $tracing
91
+
92
+ (( opt_time )) && warn "echo nofuncgraph-abstime > trace_options"
93
+ (( opt_proc )) && warn "echo nofuncgraph-proc > trace_options"
94
+ (( opt_cpu )) && warn "echo sleep-time > trace_options"
95
+
96
+ warn "echo nop > current_tracer"
97
+ (( opt_pid )) && warn "echo > set_ftrace_pid"
98
+ warn "echo > set_ftrace_filter"
99
+ warn "echo > set_graph_function"
100
+ warn "echo 0 > tracing_thresh"
101
+ warn "echo > trace"
102
+
103
+ (( wroteflock )) && warn "rm $flock"
104
+ }
105
+
106
+ function die {
107
+ echo >&2 "$@"
108
+ exit 1
109
+ }
110
+
111
+ function edie {
112
+ # die with a quiet end()
113
+ echo >&2 "$@"
114
+ exec >/dev/null 2>&1
115
+ end
116
+ exit 1
117
+ }
118
+
119
+ ### process options
120
+ while getopts aCd:hHp:L:Pt opt
121
+ do
122
+ case $opt in
123
+ a) opt_headers=1; opt_proc=1; opt_time=1 ;;
124
+ C) opt_cpu=1; ;;
125
+ d) opt_duration=1; duration=$OPTARG ;;
126
+ p) opt_pid=1; pid=$OPTARG ;;
127
+ L) opt_tid=1; tid=$OPTARG ;;
128
+ H) opt_headers=1; ;;
129
+ P) opt_proc=1; ;;
130
+ t) opt_time=1; ;;
131
+ h|?) usage ;;
132
+ esac
133
+ done
134
+ shift $(( $OPTIND - 1 ))
135
+
136
+ ### option logic
137
+ (( $# < 2 )) && usage
138
+ (( opt_pid && opt_tid )) && edie "ERROR: You can use -p or -L but not both."
139
+ funcs="$1"
140
+ shift
141
+ thresh=$1
142
+ (( opt_pid )) && pidtext=" for PID $pid"
143
+ (( opt_tid )) && pidtext=" for TID $tid"
144
+ printf "Tracing \"$funcs\"$pidtext slower than $thresh us"
145
+ if (( opt_duration )); then
146
+ echo " for $duration seconds..."
147
+ else
148
+ echo "... Ctrl-C to end."
149
+ fi
150
+
151
+ ## select awk
152
+ if (( opt_duration )); then
153
+ [[ -x /usr/bin/mawk ]] && awk=mawk || awk=awk
154
+ else
155
+ # workarounds for mawk/gawk fflush behavior
156
+ if [[ -x /usr/bin/gawk ]]; then
157
+ awk=gawk
158
+ elif [[ -x /usr/bin/mawk ]]; then
159
+ awk="mawk -W interactive"
160
+ else
161
+ awk=awk
162
+ fi
163
+ fi
164
+
165
+ ### check permissions
166
+ cd $tracing || die "ERROR: accessing tracing. Root user? Kernel has FTRACE?
167
+ debugfs mounted? (mount -t debugfs debugfs /sys/kernel/debug)"
168
+
169
+ ### ftrace lock
170
+ [[ -e $flock ]] && die "ERROR: ftrace may be in use by PID $(cat $flock) $flock"
171
+ echo $$ > $flock || die "ERROR: unable to write $flock."
172
+ wroteflock=1
173
+
174
+ ### setup and commence tracing
175
+ sysctl -q kernel.ftrace_enabled=1 # doesn't set exit status
176
+ read mode < current_tracer
177
+ [[ "$mode" != "nop" ]] && edie "ERROR: ftrace active (current_tracer=$mode)"
178
+ if ! echo $thresh > tracing_thresh; then
179
+ edie "ERROR: setting tracing_thresh to $thresh. Exiting."
180
+ fi
181
+ if (( opt_pid )); then
182
+ echo '' > set_ftrace_pid
183
+ # ftrace expects kernel pids, which are thread ids
184
+ for tid in /proc/$pid/task/*; do
185
+ if ! echo ${tid##*/} >> set_ftrace_pid; then
186
+ edie "ERROR: setting -p $pid (PID exist?). Exiting."
187
+ fi
188
+ done
189
+ fi
190
+ if (( opt_tid )); then
191
+ if ! echo $tid > set_ftrace_pid; then
192
+ edie "ERROR: setting -L $tid (TID exist?). Exiting."
193
+ fi
194
+ fi
195
+ if ! echo "$funcs" > set_ftrace_filter; then
196
+ edie "ERROR: enabling \"$funcs\" filter. Function exist? Exiting."
197
+ fi
198
+ if ! echo "$funcs" > set_graph_function; then
199
+ edie "ERROR: enabling \"$funcs\" graph. Exiting."
200
+ fi
201
+ if ! echo function_graph > current_tracer; then
202
+ edie "ERROR: setting current_tracer to \"function_graph\". Exiting."
203
+ fi
204
+ if (( opt_cpu )); then
205
+ if ! echo nosleep-time > trace_options; then
206
+ edie "ERROR: setting -C (nosleep-time). Exiting."
207
+ fi
208
+ fi
209
+ # the following must be done after setting current_tracer
210
+ if (( opt_time )); then
211
+ if ! echo funcgraph-abstime > trace_options; then
212
+ edie "ERROR: setting -t (funcgraph-abstime). Exiting."
213
+ fi
214
+ fi
215
+ if (( opt_proc )); then
216
+ if ! echo funcgraph-proc > trace_options; then
217
+ edie "ERROR: setting -P (funcgraph-proc). Exiting."
218
+ fi
219
+ fi
220
+
221
+ ### setup output filter
222
+ cat=cat
223
+ if (( opt_proc )); then
224
+ # remove proc change entries, since PID is included. example:
225
+ # ------------------------------------------
226
+ # 0) supervi-1699 => supervi-1693
227
+ # ------------------------------------------
228
+ #
229
+ cat=$awk' "/(^ ---|^$)/ || \$3 == \"=>\" { next } { print \$0 }"'
230
+ fi
231
+
232
+ ### print trace buffer
233
+ warn "echo > trace"
234
+ if (( opt_duration )); then
235
+ sleep $duration
236
+ if (( opt_headers )); then
237
+ $cat trace
238
+ else
239
+ $cat trace | grep -v '^#'
240
+ fi
241
+ else
242
+ # trace_pipe lack headers, so fetch them from trace
243
+ (( opt_headers )) && cat trace
244
+ eval $cat trace_pipe
245
+ fi
246
+
247
+ ### end tracing
248
+ end
@@ -0,0 +1,192 @@
1
+ #!/bin/bash
2
+ #
3
+ # functrace - trace kernel function calls matching specified wildcards.
4
+ # Uses Linux ftrace.
5
+ #
6
+ # This is a proof of concept using Linux ftrace capabilities on older kernels.
7
+ #
8
+ # USAGE: functrace [-hH] [-p PID] [-L TID] [-d secs] funcstring
9
+ # eg,
10
+ # functrace '*sleep' # trace all functions ending in "sleep"
11
+ #
12
+ # Run "functrace -h" for full usage.
13
+ #
14
+ # The output format is the same as the ftrace function trace format, described
15
+ # in the kernel source under Documentation/trace/ftrace.txt.
16
+ #
17
+ # The "-d duration" mode leaves the trace data in the kernel buffer, and
18
+ # only reads it at the end. If the trace data is large, beware of exhausting
19
+ # buffer space (/sys/kernel/debug/tracing/buffer_size_kb) and losing data.
20
+ #
21
+ # Also beware of feedback loops: tracing tcp* functions over an ssh session,
22
+ # or writing ext4* functions to an ext4 file system. For the former, tcp
23
+ # trace data could be redirected to a file (as in the usage message). For
24
+ # the latter, trace to the screen or a different file system.
25
+ #
26
+ # WARNING: This uses dynamic tracing of kernel functions, and could cause
27
+ # kernel panics or freezes. Test, and know what you are doing, before use.
28
+ #
29
+ # OVERHEADS: This can generate a lot of trace data quickly, depending on the
30
+ # frequency of the traced events. Such data will cause performance overheads.
31
+ # This also works without buffering by default, printing function events
32
+ # as they happen (uses trace_pipe), context switching and consuming CPU to do
33
+ # so. If needed, you can try the "-d secs" option, which buffers events
34
+ # instead, reducing overhead. If you think the buffer option is losing events,
35
+ # try increasing the buffer size (buffer_size_kb).
36
+ #
37
+ # From perf-tools: https://github.com/brendangregg/perf-tools
38
+ #
39
+ # COPYRIGHT: Copyright (c) 2014 Brendan Gregg.
40
+ #
41
+ # This program is free software; you can redistribute it and/or
42
+ # modify it under the terms of the GNU General Public License
43
+ # as published by the Free Software Foundation; either version 2
44
+ # of the License, or (at your option) any later version.
45
+ #
46
+ # This program is distributed in the hope that it will be useful,
47
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
48
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49
+ # GNU General Public License for more details.
50
+ #
51
+ # You should have received a copy of the GNU General Public License
52
+ # along with this program; if not, write to the Free Software Foundation,
53
+ # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
54
+ #
55
+ # (http://www.gnu.org/copyleft/gpl.html)
56
+ #
57
+ # 12-Jul-2014 Brendan Gregg Created this.
58
+
59
+ ### default variables
60
+ tracing=/sys/kernel/debug/tracing
61
+ flock=/var/tmp/.ftrace-lock
62
+ opt_duration=0; duration=; opt_pid=0; pid=; opt_tid=0; tid=; pidtext=
63
+ opt_headers=0
64
+ trap ':' INT QUIT TERM PIPE HUP # sends execution to end tracing section
65
+
66
+ function usage {
67
+ cat <<-END >&2
68
+ USAGE: functrace [-hH] [-p PID] [-L TID] [-d secs] funcstring
69
+ -d seconds # trace duration, and use buffers
70
+ -h # this usage message
71
+ -H # include column headers
72
+ -p PID # trace when this pid is on-CPU
73
+ -L TID # trace when this thread is on-CPU
74
+ eg,
75
+ functrace do_nanosleep # trace the do_nanosleep() function
76
+ functrace '*sleep' # trace functions ending in "sleep"
77
+ functrace -p 198 'vfs*' # trace "vfs*" funcs for PID 198
78
+ functrace 'tcp*' > out # trace all "tcp*" funcs to out file
79
+ functrace -d 1 'tcp*' > out # trace 1 sec, then write out file
80
+
81
+ See the man page and example file for more info.
82
+ END
83
+ exit
84
+ }
85
+
86
+ function warn {
87
+ if ! eval "$@"; then
88
+ echo >&2 "WARNING: command failed \"$@\""
89
+ fi
90
+ }
91
+
92
+ function end {
93
+ # disable tracing
94
+ echo 2>/dev/null
95
+ echo "Ending tracing..." 2>/dev/null
96
+ cd $tracing
97
+ warn "echo nop > current_tracer"
98
+ (( opt_pid || opt_tid )) && warn "echo > set_ftrace_pid"
99
+ warn "echo > set_ftrace_filter"
100
+ warn "echo > trace"
101
+ (( wroteflock )) && warn "rm $flock"
102
+ }
103
+
104
+ function die {
105
+ echo >&2 "$@"
106
+ exit 1
107
+ }
108
+
109
+ function edie {
110
+ # die with a quiet end()
111
+ echo >&2 "$@"
112
+ exec >/dev/null 2>&1
113
+ end
114
+ exit 1
115
+ }
116
+
117
+ ### process options
118
+ while getopts d:hHp:L: opt
119
+ do
120
+ case $opt in
121
+ d) opt_duration=1; duration=$OPTARG ;;
122
+ p) opt_pid=1; pid=$OPTARG ;;
123
+ L) opt_tid=1; tid=$OPTARG ;;
124
+ H) opt_headers=1; ;;
125
+ h|?) usage ;;
126
+ esac
127
+ done
128
+ shift $(( $OPTIND - 1 ))
129
+
130
+ ### option logic
131
+ (( $# == 0 )) && usage
132
+ (( opt_pid && opt_tid )) && edie "ERROR: You can use -p or -L but not both."
133
+ funcs="$1"
134
+ (( opt_pid )) && pidtext=" for PID $pid"
135
+ (( opt_tid )) && pidtext=" for TID $pid"
136
+ if (( opt_duration )); then
137
+ echo "Tracing \"$funcs\"$pidtext for $duration seconds..."
138
+ else
139
+ echo "Tracing \"$funcs\"$pidtext... Ctrl-C to end."
140
+ fi
141
+
142
+ ### check permissions
143
+ cd $tracing || die "ERROR: accessing tracing. Root user? Kernel has FTRACE?
144
+ debugfs mounted? (mount -t debugfs debugfs /sys/kernel/debug)"
145
+
146
+ ### ftrace lock
147
+ [[ -e $flock ]] && die "ERROR: ftrace may be in use by PID $(cat $flock) $flock"
148
+ echo $$ > $flock || die "ERROR: unable to write $flock."
149
+ wroteflock=1
150
+
151
+ ### setup and commence tracing
152
+ sysctl -q kernel.ftrace_enabled=1 # doesn't set exit status
153
+ read mode < current_tracer
154
+ [[ "$mode" != "nop" ]] && edie "ERROR: ftrace active (current_tracer=$mode)"
155
+ if (( opt_pid )); then
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
168
+ fi
169
+ if ! echo "$funcs" > set_ftrace_filter; then
170
+ edie "ERROR: enabling \"$funcs\". Exiting."
171
+ fi
172
+ if ! echo function > current_tracer; then
173
+ edie "ERROR: setting current_tracer to \"function\". Exiting."
174
+ fi
175
+
176
+ ### print trace buffer
177
+ warn "echo > trace"
178
+ if (( opt_duration )); then
179
+ sleep $duration
180
+ if (( opt_headers )); then
181
+ cat trace
182
+ else
183
+ grep -v '^#' trace
184
+ fi
185
+ else
186
+ # trace_pipe lack headers, so fetch them from trace
187
+ (( opt_headers )) && cat trace
188
+ cat trace_pipe
189
+ fi
190
+
191
+ ### end tracing
192
+ end
@@ -0,0 +1,270 @@
1
+ #!/bin/bash
2
+ #
3
+ # kprobe - trace a given kprobe definition. Kernel dynamic tracing.
4
+ # Written using Linux ftrace.
5
+ #
6
+ # This will create, trace, then destroy a given kprobe definition. See
7
+ # Documentation/trace/kprobetrace.txt in the Linux kernel source for the
8
+ # syntax of a kprobe definition, and "kprobe -h" for examples. With this tool,
9
+ # the probe alias is optional (it will become to kprobe:<funcname> if not
10
+ # specified).
11
+ #
12
+ # USAGE: ./kprobe [-FhHsv] [-d secs] [-p pid] [-L tid] kprobe_definition [filter]
13
+ #
14
+ # Run "kprobe -h" for full usage.
15
+ #
16
+ # I wrote this because I kept testing different custom kprobes at the command
17
+ # line, and wanted a way to automate the steps.
18
+ #
19
+ # WARNING: This uses dynamic tracing of kernel functions, and could cause
20
+ # kernel panics or freezes, depending on the function traced. Test in a lab
21
+ # environment, and know what you are doing, before use.
22
+ #
23
+ # REQUIREMENTS: FTRACE and KPROBE CONFIG, which you may already have on recent
24
+ # kernel versions.
25
+ #
26
+ # From perf-tools: https://github.com/brendangregg/perf-tools
27
+ #
28
+ # See the kprobe(8) man page (in perf-tools) for more info.
29
+ #
30
+ # COPYRIGHT: Copyright (c) 2014 Brendan Gregg.
31
+ #
32
+ # This program is free software; you can redistribute it and/or
33
+ # modify it under the terms of the GNU General Public License
34
+ # as published by the Free Software Foundation; either version 2
35
+ # of the License, or (at your option) any later version.
36
+ #
37
+ # This program is distributed in the hope that it will be useful,
38
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
39
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40
+ # GNU General Public License for more details.
41
+ #
42
+ # You should have received a copy of the GNU General Public License
43
+ # along with this program; if not, write to the Free Software Foundation,
44
+ # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
45
+ #
46
+ # (http://www.gnu.org/copyleft/gpl.html)
47
+ #
48
+ # 22-Jul-2014 Brendan Gregg Created this.
49
+
50
+ ### default variables
51
+ tracing=/sys/kernel/debug/tracing
52
+ flock=/var/tmp/.ftrace-lock; wroteflock=0
53
+ opt_duration=0; duration=; opt_pid=0; pid=; opt_tid=0; tid=
54
+ opt_filter=0; filter=; opt_view=0; opt_headers=0; opt_stack=0; dmesg=2
55
+ debug=0; opt_force=0
56
+ trap ':' INT QUIT TERM PIPE HUP # sends execution to end tracing section
57
+
58
+ function usage {
59
+ cat <<-END >&2
60
+ USAGE: kprobe [-FhHsv] [-d secs] [-p PID] [-L TID] kprobe_definition [filter]
61
+ -F # force. trace despite warnings.
62
+ -d seconds # trace duration, and use buffers
63
+ -p PID # PID to match on events
64
+ -L TID # thread id to match on events
65
+ -v # view format file (don't trace)
66
+ -H # include column headers
67
+ -s # show kernel stack traces
68
+ -h # this usage message
69
+
70
+ Note that these examples may need modification to match your kernel
71
+ version's function names and platform's register usage.
72
+ eg,
73
+ kprobe p:do_sys_open
74
+ # trace open() entry
75
+ kprobe r:do_sys_open
76
+ # trace open() return
77
+ kprobe 'r:do_sys_open \$retval'
78
+ # trace open() return value
79
+ kprobe 'r:myopen do_sys_open \$retval'
80
+ # use a custom probe name
81
+ kprobe 'p:myopen do_sys_open mode=%cx:u16'
82
+ # trace open() file mode
83
+ kprobe 'p:myopen do_sys_open filename=+0(%si):string'
84
+ # trace open() with filename
85
+ kprobe -s 'p:myprobe tcp_retransmit_skb'
86
+ # show kernel stacks
87
+ kprobe 'p:do_sys_open file=+0(%si):string' 'file ~ "*stat"'
88
+ # opened files ending in "stat"
89
+
90
+ See the man page and example file for more info.
91
+ END
92
+ exit
93
+ }
94
+
95
+ function warn {
96
+ if ! eval "$@"; then
97
+ echo >&2 "WARNING: command failed \"$@\""
98
+ fi
99
+ }
100
+
101
+ function end {
102
+ # disable tracing
103
+ echo 2>/dev/null
104
+ echo "Ending tracing..." 2>/dev/null
105
+ cd $tracing
106
+ warn "echo 0 > events/kprobes/$kname/enable"
107
+ if (( opt_filter )); then
108
+ warn "echo 0 > events/kprobes/$kname/filter"
109
+ fi
110
+ warn "echo -:$kname >> kprobe_events"
111
+ (( opt_stack )) && warn "echo 0 > options/stacktrace"
112
+ warn "echo > trace"
113
+ (( wroteflock )) && warn "rm $flock"
114
+ }
115
+
116
+ function die {
117
+ echo >&2 "$@"
118
+ exit 1
119
+ }
120
+
121
+ function edie {
122
+ # die with a quiet end()
123
+ echo >&2 "$@"
124
+ exec >/dev/null 2>&1
125
+ end
126
+ exit 1
127
+ }
128
+
129
+ ### process options
130
+ while getopts Fd:hHp:L:sv opt
131
+ do
132
+ case $opt in
133
+ F) opt_force=1 ;;
134
+ d) opt_duration=1; duration=$OPTARG ;;
135
+ p) opt_pid=1; pid=$OPTARG ;;
136
+ L) opt_tid=1; tid=$OPTARG ;;
137
+ H) opt_headers=1 ;;
138
+ s) opt_stack=1 ;;
139
+ v) opt_view=1 ;;
140
+ h|?) usage ;;
141
+ esac
142
+ done
143
+ shift $(( $OPTIND - 1 ))
144
+ (( $# )) || usage
145
+ kprobe=$1
146
+ shift
147
+ if (( $# )); then
148
+ opt_filter=1
149
+ filter=$1
150
+ fi
151
+
152
+ ### option logic
153
+ (( opt_pid + opt_filter + opt_tid > 1 )) && \
154
+ die "ERROR: use at most one of -p, -L, or filter."
155
+ (( opt_duration && opt_view )) && die "ERROR: use either -d or -v."
156
+ if (( opt_pid )); then
157
+ # convert to filter
158
+ opt_filter=1
159
+ # ftrace common_pid is thread id from user's perspective
160
+ for tid in /proc/$pid/task/*; do
161
+ filter="$filter || common_pid == ${tid##*/}"
162
+ done
163
+ filter=${filter:3} # trim leading ' || ' (four characters)
164
+ fi
165
+ if (( opt_tid )); then
166
+ opt_filter=1
167
+ filter="common_pid == $tid"
168
+ fi
169
+ if [[ "$kprobe" != p:* && "$kprobe" != r:* ]]; then
170
+ echo >&2 "ERROR: invalid kprobe definition (should start with p: or r:)"
171
+ usage
172
+ fi
173
+ #
174
+ # parse the following:
175
+ # r:do_sys_open
176
+ # r:my_sys_open do_sys_open
177
+ # r:do_sys_open %ax
178
+ # r:do_sys_open $retval %ax
179
+ # r:my_sys_open do_sys_open $retval %ax
180
+ # r:do_sys_open rval=$retval
181
+ # r:my_sys_open do_sys_open rval=$retval
182
+ # r:my_sys_open do_sys_open rval=$retval %ax
183
+ # ... and examples from USAGE message
184
+ #
185
+ krest=${kprobe#*:}
186
+ kname=${krest%% *}
187
+ set -- $krest
188
+ if [[ $2 == "" || $2 == *[=%\$]* ]]; then
189
+ # if probe name unspecified, default to function name
190
+ ktype=${kprobe%%:*}
191
+ kprobe="$ktype:$kname $krest"
192
+ fi
193
+ if (( debug )); then
194
+ echo "kname: $kname, kprobe: $kprobe"
195
+ fi
196
+
197
+ ### check permissions
198
+ cd $tracing || die "ERROR: accessing tracing. Root user? Kernel has FTRACE?
199
+ debugfs mounted? (mount -t debugfs debugfs /sys/kernel/debug)"
200
+
201
+ ## check function
202
+ set -- $kprobe
203
+ fname=$2
204
+ if (( !opt_force )) && ! grep -w $fname available_filter_functions >/dev/null \
205
+ 2>&1
206
+ then
207
+ echo >&2 "ERROR: func $fname not in $PWD/available_filter_functions."
208
+ printf >&2 "Either it doesn't exist, or, it might be unsafe to kprobe. "
209
+ echo >&2 "Exiting. Use -F to override."
210
+ exit 1
211
+ fi
212
+
213
+ if (( !opt_view )); then
214
+ if (( opt_duration )); then
215
+ echo "Tracing kprobe $kname for $duration seconds (buffered)..."
216
+ else
217
+ echo "Tracing kprobe $kname. Ctrl-C to end."
218
+ fi
219
+ fi
220
+
221
+ ### ftrace lock
222
+ [[ -e $flock ]] && die "ERROR: ftrace may be in use by PID $(cat $flock) $flock"
223
+ echo $$ > $flock || die "ERROR: unable to write $flock."
224
+ wroteflock=1
225
+
226
+ ### setup and begin tracing
227
+ echo nop > current_tracer
228
+ if ! echo "$kprobe" >> kprobe_events; then
229
+ echo >&2 "ERROR: adding kprobe \"$kprobe\"."
230
+ if (( dmesg )); then
231
+ echo >&2 "Last $dmesg dmesg entries (might contain reason):"
232
+ dmesg | tail -$dmesg | sed 's/^/ /'
233
+ fi
234
+ edie "Exiting."
235
+ fi
236
+ if (( opt_view )); then
237
+ cat events/kprobes/$kname/format
238
+ edie ""
239
+ fi
240
+ if (( opt_filter )); then
241
+ if ! echo "$filter" > events/kprobes/$kname/filter; then
242
+ edie "ERROR: setting filter or -p. Exiting."
243
+ fi
244
+ fi
245
+ if (( opt_stack )); then
246
+ if ! echo 1 > options/stacktrace; then
247
+ edie "ERROR: enabling stack traces (-s). Exiting"
248
+ fi
249
+ fi
250
+ if ! echo 1 > events/kprobes/$kname/enable; then
251
+ edie "ERROR: enabling kprobe $kname. Exiting."
252
+ fi
253
+
254
+ ### print trace buffer
255
+ warn "echo > trace"
256
+ if (( opt_duration )); then
257
+ sleep $duration
258
+ if (( opt_headers )); then
259
+ cat trace
260
+ else
261
+ grep -v '^#' trace
262
+ fi
263
+ else
264
+ # trace_pipe lack headers, so fetch them from trace
265
+ (( opt_headers )) && cat trace
266
+ cat trace_pipe
267
+ fi
268
+
269
+ ### end tracing
270
+ end