diff options
Diffstat (limited to 'script/perf-copy-mapped-files.bash')
| -rwxr-xr-x | script/perf-copy-mapped-files.bash | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/script/perf-copy-mapped-files.bash b/script/perf-copy-mapped-files.bash new file mode 100755 index 000000000000..6da81f98649c --- /dev/null +++ b/script/perf-copy-mapped-files.bash @@ -0,0 +1,275 @@ +#! /bin/bash +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +set -e + +prog=`basename $0` + +outdir="." +dryrun=0 + +buildid_cache=$(perf config buildid.dir || true) +if [[ -z $buildid_cache ]]; then + buildid_cache="$HOME/.debug" +fi + +usage() { + cat <<EOF +usage: $prog [<options>] <perf.data-file> + +Scan the perf data file for MMAP records and copy the referenced files to the +output directory set via the -o option. + +options: + + -h this text + -o <dir> set the output directory to <dir> (current: $outdir) + -b <dir> set the buildid cache directory to <dir> (current: $buildid_cache) + -n print commands instead of executing them + +<perf.data-file> defaults to perf.data. +EOF +} + +while getopts "ho:b:n" opt; do + case $opt in + h) + usage + exit 0 + ;; + o) + outdir=$OPTARG + ;; + b) + buildid_cache=$OPTARG + ;; + n) + dryrun=1 + ;; + esac +done + +shift $(($OPTIND-1)) + + +if [[ $# == 0 ]]; then + file="perf.data" +elif [[ $# == 1 ]]; then + file="$1" + shift +fi + +if [[ $# != 0 ]]; then + echo "$prog: unknown argument: $1. use -h for help." + exit 1 +fi + + +# Read the vdsos first. +# +# This creates the output directory for vdsos. +# +have_vdso32=$(which perf-read-vdso32 2>/dev/null || true) +have_vdsox32=$(which perf-read-vdsox32 2>/dev/null || true) + +if [[ $dryrun == 0 ]]; then + mkdir -p "$outdir/vdso" +else + echo "mkdir -p $outdir/vdso" +fi + +if [[ -n $have_vdso32 && ! -e "$outdir/vdso/vdso-ia32.so" ]]; then + if [[ $dryrun == 0 ]]; then + perf-read-vdso32 > "$outdir/vdso/vdso-ia32.so" + else + echo "perf-read-vdso32 > $outdir/vdso/vdso-ia32.so" + fi +fi + +if [[ -n $have_vdsox32 && ! -e "$outdir/vdso/vdso-x32.so" ]]; then + if [[ $dryrun == 0 ]]; then + perf-read-vdsox32 > "$outdir/vdso/vdso-x32.so" + else + echo "perf-read-vdsox32 > $outdir/vdso/vdso-x32.so" + fi +fi + +# If we have a buildid cache, use it. +# +if [[ -d $buildid_cache ]]; then + perf buildid-list -i "$file" | gawk -F' ' -- ' + function run(cmd) { + if (dryrun != 0) { + printf("%s\n", cmd) + } else { + system(cmd) + } + } + + function dirname(file) { + items = split(file, parts, "/", seps) + + delete parts[items] + + dname = "" + for (part in parts) { + dname = dname seps[part-1] parts[part] + } + + return dname + } + + function copy(src, dst) { + # do not overwrite existing files + # + status = system("ls " dst " > /dev/null 2>&1") + if (status == 0) { + return + } + + dir = dirname(dst) + + run("mkdir -p " dir) + run("cp " src " " dst) + } + + /^[0-9a-z]+ *\[vdso/ { + src = cache "/[vdso]/" $1 "/vdso" + + status = system("file " src " | grep -e \"ELF 64-bit.*x86-64\" >/dev/null 2>&1") + if (status == 0) { + copy(src, outdir "/vdso/vdso-x64.so") + next + } + + status = system("file " src " | grep -e \"ELF 32-bit.*x86-64\" >/dev/null 2>&1") + if (status == 0) { + copy(src, outdir "/vdso/vdso-x32.so") + next + } + + status = system("file " src " | grep -e \"ELF 32-bit.*Intel 80386\" >/dev/null 2>&1") + if (status == 0) { + copy(src, outdir "/vdso/vdso-x32.so") + next + } + + printf("%s: failed to determine flavor of %s.\n", prog, src) + next + } + + /^[0-9a-z]+ *\[/ { + next + } + + /^[0-9a-z]+ *.*.ko$/ { + next + } + + /^[0-9a-z]+ *.*.ko.xz$/ { + next + } + + /^[0-9a-z]+ *\// { + copy(cache $2 "/" $1 "/elf", outdir $2) + next + } + + ' dryrun="$dryrun" outdir="$outdir" cache="$buildid_cache" +fi + +# Copy files that were referenced but not in the buildid cache. +# +# We will skip files we already have so we don't overwrite anything we found in +# the buildid cache. +# +perf script --no-itrace -i "$file" -D | gawk -F' ' -- ' + function run(cmd) { + if (dryrun != 0) { + printf("%s\n", cmd) + } else { + system(cmd) + } + } + + function dirname(file) { + items = split(file, parts, "/", seps) + + delete parts[items] + + dname = "" + for (part in parts) { + dname = dname seps[part-1] parts[part] + } + + return dname + } + + function handle_mmap(file) { + # ignore any non-absolute filename + # + # this covers pseudo-files like [kallsyms] or [vdso] + # + if (substr(file, 0, 1) != "/") { + return + } + + # ignore kernel modules + # + # we rely on kcore + # + if (match(file, /\.ko$/) != 0) { + return + } + if (match(file, /\.ko.xz$/) != 0) { + return + } + + # ignore //anon + # + if (file == "//anon") { + return + } + + dst = outdir file + + # do not overwrite existing files + # + status = system("ls " dst " > /dev/null 2>&1") + if (status == 0) { + return + } + + dir = dirname(dst) + + run("mkdir -p " dir) + run("cp " file " " dst) + } + + /PERF_RECORD_MMAP/ { handle_mmap($NF) } +' dryrun="$dryrun" outdir="$outdir" |
