mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 08:44:21 +08:00
perf/core improvements and fixes:
User visible: o Add +field argument support for --sort option (Jiri Olsa) o Do not access kallsyms when analyzing user binaries with 'probe' (Masami Hiramatsu) o Ignore stripped vmlinux and fallback to kallsyms (Anton Blanchard) o Add path to Ubuntu kernel debuginfo file (Anton Blanchard) o Disable kernel symbol demangling by default (Avi Kivity) Infrastructure: o More intel PT prep work, from Adrian Hunter, including: - Let a user specify a PMU event without any config terms - Add perf-with-kcore script - Let default config be defined for a PMU - Add perf_pmu__scan_file() o "perf kvm stat report" improvements by Alexander Yarygin: o Save pid string in opts.target.pid o Enable the target.system_wide flag o Unify the title bar output o Fix build issue on powerpc when DWARF support is disabled (Anton Blanchard) o Allow to specify lib compile variable for spec usage (Jiri Olsa) o Fix build on ARM (Stephane Eranian) o Fix build on powerpc when DWARF support is disabled (Anton Blanchard) o Don't include sys/poll.h directly (Arnaldo Carvalho de Melo) o Use ring buffer consume method to look like other tools (Arnaldo Carvalho de Melo) Chanho Park (1): perf tools: define _DEFAULT_SOURCE for glibc_2.20 o Allow to specify lib compile variable for spec usage (Jiri Olsa) o Fix GNU-only grep usage in Makefile (John Spencer) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJUGfrFAAoJENZQFvNTUqpAMt8P/RG+9YFHvuu2bTgEKgyBI/Q5 90uJvIdEg3+VmjRgTYBHIhvgLOZZqZK5NFmroH8adpohjjVgDDe9LzC/CthCYugO +R4Tro335U+lYPro6uRb5Y3bpTXOLOaSN+w0zN0ZbENgbbZz5OLDWKdBxXpHkGxO 1hDAy5U4wrM0/1m2yEvWjHUQaq6n8wAvosuA74xTigsW4KlZridT1yrqD+9jwdf0 8TJZTkaM/C9wIfJlpAOS+sUvsPXS6KvlpP8lgsrlT+EGx8dr242StpaBQqBurIIu HRVZDHKZB47eNUEHxWJx3Nxls2s2I714fwzwcnaW2zXQfzS+HvNyA+gRKyDJN0CY c70F/xcKsC7XTrUuXK/qtPha4Hy2+0pCe0jXxIxlQ3nOaoCmykzcmhTgkxS9pLAd 2r9l+mCPWy05qg4Y89FO8Pr2EBZLFE/MoiFflhJ/mCD/ac4amqEsJ8VZpaw7cMUH ZSv1nVQNf4TY+jjhIAI3iW44qVhqk37vpfgCsJmnxMZgON1lO4K8Y5BQZ/GtVg2l fQt7g7vrds1LgqEvLvD8wuohUUVioc5K6hiKF1KyOhnUdYnRyyE15K9IokDm83te Os4NJAjFeUQ3nRAvw8hiw+yVTCqK0paXFwULrlOrtzI7WzYCbtTdpyIzL3KXLZqT QrluzKo8Cu68ivrwr6nq =CKWF -----END PGP SIGNATURE----- Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: o Add +field argument support for --sort option (Jiri Olsa) o Do not access kallsyms when analyzing user binaries with 'probe' (Masami Hiramatsu) o Ignore stripped vmlinux and fallback to kallsyms (Anton Blanchard) o Add path to Ubuntu kernel debuginfo file (Anton Blanchard) o Disable kernel symbol demangling by default (Avi Kivity) Infrastructure changes: o More intel PT prep work, from Adrian Hunter, including: - Let a user specify a PMU event without any config terms - Add perf-with-kcore script - Let default config be defined for a PMU - Add perf_pmu__scan_file() o "perf kvm stat report" improvements by Alexander Yarygin: o Save pid string in opts.target.pid o Enable the target.system_wide flag o Unify the title bar output o Fix build issue on powerpc when DWARF support is disabled (Anton Blanchard) o Allow to specify lib compile variable for spec usage (Jiri Olsa) o Fix build on ARM (Stephane Eranian) o Fix build on powerpc when DWARF support is disabled (Anton Blanchard) o Don't include sys/poll.h directly (Arnaldo Carvalho de Melo) o Use ring buffer consume method to look like other tools (Arnaldo Carvalho de Melo) o Allow to specify lib compile variable for spec usage (Jiri Olsa) o Fix GNU-only grep usage in Makefile (John Spencer) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
4f7cf3a992
1
tools/perf/.gitignore
vendored
1
tools/perf/.gitignore
vendored
@ -15,6 +15,7 @@ perf.data
|
||||
perf.data.old
|
||||
output.svg
|
||||
perf-archive
|
||||
perf-with-kcore
|
||||
tags
|
||||
TAGS
|
||||
cscope*
|
||||
|
@ -104,6 +104,9 @@ OPTIONS
|
||||
Specify path to the executable or shared library file for user
|
||||
space tracing. Can also be used with --funcs option.
|
||||
|
||||
--demangle-kernel::
|
||||
Demangle kernel symbols.
|
||||
|
||||
In absence of -m/-x options, perf probe checks if the first argument after
|
||||
the options is an absolute path name. If its an absolute path, perf probe
|
||||
uses it as a target module/target user space binary to probe.
|
||||
|
@ -276,6 +276,9 @@ OPTIONS
|
||||
Demangle symbol names to human readable form. It's enabled by default,
|
||||
disable with --no-demangle.
|
||||
|
||||
--demangle-kernel::
|
||||
Demangle kernel symbol names to human readable form (for C++ kernels).
|
||||
|
||||
--mem-mode::
|
||||
Use the data addresses of samples in addition to instruction addresses
|
||||
to build the histograms. To generate meaningful output, the perf.data
|
||||
|
@ -98,6 +98,9 @@ Default is to monitor all CPUS.
|
||||
--hide_user_symbols::
|
||||
Hide user symbols.
|
||||
|
||||
--demangle-kernel::
|
||||
Demangle kernel symbols.
|
||||
|
||||
-D::
|
||||
--dump-symtab::
|
||||
Dump the symbol table used for profiling.
|
||||
|
@ -126,6 +126,7 @@ PYRF_OBJS =
|
||||
SCRIPT_SH =
|
||||
|
||||
SCRIPT_SH += perf-archive.sh
|
||||
SCRIPT_SH += perf-with-kcore.sh
|
||||
|
||||
grep-libs = $(filter -l%,$(1))
|
||||
strip-libs = $(filter-out -l%,$(1))
|
||||
@ -878,6 +879,8 @@ install-bin: all install-gtk
|
||||
$(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'; \
|
||||
@ -923,7 +926,7 @@ config-clean:
|
||||
@$(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
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "thread.h"
|
||||
#include "map.h"
|
||||
#include "event.h"
|
||||
#include "debug.h"
|
||||
#include "tests/tests.h"
|
||||
|
||||
#define STACK_SIZE 8192
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <libunwind.h>
|
||||
#include "perf_regs.h"
|
||||
#include "../../util/unwind.h"
|
||||
#include "../../util/debug.h"
|
||||
|
||||
int libunwind__arch_reg_id(int regnum)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
ifndef NO_DWARF
|
||||
PERF_HAVE_DWARF_REGS := 1
|
||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
|
||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
|
||||
endif
|
||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
|
||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/poll.h>
|
||||
#include <poll.h>
|
||||
#include <limits.h>
|
||||
#include <err.h>
|
||||
|
||||
|
@ -543,14 +543,12 @@ static void print_vcpu_info(struct perf_kvm_stat *kvm)
|
||||
|
||||
pr_info("Analyze events for ");
|
||||
|
||||
if (kvm->live) {
|
||||
if (kvm->opts.target.system_wide)
|
||||
pr_info("all VMs, ");
|
||||
else if (kvm->opts.target.pid)
|
||||
pr_info("pid(s) %s, ", kvm->opts.target.pid);
|
||||
else
|
||||
pr_info("dazed and confused on what is monitored, ");
|
||||
}
|
||||
if (kvm->opts.target.system_wide)
|
||||
pr_info("all VMs, ");
|
||||
else if (kvm->opts.target.pid)
|
||||
pr_info("pid(s) %s, ", kvm->opts.target.pid);
|
||||
else
|
||||
pr_info("dazed and confused on what is monitored, ");
|
||||
|
||||
if (vcpu == -1)
|
||||
pr_info("all VCPUs:\n\n");
|
||||
@ -1085,8 +1083,8 @@ static int read_events(struct perf_kvm_stat *kvm)
|
||||
|
||||
static int parse_target_str(struct perf_kvm_stat *kvm)
|
||||
{
|
||||
if (kvm->pid_str) {
|
||||
kvm->pid_list = intlist__new(kvm->pid_str);
|
||||
if (kvm->opts.target.pid) {
|
||||
kvm->pid_list = intlist__new(kvm->opts.target.pid);
|
||||
if (kvm->pid_list == NULL) {
|
||||
pr_err("Error parsing process id string\n");
|
||||
return -EINVAL;
|
||||
@ -1188,7 +1186,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
|
||||
OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
|
||||
"key for sorting: sample(sort by samples number)"
|
||||
" time (sort by avg time)"),
|
||||
OPT_STRING('p', "pid", &kvm->pid_str, "pid",
|
||||
OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
|
||||
"analyze events only for given process id(s)"),
|
||||
OPT_END()
|
||||
};
|
||||
@ -1207,6 +1205,9 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
|
||||
kvm_events_report_options);
|
||||
}
|
||||
|
||||
if (!kvm->opts.target.pid)
|
||||
kvm->opts.target.system_wide = true;
|
||||
|
||||
return kvm_events_report_vcpu(kvm);
|
||||
}
|
||||
|
||||
|
@ -376,6 +376,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
"target executable name or path", opt_set_target),
|
||||
OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
|
||||
"Disable symbol demangling"),
|
||||
OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
|
||||
"Enable kernel symbol demangling"),
|
||||
OPT_END()
|
||||
};
|
||||
int ret;
|
||||
@ -470,7 +472,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
usage_with_options(probe_usage, options);
|
||||
}
|
||||
|
||||
ret = show_line_range(¶ms.line_range, params.target);
|
||||
ret = show_line_range(¶ms.line_range, params.target,
|
||||
params.uprobes);
|
||||
if (ret < 0)
|
||||
pr_err_with_code(" Error: Failed to show lines.", ret);
|
||||
return ret;
|
||||
|
@ -65,8 +65,9 @@ static int process_synthesized_event(struct perf_tool *tool,
|
||||
return record__write(rec, event, event->header.size);
|
||||
}
|
||||
|
||||
static int record__mmap_read(struct record *rec, struct perf_mmap *md)
|
||||
static int record__mmap_read(struct record *rec, int idx)
|
||||
{
|
||||
struct perf_mmap *md = &rec->evlist->mmap[idx];
|
||||
unsigned int head = perf_mmap__read_head(md);
|
||||
unsigned int old = md->prev;
|
||||
unsigned char *data = md->base + page_size;
|
||||
@ -102,8 +103,7 @@ static int record__mmap_read(struct record *rec, struct perf_mmap *md)
|
||||
}
|
||||
|
||||
md->prev = old;
|
||||
perf_mmap__write_tail(md, old);
|
||||
|
||||
perf_evlist__mmap_consume(rec->evlist, idx);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
@ -245,7 +245,7 @@ static int record__mmap_read_all(struct record *rec)
|
||||
|
||||
for (i = 0; i < rec->evlist->nr_mmaps; i++) {
|
||||
if (rec->evlist->mmap[i].base) {
|
||||
if (record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
|
||||
if (record__mmap_read(rec, i) != 0) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
@ -680,6 +680,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
"objdump binary to use for disassembly and annotations"),
|
||||
OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
|
||||
"Disable symbol demangling"),
|
||||
OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
|
||||
"Enable kernel symbol demangling"),
|
||||
OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
|
||||
OPT_CALLBACK(0, "percent-limit", &report, "percent",
|
||||
"Don't show entries under that percent", parse_percent_limit),
|
||||
|
@ -59,7 +59,7 @@
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/poll.h>
|
||||
#include <poll.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/uio.h>
|
||||
@ -1142,6 +1142,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
"Interleave source code with assembly code (default)"),
|
||||
OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
|
||||
"Display raw encoding of assembly instructions (default)"),
|
||||
OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
|
||||
"Enable kernel symbol demangling"),
|
||||
OPT_STRING(0, "objdump", &objdump_path, "path",
|
||||
"objdump binary to use for disassembly and annotations"),
|
||||
OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
|
||||
|
@ -48,10 +48,6 @@ ifneq ($(ARCH),$(filter $(ARCH),x86 arm))
|
||||
NO_LIBDW_DWARF_UNWIND := 1
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),powerpc)
|
||||
CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
|
||||
endif
|
||||
|
||||
ifeq ($(LIBUNWIND_LIBS),)
|
||||
NO_LIBUNWIND := 1
|
||||
else
|
||||
@ -378,6 +374,12 @@ ifndef NO_LIBELF
|
||||
endif # NO_DWARF
|
||||
endif # NO_LIBELF
|
||||
|
||||
ifeq ($(ARCH),powerpc)
|
||||
ifndef NO_DWARF
|
||||
CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef NO_LIBUNWIND
|
||||
ifneq ($(feature-libunwind), 1)
|
||||
msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR);
|
||||
@ -651,11 +653,13 @@ else
|
||||
sysconfdir = $(prefix)/etc
|
||||
ETC_PERFCONFIG = etc/perfconfig
|
||||
endif
|
||||
ifndef lib
|
||||
ifeq ($(IS_X86_64),1)
|
||||
lib = lib64
|
||||
else
|
||||
lib = lib
|
||||
endif
|
||||
endif # lib
|
||||
libdir = $(prefix)/$(lib)
|
||||
|
||||
# Shell quote (do not use $(call) to accommodate ancient setups);
|
||||
|
@ -132,7 +132,7 @@ endef
|
||||
#
|
||||
# Usage: bool-value = $(call is-absolute,path)
|
||||
#
|
||||
is-absolute = $(shell echo $(shell-sq) | grep ^/ -q && echo y)
|
||||
is-absolute = $(shell echo $(shell-sq) | grep -q ^/ && echo y)
|
||||
|
||||
# lookup
|
||||
#
|
||||
|
259
tools/perf/perf-with-kcore.sh
Normal file
259
tools/perf/perf-with-kcore.sh
Normal file
@ -0,0 +1,259 @@
|
||||
#!/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
|
@ -152,7 +152,7 @@ int test__pmu(void)
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
ret = perf_pmu__config_terms(&formats, &attr, terms);
|
||||
ret = perf_pmu__config_terms(&formats, &attr, terms, false);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
|
@ -92,7 +92,6 @@ struct perf_kvm_stat {
|
||||
u64 lost_events;
|
||||
u64 duration;
|
||||
|
||||
const char *pid_str;
|
||||
struct intlist *pid_list;
|
||||
|
||||
struct rb_root result;
|
||||
|
@ -643,7 +643,18 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
|
||||
if (!pmu)
|
||||
return -EINVAL;
|
||||
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
if (pmu->default_config) {
|
||||
memcpy(&attr, pmu->default_config,
|
||||
sizeof(struct perf_event_attr));
|
||||
} else {
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
}
|
||||
|
||||
if (!head_config) {
|
||||
attr.type = pmu->type;
|
||||
evsel = __add_event(list, idx, &attr, NULL, pmu->cpus);
|
||||
return evsel ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
if (perf_pmu__check_alias(pmu, head_config, &unit, &scale))
|
||||
return -EINVAL;
|
||||
|
@ -210,6 +210,16 @@ PE_NAME '/' event_config '/'
|
||||
parse_events__free_terms($3);
|
||||
$$ = list;
|
||||
}
|
||||
|
|
||||
PE_NAME '/' '/'
|
||||
{
|
||||
struct parse_events_evlist *data = _data;
|
||||
struct list_head *list;
|
||||
|
||||
ALLOC_LIST(list);
|
||||
ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, NULL));
|
||||
$$ = list;
|
||||
}
|
||||
|
||||
value_sym:
|
||||
PE_VALUE_SYM_HW
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <dirent.h>
|
||||
#include <api/fs/fs.h>
|
||||
#include <locale.h>
|
||||
@ -387,6 +389,12 @@ static struct cpu_map *pmu_cpumask(const char *name)
|
||||
return cpus;
|
||||
}
|
||||
|
||||
struct perf_event_attr *__attribute__((weak))
|
||||
perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct perf_pmu *pmu_lookup(const char *name)
|
||||
{
|
||||
struct perf_pmu *pmu;
|
||||
@ -421,6 +429,9 @@ static struct perf_pmu *pmu_lookup(const char *name)
|
||||
pmu->name = strdup(name);
|
||||
pmu->type = type;
|
||||
list_add_tail(&pmu->list, &pmus);
|
||||
|
||||
pmu->default_config = perf_pmu__get_default_config(pmu);
|
||||
|
||||
return pmu;
|
||||
}
|
||||
|
||||
@ -479,28 +490,24 @@ pmu_find_format(struct list_head *formats, char *name)
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns value based on the format definition (format parameter)
|
||||
* Sets value based on the format definition (format parameter)
|
||||
* and unformated value (value parameter).
|
||||
*
|
||||
* TODO maybe optimize a little ;)
|
||||
*/
|
||||
static __u64 pmu_format_value(unsigned long *format, __u64 value)
|
||||
static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
|
||||
bool zero)
|
||||
{
|
||||
unsigned long fbit, vbit;
|
||||
__u64 v = 0;
|
||||
|
||||
for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
|
||||
|
||||
if (!test_bit(fbit, format))
|
||||
continue;
|
||||
|
||||
if (!(value & (1llu << vbit++)))
|
||||
continue;
|
||||
|
||||
v |= (1llu << fbit);
|
||||
if (value & (1llu << vbit++))
|
||||
*v |= (1llu << fbit);
|
||||
else if (zero)
|
||||
*v &= ~(1llu << fbit);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -509,7 +516,8 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value)
|
||||
*/
|
||||
static int pmu_config_term(struct list_head *formats,
|
||||
struct perf_event_attr *attr,
|
||||
struct parse_events_term *term)
|
||||
struct parse_events_term *term,
|
||||
bool zero)
|
||||
{
|
||||
struct perf_pmu_format *format;
|
||||
__u64 *vp;
|
||||
@ -548,18 +556,19 @@ static int pmu_config_term(struct list_head *formats,
|
||||
* non-hardcoded terms, here's the place to translate
|
||||
* them into value.
|
||||
*/
|
||||
*vp |= pmu_format_value(format->bits, term->val.num);
|
||||
pmu_format_value(format->bits, term->val.num, vp, zero);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int perf_pmu__config_terms(struct list_head *formats,
|
||||
struct perf_event_attr *attr,
|
||||
struct list_head *head_terms)
|
||||
struct list_head *head_terms,
|
||||
bool zero)
|
||||
{
|
||||
struct parse_events_term *term;
|
||||
|
||||
list_for_each_entry(term, head_terms, list)
|
||||
if (pmu_config_term(formats, attr, term))
|
||||
if (pmu_config_term(formats, attr, term, zero))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@ -573,8 +582,10 @@ int perf_pmu__config_terms(struct list_head *formats,
|
||||
int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
|
||||
struct list_head *head_terms)
|
||||
{
|
||||
bool zero = !!pmu->default_config;
|
||||
|
||||
attr->type = pmu->type;
|
||||
return perf_pmu__config_terms(&pmu->format, attr, head_terms);
|
||||
return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
|
||||
}
|
||||
|
||||
static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
|
||||
@ -794,3 +805,39 @@ bool pmu_have_event(const char *pname, const char *name)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
|
||||
{
|
||||
struct stat st;
|
||||
char path[PATH_MAX];
|
||||
const char *sysfs;
|
||||
|
||||
sysfs = sysfs__mountpoint();
|
||||
if (!sysfs)
|
||||
return NULL;
|
||||
|
||||
snprintf(path, PATH_MAX,
|
||||
"%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
|
||||
|
||||
if (stat(path, &st) < 0)
|
||||
return NULL;
|
||||
|
||||
return fopen(path, "r");
|
||||
}
|
||||
|
||||
int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
FILE *file;
|
||||
int ret = EOF;
|
||||
|
||||
va_start(args, fmt);
|
||||
file = perf_pmu__open_file(pmu, name);
|
||||
if (file) {
|
||||
ret = vfscanf(file, fmt, args);
|
||||
fclose(file);
|
||||
}
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
@ -13,9 +13,12 @@ enum {
|
||||
|
||||
#define PERF_PMU_FORMAT_BITS 64
|
||||
|
||||
struct perf_event_attr;
|
||||
|
||||
struct perf_pmu {
|
||||
char *name;
|
||||
__u32 type;
|
||||
struct perf_event_attr *default_config;
|
||||
struct cpu_map *cpus;
|
||||
struct list_head format; /* HEAD struct perf_pmu_format -> list */
|
||||
struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */
|
||||
@ -27,7 +30,8 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
|
||||
struct list_head *head_terms);
|
||||
int perf_pmu__config_terms(struct list_head *formats,
|
||||
struct perf_event_attr *attr,
|
||||
struct list_head *head_terms);
|
||||
struct list_head *head_terms,
|
||||
bool zero);
|
||||
int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
|
||||
const char **unit, double *scale);
|
||||
struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
|
||||
@ -45,5 +49,11 @@ struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
|
||||
void print_pmu_events(const char *event_glob, bool name_only);
|
||||
bool pmu_have_event(const char *pname, const char *name);
|
||||
|
||||
int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
|
||||
...) __attribute__((format(scanf, 3, 4)));
|
||||
|
||||
int perf_pmu__test(void);
|
||||
|
||||
struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
|
||||
|
||||
#endif /* __PMU_H */
|
||||
|
@ -697,11 +697,11 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int show_line_range(struct line_range *lr, const char *module)
|
||||
int show_line_range(struct line_range *lr, const char *module, bool user)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = init_symbol_maps(false);
|
||||
ret = init_symbol_maps(user);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = __show_line_range(lr, module);
|
||||
@ -776,7 +776,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
|
||||
int i, ret = 0;
|
||||
struct debuginfo *dinfo;
|
||||
|
||||
ret = init_symbol_maps(false);
|
||||
ret = init_symbol_maps(pevs->uprobes);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -822,7 +822,8 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
|
||||
}
|
||||
|
||||
int show_line_range(struct line_range *lr __maybe_unused,
|
||||
const char *module __maybe_unused)
|
||||
const char *module __maybe_unused,
|
||||
bool user __maybe_unused)
|
||||
{
|
||||
pr_warning("Debuginfo-analysis is not supported.\n");
|
||||
return -ENOSYS;
|
||||
|
@ -128,7 +128,8 @@ extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
|
||||
bool force_add);
|
||||
extern int del_perf_probe_events(struct strlist *dellist);
|
||||
extern int show_perf_probe_events(void);
|
||||
extern int show_line_range(struct line_range *lr, const char *module);
|
||||
extern int show_line_range(struct line_range *lr, const char *module,
|
||||
bool user);
|
||||
extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
|
||||
int max_probe_points, const char *module,
|
||||
struct strfilter *filter, bool externs);
|
||||
|
@ -609,14 +609,18 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get an appropriate symbol from symtab */
|
||||
symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
|
||||
symbol = dwarf_diename(sp_die);
|
||||
if (!symbol) {
|
||||
pr_warning("Failed to find symbol at 0x%lx\n",
|
||||
(unsigned long)paddr);
|
||||
return -ENOENT;
|
||||
/* Try to get the symbol name from symtab */
|
||||
symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
|
||||
if (!symbol) {
|
||||
pr_warning("Failed to find symbol at 0x%lx\n",
|
||||
(unsigned long)paddr);
|
||||
return -ENOENT;
|
||||
}
|
||||
eaddr = sym.st_value;
|
||||
}
|
||||
tp->offset = (unsigned long)(paddr - sym.st_value);
|
||||
tp->offset = (unsigned long)(paddr - eaddr);
|
||||
tp->address = (unsigned long)paddr;
|
||||
tp->symbol = strdup(symbol);
|
||||
if (!tp->symbol)
|
||||
|
@ -1446,12 +1446,47 @@ static const char *get_default_sort_order(void)
|
||||
return default_sort_orders[sort__mode];
|
||||
}
|
||||
|
||||
static int setup_sort_order(void)
|
||||
{
|
||||
char *new_sort_order;
|
||||
|
||||
/*
|
||||
* Append '+'-prefixed sort order to the default sort
|
||||
* order string.
|
||||
*/
|
||||
if (!sort_order || is_strict_order(sort_order))
|
||||
return 0;
|
||||
|
||||
if (sort_order[1] == '\0') {
|
||||
error("Invalid --sort key: `+'");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* We allocate new sort_order string, but we never free it,
|
||||
* because it's checked over the rest of the code.
|
||||
*/
|
||||
if (asprintf(&new_sort_order, "%s,%s",
|
||||
get_default_sort_order(), sort_order + 1) < 0) {
|
||||
error("Not enough memory to set up --sort");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
sort_order = new_sort_order;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __setup_sorting(void)
|
||||
{
|
||||
char *tmp, *tok, *str;
|
||||
const char *sort_keys = sort_order;
|
||||
const char *sort_keys;
|
||||
int ret = 0;
|
||||
|
||||
ret = setup_sort_order();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sort_keys = sort_order;
|
||||
if (sort_keys == NULL) {
|
||||
if (is_strict_order(field_order)) {
|
||||
/*
|
||||
|
@ -680,6 +680,11 @@ static u64 ref_reloc(struct kmap *kmap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool want_demangle(bool is_kernel_sym)
|
||||
{
|
||||
return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
|
||||
}
|
||||
|
||||
int dso__load_sym(struct dso *dso, struct map *map,
|
||||
struct symsrc *syms_ss, struct symsrc *runtime_ss,
|
||||
symbol_filter_t filter, int kmodule)
|
||||
@ -712,6 +717,14 @@ int dso__load_sym(struct dso *dso, struct map *map,
|
||||
symbols__delete(&dso->symbols[map->type]);
|
||||
|
||||
if (!syms_ss->symtab) {
|
||||
/*
|
||||
* If the vmlinux is stripped, fail so we will fall back
|
||||
* to using kallsyms. The vmlinux runtime symbols aren't
|
||||
* of much use.
|
||||
*/
|
||||
if (dso->kernel)
|
||||
goto out_elf_end;
|
||||
|
||||
syms_ss->symtab = syms_ss->dynsym;
|
||||
syms_ss->symshdr = syms_ss->dynshdr;
|
||||
}
|
||||
@ -938,7 +951,7 @@ new_symbol:
|
||||
* DWARF DW_compile_unit has this, but we don't always have access
|
||||
* to it...
|
||||
*/
|
||||
if (symbol_conf.demangle) {
|
||||
if (want_demangle(dso->kernel || kmodule)) {
|
||||
int demangle_flags = DMGL_NO_OPTS;
|
||||
if (verbose)
|
||||
demangle_flags = DMGL_PARAMS | DMGL_ANSI;
|
||||
|
@ -34,6 +34,7 @@ struct symbol_conf symbol_conf = {
|
||||
.try_vmlinux_path = true,
|
||||
.annotate_src = true,
|
||||
.demangle = true,
|
||||
.demangle_kernel = false,
|
||||
.cumulate_callchain = true,
|
||||
.show_hist_headers = true,
|
||||
.symfs = "",
|
||||
@ -1756,7 +1757,7 @@ static int vmlinux_path__init(struct perf_session_env *env)
|
||||
char bf[PATH_MAX];
|
||||
char *kernel_version;
|
||||
|
||||
vmlinux_path = malloc(sizeof(char *) * 5);
|
||||
vmlinux_path = malloc(sizeof(char *) * 6);
|
||||
if (vmlinux_path == NULL)
|
||||
return -1;
|
||||
|
||||
@ -1787,6 +1788,12 @@ static int vmlinux_path__init(struct perf_session_env *env)
|
||||
if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
|
||||
goto out_fail;
|
||||
++vmlinux_path__nr_entries;
|
||||
snprintf(bf, sizeof(bf), "/usr/lib/debug/boot/vmlinux-%s",
|
||||
kernel_version);
|
||||
vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
|
||||
if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
|
||||
goto out_fail;
|
||||
++vmlinux_path__nr_entries;
|
||||
snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", kernel_version);
|
||||
vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
|
||||
if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
|
||||
|
@ -120,6 +120,7 @@ struct symbol_conf {
|
||||
annotate_src,
|
||||
event_group,
|
||||
demangle,
|
||||
demangle_kernel,
|
||||
filter_relative,
|
||||
show_hist_headers;
|
||||
const char *vmlinux_name,
|
||||
|
@ -39,6 +39,8 @@
|
||||
|
||||
#define _ALL_SOURCE 1
|
||||
#define _BSD_SOURCE 1
|
||||
/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
|
||||
#define _DEFAULT_SOURCE 1
|
||||
#define HAS_BOOL
|
||||
|
||||
#include <unistd.h>
|
||||
@ -64,7 +66,7 @@
|
||||
#include <regex.h>
|
||||
#include <utime.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/poll.h>
|
||||
#include <poll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <inttypes.h>
|
||||
|
Loading…
Reference in New Issue
Block a user