Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tools: Add perf-with-kcore script

Decoding an Intel PT trace of the kernel requires an accurate kernel
object image. This is provided by making a copy of kcore. However the
copy needs to be made under the same conditions as the original
recording, and then it needs to be associated with the perf.data file.
The perf-with-kcore script does that.

The script also checks the permissions on the buildid cache and can be
used to fix them. That is needed for distributions where root does not
have a home directory and consequently writes to the same buildid cache
as the user, resulting in cached files that the user does not have
access to.

Example:

$ ./perf-with-kcore
Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]
<perf sub-command> can be record, script, report or inject
or: perf-with-kcore fix_buildid_cache_permissions
$ ./perf-with-kcore record pt_uname -e intel_pt// -- uname
Recording
Using /home/ahunter/bin/perf
perf version 3.15.rc3.g4549ba
/home/ahunter/bin/perf record -o pt_uname/perf.data -e intel_pt// -- uname
Linux
[ perf record: Woken up 3 times to write data ]
[ perf record: Captured and wrote 0.023 MB pt_uname/perf.data ]
Copying kcore
[sudo] password for ahunter:
Done
$ tools/perf/perf-with-kcore.sh script pt_uname | head
Using /home/ahunter/bin/perf
perf version 3.15.rc3.g4549ba
/home/ahunter/bin/perf script -i pt_uname/perf.data --kallsyms=pt_uname/kcore_dir/kallsyms
swapper 0 [002] 161533.969666: sched:sched_switch: swapper/2:0 [120] R ==> perf:11316 [120]
:11315 11315 [003] 161533.969704: sched:sched_switch: perf:11315 [120] S ==> swapper/3:0 [120]
:11316 11316 [002] 161533.969783: sched:sched_switch: perf:11316 [120] R ==> migration/2:33 [0]
:33 33 [002] 161533.969791: sched:sched_switch: migration/2:33 [0] S ==> swapper/2:0 [120]
swapper 0 [003] 161533.969792: sched:sched_switch: swapper/3:0 [120] R ==> perf:11316 [120]
:11316 11316 [003] 161533.970062: branches: 0 [unknown] ([unknown]) => ffffffff810532fa native_write_msr_safe ([kernel.kallsyms])
:11316 11316 [003] 161533.970062: branches: ffffffff810532fd native_write_msr_safe ([kernel.kallsyms]) => ffffffff81035b31 pt_config_start ([kernel.kallsyms])

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1406786474-9306-30-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Adrian Hunter and committed by
Arnaldo Carvalho de Melo
c501e90b ad962273

