SCRIPT_SH =
 
 SCRIPT_SH += perf-archive.sh
+SCRIPT_SH += perf-with-kcore.sh
 
 grep-libs = $(filter -l%,$(1))
 strip-libs = $(filter-out -l%,$(1))
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
        $(call QUIET_INSTALL, perf-archive) \
                $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
+       $(call QUIET_INSTALL, perf-with-kcore) \
+               $(INSTALL) $(OUTPUT)perf-with-kcore -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
 ifndef NO_LIBPERL
        $(call QUIET_INSTALL, perl-scripts) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
        @$(MAKE) -C config/feature-checks clean >/dev/null
 
 clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
-       $(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
+       $(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
        $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
        $(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
        $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
 
--- /dev/null
+#!/bin/bash
+# perf-with-kcore: use perf with a copy of kcore
+# Copyright (c) 2014, Intel Corporation.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+
+set -e
+
+usage()
+{
+        echo "Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]" >&2
+        echo "       <perf sub-command> can be record, script, report or inject" >&2
+        echo "   or: perf-with-kcore fix_buildid_cache_permissions" >&2
+        exit 1
+}
+
+find_perf()
+{
+       if [ -n "$PERF" ] ; then
+               return
+       fi
+       PERF=`which perf || true`
+       if [ -z "$PERF" ] ; then
+               echo "Failed to find perf" >&2
+               exit 1
+       fi
+       if [ ! -x "$PERF" ] ; then
+               echo "Failed to find perf" >&2
+               exit 1
+       fi
+       echo "Using $PERF"
+       "$PERF" version
+}
+
+copy_kcore()
+{
+       echo "Copying kcore"
+
+       if [ $EUID -eq 0 ] ; then
+               SUDO=""
+       else
+               SUDO="sudo"
+       fi
+
+       rm -f perf.data.junk
+       ("$PERF" record -o perf.data.junk $PERF_OPTIONS -- sleep 60) >/dev/null 2>/dev/null &
+       PERF_PID=$!
+
+       # Need to make sure that perf has started
+       sleep 1
+
+       KCORE=$(($SUDO "$PERF" buildid-cache -v -f -k /proc/kcore >/dev/null) 2>&1)
+       case "$KCORE" in
+       "kcore added to build-id cache directory "*)
+               KCORE_DIR=${KCORE#"kcore added to build-id cache directory "}
+       ;;
+       *)
+               kill $PERF_PID
+               wait >/dev/null 2>/dev/null || true
+               rm perf.data.junk
+               echo "$KCORE"
+               echo "Failed to find kcore" >&2
+               exit 1
+       ;;
+       esac
+
+       kill $PERF_PID
+       wait >/dev/null 2>/dev/null || true
+       rm perf.data.junk
+
+       $SUDO cp -a "$KCORE_DIR" "$(pwd)/$PERF_DATA_DIR"
+       $SUDO rm -f "$KCORE_DIR/kcore"
+       $SUDO rm -f "$KCORE_DIR/kallsyms"
+       $SUDO rm -f "$KCORE_DIR/modules"
+       $SUDO rmdir "$KCORE_DIR"
+
+       KCORE_DIR_BASENAME=$(basename "$KCORE_DIR")
+       KCORE_DIR="$(pwd)/$PERF_DATA_DIR/$KCORE_DIR_BASENAME"
+
+       $SUDO chown $UID "$KCORE_DIR"
+       $SUDO chown $UID "$KCORE_DIR/kcore"
+       $SUDO chown $UID "$KCORE_DIR/kallsyms"
+       $SUDO chown $UID "$KCORE_DIR/modules"
+
+       $SUDO chgrp $GROUPS "$KCORE_DIR"
+       $SUDO chgrp $GROUPS "$KCORE_DIR/kcore"
+       $SUDO chgrp $GROUPS "$KCORE_DIR/kallsyms"
+       $SUDO chgrp $GROUPS "$KCORE_DIR/modules"
+
+       ln -s "$KCORE_DIR_BASENAME" "$PERF_DATA_DIR/kcore_dir"
+}
+
+fix_buildid_cache_permissions()
+{
+       if [ $EUID -ne 0 ] ; then
+               echo "This script must be run as root via sudo " >&2
+               exit 1
+       fi
+
+       if [ -z "$SUDO_USER" ] ; then
+               echo "This script must be run via sudo" >&2
+               exit 1
+       fi
+
+       USER_HOME=$(bash <<< "echo ~$SUDO_USER")
+
+       if [ "$HOME" != "$USER_HOME" ] ; then
+               echo "Fix unnecessary because root has a home: $HOME" >&2
+               exit 1
+       fi
+
+       echo "Fixing buildid cache permissions"
+
+       find "$USER_HOME/.debug" -xdev -type d          ! -user "$SUDO_USER" -ls -exec chown    "$SUDO_USER" \{\} \;
+       find "$USER_HOME/.debug" -xdev -type f -links 1 ! -user "$SUDO_USER" -ls -exec chown    "$SUDO_USER" \{\} \;
+       find "$USER_HOME/.debug" -xdev -type l          ! -user "$SUDO_USER" -ls -exec chown -h "$SUDO_USER" \{\} \;
+
+       if [ -n "$SUDO_GID" ] ; then
+               find "$USER_HOME/.debug" -xdev -type d          ! -group "$SUDO_GID" -ls -exec chgrp    "$SUDO_GID" \{\} \;
+               find "$USER_HOME/.debug" -xdev -type f -links 1 ! -group "$SUDO_GID" -ls -exec chgrp    "$SUDO_GID" \{\} \;
+               find "$USER_HOME/.debug" -xdev -type l          ! -group "$SUDO_GID" -ls -exec chgrp -h "$SUDO_GID" \{\} \;
+       fi
+
+       echo "Done"
+}
+
+check_buildid_cache_permissions()
+{
+       if [ $EUID -eq 0 ] ; then
+               return
+       fi
+
+       PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d          ! -user "$USER" -print -quit)
+       PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -user "$USER" -print -quit)
+       PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l          ! -user "$USER" -print -quit)
+
+       PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d          ! -group "$GROUPS" -print -quit)
+       PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -group "$GROUPS" -print -quit)
+       PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l          ! -group "$GROUPS" -print -quit)
+
+       if [ -n "$PERMISSIONS_OK" ] ; then
+               echo "*** WARNING *** buildid cache permissions may need fixing" >&2
+       fi
+}
+
+record()
+{
+       echo "Recording"
+
+       if [ $EUID -ne 0 ] ; then
+
+               if [ "$(cat /proc/sys/kernel/kptr_restrict)" -ne 0 ] ; then
+                       echo "*** WARNING *** /proc/sys/kernel/kptr_restrict prevents access to kernel addresses" >&2
+               fi
+
+               if echo "$PERF_OPTIONS" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then
+                       echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2
+               fi
+
+               if echo "$PERF_OPTIONS" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then
+                       if [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt -1 ] ; then
+                               echo "*** WARNING *** /proc/sys/kernel/perf_event_paranoid restricts buffer size and tracepoint (sched_switch) use" >&2
+                       fi
+
+                       if echo "$PERF_OPTIONS" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then
+                               true
+                       elif echo "$PERF_OPTIONS" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then
+                               true
+                       elif [ ! -r /sys/kernel/debug -o ! -x /sys/kernel/debug ] ; then
+                               echo "*** WARNING *** /sys/kernel/debug permissions prevent tracepoint (sched_switch) use" >&2
+                       fi
+               fi
+       fi
+
+       if [ -z "$1" ] ; then
+               echo "Workload is required for recording" >&2
+               usage
+       fi
+
+       if [ -e "$PERF_DATA_DIR" ] ; then
+               echo "'$PERF_DATA_DIR' exists" >&2
+               exit 1
+       fi
+
+       find_perf
+
+       mkdir "$PERF_DATA_DIR"
+
+       echo "$PERF record -o $PERF_DATA_DIR/perf.data $PERF_OPTIONS -- $*"
+       "$PERF" record -o "$PERF_DATA_DIR/perf.data" $PERF_OPTIONS -- $* || true
+
+       if rmdir "$PERF_DATA_DIR" > /dev/null 2>/dev/null ; then
+               exit 1
+       fi
+
+       copy_kcore
+
+       echo "Done"
+}
+
+subcommand()
+{
+       find_perf
+       check_buildid_cache_permissions
+       echo "$PERF $PERF_SUB_COMMAND -i $PERF_DATA_DIR/perf.data --kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms $*"
+       "$PERF" $PERF_SUB_COMMAND -i "$PERF_DATA_DIR/perf.data" "--kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms" $*
+}
+
+if [ "$1" = "fix_buildid_cache_permissions" ] ; then
+       fix_buildid_cache_permissions
+       exit 0
+fi
+
+PERF_SUB_COMMAND=$1
+PERF_DATA_DIR=$2
+shift || true
+shift || true
+
+if [ -z "$PERF_SUB_COMMAND" ] ; then
+       usage
+fi
+
+if [ -z "$PERF_DATA_DIR" ] ; then
+       usage
+fi
+
+case "$PERF_SUB_COMMAND" in
+"record")
+       while [ "$1" != "--" ] ; do
+               PERF_OPTIONS+="$1 "
+               shift || break
+       done
+       if [ "$1" != "--" ] ; then
+               echo "Options and workload are required for recording" >&2
+               usage
+       fi
+       shift
+       record $*
+;;
+"script")
+       subcommand $*
+;;
+"report")
+       subcommand $*
+;;
+"inject")
+       subcommand $*
+;;
+*)
+       usage
+;;
+esac