perf-with-kcore.sh 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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. set -e
  7. usage()
  8. {
  9. echo "Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]" >&2
  10. echo " <perf sub-command> can be record, script, report or inject" >&2
  11. echo " or: perf-with-kcore fix_buildid_cache_permissions" >&2
  12. exit 1
  13. }
  14. find_perf()
  15. {
  16. if [ -n "$PERF" ] ; then
  17. return
  18. fi
  19. PERF=`which perf || true`
  20. if [ -z "$PERF" ] ; then
  21. echo "Failed to find perf" >&2
  22. exit 1
  23. fi
  24. if [ ! -x "$PERF" ] ; then
  25. echo "Failed to find perf" >&2
  26. exit 1
  27. fi
  28. echo "Using $PERF"
  29. "$PERF" version
  30. }
  31. copy_kcore()
  32. {
  33. echo "Copying kcore"
  34. if [ $EUID -eq 0 ] ; then
  35. SUDO=""
  36. else
  37. SUDO="sudo"
  38. fi
  39. rm -f perf.data.junk
  40. ("$PERF" record -o perf.data.junk "${PERF_OPTIONS[@]}" -- sleep 60) >/dev/null 2>/dev/null &
  41. PERF_PID=$!
  42. # Need to make sure that perf has started
  43. sleep 1
  44. KCORE=$(($SUDO "$PERF" buildid-cache -v -f -k /proc/kcore >/dev/null) 2>&1)
  45. case "$KCORE" in
  46. "kcore added to build-id cache directory "*)
  47. KCORE_DIR=${KCORE#"kcore added to build-id cache directory "}
  48. ;;
  49. *)
  50. kill $PERF_PID
  51. wait >/dev/null 2>/dev/null || true
  52. rm perf.data.junk
  53. echo "$KCORE"
  54. echo "Failed to find kcore" >&2
  55. exit 1
  56. ;;
  57. esac
  58. kill $PERF_PID
  59. wait >/dev/null 2>/dev/null || true
  60. rm perf.data.junk
  61. $SUDO cp -a "$KCORE_DIR" "$(pwd)/$PERF_DATA_DIR"
  62. $SUDO rm -f "$KCORE_DIR/kcore"
  63. $SUDO rm -f "$KCORE_DIR/kallsyms"
  64. $SUDO rm -f "$KCORE_DIR/modules"
  65. $SUDO rmdir "$KCORE_DIR"
  66. KCORE_DIR_BASENAME=$(basename "$KCORE_DIR")
  67. KCORE_DIR="$(pwd)/$PERF_DATA_DIR/$KCORE_DIR_BASENAME"
  68. $SUDO chown $UID "$KCORE_DIR"
  69. $SUDO chown $UID "$KCORE_DIR/kcore"
  70. $SUDO chown $UID "$KCORE_DIR/kallsyms"
  71. $SUDO chown $UID "$KCORE_DIR/modules"
  72. $SUDO chgrp $GROUPS "$KCORE_DIR"
  73. $SUDO chgrp $GROUPS "$KCORE_DIR/kcore"
  74. $SUDO chgrp $GROUPS "$KCORE_DIR/kallsyms"
  75. $SUDO chgrp $GROUPS "$KCORE_DIR/modules"
  76. ln -s "$KCORE_DIR_BASENAME" "$PERF_DATA_DIR/kcore_dir"
  77. }
  78. fix_buildid_cache_permissions()
  79. {
  80. if [ $EUID -ne 0 ] ; then
  81. echo "This script must be run as root via sudo " >&2
  82. exit 1
  83. fi
  84. if [ -z "$SUDO_USER" ] ; then
  85. echo "This script must be run via sudo" >&2
  86. exit 1
  87. fi
  88. USER_HOME=$(bash <<< "echo ~$SUDO_USER")
  89. echo "Fixing buildid cache permissions"
  90. find "$USER_HOME/.debug" -xdev -type d ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
  91. find "$USER_HOME/.debug" -xdev -type f -links 1 ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
  92. find "$USER_HOME/.debug" -xdev -type l ! -user "$SUDO_USER" -ls -exec chown -h "$SUDO_USER" \{\} \;
  93. if [ -n "$SUDO_GID" ] ; then
  94. find "$USER_HOME/.debug" -xdev -type d ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
  95. find "$USER_HOME/.debug" -xdev -type f -links 1 ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
  96. find "$USER_HOME/.debug" -xdev -type l ! -group "$SUDO_GID" -ls -exec chgrp -h "$SUDO_GID" \{\} \;
  97. fi
  98. echo "Done"
  99. }
  100. check_buildid_cache_permissions()
  101. {
  102. if [ $EUID -eq 0 ] ; then
  103. return
  104. fi
  105. PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -user "$USER" -print -quit)
  106. PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -user "$USER" -print -quit)
  107. PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -user "$USER" -print -quit)
  108. PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -group "$GROUPS" -print -quit)
  109. PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -group "$GROUPS" -print -quit)
  110. PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -group "$GROUPS" -print -quit)
  111. if [ -n "$PERMISSIONS_OK" ] ; then
  112. echo "*** WARNING *** buildid cache permissions may need fixing" >&2
  113. fi
  114. }
  115. record()
  116. {
  117. echo "Recording"
  118. if [ $EUID -ne 0 ] ; then
  119. if [ "$(cat /proc/sys/kernel/kptr_restrict)" -ne 0 ] ; then
  120. echo "*** WARNING *** /proc/sys/kernel/kptr_restrict prevents access to kernel addresses" >&2
  121. fi
  122. if echo "${PERF_OPTIONS[@]}" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then
  123. echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2
  124. fi
  125. if echo "${PERF_OPTIONS[@]}" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then
  126. if [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt -1 ] ; then
  127. echo "*** WARNING *** /proc/sys/kernel/perf_event_paranoid restricts buffer size and tracepoint (sched_switch) use" >&2
  128. fi
  129. if echo "${PERF_OPTIONS[@]}" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then
  130. true
  131. elif echo "${PERF_OPTIONS[@]}" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then
  132. true
  133. elif [ ! -r /sys/kernel/debug -o ! -x /sys/kernel/debug ] ; then
  134. echo "*** WARNING *** /sys/kernel/debug permissions prevent tracepoint (sched_switch) use" >&2
  135. fi
  136. fi
  137. fi
  138. if [ -z "$1" ] ; then
  139. echo "Workload is required for recording" >&2
  140. usage
  141. fi
  142. if [ -e "$PERF_DATA_DIR" ] ; then
  143. echo "'$PERF_DATA_DIR' exists" >&2
  144. exit 1
  145. fi
  146. find_perf
  147. mkdir "$PERF_DATA_DIR"
  148. echo "$PERF record -o $PERF_DATA_DIR/perf.data ${PERF_OPTIONS[@]} -- $@"
  149. "$PERF" record -o "$PERF_DATA_DIR/perf.data" "${PERF_OPTIONS[@]}" -- "$@" || true
  150. if rmdir "$PERF_DATA_DIR" > /dev/null 2>/dev/null ; then
  151. exit 1
  152. fi
  153. copy_kcore
  154. echo "Done"
  155. }
  156. subcommand()
  157. {
  158. find_perf
  159. check_buildid_cache_permissions
  160. echo "$PERF $PERF_SUB_COMMAND -i $PERF_DATA_DIR/perf.data --kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms $@"
  161. "$PERF" $PERF_SUB_COMMAND -i "$PERF_DATA_DIR/perf.data" "--kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms" "$@"
  162. }
  163. if [ "$1" = "fix_buildid_cache_permissions" ] ; then
  164. fix_buildid_cache_permissions
  165. exit 0
  166. fi
  167. PERF_SUB_COMMAND=$1
  168. PERF_DATA_DIR=$2
  169. shift || true
  170. shift || true
  171. if [ -z "$PERF_SUB_COMMAND" ] ; then
  172. usage
  173. fi
  174. if [ -z "$PERF_DATA_DIR" ] ; then
  175. usage
  176. fi
  177. case "$PERF_SUB_COMMAND" in
  178. "record")
  179. while [ "$1" != "--" ] ; do
  180. PERF_OPTIONS+=("$1")
  181. shift || break
  182. done
  183. if [ "$1" != "--" ] ; then
  184. echo "Options and workload are required for recording" >&2
  185. usage
  186. fi
  187. shift
  188. record "$@"
  189. ;;
  190. "script")
  191. subcommand "$@"
  192. ;;
  193. "report")
  194. subcommand "$@"
  195. ;;
  196. "inject")
  197. subcommand "$@"
  198. ;;
  199. *)
  200. usage
  201. ;;
  202. esac