diff --git a/Makefile b/Makefile index 1496972b..e1ca8d52 100644 --- a/Makefile +++ b/Makefile @@ -94,7 +94,7 @@ check_static: .PHONY: check_license check_license: @echo "Confirming source files have license headers..." - @for f in `find . -type f ! -path './perfspect_202*' ! -path './tools/bin/*' ! -path './internal/script/resources/*' ! -path './scripts/.venv/*' ! -path './test/output/*' ! -path './debug_out/*' \( -name "*.go" -o -name "*.s" -o -name "*.html" -o -name "Makefile" -o -name "*.sh" -o -name "*.Dockerfile" -o -name "*.py" \)`; do \ + @for f in `find . -type f ! -path './perfspect_202*' ! -path './tools/bin/*' ! -path './internal/script/resources/*' ! -path './scripts/.venv/*' ! -path './test/output/*' ! -path './debug_out/*' ! -path './tools/perf-archive/*' \( -name "*.go" -o -name "*.s" -o -name "*.html" -o -name "Makefile" -o -name "*.sh" -o -name "*.Dockerfile" -o -name "*.py" \)`; do \ if ! grep -E 'SPDX-License-Identifier: BSD-3-Clause' "$$f" >/dev/null; then echo "Error: license not found: $$f"; fail=1; fi; \ done; if [ -n "$$fail" ]; then exit 1; fi diff --git a/tools/perf-archive/perf-archive.sh b/tools/perf-archive/perf-archive.sh new file mode 100755 index 00000000..e5ff840a --- /dev/null +++ b/tools/perf-archive/perf-archive.sh @@ -0,0 +1,146 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# perf archive +# Arnaldo Carvalho de Melo + +PERF_DATA=perf.data +PERF_SYMBOLS=perf.symbols +PERF_ALL=perf.all +ALL=0 +UNPACK=0 + +while [ $# -gt 0 ] ; do + if [ $1 == "--all" ]; then + ALL=1 + shift + elif [ $1 == "--unpack" ]; then + UNPACK=1 + shift + elif [ $1 == "--buildids-blacklist" ]; then + BUILDIDS_BLACKLIST="$2" + if [ ! -e "$BUILDIDS_BLACKLIST" ]; then + echo "Provided buildids blacklist file $BUILDIDS_BLACKLIST does not exist" + exit 1 + fi + shift 2 + else + PERF_DATA=$1 + UNPACK_TAR=$1 + shift + fi +done + +if [ $UNPACK -eq 1 ]; then + if [ ! -z "$UNPACK_TAR" ]; then # tar given as an argument + if [ ! -e "$UNPACK_TAR" ]; then + echo "Provided file $UNPACK_TAR does not exist" + exit 1 + fi + TARGET="$UNPACK_TAR" + else # search for perf tar in the current directory + TARGET=`find . -regex "\./perf.*\.tar\.bz2"` + TARGET_NUM=`echo -n "$TARGET" | grep -c '^'` + + if [ -z "$TARGET" ] || [ $TARGET_NUM -gt 1 ]; then + echo -e "Error: $TARGET_NUM files found for unpacking:\n$TARGET" + echo "Provide the requested file as an argument" + exit 1 + else + echo "Found target file for unpacking: $TARGET" + fi + fi + + if [[ "$TARGET" =~ (\./)?$PERF_ALL.*.tar.bz2 ]]; then # perf tar generated by --all option + TAR_CONTENTS=`tar tvf "$TARGET" | tr -s " " | cut -d " " -f 6` + VALID_TAR=`echo "$TAR_CONTENTS" | grep "$PERF_SYMBOLS.tar.bz2" | wc -l` # check if it contains a sub-tar perf.symbols + if [ $VALID_TAR -ne 1 ]; then + echo "Error: $TARGET file is not valid (contains zero or multiple sub-tar files with debug symbols)" + exit 1 + fi + + INTERSECT=`comm -12 <(ls) <(echo "$TAR_CONTENTS") | tr "\n" " "` # check for overwriting + if [ ! -z "$INTERSECT" ]; then # prompt if file(s) already exist in the current directory + echo "File(s) ${INTERSECT::-1} already exist in the current directory." + while true; do + read -p 'Do you wish to overwrite them? ' yn + case $yn in + [Yy]* ) break;; + [Nn]* ) exit 1;; + * ) echo "Please answer yes or no.";; + esac + done + fi + + # unzip the perf.data file in the current working directory and debug symbols in ~/.debug directory + tar xvf $TARGET && tar xvf $PERF_SYMBOLS.tar.bz2 -C ~/.debug + + else # perf tar generated by perf archive (contains only debug symbols) + tar xvf $TARGET -C ~/.debug + fi + exit 0 +fi + +# +# PERF_BUILDID_DIR environment variable set by perf +# path to buildid directory, default to $HOME/.debug +# +if [ -z $PERF_BUILDID_DIR ]; then + PERF_BUILDID_DIR=~/.debug/ +else + # append / to make substitutions work + PERF_BUILDID_DIR=$PERF_BUILDID_DIR/ +fi + +BUILDIDS=$(mktemp /tmp/perf-archive-buildids.XXXXXX) + +# +# BUILDIDS_BLACKLIST is an optional file that contains build-ids to be excluded from the +# archive. It is a list of build-ids, one per line, without any leading or trailing spaces. +# If the file is empty, all build-ids will be included in the archive. To create a blacklist +# file, you can use the following command: +# perf buildid-list -i perf.data --with-hits | grep -v "^ " > buildids_blacklist.txt +# You can edit the file to remove the lines that you want to keep in the archive, then: +# perf archive --buildids-blacklist buildids_blacklist.txt +# +if [ ! -s $BUILDIDS_BLACKLIST ]; then + perf buildid-list -i $PERF_DATA --with-hits | grep -v "^ " > $BUILDIDS + if [ ! -s $BUILDIDS ] ; then + echo "perf archive: no build-ids found" + rm $BUILDIDS || true + exit 1 + fi +else + perf buildid-list -i $PERF_DATA --with-hits | grep -v "^ " | grep -Fv -f $BUILDIDS_BLACKLIST > $BUILDIDS + if [ ! -s $BUILDIDS ] ; then + echo "perf archive: no build-ids found after applying blacklist" + rm $BUILDIDS || true + exit 1 + fi +fi + +MANIFEST=$(mktemp /tmp/perf-archive-manifest.XXXXXX) +PERF_BUILDID_LINKDIR=$(readlink -f $PERF_BUILDID_DIR)/ + +cut -d ' ' -f 1 $BUILDIDS | \ +while read build_id ; do + linkname=$PERF_BUILDID_DIR.build-id/${build_id:0:2}/${build_id:2} + filename=$(readlink -f $linkname) + echo ${linkname#$PERF_BUILDID_DIR} >> $MANIFEST + echo ${filename#$PERF_BUILDID_LINKDIR} >> $MANIFEST +done + +if [ $ALL -eq 1 ]; then # pack perf.data file together with tar containing debug symbols + HOSTNAME=$(hostname) + DATE=$(date '+%Y%m%d-%H%M%S') + tar cjf $PERF_SYMBOLS.tar.bz2 -C $PERF_BUILDID_DIR -T $MANIFEST + tar cjf $PERF_ALL-$HOSTNAME-$DATE.tar.bz2 $PERF_DATA $PERF_SYMBOLS.tar.bz2 + rm $PERF_SYMBOLS.tar.bz2 $MANIFEST $BUILDIDS || true +else # pack only the debug symbols + tar cjf $PERF_DATA.tar.bz2 -C $PERF_BUILDID_DIR -T $MANIFEST + rm $MANIFEST $BUILDIDS || true +fi + +echo -e "Now please run:\n" +echo -e "$ perf archive --unpack\n" +echo "or unpack the tar manually wherever you need to run 'perf report' on." +exit 0