linux/tools/perf/perf-with-kcore.sh
<<
>>
Prefs
   1#!/bin/bash
   2# SPDX-License-Identifier: GPL-2.0-only
   3# perf-with-kcore: use perf with a copy of kcore
   4# Copyright (c) 2014, Intel Corporation.
   5#
   6
   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
  46        ("$PERF" record -o perf.data.junk "${PERF_OPTIONS[@]}" -- sleep 60) >/dev/null 2>/dev/null &
  47        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
 107        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
 151                if echo "${PERF_OPTIONS[@]}" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then
 152                        echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2
 153                fi
 154
 155                if echo "${PERF_OPTIONS[@]}" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then
 156                        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
 160                        if echo "${PERF_OPTIONS[@]}" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then
 161                                true
 162                        elif echo "${PERF_OPTIONS[@]}" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then
 163                                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
 184        echo "$PERF record -o $PERF_DATA_DIR/perf.data ${PERF_OPTIONS[@]} -- $@"
 185        "$PERF" record -o "$PERF_DATA_DIR/perf.data" "${PERF_OPTIONS[@]}" -- "$@" || true
 186
 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
 200        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" "$@"
 202}
 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
 225                PERF_OPTIONS+=("$1")
 226                shift || break
 227        done
 228        if [ "$1" != "--" ] ; then
 229                echo "Options and workload are required for recording" >&2
 230                usage
 231        fi
 232        shift
 233        record "$@"
 234;;
 235"script")
 236        subcommand "$@"
 237;;
 238"report")
 239        subcommand "$@"
 240;;
 241"inject")
 242        subcommand "$@"
 243;;
 244*)
 245        usage
 246;;
 247esac
 248