aboutsummaryrefslogtreecommitdiff
path: root/script/perf-copy-mapped-files.bash
diff options
context:
space:
mode:
Diffstat (limited to 'script/perf-copy-mapped-files.bash')
-rwxr-xr-xscript/perf-copy-mapped-files.bash275
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"