123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- #!/bin/bash
- # perf-with-kcore: use perf with a copy of kcore
- # Copyright (c) 2014, Intel Corporation.
- #
- # This program is free software; you can redistribute it and/or modify it
- # under the terms and conditions of the GNU General Public License,
- # version 2, as published by the Free Software Foundation.
- #
- # This program is distributed in the hope it will be useful, but WITHOUT
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- # more details.
- set -e
- usage()
- {
- echo "Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]" >&2
- echo " <perf sub-command> can be record, script, report or inject" >&2
- echo " or: perf-with-kcore fix_buildid_cache_permissions" >&2
- exit 1
- }
- find_perf()
- {
- if [ -n "$PERF" ] ; then
- return
- fi
- PERF=`which perf || true`
- if [ -z "$PERF" ] ; then
- echo "Failed to find perf" >&2
- exit 1
- fi
- if [ ! -x "$PERF" ] ; then
- echo "Failed to find perf" >&2
- exit 1
- fi
- echo "Using $PERF"
- "$PERF" version
- }
- copy_kcore()
- {
- echo "Copying kcore"
- if [ $EUID -eq 0 ] ; then
- SUDO=""
- else
- SUDO="sudo"
- fi
- rm -f perf.data.junk
- ("$PERF" record -o perf.data.junk $PERF_OPTIONS -- sleep 60) >/dev/null 2>/dev/null &
- PERF_PID=$!
- # Need to make sure that perf has started
- sleep 1
- KCORE=$(($SUDO "$PERF" buildid-cache -v -f -k /proc/kcore >/dev/null) 2>&1)
- case "$KCORE" in
- "kcore added to build-id cache directory "*)
- KCORE_DIR=${KCORE#"kcore added to build-id cache directory "}
- ;;
- *)
- kill $PERF_PID
- wait >/dev/null 2>/dev/null || true
- rm perf.data.junk
- echo "$KCORE"
- echo "Failed to find kcore" >&2
- exit 1
- ;;
- esac
- kill $PERF_PID
- wait >/dev/null 2>/dev/null || true
- rm perf.data.junk
- $SUDO cp -a "$KCORE_DIR" "$(pwd)/$PERF_DATA_DIR"
- $SUDO rm -f "$KCORE_DIR/kcore"
- $SUDO rm -f "$KCORE_DIR/kallsyms"
- $SUDO rm -f "$KCORE_DIR/modules"
- $SUDO rmdir "$KCORE_DIR"
- KCORE_DIR_BASENAME=$(basename "$KCORE_DIR")
- KCORE_DIR="$(pwd)/$PERF_DATA_DIR/$KCORE_DIR_BASENAME"
- $SUDO chown $UID "$KCORE_DIR"
- $SUDO chown $UID "$KCORE_DIR/kcore"
- $SUDO chown $UID "$KCORE_DIR/kallsyms"
- $SUDO chown $UID "$KCORE_DIR/modules"
- $SUDO chgrp $GROUPS "$KCORE_DIR"
- $SUDO chgrp $GROUPS "$KCORE_DIR/kcore"
- $SUDO chgrp $GROUPS "$KCORE_DIR/kallsyms"
- $SUDO chgrp $GROUPS "$KCORE_DIR/modules"
- ln -s "$KCORE_DIR_BASENAME" "$PERF_DATA_DIR/kcore_dir"
- }
- fix_buildid_cache_permissions()
- {
- if [ $EUID -ne 0 ] ; then
- echo "This script must be run as root via sudo " >&2
- exit 1
- fi
- if [ -z "$SUDO_USER" ] ; then
- echo "This script must be run via sudo" >&2
- exit 1
- fi
- USER_HOME=$(bash <<< "echo ~$SUDO_USER")
- if [ "$HOME" != "$USER_HOME" ] ; then
- echo "Fix unnecessary because root has a home: $HOME" >&2
- exit 1
- fi
- echo "Fixing buildid cache permissions"
- find "$USER_HOME/.debug" -xdev -type d ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
- find "$USER_HOME/.debug" -xdev -type f -links 1 ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
- find "$USER_HOME/.debug" -xdev -type l ! -user "$SUDO_USER" -ls -exec chown -h "$SUDO_USER" \{\} \;
- if [ -n "$SUDO_GID" ] ; then
- find "$USER_HOME/.debug" -xdev -type d ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
- find "$USER_HOME/.debug" -xdev -type f -links 1 ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
- find "$USER_HOME/.debug" -xdev -type l ! -group "$SUDO_GID" -ls -exec chgrp -h "$SUDO_GID" \{\} \;
- fi
- echo "Done"
- }
- check_buildid_cache_permissions()
- {
- if [ $EUID -eq 0 ] ; then
- return
- fi
- PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -user "$USER" -print -quit)
- PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -user "$USER" -print -quit)
- PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -user "$USER" -print -quit)
- PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -group "$GROUPS" -print -quit)
- PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -group "$GROUPS" -print -quit)
- PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -group "$GROUPS" -print -quit)
- if [ -n "$PERMISSIONS_OK" ] ; then
- echo "*** WARNING *** buildid cache permissions may need fixing" >&2
- fi
- }
- record()
- {
- echo "Recording"
- if [ $EUID -ne 0 ] ; then
- if [ "$(cat /proc/sys/kernel/kptr_restrict)" -ne 0 ] ; then
- echo "*** WARNING *** /proc/sys/kernel/kptr_restrict prevents access to kernel addresses" >&2
- fi
- if echo "$PERF_OPTIONS" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then
- echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2
- fi
- if echo "$PERF_OPTIONS" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then
- if [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt -1 ] ; then
- echo "*** WARNING *** /proc/sys/kernel/perf_event_paranoid restricts buffer size and tracepoint (sched_switch) use" >&2
- fi
- if echo "$PERF_OPTIONS" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then
- true
- elif echo "$PERF_OPTIONS" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then
- true
- elif [ ! -r /sys/kernel/debug -o ! -x /sys/kernel/debug ] ; then
- echo "*** WARNING *** /sys/kernel/debug permissions prevent tracepoint (sched_switch) use" >&2
- fi
- fi
- fi
- if [ -z "$1" ] ; then
- echo "Workload is required for recording" >&2
- usage
- fi
- if [ -e "$PERF_DATA_DIR" ] ; then
- echo "'$PERF_DATA_DIR' exists" >&2
- exit 1
- fi
- find_perf
- mkdir "$PERF_DATA_DIR"
- echo "$PERF record -o $PERF_DATA_DIR/perf.data $PERF_OPTIONS -- $*"
- "$PERF" record -o "$PERF_DATA_DIR/perf.data" $PERF_OPTIONS -- $* || true
- if rmdir "$PERF_DATA_DIR" > /dev/null 2>/dev/null ; then
- exit 1
- fi
- copy_kcore
- echo "Done"
- }
- subcommand()
- {
- find_perf
- check_buildid_cache_permissions
- echo "$PERF $PERF_SUB_COMMAND -i $PERF_DATA_DIR/perf.data --kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms $*"
- "$PERF" $PERF_SUB_COMMAND -i "$PERF_DATA_DIR/perf.data" "--kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms" $*
- }
- if [ "$1" = "fix_buildid_cache_permissions" ] ; then
- fix_buildid_cache_permissions
- exit 0
- fi
- PERF_SUB_COMMAND=$1
- PERF_DATA_DIR=$2
- shift || true
- shift || true
- if [ -z "$PERF_SUB_COMMAND" ] ; then
- usage
- fi
- if [ -z "$PERF_DATA_DIR" ] ; then
- usage
- fi
- case "$PERF_SUB_COMMAND" in
- "record")
- while [ "$1" != "--" ] ; do
- PERF_OPTIONS+="$1 "
- shift || break
- done
- if [ "$1" != "--" ] ; then
- echo "Options and workload are required for recording" >&2
- usage
- fi
- shift
- record $*
- ;;
- "script")
- subcommand $*
- ;;
- "report")
- subcommand $*
- ;;
- "inject")
- subcommand $*
- ;;
- *)
- usage
- ;;
- esac
|