blob: 0b96545c8184117bbd20e33b0e5d6f077fff145e [file] [log] [blame]
Adrian Hunterc501e902014-07-31 09:01:12 +03001#!/bin/bash
Thomas Gleixner2025cf92019-05-29 07:18:02 -07002# SPDX-License-Identifier: GPL-2.0-only
Adrian Hunterc501e902014-07-31 09:01:12 +03003# perf-with-kcore: use perf with a copy of kcore
4# Copyright (c) 2014, Intel Corporation.
5#
Adrian Hunterc501e902014-07-31 09:01:12 +03006
7set -e
8
9usage()
10{
11 echo "Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]" >&2
12 echo " <perf sub-command> can be record, script, report or inject" >&2
13 echo " or: perf-with-kcore fix_buildid_cache_permissions" >&2
14 exit 1
15}
16
17find_perf()
18{
19 if [ -n "$PERF" ] ; then
20 return
21 fi
22 PERF=`which perf || true`
23 if [ -z "$PERF" ] ; then
24 echo "Failed to find perf" >&2
25 exit 1
26 fi
27 if [ ! -x "$PERF" ] ; then
28 echo "Failed to find perf" >&2
29 exit 1
30 fi
31 echo "Using $PERF"
32 "$PERF" version
33}
34
35copy_kcore()
36{
37 echo "Copying kcore"
38
39 if [ $EUID -eq 0 ] ; then
40 SUDO=""
41 else
42 SUDO="sudo"
43 fi
44
45 rm -f perf.data.junk
Adrian Hunter8bd1b2d2015-07-17 19:33:47 +030046 ("$PERF" record -o perf.data.junk "${PERF_OPTIONS[@]}" -- sleep 60) >/dev/null 2>/dev/null &
Adrian Hunterc501e902014-07-31 09:01:12 +030047 PERF_PID=$!
48
49 # Need to make sure that perf has started
50 sleep 1
51
52 KCORE=$(($SUDO "$PERF" buildid-cache -v -f -k /proc/kcore >/dev/null) 2>&1)
53 case "$KCORE" in
54 "kcore added to build-id cache directory "*)
55 KCORE_DIR=${KCORE#"kcore added to build-id cache directory "}
56 ;;
57 *)
58 kill $PERF_PID
59 wait >/dev/null 2>/dev/null || true
60 rm perf.data.junk
61 echo "$KCORE"
62 echo "Failed to find kcore" >&2
63 exit 1
64 ;;
65 esac
66
67 kill $PERF_PID
68 wait >/dev/null 2>/dev/null || true
69 rm perf.data.junk
70
71 $SUDO cp -a "$KCORE_DIR" "$(pwd)/$PERF_DATA_DIR"
72 $SUDO rm -f "$KCORE_DIR/kcore"
73 $SUDO rm -f "$KCORE_DIR/kallsyms"
74 $SUDO rm -f "$KCORE_DIR/modules"
75 $SUDO rmdir "$KCORE_DIR"
76
77 KCORE_DIR_BASENAME=$(basename "$KCORE_DIR")
78 KCORE_DIR="$(pwd)/$PERF_DATA_DIR/$KCORE_DIR_BASENAME"
79
80 $SUDO chown $UID "$KCORE_DIR"
81 $SUDO chown $UID "$KCORE_DIR/kcore"
82 $SUDO chown $UID "$KCORE_DIR/kallsyms"
83 $SUDO chown $UID "$KCORE_DIR/modules"
84
85 $SUDO chgrp $GROUPS "$KCORE_DIR"
86 $SUDO chgrp $GROUPS "$KCORE_DIR/kcore"
87 $SUDO chgrp $GROUPS "$KCORE_DIR/kallsyms"
88 $SUDO chgrp $GROUPS "$KCORE_DIR/modules"
89
90 ln -s "$KCORE_DIR_BASENAME" "$PERF_DATA_DIR/kcore_dir"
91}
92
93fix_buildid_cache_permissions()
94{
95 if [ $EUID -ne 0 ] ; then
96 echo "This script must be run as root via sudo " >&2
97 exit 1
98 fi
99
100 if [ -z "$SUDO_USER" ] ; then
101 echo "This script must be run via sudo" >&2
102 exit 1
103 fi
104
105 USER_HOME=$(bash <<< "echo ~$SUDO_USER")
106
Adrian Hunterc501e902014-07-31 09:01:12 +0300107 echo "Fixing buildid cache permissions"
108
109 find "$USER_HOME/.debug" -xdev -type d ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
110 find "$USER_HOME/.debug" -xdev -type f -links 1 ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
111 find "$USER_HOME/.debug" -xdev -type l ! -user "$SUDO_USER" -ls -exec chown -h "$SUDO_USER" \{\} \;
112
113 if [ -n "$SUDO_GID" ] ; then
114 find "$USER_HOME/.debug" -xdev -type d ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
115 find "$USER_HOME/.debug" -xdev -type f -links 1 ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
116 find "$USER_HOME/.debug" -xdev -type l ! -group "$SUDO_GID" -ls -exec chgrp -h "$SUDO_GID" \{\} \;
117 fi
118
119 echo "Done"
120}
121
122check_buildid_cache_permissions()
123{
124 if [ $EUID -eq 0 ] ; then
125 return
126 fi
127
128 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -user "$USER" -print -quit)
129 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -user "$USER" -print -quit)
130 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -user "$USER" -print -quit)
131
132 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -group "$GROUPS" -print -quit)
133 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -group "$GROUPS" -print -quit)
134 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -group "$GROUPS" -print -quit)
135
136 if [ -n "$PERMISSIONS_OK" ] ; then
137 echo "*** WARNING *** buildid cache permissions may need fixing" >&2
138 fi
139}
140
141record()
142{
143 echo "Recording"
144
145 if [ $EUID -ne 0 ] ; then
146
147 if [ "$(cat /proc/sys/kernel/kptr_restrict)" -ne 0 ] ; then
148 echo "*** WARNING *** /proc/sys/kernel/kptr_restrict prevents access to kernel addresses" >&2
149 fi
150
Adrian Hunter8bd1b2d2015-07-17 19:33:47 +0300151 if echo "${PERF_OPTIONS[@]}" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then
Adrian Hunterc501e902014-07-31 09:01:12 +0300152 echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2
153 fi
154
Adrian Hunter8bd1b2d2015-07-17 19:33:47 +0300155 if echo "${PERF_OPTIONS[@]}" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then
Adrian Hunterc501e902014-07-31 09:01:12 +0300156 if [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt -1 ] ; then
157 echo "*** WARNING *** /proc/sys/kernel/perf_event_paranoid restricts buffer size and tracepoint (sched_switch) use" >&2
158 fi
159
Adrian Hunter8bd1b2d2015-07-17 19:33:47 +0300160 if echo "${PERF_OPTIONS[@]}" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then
Adrian Hunterc501e902014-07-31 09:01:12 +0300161 true
Adrian Hunter8bd1b2d2015-07-17 19:33:47 +0300162 elif echo "${PERF_OPTIONS[@]}" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then
Adrian Hunterc501e902014-07-31 09:01:12 +0300163 true
164 elif [ ! -r /sys/kernel/debug -o ! -x /sys/kernel/debug ] ; then
165 echo "*** WARNING *** /sys/kernel/debug permissions prevent tracepoint (sched_switch) use" >&2
166 fi
167 fi
168 fi
169
170 if [ -z "$1" ] ; then
171 echo "Workload is required for recording" >&2
172 usage
173 fi
174
175 if [ -e "$PERF_DATA_DIR" ] ; then
176 echo "'$PERF_DATA_DIR' exists" >&2
177 exit 1
178 fi
179
180 find_perf
181
182 mkdir "$PERF_DATA_DIR"
183
Adrian Hunter8bd1b2d2015-07-17 19:33:47 +0300184 echo "$PERF record -o $PERF_DATA_DIR/perf.data ${PERF_OPTIONS[@]} -- $@"
185 "$PERF" record -o "$PERF_DATA_DIR/perf.data" "${PERF_OPTIONS[@]}" -- "$@" || true
Adrian Hunterc501e902014-07-31 09:01:12 +0300186
187 if rmdir "$PERF_DATA_DIR" > /dev/null 2>/dev/null ; then
188 exit 1
189 fi
190
191 copy_kcore
192
193 echo "Done"
194}
195
196subcommand()
197{
198 find_perf
199 check_buildid_cache_permissions
Adrian Hunter8bd1b2d2015-07-17 19:33:47 +0300200 echo "$PERF $PERF_SUB_COMMAND -i $PERF_DATA_DIR/perf.data --kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms $@"
201 "$PERF" $PERF_SUB_COMMAND -i "$PERF_DATA_DIR/perf.data" "--kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms" "$@"
Adrian Hunterc501e902014-07-31 09:01:12 +0300202}
203
204if [ "$1" = "fix_buildid_cache_permissions" ] ; then
205 fix_buildid_cache_permissions
206 exit 0
207fi
208
209PERF_SUB_COMMAND=$1
210PERF_DATA_DIR=$2
211shift || true
212shift || true
213
214if [ -z "$PERF_SUB_COMMAND" ] ; then
215 usage
216fi
217
218if [ -z "$PERF_DATA_DIR" ] ; then
219 usage
220fi
221
222case "$PERF_SUB_COMMAND" in
223"record")
224 while [ "$1" != "--" ] ; do
Adrian Hunter8bd1b2d2015-07-17 19:33:47 +0300225 PERF_OPTIONS+=("$1")
Adrian Hunterc501e902014-07-31 09:01:12 +0300226 shift || break
227 done
228 if [ "$1" != "--" ] ; then
229 echo "Options and workload are required for recording" >&2
230 usage
231 fi
232 shift
Adrian Hunter8bd1b2d2015-07-17 19:33:47 +0300233 record "$@"
Adrian Hunterc501e902014-07-31 09:01:12 +0300234;;
235"script")
Adrian Hunter8bd1b2d2015-07-17 19:33:47 +0300236 subcommand "$@"
Adrian Hunterc501e902014-07-31 09:01:12 +0300237;;
238"report")
Adrian Hunter8bd1b2d2015-07-17 19:33:47 +0300239 subcommand "$@"
Adrian Hunterc501e902014-07-31 09:01:12 +0300240;;
241"inject")
Adrian Hunter8bd1b2d2015-07-17 19:33:47 +0300242 subcommand "$@"
Adrian Hunterc501e902014-07-31 09:01:12 +0300243;;
244*)
245 usage
246;;
247esac