+264 -1
+1
tools/perf/.gitignore
··· 15 15 perf.data.old 16 16 output.svg 17 17 perf-archive 18 + perf-with-kcore 18 19 tags 19 20 TAGS 20 21 cscope*
+4 -1
tools/perf/Makefile.perf
··· 126 126 SCRIPT_SH = 127 127 128 128 SCRIPT_SH += perf-archive.sh 129 + SCRIPT_SH += perf-with-kcore.sh 129 130 130 131 grep-libs = $(filter -l%,$(1)) 131 132 strip-libs = $(filter-out -l%,$(1)) ··· 879 878 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 880 879 $(call QUIET_INSTALL, perf-archive) \ 881 880 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 881 + $(call QUIET_INSTALL, perf-with-kcore) \ 882 + $(INSTALL) $(OUTPUT)perf-with-kcore -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 882 883 ifndef NO_LIBPERL 883 884 $(call QUIET_INSTALL, perl-scripts) \ 884 885 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \ ··· 926 923 @$(MAKE) -C config/feature-checks clean >/dev/null 927 924 928 925 clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean 929 - $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) 926 + $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) 930 927 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf 931 928 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* 932 929 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
+259
tools/perf/perf-with-kcore.sh
··· 1 + #!/bin/bash 2 + # perf-with-kcore: use perf with a copy of kcore 3 + # Copyright (c) 2014, Intel Corporation. 4 + # 5 + # This program is free software; you can redistribute it and/or modify it 6 + # under the terms and conditions of the GNU General Public License, 7 + # version 2, as published by the Free Software Foundation. 8 + # 9 + # This program is distributed in the hope it will be useful, but WITHOUT 10 + # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 + # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 + # more details. 13 + 14 + set -e 15 + 16 + usage() 17 + { 18 + echo "Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]" >&2 19 + echo " <perf sub-command> can be record, script, report or inject" >&2 20 + echo " or: perf-with-kcore fix_buildid_cache_permissions" >&2 21 + exit 1 22 + } 23 + 24 + find_perf() 25 + { 26 + if [ -n "$PERF" ] ; then 27 + return 28 + fi 29 + PERF=`which perf || true` 30 + if [ -z "$PERF" ] ; then 31 + echo "Failed to find perf" >&2 32 + exit 1 33 + fi 34 + if [ ! -x "$PERF" ] ; then 35 + echo "Failed to find perf" >&2 36 + exit 1 37 + fi 38 + echo "Using $PERF" 39 + "$PERF" version 40 + } 41 + 42 + copy_kcore() 43 + { 44 + echo "Copying kcore" 45 + 46 + if [ $EUID -eq 0 ] ; then 47 + SUDO="" 48 + else 49 + SUDO="sudo" 50 + fi 51 + 52 + rm -f perf.data.junk 53 + ("$PERF" record -o perf.data.junk $PERF_OPTIONS -- sleep 60) >/dev/null 2>/dev/null & 54 + PERF_PID=$! 55 + 56 + # Need to make sure that perf has started 57 + sleep 1 58 + 59 + KCORE=$(($SUDO "$PERF" buildid-cache -v -f -k /proc/kcore >/dev/null) 2>&1) 60 + case "$KCORE" in 61 + "kcore added to build-id cache directory "*) 62 + KCORE_DIR=${KCORE#"kcore added to build-id cache directory "} 63 + ;; 64 + *) 65 + kill $PERF_PID 66 + wait >/dev/null 2>/dev/null || true 67 + rm perf.data.junk 68 + echo "$KCORE" 69 + echo "Failed to find kcore" >&2 70 + exit 1 71 + ;; 72 + esac 73 + 74 + kill $PERF_PID 75 + wait >/dev/null 2>/dev/null || true 76 + rm perf.data.junk 77 + 78 + $SUDO cp -a "$KCORE_DIR" "$(pwd)/$PERF_DATA_DIR" 79 + $SUDO rm -f "$KCORE_DIR/kcore" 80 + $SUDO rm -f "$KCORE_DIR/kallsyms" 81 + $SUDO rm -f "$KCORE_DIR/modules" 82 + $SUDO rmdir "$KCORE_DIR" 83 + 84 + KCORE_DIR_BASENAME=$(basename "$KCORE_DIR") 85 + KCORE_DIR="$(pwd)/$PERF_DATA_DIR/$KCORE_DIR_BASENAME" 86 + 87 + $SUDO chown $UID "$KCORE_DIR" 88 + $SUDO chown $UID "$KCORE_DIR/kcore" 89 + $SUDO chown $UID "$KCORE_DIR/kallsyms" 90 + $SUDO chown $UID "$KCORE_DIR/modules" 91 + 92 + $SUDO chgrp $GROUPS "$KCORE_DIR" 93 + $SUDO chgrp $GROUPS "$KCORE_DIR/kcore" 94 + $SUDO chgrp $GROUPS "$KCORE_DIR/kallsyms" 95 + $SUDO chgrp $GROUPS "$KCORE_DIR/modules" 96 + 97 + ln -s "$KCORE_DIR_BASENAME" "$PERF_DATA_DIR/kcore_dir" 98 + } 99 + 100 + fix_buildid_cache_permissions() 101 + { 102 + if [ $EUID -ne 0 ] ; then 103 + echo "This script must be run as root via sudo " >&2 104 + exit 1 105 + fi 106 + 107 + if [ -z "$SUDO_USER" ] ; then 108 + echo "This script must be run via sudo" >&2 109 + exit 1 110 + fi 111 + 112 + USER_HOME=$(bash <<< "echo ~$SUDO_USER") 113 + 114 + if [ "$HOME" != "$USER_HOME" ] ; then 115 + echo "Fix unnecessary because root has a home: $HOME" >&2 116 + exit 1 117 + fi 118 + 119 + echo "Fixing buildid cache permissions" 120 + 121 + find "$USER_HOME/.debug" -xdev -type d ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \; 122 + find "$USER_HOME/.debug" -xdev -type f -links 1 ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \; 123 + find "$USER_HOME/.debug" -xdev -type l ! -user "$SUDO_USER" -ls -exec chown -h "$SUDO_USER" \{\} \; 124 + 125 + if [ -n "$SUDO_GID" ] ; then 126 + find "$USER_HOME/.debug" -xdev -type d ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \; 127 + find "$USER_HOME/.debug" -xdev -type f -links 1 ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \; 128 + find "$USER_HOME/.debug" -xdev -type l ! -group "$SUDO_GID" -ls -exec chgrp -h "$SUDO_GID" \{\} \; 129 + fi 130 + 131 + echo "Done" 132 + } 133 + 134 + check_buildid_cache_permissions() 135 + { 136 + if [ $EUID -eq 0 ] ; then 137 + return 138 + fi 139 + 140 + PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -user "$USER" -print -quit) 141 + PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -user "$USER" -print -quit) 142 + PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -user "$USER" -print -quit) 143 + 144 + PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -group "$GROUPS" -print -quit) 145 + PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -group "$GROUPS" -print -quit) 146 + PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -group "$GROUPS" -print -quit) 147 + 148 + if [ -n "$PERMISSIONS_OK" ] ; then 149 + echo "*** WARNING *** buildid cache permissions may need fixing" >&2 150 + fi 151 + } 152 + 153 + record() 154 + { 155 + echo "Recording" 156 + 157 + if [ $EUID -ne 0 ] ; then 158 + 159 + if [ "$(cat /proc/sys/kernel/kptr_restrict)" -ne 0 ] ; then 160 + echo "*** WARNING *** /proc/sys/kernel/kptr_restrict prevents access to kernel addresses" >&2 161 + fi 162 + 163 + if echo "$PERF_OPTIONS" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then 164 + echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2 165 + fi 166 + 167 + if echo "$PERF_OPTIONS" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then 168 + if [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt -1 ] ; then 169 + echo "*** WARNING *** /proc/sys/kernel/perf_event_paranoid restricts buffer size and tracepoint (sched_switch) use" >&2 170 + fi 171 + 172 + if echo "$PERF_OPTIONS" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then 173 + true 174 + elif echo "$PERF_OPTIONS" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then 175 + true 176 + elif [ ! -r /sys/kernel/debug -o ! -x /sys/kernel/debug ] ; then 177 + echo "*** WARNING *** /sys/kernel/debug permissions prevent tracepoint (sched_switch) use" >&2 178 + fi 179 + fi 180 + fi 181 + 182 + if [ -z "$1" ] ; then 183 + echo "Workload is required for recording" >&2 184 + usage 185 + fi 186 + 187 + if [ -e "$PERF_DATA_DIR" ] ; then 188 + echo "'$PERF_DATA_DIR' exists" >&2 189 + exit 1 190 + fi 191 + 192 + find_perf 193 + 194 + mkdir "$PERF_DATA_DIR" 195 + 196 + echo "$PERF record -o $PERF_DATA_DIR/perf.data $PERF_OPTIONS -- $*" 197 + "$PERF" record -o "$PERF_DATA_DIR/perf.data" $PERF_OPTIONS -- $* || true 198 + 199 + if rmdir "$PERF_DATA_DIR" > /dev/null 2>/dev/null ; then 200 + exit 1 201 + fi 202 + 203 + copy_kcore 204 + 205 + echo "Done" 206 + } 207 + 208 + subcommand() 209 + { 210 + find_perf 211 + check_buildid_cache_permissions 212 + echo "$PERF $PERF_SUB_COMMAND -i $PERF_DATA_DIR/perf.data --kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms $*" 213 + "$PERF" $PERF_SUB_COMMAND -i "$PERF_DATA_DIR/perf.data" "--kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms" $* 214 + } 215 + 216 + if [ "$1" = "fix_buildid_cache_permissions" ] ; then 217 + fix_buildid_cache_permissions 218 + exit 0 219 + fi 220 + 221 + PERF_SUB_COMMAND=$1 222 + PERF_DATA_DIR=$2 223 + shift || true 224 + shift || true 225 + 226 + if [ -z "$PERF_SUB_COMMAND" ] ; then 227 + usage 228 + fi 229 + 230 + if [ -z "$PERF_DATA_DIR" ] ; then 231 + usage 232 + fi 233 + 234 + case "$PERF_SUB_COMMAND" in 235 + "record") 236 + while [ "$1" != "--" ] ; do 237 + PERF_OPTIONS+="$1 " 238 + shift || break 239 + done 240 + if [ "$1" != "--" ] ; then 241 + echo "Options and workload are required for recording" >&2 242 + usage 243 + fi 244 + shift 245 + record $* 246 + ;; 247 + "script") 248 + subcommand $* 249 + ;; 250 + "report") 251 + subcommand $* 252 + ;; 253 + "inject") 254 + subcommand $* 255 + ;; 256 + *) 257 + usage 258 + ;; 259 + esac