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