Merge branch 'perf' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
This commit is contained in:
commit
70a7c1271e
25 changed files with 802 additions and 583 deletions
|
@ -1,3 +1,7 @@
|
|||
ifeq ("$(origin O)", "command line")
|
||||
OUTPUT := $(O)/
|
||||
endif
|
||||
|
||||
# The default target of this Makefile is...
|
||||
all::
|
||||
|
||||
|
@ -153,9 +157,13 @@ all::
|
|||
#
|
||||
# Define NO_DWARF if you do not want debug-info analysis feature at all.
|
||||
|
||||
PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
|
||||
@$(SHELL_PATH) util/PERF-VERSION-GEN
|
||||
-include PERF-VERSION-FILE
|
||||
$(shell sh -c 'mkdir -p $(OUTPUT)scripts/python/Perf-Trace-Util/' 2> /dev/null)
|
||||
$(shell sh -c 'mkdir -p $(OUTPUT)util/scripting-engines/' 2> /dev/null)
|
||||
$(shell sh -c 'mkdir $(OUTPUT)bench' 2> /dev/null)
|
||||
|
||||
$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
|
||||
@$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
|
||||
-include $(OUTPUT)PERF-VERSION-FILE
|
||||
|
||||
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
||||
uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
|
||||
|
@ -310,7 +318,7 @@ PROGRAMS += $(EXTRA_PROGRAMS)
|
|||
#
|
||||
# Single 'perf' binary right now:
|
||||
#
|
||||
PROGRAMS += perf
|
||||
PROGRAMS += $(OUTPUT)perf
|
||||
|
||||
# List built-in command $C whose implementation cmd_$C() is not in
|
||||
# builtin-$C.o but is linked in as part of some other command.
|
||||
|
@ -320,7 +328,7 @@ PROGRAMS += perf
|
|||
ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
|
||||
|
||||
# what 'all' will build but not install in perfexecdir
|
||||
OTHER_PROGRAMS = perf$X
|
||||
OTHER_PROGRAMS = $(OUTPUT)perf$X
|
||||
|
||||
# Set paths to tools early so that they can be used for version tests.
|
||||
ifndef SHELL_PATH
|
||||
|
@ -332,7 +340,7 @@ endif
|
|||
|
||||
export PERL_PATH
|
||||
|
||||
LIB_FILE=libperf.a
|
||||
LIB_FILE=$(OUTPUT)libperf.a
|
||||
|
||||
LIB_H += ../../include/linux/perf_event.h
|
||||
LIB_H += ../../include/linux/rbtree.h
|
||||
|
@ -377,7 +385,6 @@ LIB_H += util/header.h
|
|||
LIB_H += util/help.h
|
||||
LIB_H += util/session.h
|
||||
LIB_H += util/strbuf.h
|
||||
LIB_H += util/string.h
|
||||
LIB_H += util/strlist.h
|
||||
LIB_H += util/svghelper.h
|
||||
LIB_H += util/run-command.h
|
||||
|
@ -393,77 +400,77 @@ LIB_H += util/probe-finder.h
|
|||
LIB_H += util/probe-event.h
|
||||
LIB_H += util/cpumap.h
|
||||
|
||||
LIB_OBJS += util/abspath.o
|
||||
LIB_OBJS += util/alias.o
|
||||
LIB_OBJS += util/build-id.o
|
||||
LIB_OBJS += util/config.o
|
||||
LIB_OBJS += util/ctype.o
|
||||
LIB_OBJS += util/debugfs.o
|
||||
LIB_OBJS += util/environment.o
|
||||
LIB_OBJS += util/event.o
|
||||
LIB_OBJS += util/exec_cmd.o
|
||||
LIB_OBJS += util/help.o
|
||||
LIB_OBJS += util/levenshtein.o
|
||||
LIB_OBJS += util/parse-options.o
|
||||
LIB_OBJS += util/parse-events.o
|
||||
LIB_OBJS += util/path.o
|
||||
LIB_OBJS += util/rbtree.o
|
||||
LIB_OBJS += util/bitmap.o
|
||||
LIB_OBJS += util/hweight.o
|
||||
LIB_OBJS += util/find_next_bit.o
|
||||
LIB_OBJS += util/run-command.o
|
||||
LIB_OBJS += util/quote.o
|
||||
LIB_OBJS += util/strbuf.o
|
||||
LIB_OBJS += util/string.o
|
||||
LIB_OBJS += util/strlist.o
|
||||
LIB_OBJS += util/usage.o
|
||||
LIB_OBJS += util/wrapper.o
|
||||
LIB_OBJS += util/sigchain.o
|
||||
LIB_OBJS += util/symbol.o
|
||||
LIB_OBJS += util/color.o
|
||||
LIB_OBJS += util/pager.o
|
||||
LIB_OBJS += util/header.o
|
||||
LIB_OBJS += util/callchain.o
|
||||
LIB_OBJS += util/values.o
|
||||
LIB_OBJS += util/debug.o
|
||||
LIB_OBJS += util/map.o
|
||||
LIB_OBJS += util/session.o
|
||||
LIB_OBJS += util/thread.o
|
||||
LIB_OBJS += util/trace-event-parse.o
|
||||
LIB_OBJS += util/trace-event-read.o
|
||||
LIB_OBJS += util/trace-event-info.o
|
||||
LIB_OBJS += util/trace-event-scripting.o
|
||||
LIB_OBJS += util/svghelper.o
|
||||
LIB_OBJS += util/sort.o
|
||||
LIB_OBJS += util/hist.o
|
||||
LIB_OBJS += util/probe-event.o
|
||||
LIB_OBJS += util/util.o
|
||||
LIB_OBJS += util/cpumap.o
|
||||
LIB_OBJS += $(OUTPUT)util/abspath.o
|
||||
LIB_OBJS += $(OUTPUT)util/alias.o
|
||||
LIB_OBJS += $(OUTPUT)util/build-id.o
|
||||
LIB_OBJS += $(OUTPUT)util/config.o
|
||||
LIB_OBJS += $(OUTPUT)util/ctype.o
|
||||
LIB_OBJS += $(OUTPUT)util/debugfs.o
|
||||
LIB_OBJS += $(OUTPUT)util/environment.o
|
||||
LIB_OBJS += $(OUTPUT)util/event.o
|
||||
LIB_OBJS += $(OUTPUT)util/exec_cmd.o
|
||||
LIB_OBJS += $(OUTPUT)util/help.o
|
||||
LIB_OBJS += $(OUTPUT)util/levenshtein.o
|
||||
LIB_OBJS += $(OUTPUT)util/parse-options.o
|
||||
LIB_OBJS += $(OUTPUT)util/parse-events.o
|
||||
LIB_OBJS += $(OUTPUT)util/path.o
|
||||
LIB_OBJS += $(OUTPUT)util/rbtree.o
|
||||
LIB_OBJS += $(OUTPUT)util/bitmap.o
|
||||
LIB_OBJS += $(OUTPUT)util/hweight.o
|
||||
LIB_OBJS += $(OUTPUT)util/find_next_bit.o
|
||||
LIB_OBJS += $(OUTPUT)util/run-command.o
|
||||
LIB_OBJS += $(OUTPUT)util/quote.o
|
||||
LIB_OBJS += $(OUTPUT)util/strbuf.o
|
||||
LIB_OBJS += $(OUTPUT)util/string.o
|
||||
LIB_OBJS += $(OUTPUT)util/strlist.o
|
||||
LIB_OBJS += $(OUTPUT)util/usage.o
|
||||
LIB_OBJS += $(OUTPUT)util/wrapper.o
|
||||
LIB_OBJS += $(OUTPUT)util/sigchain.o
|
||||
LIB_OBJS += $(OUTPUT)util/symbol.o
|
||||
LIB_OBJS += $(OUTPUT)util/color.o
|
||||
LIB_OBJS += $(OUTPUT)util/pager.o
|
||||
LIB_OBJS += $(OUTPUT)util/header.o
|
||||
LIB_OBJS += $(OUTPUT)util/callchain.o
|
||||
LIB_OBJS += $(OUTPUT)util/values.o
|
||||
LIB_OBJS += $(OUTPUT)util/debug.o
|
||||
LIB_OBJS += $(OUTPUT)util/map.o
|
||||
LIB_OBJS += $(OUTPUT)util/session.o
|
||||
LIB_OBJS += $(OUTPUT)util/thread.o
|
||||
LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
|
||||
LIB_OBJS += $(OUTPUT)util/trace-event-read.o
|
||||
LIB_OBJS += $(OUTPUT)util/trace-event-info.o
|
||||
LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
|
||||
LIB_OBJS += $(OUTPUT)util/svghelper.o
|
||||
LIB_OBJS += $(OUTPUT)util/sort.o
|
||||
LIB_OBJS += $(OUTPUT)util/hist.o
|
||||
LIB_OBJS += $(OUTPUT)util/probe-event.o
|
||||
LIB_OBJS += $(OUTPUT)util/util.o
|
||||
LIB_OBJS += $(OUTPUT)util/cpumap.o
|
||||
|
||||
BUILTIN_OBJS += builtin-annotate.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
|
||||
|
||||
BUILTIN_OBJS += builtin-bench.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
|
||||
|
||||
# Benchmark modules
|
||||
BUILTIN_OBJS += bench/sched-messaging.o
|
||||
BUILTIN_OBJS += bench/sched-pipe.o
|
||||
BUILTIN_OBJS += bench/mem-memcpy.o
|
||||
BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
|
||||
BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
|
||||
BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
|
||||
|
||||
BUILTIN_OBJS += builtin-diff.o
|
||||
BUILTIN_OBJS += builtin-help.o
|
||||
BUILTIN_OBJS += builtin-sched.o
|
||||
BUILTIN_OBJS += builtin-buildid-list.o
|
||||
BUILTIN_OBJS += builtin-buildid-cache.o
|
||||
BUILTIN_OBJS += builtin-list.o
|
||||
BUILTIN_OBJS += builtin-record.o
|
||||
BUILTIN_OBJS += builtin-report.o
|
||||
BUILTIN_OBJS += builtin-stat.o
|
||||
BUILTIN_OBJS += builtin-timechart.o
|
||||
BUILTIN_OBJS += builtin-top.o
|
||||
BUILTIN_OBJS += builtin-trace.o
|
||||
BUILTIN_OBJS += builtin-probe.o
|
||||
BUILTIN_OBJS += builtin-kmem.o
|
||||
BUILTIN_OBJS += builtin-lock.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-help.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-list.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-record.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-report.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-top.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
|
||||
|
||||
PERFLIBS = $(LIB_FILE)
|
||||
|
||||
|
@ -494,6 +501,10 @@ ifeq ($(uname_S),Darwin)
|
|||
PTHREAD_LIBS =
|
||||
endif
|
||||
|
||||
ifneq ($(OUTPUT),)
|
||||
BASIC_CFLAGS += -I$(OUTPUT)
|
||||
endif
|
||||
|
||||
ifeq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
|
||||
ifneq ($(shell sh -c "(echo '\#include <gnu/libc-version.h>'; echo 'int main(void) { const char * version = gnu_get_libc_version(); return (long)version; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
|
||||
msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
|
||||
|
@ -512,7 +523,7 @@ else
|
|||
ifndef NO_DWARF
|
||||
BASIC_CFLAGS += -I/usr/include/elfutils -DDWARF_SUPPORT
|
||||
EXTLIBS += -lelf -ldw
|
||||
LIB_OBJS += util/probe-finder.o
|
||||
LIB_OBJS += $(OUTPUT)util/probe-finder.o
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -521,7 +532,7 @@ ifneq ($(shell sh -c "(echo '\#include <newt.h>'; echo 'int main(void) { newtIni
|
|||
BASIC_CFLAGS += -DNO_NEWT_SUPPORT
|
||||
else
|
||||
EXTLIBS += -lnewt
|
||||
LIB_OBJS += util/newt.o
|
||||
LIB_OBJS += $(OUTPUT)util/newt.o
|
||||
endif
|
||||
|
||||
ifndef NO_LIBPERL
|
||||
|
@ -533,8 +544,8 @@ ifneq ($(shell sh -c "(echo '\#include <EXTERN.h>'; echo '\#include <perl.h>'; e
|
|||
BASIC_CFLAGS += -DNO_LIBPERL
|
||||
else
|
||||
ALL_LDFLAGS += $(PERL_EMBED_LDOPTS)
|
||||
LIB_OBJS += util/scripting-engines/trace-event-perl.o
|
||||
LIB_OBJS += scripts/perl/Perf-Trace-Util/Context.o
|
||||
LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
|
||||
LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
|
||||
endif
|
||||
|
||||
ifndef NO_LIBPYTHON
|
||||
|
@ -542,12 +553,12 @@ PYTHON_EMBED_LDOPTS = `python-config --ldflags 2>/dev/null`
|
|||
PYTHON_EMBED_CCOPTS = `python-config --cflags 2>/dev/null`
|
||||
endif
|
||||
|
||||
ifneq ($(shell sh -c "(echo '\#include <Python.h>'; echo 'int main(void) { Py_Initialize(); return 0; }') | $(CC) -x c - $(PYTHON_EMBED_CCOPTS) -o /dev/null $(PYTHON_EMBED_LDOPTS) > /dev/null 2>&1 && echo y"), y)
|
||||
ifneq ($(shell sh -c "(echo '\#include <Python.h>'; echo 'int main(void) { Py_Initialize(); return 0; }') | $(CC) -x c - $(PYTHON_EMBED_CCOPTS) -o $(BITBUCKET) $(PYTHON_EMBED_LDOPTS) > /dev/null 2>&1 && echo y"), y)
|
||||
BASIC_CFLAGS += -DNO_LIBPYTHON
|
||||
else
|
||||
ALL_LDFLAGS += $(PYTHON_EMBED_LDOPTS)
|
||||
LIB_OBJS += util/scripting-engines/trace-event-python.o
|
||||
LIB_OBJS += scripts/python/Perf-Trace-Util/Context.o
|
||||
LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
|
||||
LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
|
||||
endif
|
||||
|
||||
ifdef NO_DEMANGLE
|
||||
|
@ -618,53 +629,53 @@ ifdef NO_C99_FORMAT
|
|||
endif
|
||||
ifdef SNPRINTF_RETURNS_BOGUS
|
||||
COMPAT_CFLAGS += -DSNPRINTF_RETURNS_BOGUS
|
||||
COMPAT_OBJS += compat/snprintf.o
|
||||
COMPAT_OBJS += $(OUTPUT)compat/snprintf.o
|
||||
endif
|
||||
ifdef FREAD_READS_DIRECTORIES
|
||||
COMPAT_CFLAGS += -DFREAD_READS_DIRECTORIES
|
||||
COMPAT_OBJS += compat/fopen.o
|
||||
COMPAT_OBJS += $(OUTPUT)compat/fopen.o
|
||||
endif
|
||||
ifdef NO_SYMLINK_HEAD
|
||||
BASIC_CFLAGS += -DNO_SYMLINK_HEAD
|
||||
endif
|
||||
ifdef NO_STRCASESTR
|
||||
COMPAT_CFLAGS += -DNO_STRCASESTR
|
||||
COMPAT_OBJS += compat/strcasestr.o
|
||||
COMPAT_OBJS += $(OUTPUT)compat/strcasestr.o
|
||||
endif
|
||||
ifdef NO_STRTOUMAX
|
||||
COMPAT_CFLAGS += -DNO_STRTOUMAX
|
||||
COMPAT_OBJS += compat/strtoumax.o
|
||||
COMPAT_OBJS += $(OUTPUT)compat/strtoumax.o
|
||||
endif
|
||||
ifdef NO_STRTOULL
|
||||
COMPAT_CFLAGS += -DNO_STRTOULL
|
||||
endif
|
||||
ifdef NO_SETENV
|
||||
COMPAT_CFLAGS += -DNO_SETENV
|
||||
COMPAT_OBJS += compat/setenv.o
|
||||
COMPAT_OBJS += $(OUTPUT)compat/setenv.o
|
||||
endif
|
||||
ifdef NO_MKDTEMP
|
||||
COMPAT_CFLAGS += -DNO_MKDTEMP
|
||||
COMPAT_OBJS += compat/mkdtemp.o
|
||||
COMPAT_OBJS += $(OUTPUT)compat/mkdtemp.o
|
||||
endif
|
||||
ifdef NO_UNSETENV
|
||||
COMPAT_CFLAGS += -DNO_UNSETENV
|
||||
COMPAT_OBJS += compat/unsetenv.o
|
||||
COMPAT_OBJS += $(OUTPUT)compat/unsetenv.o
|
||||
endif
|
||||
ifdef NO_SYS_SELECT_H
|
||||
BASIC_CFLAGS += -DNO_SYS_SELECT_H
|
||||
endif
|
||||
ifdef NO_MMAP
|
||||
COMPAT_CFLAGS += -DNO_MMAP
|
||||
COMPAT_OBJS += compat/mmap.o
|
||||
COMPAT_OBJS += $(OUTPUT)compat/mmap.o
|
||||
else
|
||||
ifdef USE_WIN32_MMAP
|
||||
COMPAT_CFLAGS += -DUSE_WIN32_MMAP
|
||||
COMPAT_OBJS += compat/win32mmap.o
|
||||
COMPAT_OBJS += $(OUTPUT)compat/win32mmap.o
|
||||
endif
|
||||
endif
|
||||
ifdef NO_PREAD
|
||||
COMPAT_CFLAGS += -DNO_PREAD
|
||||
COMPAT_OBJS += compat/pread.o
|
||||
COMPAT_OBJS += $(OUTPUT)compat/pread.o
|
||||
endif
|
||||
ifdef NO_FAST_WORKING_DIRECTORY
|
||||
BASIC_CFLAGS += -DNO_FAST_WORKING_DIRECTORY
|
||||
|
@ -686,10 +697,10 @@ else
|
|||
endif
|
||||
endif
|
||||
ifdef NO_INET_NTOP
|
||||
LIB_OBJS += compat/inet_ntop.o
|
||||
LIB_OBJS += $(OUTPUT)compat/inet_ntop.o
|
||||
endif
|
||||
ifdef NO_INET_PTON
|
||||
LIB_OBJS += compat/inet_pton.o
|
||||
LIB_OBJS += $(OUTPUT)compat/inet_pton.o
|
||||
endif
|
||||
|
||||
ifdef NO_ICONV
|
||||
|
@ -706,15 +717,15 @@ endif
|
|||
|
||||
ifdef PPC_SHA1
|
||||
SHA1_HEADER = "ppc/sha1.h"
|
||||
LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o
|
||||
LIB_OBJS += $(OUTPUT)ppc/sha1.o ppc/sha1ppc.o
|
||||
else
|
||||
ifdef ARM_SHA1
|
||||
SHA1_HEADER = "arm/sha1.h"
|
||||
LIB_OBJS += arm/sha1.o arm/sha1_arm.o
|
||||
LIB_OBJS += $(OUTPUT)arm/sha1.o $(OUTPUT)arm/sha1_arm.o
|
||||
else
|
||||
ifdef MOZILLA_SHA1
|
||||
SHA1_HEADER = "mozilla-sha1/sha1.h"
|
||||
LIB_OBJS += mozilla-sha1/sha1.o
|
||||
LIB_OBJS += $(OUTPUT)mozilla-sha1/sha1.o
|
||||
else
|
||||
SHA1_HEADER = <openssl/sha.h>
|
||||
EXTLIBS += $(LIB_4_CRYPTO)
|
||||
|
@ -726,15 +737,15 @@ ifdef NO_PERL_MAKEMAKER
|
|||
endif
|
||||
ifdef NO_HSTRERROR
|
||||
COMPAT_CFLAGS += -DNO_HSTRERROR
|
||||
COMPAT_OBJS += compat/hstrerror.o
|
||||
COMPAT_OBJS += $(OUTPUT)compat/hstrerror.o
|
||||
endif
|
||||
ifdef NO_MEMMEM
|
||||
COMPAT_CFLAGS += -DNO_MEMMEM
|
||||
COMPAT_OBJS += compat/memmem.o
|
||||
COMPAT_OBJS += $(OUTPUT)compat/memmem.o
|
||||
endif
|
||||
ifdef INTERNAL_QSORT
|
||||
COMPAT_CFLAGS += -DINTERNAL_QSORT
|
||||
COMPAT_OBJS += compat/qsort.o
|
||||
COMPAT_OBJS += $(OUTPUT)compat/qsort.o
|
||||
endif
|
||||
ifdef RUNTIME_PREFIX
|
||||
COMPAT_CFLAGS += -DRUNTIME_PREFIX
|
||||
|
@ -814,7 +825,7 @@ export TAR INSTALL DESTDIR SHELL_PATH
|
|||
|
||||
SHELL = $(SHELL_PATH)
|
||||
|
||||
all:: .perf.dev.null shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) PERF-BUILD-OPTIONS
|
||||
all:: .perf.dev.null shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) $(OUTPUT)PERF-BUILD-OPTIONS
|
||||
ifneq (,$X)
|
||||
$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) perf$X)), test '$p' -ef '$p$X' || $(RM) '$p';)
|
||||
endif
|
||||
|
@ -826,39 +837,39 @@ please_set_SHELL_PATH_to_a_more_modern_shell:
|
|||
|
||||
shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
|
||||
|
||||
strip: $(PROGRAMS) perf$X
|
||||
$(STRIP) $(STRIP_OPTS) $(PROGRAMS) perf$X
|
||||
strip: $(PROGRAMS) $(OUTPUT)perf$X
|
||||
$(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf$X
|
||||
|
||||
perf.o: perf.c common-cmds.h PERF-CFLAGS
|
||||
$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -DPERF_VERSION='"$(PERF_VERSION)"' \
|
||||
'-DPERF_HTML_PATH="$(htmldir_SQ)"' \
|
||||
$(ALL_CFLAGS) -c $(filter %.c,$^)
|
||||
$(ALL_CFLAGS) -c $(filter %.c,$^) -o $@
|
||||
|
||||
perf$X: perf.o $(BUILTIN_OBJS) $(PERFLIBS)
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ perf.o \
|
||||
$(OUTPUT)perf$X: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(OUTPUT)perf.o \
|
||||
$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
|
||||
|
||||
builtin-help.o: builtin-help.c common-cmds.h PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \
|
||||
$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
|
||||
'-DPERF_HTML_PATH="$(htmldir_SQ)"' \
|
||||
'-DPERF_MAN_PATH="$(mandir_SQ)"' \
|
||||
'-DPERF_INFO_PATH="$(infodir_SQ)"' $<
|
||||
|
||||
builtin-timechart.o: builtin-timechart.c common-cmds.h PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \
|
||||
$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
|
||||
'-DPERF_HTML_PATH="$(htmldir_SQ)"' \
|
||||
'-DPERF_MAN_PATH="$(mandir_SQ)"' \
|
||||
'-DPERF_INFO_PATH="$(infodir_SQ)"' $<
|
||||
|
||||
$(BUILT_INS): perf$X
|
||||
$(BUILT_INS): $(OUTPUT)perf$X
|
||||
$(QUIET_BUILT_IN)$(RM) $@ && \
|
||||
ln perf$X $@ 2>/dev/null || \
|
||||
ln -s perf$X $@ 2>/dev/null || \
|
||||
cp perf$X $@
|
||||
|
||||
common-cmds.h: util/generate-cmdlist.sh command-list.txt
|
||||
$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
|
||||
|
||||
common-cmds.h: $(wildcard Documentation/perf-*.txt)
|
||||
$(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt)
|
||||
$(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@
|
||||
|
||||
$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
|
||||
|
@ -870,7 +881,7 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
|
|||
-e 's/@@NO_CURL@@/$(NO_CURL)/g' \
|
||||
$@.sh >$@+ && \
|
||||
chmod +x $@+ && \
|
||||
mv $@+ $@
|
||||
mv $@+ $(OUTPUT)$@
|
||||
|
||||
configure: configure.ac
|
||||
$(QUIET_GEN)$(RM) $@ $<+ && \
|
||||
|
@ -880,60 +891,60 @@ configure: configure.ac
|
|||
$(RM) $<+
|
||||
|
||||
# These can record PERF_VERSION
|
||||
perf.o perf.spec \
|
||||
$(OUTPUT)perf.o perf.spec \
|
||||
$(patsubst %.sh,%,$(SCRIPT_SH)) \
|
||||
$(patsubst %.perl,%,$(SCRIPT_PERL)) \
|
||||
: PERF-VERSION-FILE
|
||||
: $(OUTPUT)PERF-VERSION-FILE
|
||||
|
||||
%.o: %.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
|
||||
%.s: %.c PERF-CFLAGS
|
||||
$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
|
||||
$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $<
|
||||
%.o: %.S
|
||||
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
|
||||
$(OUTPUT)%.o: %.S
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
|
||||
|
||||
util/exec_cmd.o: util/exec_cmd.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \
|
||||
$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
|
||||
'-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
|
||||
'-DBINDIR="$(bindir_relative_SQ)"' \
|
||||
'-DPREFIX="$(prefix_SQ)"' \
|
||||
$<
|
||||
|
||||
builtin-init-db.o: builtin-init-db.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_PERF_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
|
||||
$(OUTPUT)builtin-init-db.o: builtin-init-db.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DDEFAULT_PERF_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
|
||||
|
||||
util/config.o: util/config.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
|
||||
util/rbtree.o: ../../lib/rbtree.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o util/rbtree.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
|
||||
# some perf warning policies can't fit to lib/bitmap.c, eg: it warns about variable shadowing
|
||||
# from <string.h> that comes from kernel headers wrapping.
|
||||
KBITMAP_FLAGS=`echo $(ALL_CFLAGS) | sed s/-Wshadow// | sed s/-Wswitch-default// | sed s/-Wextra//`
|
||||
|
||||
util/bitmap.o: ../../lib/bitmap.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o util/bitmap.o -c $(KBITMAP_FLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
$(OUTPUT)util/bitmap.o: ../../lib/bitmap.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(KBITMAP_FLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
|
||||
util/hweight.o: ../../lib/hweight.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o util/hweight.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
$(OUTPUT)util/hweight.o: ../../lib/hweight.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
|
||||
util/find_next_bit.o: ../../lib/find_next_bit.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o util/find_next_bit.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
$(OUTPUT)util/find_next_bit.o: ../../lib/find_next_bit.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
|
||||
util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o util/scripting-engines/trace-event-perl.o -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
|
||||
$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
|
||||
|
||||
scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o scripts/perl/Perf-Trace-Util/Context.o -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
|
||||
$(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
|
||||
|
||||
util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o util/scripting-engines/trace-event-python.o -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
|
||||
$(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
|
||||
|
||||
scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o scripts/python/Perf-Trace-Util/Context.o -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
|
||||
$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
|
||||
|
||||
perf-%$X: %.o $(PERFLIBS)
|
||||
$(OUTPUT)perf-%$X: %.o $(PERFLIBS)
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
|
||||
|
||||
$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
|
||||
|
@ -974,17 +985,17 @@ cscope:
|
|||
TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):\
|
||||
$(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
|
||||
|
||||
PERF-CFLAGS: .FORCE-PERF-CFLAGS
|
||||
$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
|
||||
@FLAGS='$(TRACK_CFLAGS)'; \
|
||||
if test x"$$FLAGS" != x"`cat PERF-CFLAGS 2>/dev/null`" ; then \
|
||||
if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \
|
||||
echo 1>&2 " * new build flags or prefix"; \
|
||||
echo "$$FLAGS" >PERF-CFLAGS; \
|
||||
echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
|
||||
fi
|
||||
|
||||
# We need to apply sq twice, once to protect from the shell
|
||||
# that runs PERF-BUILD-OPTIONS, and then again to protect it
|
||||
# that runs $(OUTPUT)PERF-BUILD-OPTIONS, and then again to protect it
|
||||
# and the first level quoting from the shell that runs "echo".
|
||||
PERF-BUILD-OPTIONS: .FORCE-PERF-BUILD-OPTIONS
|
||||
$(OUTPUT)PERF-BUILD-OPTIONS: .FORCE-PERF-BUILD-OPTIONS
|
||||
@echo SHELL_PATH=\''$(subst ','\'',$(SHELL_PATH_SQ))'\' >$@
|
||||
@echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@
|
||||
@echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@
|
||||
|
@ -1005,7 +1016,7 @@ all:: $(TEST_PROGRAMS)
|
|||
|
||||
export NO_SVN_TESTS
|
||||
|
||||
check: common-cmds.h
|
||||
check: $(OUTPUT)common-cmds.h
|
||||
if sparse; \
|
||||
then \
|
||||
for i in *.c */*.c; \
|
||||
|
@ -1039,10 +1050,10 @@ export perfexec_instdir
|
|||
|
||||
install: all
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
|
||||
$(INSTALL) perf$X '$(DESTDIR_SQ)$(bindir_SQ)'
|
||||
$(INSTALL) $(OUTPUT)perf$X '$(DESTDIR_SQ)$(bindir_SQ)'
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
|
||||
$(INSTALL) perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
|
||||
$(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
|
||||
$(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
|
||||
$(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'
|
||||
$(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
|
||||
|
@ -1056,7 +1067,7 @@ ifdef BUILT_INS
|
|||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
|
||||
$(INSTALL) $(BUILT_INS) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
|
||||
ifneq (,$X)
|
||||
$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) perf$X)), $(RM) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$p';)
|
||||
$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) $(OUTPUT)perf$X)), $(RM) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$p';)
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -1140,14 +1151,14 @@ clean:
|
|||
$(RM) *.o */*.o */*/*.o */*/*/*.o $(LIB_FILE)
|
||||
$(RM) $(ALL_PROGRAMS) $(BUILT_INS) perf$X
|
||||
$(RM) $(TEST_PROGRAMS)
|
||||
$(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope*
|
||||
$(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
|
||||
$(RM) -r autom4te.cache
|
||||
$(RM) config.log config.mak.autogen config.mak.append config.status config.cache
|
||||
$(RM) -r $(PERF_TARNAME) .doc-tmp-dir
|
||||
$(RM) $(PERF_TARNAME).tar.gz perf-core_$(PERF_VERSION)-*.tar.gz
|
||||
$(RM) $(htmldocs).tar.gz $(manpages).tar.gz
|
||||
$(MAKE) -C Documentation/ clean
|
||||
$(RM) PERF-VERSION-FILE PERF-CFLAGS PERF-BUILD-OPTIONS
|
||||
$(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-BUILD-OPTIONS
|
||||
|
||||
.PHONY: all install clean strip
|
||||
.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "../perf.h"
|
||||
#include "../util/util.h"
|
||||
#include "../util/parse-options.h"
|
||||
#include "../util/string.h"
|
||||
#include "../util/header.h"
|
||||
#include "bench.h"
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "util/cache.h"
|
||||
#include <linux/rbtree.h>
|
||||
#include "util/symbol.h"
|
||||
#include "util/string.h"
|
||||
|
||||
#include "perf.h"
|
||||
#include "util/debug.h"
|
||||
|
|
|
@ -363,19 +363,21 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
|
|||
struct alloc_stat *data = rb_entry(next, struct alloc_stat,
|
||||
node);
|
||||
struct symbol *sym = NULL;
|
||||
struct map *map;
|
||||
char buf[BUFSIZ];
|
||||
u64 addr;
|
||||
|
||||
if (is_caller) {
|
||||
addr = data->call_site;
|
||||
if (!raw_ip)
|
||||
sym = map_groups__find_function(&session->kmaps, addr, NULL);
|
||||
sym = map_groups__find_function(&session->kmaps,
|
||||
addr, &map, NULL);
|
||||
} else
|
||||
addr = data->ptr;
|
||||
|
||||
if (sym != NULL)
|
||||
snprintf(buf, sizeof(buf), "%s+%Lx", sym->name,
|
||||
addr - sym->start);
|
||||
addr - map->unmap_ip(map, sym->start));
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%#Lx", addr);
|
||||
printf(" %-34s |", buf);
|
||||
|
@ -488,6 +490,9 @@ static int __cmd_kmem(void)
|
|||
if (session == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (perf_session__create_kernel_maps(session) < 0)
|
||||
goto out_delete;
|
||||
|
||||
if (!perf_session__has_traces(session, "kmem record"))
|
||||
goto out_delete;
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include "util/util.h"
|
||||
#include "util/parse-options.h"
|
||||
#include "util/parse-events.h"
|
||||
#include "util/string.h"
|
||||
|
||||
#include "util/header.h"
|
||||
#include "util/event.h"
|
||||
|
@ -575,6 +574,9 @@ static int __cmd_record(int argc, const char **argv)
|
|||
|
||||
err = event__synthesize_kernel_mmap(process_synthesized_event,
|
||||
session, "_text");
|
||||
if (err < 0)
|
||||
err = event__synthesize_kernel_mmap(process_synthesized_event,
|
||||
session, "_stext");
|
||||
if (err < 0) {
|
||||
pr_err("Couldn't record kernel reference relocation symbol.\n");
|
||||
return err;
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "util/cache.h"
|
||||
#include <linux/rbtree.h>
|
||||
#include "util/symbol.h"
|
||||
#include "util/string.h"
|
||||
#include "util/callchain.h"
|
||||
#include "util/strlist.h"
|
||||
#include "util/values.h"
|
||||
|
@ -89,9 +88,12 @@ static int perf_session__add_hist_entry(struct perf_session *self,
|
|||
struct event_stat_id *stats;
|
||||
struct perf_event_attr *attr;
|
||||
|
||||
if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain)
|
||||
if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) {
|
||||
syms = perf_session__resolve_callchain(self, al->thread,
|
||||
data->callchain, &parent);
|
||||
if (syms == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
attr = perf_header__find_attr(data->id, &self->header);
|
||||
if (attr)
|
||||
|
@ -110,8 +112,8 @@ static int perf_session__add_hist_entry(struct perf_session *self,
|
|||
|
||||
if (symbol_conf.use_callchain) {
|
||||
if (!hit)
|
||||
callchain_init(&he->callchain);
|
||||
err = append_chain(&he->callchain, data->callchain, syms);
|
||||
callchain_init(he->callchain);
|
||||
err = append_chain(he->callchain, data->callchain, syms);
|
||||
free(syms);
|
||||
|
||||
if (err)
|
||||
|
@ -303,14 +305,16 @@ static int __cmd_report(void)
|
|||
next = rb_first(&session->stats_by_id);
|
||||
while (next) {
|
||||
struct event_stat_id *stats;
|
||||
u64 nr_hists;
|
||||
|
||||
stats = rb_entry(next, struct event_stat_id, rb_node);
|
||||
perf_session__collapse_resort(&stats->hists);
|
||||
perf_session__output_resort(&stats->hists, stats->stats.total);
|
||||
|
||||
nr_hists = perf_session__output_resort(&stats->hists,
|
||||
stats->stats.total);
|
||||
if (use_browser)
|
||||
perf_session__browse_hists(&stats->hists,
|
||||
stats->stats.total, help);
|
||||
perf_session__browse_hists(&stats->hists, nr_hists,
|
||||
stats->stats.total, help,
|
||||
input_name);
|
||||
else {
|
||||
if (rb_first(&session->stats_by_id) ==
|
||||
rb_last(&session->stats_by_id))
|
||||
|
@ -469,7 +473,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
|
|||
setup_sorting(report_usage, options);
|
||||
|
||||
if (parent_pattern != default_parent_pattern) {
|
||||
sort_dimension__add("parent");
|
||||
if (sort_dimension__add("parent") < 0)
|
||||
return -1;
|
||||
sort_parent.elide = 1;
|
||||
} else
|
||||
symbol_conf.exclude_other = false;
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "util/cache.h"
|
||||
#include <linux/rbtree.h>
|
||||
#include "util/symbol.h"
|
||||
#include "util/string.h"
|
||||
#include "util/callchain.h"
|
||||
#include "util/strlist.h"
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "util/quote.h"
|
||||
#include "util/run-command.h"
|
||||
#include "util/parse-events.h"
|
||||
#include "util/string.h"
|
||||
#include "util/debugfs.h"
|
||||
|
||||
bool use_browser;
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#!/bin/sh
|
||||
|
||||
GVF=PERF-VERSION-FILE
|
||||
if [ $# -eq 1 ] ; then
|
||||
OUTPUT=$1
|
||||
fi
|
||||
|
||||
GVF=${OUTPUT}PERF-VERSION-FILE
|
||||
DEF_VER=v0.0.2.PERF
|
||||
|
||||
LF='
|
||||
|
|
|
@ -166,6 +166,31 @@ int perf_color_default_config(const char *var, const char *value, void *cb)
|
|||
return perf_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
static int __color_vsnprintf(char *bf, size_t size, const char *color,
|
||||
const char *fmt, va_list args, const char *trail)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
/*
|
||||
* Auto-detect:
|
||||
*/
|
||||
if (perf_use_color_default < 0) {
|
||||
if (isatty(1) || pager_in_use())
|
||||
perf_use_color_default = 1;
|
||||
else
|
||||
perf_use_color_default = 0;
|
||||
}
|
||||
|
||||
if (perf_use_color_default && *color)
|
||||
r += snprintf(bf, size, "%s", color);
|
||||
r += vsnprintf(bf + r, size - r, fmt, args);
|
||||
if (perf_use_color_default && *color)
|
||||
r += snprintf(bf + r, size - r, "%s", PERF_COLOR_RESET);
|
||||
if (trail)
|
||||
r += snprintf(bf + r, size - r, "%s", trail);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
|
||||
va_list args, const char *trail)
|
||||
{
|
||||
|
@ -191,11 +216,28 @@ static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
|
|||
return r;
|
||||
}
|
||||
|
||||
int color_vsnprintf(char *bf, size_t size, const char *color,
|
||||
const char *fmt, va_list args)
|
||||
{
|
||||
return __color_vsnprintf(bf, size, color, fmt, args, NULL);
|
||||
}
|
||||
|
||||
int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args)
|
||||
{
|
||||
return __color_vfprintf(fp, color, fmt, args, NULL);
|
||||
}
|
||||
|
||||
int color_snprintf(char *bf, size_t size, const char *color,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int r;
|
||||
|
||||
va_start(args, fmt);
|
||||
r = color_vsnprintf(bf, size, color, fmt, args);
|
||||
va_end(args);
|
||||
return r;
|
||||
}
|
||||
|
||||
int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
|
||||
{
|
||||
|
@ -203,10 +245,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
|
|||
int r;
|
||||
|
||||
va_start(args, fmt);
|
||||
if (use_browser)
|
||||
r = vfprintf(fp, fmt, args);
|
||||
else
|
||||
r = color_vfprintf(fp, color, fmt, args);
|
||||
r = color_vfprintf(fp, color, fmt, args);
|
||||
va_end(args);
|
||||
return r;
|
||||
}
|
||||
|
@ -277,3 +316,9 @@ int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
|
|||
|
||||
return r;
|
||||
}
|
||||
|
||||
int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent)
|
||||
{
|
||||
const char *color = get_percent_color(percent);
|
||||
return color_snprintf(bf, size, color, fmt, percent);
|
||||
}
|
||||
|
|
|
@ -32,10 +32,14 @@ int perf_color_default_config(const char *var, const char *value, void *cb);
|
|||
int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty);
|
||||
void color_parse(const char *value, const char *var, char *dst);
|
||||
void color_parse_mem(const char *value, int len, const char *var, char *dst);
|
||||
int color_vsnprintf(char *bf, size_t size, const char *color,
|
||||
const char *fmt, va_list args);
|
||||
int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args);
|
||||
int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
|
||||
int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...);
|
||||
int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
|
||||
int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
|
||||
int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent);
|
||||
int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
|
||||
const char *get_percent_color(double percent);
|
||||
|
||||
|
|
|
@ -10,13 +10,29 @@ extern int dump_trace;
|
|||
int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
|
||||
void trace_event(event_t *event);
|
||||
|
||||
struct ui_progress;
|
||||
|
||||
#ifdef NO_NEWT_SUPPORT
|
||||
static inline int browser__show_help(const char *format __used, va_list ap __used)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct ui_progress *ui_progress__new(const char *title __used,
|
||||
u64 total __used)
|
||||
{
|
||||
return (struct ui_progress *)1;
|
||||
}
|
||||
|
||||
static inline void ui_progress__update(struct ui_progress *self __used,
|
||||
u64 curr __used) {}
|
||||
|
||||
static inline void ui_progress__delete(struct ui_progress *self __used) {}
|
||||
#else
|
||||
int browser__show_help(const char *format, va_list ap);
|
||||
struct ui_progress *ui_progress__new(const char *title, u64 total);
|
||||
void ui_progress__update(struct ui_progress *self, u64 curr);
|
||||
void ui_progress__delete(struct ui_progress *self);
|
||||
#endif
|
||||
|
||||
#endif /* __PERF_DEBUG_H */
|
||||
|
|
|
@ -130,6 +130,7 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
|
|||
continue;
|
||||
pbf += n + 3;
|
||||
if (*pbf == 'x') { /* vm_exec */
|
||||
u64 vm_pgoff;
|
||||
char *execname = strchr(bf, '/');
|
||||
|
||||
/* Catch VDSO */
|
||||
|
@ -139,6 +140,14 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
|
|||
if (execname == NULL)
|
||||
continue;
|
||||
|
||||
pbf += 3;
|
||||
n = hex2u64(pbf, &vm_pgoff);
|
||||
/* pgoff is in bytes, not pages */
|
||||
if (n >= 0)
|
||||
ev.mmap.pgoff = vm_pgoff << getpagesize();
|
||||
else
|
||||
ev.mmap.pgoff = 0;
|
||||
|
||||
size = strlen(execname);
|
||||
execname[size - 1] = '\0'; /* Remove \n */
|
||||
memcpy(ev.mmap.filename, execname, size);
|
||||
|
|
|
@ -50,7 +50,8 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
|
|||
p = &(*p)->rb_right;
|
||||
}
|
||||
|
||||
he = malloc(sizeof(*he));
|
||||
he = malloc(sizeof(*he) + (symbol_conf.use_callchain ?
|
||||
sizeof(struct callchain_node) : 0));
|
||||
if (!he)
|
||||
return NULL;
|
||||
*he = entry;
|
||||
|
@ -168,7 +169,7 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root,
|
|||
struct hist_entry *iter;
|
||||
|
||||
if (symbol_conf.use_callchain)
|
||||
callchain_param.sort(&he->sorted_chain, &he->callchain,
|
||||
callchain_param.sort(&he->sorted_chain, he->callchain,
|
||||
min_callchain_hits, &callchain_param);
|
||||
|
||||
while (*p != NULL) {
|
||||
|
@ -185,12 +186,13 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root,
|
|||
rb_insert_color(&he->rb_node, root);
|
||||
}
|
||||
|
||||
void perf_session__output_resort(struct rb_root *hists, u64 total_samples)
|
||||
u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples)
|
||||
{
|
||||
struct rb_root tmp;
|
||||
struct rb_node *next;
|
||||
struct hist_entry *n;
|
||||
u64 min_callchain_hits;
|
||||
u64 nr_hists = 0;
|
||||
|
||||
min_callchain_hits =
|
||||
total_samples * (callchain_param.min_percent / 100);
|
||||
|
@ -205,9 +207,11 @@ void perf_session__output_resort(struct rb_root *hists, u64 total_samples)
|
|||
rb_erase(&n->rb_node, hists);
|
||||
perf_session__insert_output_hist_entry(&tmp, n,
|
||||
min_callchain_hits);
|
||||
++nr_hists;
|
||||
}
|
||||
|
||||
*hists = tmp;
|
||||
return nr_hists;
|
||||
}
|
||||
|
||||
static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
|
||||
|
@ -452,16 +456,17 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
|
|||
return ret;
|
||||
}
|
||||
|
||||
size_t hist_entry__fprintf(struct hist_entry *self,
|
||||
int hist_entry__snprintf(struct hist_entry *self,
|
||||
char *s, size_t size,
|
||||
struct perf_session *pair_session,
|
||||
bool show_displacement,
|
||||
long displacement, FILE *fp,
|
||||
long displacement, bool color,
|
||||
u64 session_total)
|
||||
{
|
||||
struct sort_entry *se;
|
||||
u64 count, total;
|
||||
const char *sep = symbol_conf.field_sep;
|
||||
size_t ret;
|
||||
int ret;
|
||||
|
||||
if (symbol_conf.exclude_other && !self->parent)
|
||||
return 0;
|
||||
|
@ -474,17 +479,22 @@ size_t hist_entry__fprintf(struct hist_entry *self,
|
|||
total = session_total;
|
||||
}
|
||||
|
||||
if (total)
|
||||
ret = percent_color_fprintf(fp, sep ? "%.2f" : " %6.2f%%",
|
||||
(count * 100.0) / total);
|
||||
else
|
||||
ret = fprintf(fp, sep ? "%lld" : "%12lld ", count);
|
||||
if (total) {
|
||||
if (color)
|
||||
ret = percent_color_snprintf(s, size,
|
||||
sep ? "%.2f" : " %6.2f%%",
|
||||
(count * 100.0) / total);
|
||||
else
|
||||
ret = snprintf(s, size, sep ? "%.2f" : " %6.2f%%",
|
||||
(count * 100.0) / total);
|
||||
} else
|
||||
ret = snprintf(s, size, sep ? "%lld" : "%12lld ", count);
|
||||
|
||||
if (symbol_conf.show_nr_samples) {
|
||||
if (sep)
|
||||
ret += fprintf(fp, "%c%lld", *sep, count);
|
||||
ret += snprintf(s + ret, size - ret, "%c%lld", *sep, count);
|
||||
else
|
||||
ret += fprintf(fp, "%11lld", count);
|
||||
ret += snprintf(s + ret, size - ret, "%11lld", count);
|
||||
}
|
||||
|
||||
if (pair_session) {
|
||||
|
@ -504,9 +514,9 @@ size_t hist_entry__fprintf(struct hist_entry *self,
|
|||
snprintf(bf, sizeof(bf), " ");
|
||||
|
||||
if (sep)
|
||||
ret += fprintf(fp, "%c%s", *sep, bf);
|
||||
ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf);
|
||||
else
|
||||
ret += fprintf(fp, "%11.11s", bf);
|
||||
ret += snprintf(s + ret, size - ret, "%11.11s", bf);
|
||||
|
||||
if (show_displacement) {
|
||||
if (displacement)
|
||||
|
@ -515,9 +525,9 @@ size_t hist_entry__fprintf(struct hist_entry *self,
|
|||
snprintf(bf, sizeof(bf), " ");
|
||||
|
||||
if (sep)
|
||||
ret += fprintf(fp, "%c%s", *sep, bf);
|
||||
ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf);
|
||||
else
|
||||
ret += fprintf(fp, "%6.6s", bf);
|
||||
ret += snprintf(s + ret, size - ret, "%6.6s", bf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,11 +535,25 @@ size_t hist_entry__fprintf(struct hist_entry *self,
|
|||
if (se->elide)
|
||||
continue;
|
||||
|
||||
ret += fprintf(fp, "%s", sep ?: " ");
|
||||
ret += se->print(fp, self, se->width ? *se->width : 0);
|
||||
ret += snprintf(s + ret, size - ret, "%s", sep ?: " ");
|
||||
ret += se->snprintf(self, s + ret, size - ret,
|
||||
se->width ? *se->width : 0);
|
||||
}
|
||||
|
||||
return ret + fprintf(fp, "\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hist_entry__fprintf(struct hist_entry *self,
|
||||
struct perf_session *pair_session,
|
||||
bool show_displacement,
|
||||
long displacement, FILE *fp,
|
||||
u64 session_total)
|
||||
{
|
||||
char bf[512];
|
||||
hist_entry__snprintf(self, bf, sizeof(bf), pair_session,
|
||||
show_displacement, displacement,
|
||||
true, session_total);
|
||||
return fprintf(fp, "%s\n", bf);
|
||||
}
|
||||
|
||||
static size_t hist_entry__fprintf_callchain(struct hist_entry *self, FILE *fp,
|
||||
|
@ -658,7 +682,7 @@ size_t perf_session__fprintf_hists(struct rb_root *hists,
|
|||
|
||||
if (h->ms.map == NULL && verbose > 1) {
|
||||
__map_groups__fprintf_maps(&h->thread->mg,
|
||||
MAP__FUNCTION, fp);
|
||||
MAP__FUNCTION, verbose, fp);
|
||||
fprintf(fp, "%.10s end\n", graph_dotted_line);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,14 +18,19 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
|
|||
u64 count, bool *hit);
|
||||
extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
|
||||
extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
|
||||
size_t hist_entry__fprintf(struct hist_entry *self,
|
||||
int hist_entry__fprintf(struct hist_entry *self,
|
||||
struct perf_session *pair_session,
|
||||
bool show_displacement,
|
||||
long displacement, FILE *fp,
|
||||
u64 session_total);
|
||||
int hist_entry__snprintf(struct hist_entry *self,
|
||||
char *bf, size_t size,
|
||||
struct perf_session *pair_session,
|
||||
bool show_displacement, long displacement,
|
||||
bool color, u64 session_total);
|
||||
void hist_entry__free(struct hist_entry *);
|
||||
|
||||
void perf_session__output_resort(struct rb_root *hists, u64 total_samples);
|
||||
u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples);
|
||||
void perf_session__collapse_resort(struct rb_root *hists);
|
||||
size_t perf_session__fprintf_hists(struct rb_root *hists,
|
||||
struct perf_session *pair,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "symbol.h"
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -234,18 +235,211 @@ u64 map__objdump_2ip(struct map *map, u64 addr)
|
|||
return ip;
|
||||
}
|
||||
|
||||
void map_groups__init(struct map_groups *self)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAP__NR_TYPES; ++i) {
|
||||
self->maps[i] = RB_ROOT;
|
||||
INIT_LIST_HEAD(&self->removed_maps[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void map_groups__flush(struct map_groups *self)
|
||||
{
|
||||
int type;
|
||||
|
||||
for (type = 0; type < MAP__NR_TYPES; type++) {
|
||||
struct rb_root *root = &self->maps[type];
|
||||
struct rb_node *next = rb_first(root);
|
||||
|
||||
while (next) {
|
||||
struct map *pos = rb_entry(next, struct map, rb_node);
|
||||
next = rb_next(&pos->rb_node);
|
||||
rb_erase(&pos->rb_node, root);
|
||||
/*
|
||||
* We may have references to this map, for
|
||||
* instance in some hist_entry instances, so
|
||||
* just move them to a separate list.
|
||||
*/
|
||||
list_add_tail(&pos->node, &self->removed_maps[pos->type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct symbol *map_groups__find_symbol(struct map_groups *self,
|
||||
enum map_type type, u64 addr,
|
||||
struct map **mapp,
|
||||
symbol_filter_t filter)
|
||||
{
|
||||
struct map *map = map_groups__find(self, type, addr);
|
||||
|
||||
if (map != NULL)
|
||||
if (map != NULL) {
|
||||
if (mapp != NULL)
|
||||
*mapp = map;
|
||||
return map__find_symbol(map, map->map_ip(map, addr), filter);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct symbol *map_groups__find_symbol_by_name(struct map_groups *self,
|
||||
enum map_type type,
|
||||
const char *name,
|
||||
struct map **mapp,
|
||||
symbol_filter_t filter)
|
||||
{
|
||||
struct rb_node *nd;
|
||||
|
||||
for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
|
||||
struct map *pos = rb_entry(nd, struct map, rb_node);
|
||||
struct symbol *sym = map__find_symbol_by_name(pos, name, filter);
|
||||
|
||||
if (sym == NULL)
|
||||
continue;
|
||||
if (mapp != NULL)
|
||||
*mapp = pos;
|
||||
return sym;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t __map_groups__fprintf_maps(struct map_groups *self,
|
||||
enum map_type type, int verbose, FILE *fp)
|
||||
{
|
||||
size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
|
||||
struct rb_node *nd;
|
||||
|
||||
for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
|
||||
struct map *pos = rb_entry(nd, struct map, rb_node);
|
||||
printed += fprintf(fp, "Map:");
|
||||
printed += map__fprintf(pos, fp);
|
||||
if (verbose > 2) {
|
||||
printed += dso__fprintf(pos->dso, type, fp);
|
||||
printed += fprintf(fp, "--\n");
|
||||
}
|
||||
}
|
||||
|
||||
return printed;
|
||||
}
|
||||
|
||||
size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp)
|
||||
{
|
||||
size_t printed = 0, i;
|
||||
for (i = 0; i < MAP__NR_TYPES; ++i)
|
||||
printed += __map_groups__fprintf_maps(self, i, verbose, fp);
|
||||
return printed;
|
||||
}
|
||||
|
||||
static size_t __map_groups__fprintf_removed_maps(struct map_groups *self,
|
||||
enum map_type type,
|
||||
int verbose, FILE *fp)
|
||||
{
|
||||
struct map *pos;
|
||||
size_t printed = 0;
|
||||
|
||||
list_for_each_entry(pos, &self->removed_maps[type], node) {
|
||||
printed += fprintf(fp, "Map:");
|
||||
printed += map__fprintf(pos, fp);
|
||||
if (verbose > 1) {
|
||||
printed += dso__fprintf(pos->dso, type, fp);
|
||||
printed += fprintf(fp, "--\n");
|
||||
}
|
||||
}
|
||||
return printed;
|
||||
}
|
||||
|
||||
static size_t map_groups__fprintf_removed_maps(struct map_groups *self,
|
||||
int verbose, FILE *fp)
|
||||
{
|
||||
size_t printed = 0, i;
|
||||
for (i = 0; i < MAP__NR_TYPES; ++i)
|
||||
printed += __map_groups__fprintf_removed_maps(self, i, verbose, fp);
|
||||
return printed;
|
||||
}
|
||||
|
||||
size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp)
|
||||
{
|
||||
size_t printed = map_groups__fprintf_maps(self, verbose, fp);
|
||||
printed += fprintf(fp, "Removed maps:\n");
|
||||
return printed + map_groups__fprintf_removed_maps(self, verbose, fp);
|
||||
}
|
||||
|
||||
int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
|
||||
int verbose, FILE *fp)
|
||||
{
|
||||
struct rb_root *root = &self->maps[map->type];
|
||||
struct rb_node *next = rb_first(root);
|
||||
|
||||
while (next) {
|
||||
struct map *pos = rb_entry(next, struct map, rb_node);
|
||||
next = rb_next(&pos->rb_node);
|
||||
|
||||
if (!map__overlap(pos, map))
|
||||
continue;
|
||||
|
||||
if (verbose >= 2) {
|
||||
fputs("overlapping maps:\n", fp);
|
||||
map__fprintf(map, fp);
|
||||
map__fprintf(pos, fp);
|
||||
}
|
||||
|
||||
rb_erase(&pos->rb_node, root);
|
||||
/*
|
||||
* We may have references to this map, for instance in some
|
||||
* hist_entry instances, so just move them to a separate
|
||||
* list.
|
||||
*/
|
||||
list_add_tail(&pos->node, &self->removed_maps[map->type]);
|
||||
/*
|
||||
* Now check if we need to create new maps for areas not
|
||||
* overlapped by the new map:
|
||||
*/
|
||||
if (map->start > pos->start) {
|
||||
struct map *before = map__clone(pos);
|
||||
|
||||
if (before == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
before->end = map->start - 1;
|
||||
map_groups__insert(self, before);
|
||||
if (verbose >= 2)
|
||||
map__fprintf(before, fp);
|
||||
}
|
||||
|
||||
if (map->end < pos->end) {
|
||||
struct map *after = map__clone(pos);
|
||||
|
||||
if (after == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
after->start = map->end + 1;
|
||||
map_groups__insert(self, after);
|
||||
if (verbose >= 2)
|
||||
map__fprintf(after, fp);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX This should not really _copy_ te maps, but refcount them.
|
||||
*/
|
||||
int map_groups__clone(struct map_groups *self,
|
||||
struct map_groups *parent, enum map_type type)
|
||||
{
|
||||
struct rb_node *nd;
|
||||
for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) {
|
||||
struct map *map = rb_entry(nd, struct map, rb_node);
|
||||
struct map *new = map__clone(map);
|
||||
if (new == NULL)
|
||||
return -ENOMEM;
|
||||
map_groups__insert(self, new);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 map__reloc_map_ip(struct map *map, u64 ip)
|
||||
{
|
||||
return ip + (s64)map->pgoff;
|
||||
|
|
|
@ -97,11 +97,14 @@ struct map_groups {
|
|||
};
|
||||
|
||||
size_t __map_groups__fprintf_maps(struct map_groups *self,
|
||||
enum map_type type, FILE *fp);
|
||||
enum map_type type, int verbose, FILE *fp);
|
||||
void maps__insert(struct rb_root *maps, struct map *map);
|
||||
struct map *maps__find(struct rb_root *maps, u64 addr);
|
||||
void map_groups__init(struct map_groups *self);
|
||||
size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp);
|
||||
int map_groups__clone(struct map_groups *self,
|
||||
struct map_groups *parent, enum map_type type);
|
||||
size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp);
|
||||
size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp);
|
||||
|
||||
static inline void map_groups__insert(struct map_groups *self, struct map *map)
|
||||
{
|
||||
|
@ -116,15 +119,33 @@ static inline struct map *map_groups__find(struct map_groups *self,
|
|||
|
||||
struct symbol *map_groups__find_symbol(struct map_groups *self,
|
||||
enum map_type type, u64 addr,
|
||||
struct map **mapp,
|
||||
symbol_filter_t filter);
|
||||
|
||||
static inline struct symbol *map_groups__find_function(struct map_groups *self,
|
||||
u64 addr,
|
||||
symbol_filter_t filter)
|
||||
struct symbol *map_groups__find_symbol_by_name(struct map_groups *self,
|
||||
enum map_type type,
|
||||
const char *name,
|
||||
struct map **mapp,
|
||||
symbol_filter_t filter);
|
||||
|
||||
static inline
|
||||
struct symbol *map_groups__find_function(struct map_groups *self, u64 addr,
|
||||
struct map **mapp, symbol_filter_t filter)
|
||||
{
|
||||
return map_groups__find_symbol(self, MAP__FUNCTION, addr, filter);
|
||||
return map_groups__find_symbol(self, MAP__FUNCTION, addr, mapp, filter);
|
||||
}
|
||||
|
||||
static inline
|
||||
struct symbol *map_groups__find_function_by_name(struct map_groups *self,
|
||||
const char *name, struct map **mapp,
|
||||
symbol_filter_t filter)
|
||||
{
|
||||
return map_groups__find_symbol_by_name(self, MAP__FUNCTION, name, mapp, filter);
|
||||
}
|
||||
|
||||
int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
|
||||
int verbose, FILE *fp);
|
||||
|
||||
struct map *map_groups__find_by_name(struct map_groups *self,
|
||||
enum map_type type, const char *name);
|
||||
int __map_groups__create_kernel_maps(struct map_groups *self,
|
||||
|
@ -134,5 +155,6 @@ int map_groups__create_kernel_maps(struct map_groups *self,
|
|||
struct map *vmlinux_maps[MAP__NR_TYPES]);
|
||||
struct map *map_groups__new_module(struct map_groups *self, u64 start,
|
||||
const char *filename);
|
||||
void map_groups__flush(struct map_groups *self);
|
||||
|
||||
#endif /* __PERF_MAP_H */
|
||||
|
|
|
@ -12,6 +12,72 @@
|
|||
#include "sort.h"
|
||||
#include "symbol.h"
|
||||
|
||||
struct ui_progress {
|
||||
newtComponent form, scale;
|
||||
};
|
||||
|
||||
struct ui_progress *ui_progress__new(const char *title, u64 total)
|
||||
{
|
||||
struct ui_progress *self = malloc(sizeof(*self));
|
||||
|
||||
if (self != NULL) {
|
||||
int cols;
|
||||
newtGetScreenSize(&cols, NULL);
|
||||
cols -= 4;
|
||||
newtCenteredWindow(cols, 1, title);
|
||||
self->form = newtForm(NULL, NULL, 0);
|
||||
if (self->form == NULL)
|
||||
goto out_free_self;
|
||||
self->scale = newtScale(0, 0, cols, total);
|
||||
if (self->scale == NULL)
|
||||
goto out_free_form;
|
||||
newtFormAddComponents(self->form, self->scale, NULL);
|
||||
newtRefresh();
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
out_free_form:
|
||||
newtFormDestroy(self->form);
|
||||
out_free_self:
|
||||
free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ui_progress__update(struct ui_progress *self, u64 curr)
|
||||
{
|
||||
newtScaleSet(self->scale, curr);
|
||||
newtRefresh();
|
||||
}
|
||||
|
||||
void ui_progress__delete(struct ui_progress *self)
|
||||
{
|
||||
newtFormDestroy(self->form);
|
||||
newtPopWindow();
|
||||
free(self);
|
||||
}
|
||||
|
||||
static char browser__last_msg[1024];
|
||||
|
||||
int browser__show_help(const char *format, va_list ap)
|
||||
{
|
||||
int ret;
|
||||
static int backlog;
|
||||
|
||||
ret = vsnprintf(browser__last_msg + backlog,
|
||||
sizeof(browser__last_msg) - backlog, format, ap);
|
||||
backlog += ret;
|
||||
|
||||
if (browser__last_msg[backlog - 1] == '\n') {
|
||||
newtPopHelpLine();
|
||||
newtPushHelpLine(browser__last_msg);
|
||||
newtRefresh();
|
||||
backlog = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void newt_form__set_exit_keys(newtComponent self)
|
||||
{
|
||||
newtFormAddHotKey(self, NEWT_KEY_ESCAPE);
|
||||
|
@ -228,60 +294,17 @@ static void hist_entry__append_callchain_browser(struct hist_entry *self,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: get lib/string.c linked with perf somehow
|
||||
*/
|
||||
static char *skip_spaces(const char *str)
|
||||
{
|
||||
while (isspace(*str))
|
||||
++str;
|
||||
return (char *)str;
|
||||
}
|
||||
|
||||
static char *strim(char *s)
|
||||
{
|
||||
size_t size;
|
||||
char *end;
|
||||
|
||||
s = skip_spaces(s);
|
||||
size = strlen(s);
|
||||
if (!size)
|
||||
return s;
|
||||
|
||||
end = s + size - 1;
|
||||
while (end >= s && isspace(*end))
|
||||
end--;
|
||||
*(end + 1) = '\0';
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static size_t hist_entry__append_browser(struct hist_entry *self,
|
||||
newtComponent tree, u64 total)
|
||||
{
|
||||
char bf[1024], *s;
|
||||
FILE *fp;
|
||||
char s[256];
|
||||
size_t ret;
|
||||
|
||||
if (symbol_conf.exclude_other && !self->parent)
|
||||
return 0;
|
||||
|
||||
fp = fmemopen(bf, sizeof(bf), "w");
|
||||
if (fp == NULL)
|
||||
return 0;
|
||||
|
||||
hist_entry__fprintf(self, NULL, false, 0, fp, total);
|
||||
fclose(fp);
|
||||
|
||||
/*
|
||||
* FIXME: We shouldn't need to trim, as the printing routines shouldn't
|
||||
* add spaces it in the first place, the stdio output routines should
|
||||
* call a __snprintf method instead of the current __print (that
|
||||
* actually is a __fprintf) one, but get the raw string and _then_ add
|
||||
* the newline, as this is a detail of stdio printing, not needed in
|
||||
* other UIs, e.g. newt.
|
||||
*/
|
||||
s = strim(bf);
|
||||
|
||||
ret = hist_entry__snprintf(self, s, sizeof(s), NULL,
|
||||
false, 0, false, total);
|
||||
if (symbol_conf.use_callchain) {
|
||||
int indexes[2];
|
||||
|
||||
|
@ -291,10 +314,11 @@ static size_t hist_entry__append_browser(struct hist_entry *self,
|
|||
} else
|
||||
newtListboxAppendEntry(tree, s, &self->ms);
|
||||
|
||||
return strlen(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void map_symbol__annotate_browser(const struct map_symbol *self)
|
||||
static void map_symbol__annotate_browser(const struct map_symbol *self,
|
||||
const char *input_name)
|
||||
{
|
||||
FILE *fp;
|
||||
int cols, rows;
|
||||
|
@ -308,8 +332,8 @@ static void map_symbol__annotate_browser(const struct map_symbol *self)
|
|||
if (self->sym == NULL)
|
||||
return;
|
||||
|
||||
if (asprintf(&str, "perf annotate -d \"%s\" %s 2>&1 | expand",
|
||||
self->map->dso->name, self->sym->name) < 0)
|
||||
if (asprintf(&str, "perf annotate -i \"%s\" -d \"%s\" %s 2>&1 | expand",
|
||||
input_name, self->map->dso->name, self->sym->name) < 0)
|
||||
return;
|
||||
|
||||
fp = popen(str, "r");
|
||||
|
@ -358,90 +382,121 @@ static const void *newt__symbol_tree_get_current(newtComponent self)
|
|||
return newtListboxGetCurrent(self);
|
||||
}
|
||||
|
||||
static void perf_session__selection(newtComponent self, void *data)
|
||||
static void hist_browser__selection(newtComponent self, void *data)
|
||||
{
|
||||
const struct map_symbol **symbol_ptr = data;
|
||||
*symbol_ptr = newt__symbol_tree_get_current(self);
|
||||
}
|
||||
|
||||
void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
|
||||
const char *helpline)
|
||||
{
|
||||
struct sort_entry *se;
|
||||
struct rb_node *nd;
|
||||
char seq[] = ".";
|
||||
unsigned int width;
|
||||
char *col_width = symbol_conf.col_width_list_str;
|
||||
int rows, cols, idx;
|
||||
int max_len = 0;
|
||||
char str[1024];
|
||||
newtComponent form, tree;
|
||||
struct newtExitStruct es;
|
||||
struct hist_browser {
|
||||
newtComponent form, tree;
|
||||
const struct map_symbol *selection;
|
||||
};
|
||||
|
||||
snprintf(str, sizeof(str), "Samples: %Ld", session_total);
|
||||
newtDrawRootText(0, 0, str);
|
||||
newtPushHelpLine(helpline);
|
||||
static struct hist_browser *hist_browser__new(void)
|
||||
{
|
||||
struct hist_browser *self = malloc(sizeof(*self));
|
||||
|
||||
newtGetScreenSize(&cols, &rows);
|
||||
if (self != NULL) {
|
||||
char seq[] = ".";
|
||||
int rows;
|
||||
|
||||
if (symbol_conf.use_callchain)
|
||||
tree = newtCheckboxTreeMulti(0, 0, rows - 5, seq,
|
||||
NEWT_FLAG_SCROLL);
|
||||
else
|
||||
tree = newtListbox(0, 0, rows - 5, (NEWT_FLAG_SCROLL |
|
||||
NEWT_FLAG_RETURNEXIT));
|
||||
newtGetScreenSize(NULL, &rows);
|
||||
|
||||
newtComponentAddCallback(tree, perf_session__selection, &selection);
|
||||
|
||||
list_for_each_entry(se, &hist_entry__sort_list, list) {
|
||||
if (se->elide)
|
||||
continue;
|
||||
width = strlen(se->header);
|
||||
if (se->width) {
|
||||
if (symbol_conf.col_width_list_str) {
|
||||
if (col_width) {
|
||||
*se->width = atoi(col_width);
|
||||
col_width = strchr(col_width, ',');
|
||||
if (col_width)
|
||||
++col_width;
|
||||
}
|
||||
}
|
||||
*se->width = max(*se->width, width);
|
||||
}
|
||||
if (symbol_conf.use_callchain)
|
||||
self->tree = newtCheckboxTreeMulti(0, 0, rows - 5, seq,
|
||||
NEWT_FLAG_SCROLL);
|
||||
else
|
||||
self->tree = newtListbox(0, 0, rows - 5,
|
||||
(NEWT_FLAG_SCROLL |
|
||||
NEWT_FLAG_RETURNEXIT));
|
||||
newtComponentAddCallback(self->tree, hist_browser__selection,
|
||||
&self->selection);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static void hist_browser__delete(struct hist_browser *self)
|
||||
{
|
||||
newtFormDestroy(self->form);
|
||||
newtPopWindow();
|
||||
free(self);
|
||||
}
|
||||
|
||||
static int hist_browser__populate(struct hist_browser *self, struct rb_root *hists,
|
||||
u64 nr_hists, u64 session_total)
|
||||
{
|
||||
int max_len = 0, idx, cols, rows;
|
||||
struct ui_progress *progress;
|
||||
struct rb_node *nd;
|
||||
u64 curr_hist = 0;
|
||||
|
||||
progress = ui_progress__new("Adding entries to the browser...", nr_hists);
|
||||
if (progress == NULL)
|
||||
return -1;
|
||||
|
||||
idx = 0;
|
||||
for (nd = rb_first(hists); nd; nd = rb_next(nd)) {
|
||||
struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
|
||||
int len = hist_entry__append_browser(h, tree, session_total);
|
||||
int len = hist_entry__append_browser(h, self->tree, session_total);
|
||||
if (len > max_len)
|
||||
max_len = len;
|
||||
if (symbol_conf.use_callchain)
|
||||
hist_entry__append_callchain_browser(h, tree, session_total, idx++);
|
||||
hist_entry__append_callchain_browser(h, self->tree,
|
||||
session_total, idx++);
|
||||
++curr_hist;
|
||||
if (curr_hist % 5)
|
||||
ui_progress__update(progress, curr_hist);
|
||||
}
|
||||
|
||||
ui_progress__delete(progress);
|
||||
|
||||
newtGetScreenSize(&cols, &rows);
|
||||
|
||||
if (max_len > cols)
|
||||
max_len = cols - 3;
|
||||
|
||||
if (!symbol_conf.use_callchain)
|
||||
newtListboxSetWidth(tree, max_len);
|
||||
newtListboxSetWidth(self->tree, max_len);
|
||||
|
||||
newtCenteredWindow(max_len + (symbol_conf.use_callchain ? 5 : 0),
|
||||
rows - 5, "Report");
|
||||
form = newt_form__new();
|
||||
newtFormAddHotKey(form, 'A');
|
||||
newtFormAddHotKey(form, 'a');
|
||||
newtFormAddHotKey(form, NEWT_KEY_RIGHT);
|
||||
newtFormAddComponents(form, tree, NULL);
|
||||
selection = newt__symbol_tree_get_current(tree);
|
||||
self->form = newt_form__new();
|
||||
newtFormAddHotKey(self->form, 'A');
|
||||
newtFormAddHotKey(self->form, 'a');
|
||||
newtFormAddHotKey(self->form, NEWT_KEY_RIGHT);
|
||||
newtFormAddComponents(self->form, self->tree, NULL);
|
||||
self->selection = newt__symbol_tree_get_current(self->tree);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
|
||||
u64 session_total, const char *helpline,
|
||||
const char *input_name)
|
||||
{
|
||||
struct newtExitStruct es;
|
||||
char str[1024];
|
||||
int err = -1;
|
||||
struct hist_browser *browser = hist_browser__new();
|
||||
|
||||
if (browser == NULL)
|
||||
return -1;
|
||||
|
||||
snprintf(str, sizeof(str), "Samples: %Ld", session_total);
|
||||
newtDrawRootText(0, 0, str);
|
||||
newtPushHelpLine(helpline);
|
||||
|
||||
if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0)
|
||||
goto out;
|
||||
|
||||
while (1) {
|
||||
char annotate[512];
|
||||
const char *options[2];
|
||||
int nr_options = 0, choice = 0;
|
||||
|
||||
newtFormRun(form, &es);
|
||||
newtFormRun(browser->form, &es);
|
||||
if (es.reason == NEWT_EXIT_HOTKEY) {
|
||||
if (toupper(es.u.key) == 'A')
|
||||
goto do_annotate;
|
||||
|
@ -455,9 +510,9 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
|
|||
}
|
||||
}
|
||||
|
||||
if (selection->sym != NULL) {
|
||||
if (browser->selection->sym != NULL) {
|
||||
snprintf(annotate, sizeof(annotate),
|
||||
"Annotate %s", selection->sym->name);
|
||||
"Annotate %s", browser->selection->sym->name);
|
||||
options[nr_options++] = annotate;
|
||||
}
|
||||
|
||||
|
@ -466,41 +521,22 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
|
|||
if (choice == nr_options - 1)
|
||||
break;
|
||||
do_annotate:
|
||||
if (selection->sym != NULL && choice >= 0) {
|
||||
if (selection->map->dso->origin == DSO__ORIG_KERNEL) {
|
||||
if (browser->selection->sym != NULL && choice >= 0) {
|
||||
if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) {
|
||||
newtPopHelpLine();
|
||||
newtPushHelpLine("No vmlinux file found, can't "
|
||||
"annotate with just a "
|
||||
"kallsyms file");
|
||||
continue;
|
||||
}
|
||||
map_symbol__annotate_browser(selection);
|
||||
map_symbol__annotate_browser(browser->selection,
|
||||
input_name);
|
||||
}
|
||||
}
|
||||
|
||||
newtFormDestroy(form);
|
||||
newtPopWindow();
|
||||
}
|
||||
|
||||
static char browser__last_msg[1024];
|
||||
|
||||
int browser__show_help(const char *format, va_list ap)
|
||||
{
|
||||
int ret;
|
||||
static int backlog;
|
||||
|
||||
ret = vsnprintf(browser__last_msg + backlog,
|
||||
sizeof(browser__last_msg) - backlog, format, ap);
|
||||
backlog += ret;
|
||||
|
||||
if (browser__last_msg[backlog - 1] == '\n') {
|
||||
newtPopHelpLine();
|
||||
newtPushHelpLine(browser__last_msg);
|
||||
newtRefresh();
|
||||
backlog = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
err = 0;
|
||||
out:
|
||||
hist_browser__delete(browser);
|
||||
return err;
|
||||
}
|
||||
|
||||
void setup_browser(void)
|
||||
|
|
|
@ -52,11 +52,6 @@ static int perf_session__open(struct perf_session *self, bool force)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static inline int perf_session__create_kernel_maps(struct perf_session *self)
|
||||
{
|
||||
return map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps);
|
||||
}
|
||||
|
||||
struct perf_session *perf_session__new(const char *filename, int mode, bool force)
|
||||
{
|
||||
size_t len = filename ? strlen(filename) + 1 : 0;
|
||||
|
@ -123,16 +118,11 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
|
|||
struct symbol **parent)
|
||||
{
|
||||
u8 cpumode = PERF_RECORD_MISC_USER;
|
||||
struct map_symbol *syms = NULL;
|
||||
unsigned int i;
|
||||
struct map_symbol *syms = calloc(chain->nr, sizeof(*syms));
|
||||
|
||||
if (symbol_conf.use_callchain) {
|
||||
syms = calloc(chain->nr, sizeof(*syms));
|
||||
if (!syms) {
|
||||
fprintf(stderr, "Can't allocate memory for symbols\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
if (!syms)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < chain->nr; i++) {
|
||||
u64 ip = chain->ips[i];
|
||||
|
@ -397,6 +387,10 @@ int __perf_session__process_events(struct perf_session *self,
|
|||
event_t *event;
|
||||
uint32_t size;
|
||||
char *buf;
|
||||
struct ui_progress *progress = ui_progress__new("Processing events...",
|
||||
self->size);
|
||||
if (progress == NULL)
|
||||
return -1;
|
||||
|
||||
perf_event_ops__fill_defaults(ops);
|
||||
|
||||
|
@ -425,6 +419,7 @@ int __perf_session__process_events(struct perf_session *self,
|
|||
|
||||
more:
|
||||
event = (event_t *)(buf + head);
|
||||
ui_progress__update(progress, offset);
|
||||
|
||||
if (self->header.needs_swap)
|
||||
perf_event_header__bswap(&event->header);
|
||||
|
@ -475,6 +470,7 @@ int __perf_session__process_events(struct perf_session *self,
|
|||
done:
|
||||
err = 0;
|
||||
out_err:
|
||||
ui_progress__delete(progress);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,11 @@ static inline int __perf_session__create_kernel_maps(struct perf_session *self,
|
|||
self->vmlinux_maps, kernel);
|
||||
}
|
||||
|
||||
static inline int perf_session__create_kernel_maps(struct perf_session *self)
|
||||
{
|
||||
return map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps);
|
||||
}
|
||||
|
||||
static inline struct map *
|
||||
perf_session__new_module_map(struct perf_session *self,
|
||||
u64 start, const char *filename)
|
||||
|
@ -88,11 +93,17 @@ static inline struct map *
|
|||
}
|
||||
|
||||
#ifdef NO_NEWT_SUPPORT
|
||||
static inline void perf_session__browse_hists(struct rb_root *hists __used,
|
||||
static inline int perf_session__browse_hists(struct rb_root *hists __used,
|
||||
u64 nr_hists __used,
|
||||
u64 session_total __used,
|
||||
const char *helpline __used) {}
|
||||
const char *helpline __used,
|
||||
const char *input_name __used)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
|
||||
const char *helpline);
|
||||
int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
|
||||
u64 session_total, const char *helpline,
|
||||
const char *input_name);
|
||||
#endif
|
||||
#endif /* __PERF_SESSION_H */
|
||||
|
|
|
@ -18,10 +18,21 @@ char * field_sep;
|
|||
|
||||
LIST_HEAD(hist_entry__sort_list);
|
||||
|
||||
static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
|
||||
size_t size, unsigned int width);
|
||||
static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf,
|
||||
size_t size, unsigned int width);
|
||||
static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
|
||||
size_t size, unsigned int width);
|
||||
static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
|
||||
size_t size, unsigned int width);
|
||||
static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
|
||||
size_t size, unsigned int width);
|
||||
|
||||
struct sort_entry sort_thread = {
|
||||
.header = "Command: Pid",
|
||||
.cmp = sort__thread_cmp,
|
||||
.print = sort__thread_print,
|
||||
.snprintf = hist_entry__thread_snprintf,
|
||||
.width = &threads__col_width,
|
||||
};
|
||||
|
||||
|
@ -29,27 +40,27 @@ struct sort_entry sort_comm = {
|
|||
.header = "Command",
|
||||
.cmp = sort__comm_cmp,
|
||||
.collapse = sort__comm_collapse,
|
||||
.print = sort__comm_print,
|
||||
.snprintf = hist_entry__comm_snprintf,
|
||||
.width = &comms__col_width,
|
||||
};
|
||||
|
||||
struct sort_entry sort_dso = {
|
||||
.header = "Shared Object",
|
||||
.cmp = sort__dso_cmp,
|
||||
.print = sort__dso_print,
|
||||
.snprintf = hist_entry__dso_snprintf,
|
||||
.width = &dsos__col_width,
|
||||
};
|
||||
|
||||
struct sort_entry sort_sym = {
|
||||
.header = "Symbol",
|
||||
.cmp = sort__sym_cmp,
|
||||
.print = sort__sym_print,
|
||||
.snprintf = hist_entry__sym_snprintf,
|
||||
};
|
||||
|
||||
struct sort_entry sort_parent = {
|
||||
.header = "Parent symbol",
|
||||
.cmp = sort__parent_cmp,
|
||||
.print = sort__parent_print,
|
||||
.snprintf = hist_entry__parent_snprintf,
|
||||
.width = &parent_symbol__col_width,
|
||||
};
|
||||
|
||||
|
@ -85,45 +96,38 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||
return right->thread->pid - left->thread->pid;
|
||||
}
|
||||
|
||||
int repsep_fprintf(FILE *fp, const char *fmt, ...)
|
||||
static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
if (!field_sep)
|
||||
n = vfprintf(fp, fmt, ap);
|
||||
else {
|
||||
char *bf = NULL;
|
||||
n = vasprintf(&bf, fmt, ap);
|
||||
if (n > 0) {
|
||||
char *sep = bf;
|
||||
n = vsnprintf(bf, size, fmt, ap);
|
||||
if (field_sep && n > 0) {
|
||||
char *sep = bf;
|
||||
|
||||
while (1) {
|
||||
sep = strchr(sep, *field_sep);
|
||||
if (sep == NULL)
|
||||
break;
|
||||
*sep = '.';
|
||||
}
|
||||
while (1) {
|
||||
sep = strchr(sep, *field_sep);
|
||||
if (sep == NULL)
|
||||
break;
|
||||
*sep = '.';
|
||||
}
|
||||
fputs(bf, fp);
|
||||
free(bf);
|
||||
}
|
||||
va_end(ap);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
|
||||
static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
|
||||
size_t size, unsigned int width)
|
||||
{
|
||||
return repsep_fprintf(fp, "%*s:%5d", width - 6,
|
||||
return repsep_snprintf(bf, size, "%*s:%5d", width,
|
||||
self->thread->comm ?: "", self->thread->pid);
|
||||
}
|
||||
|
||||
size_t
|
||||
sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
|
||||
static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf,
|
||||
size_t size, unsigned int width)
|
||||
{
|
||||
return repsep_fprintf(fp, "%*s", width, self->thread->comm);
|
||||
return repsep_snprintf(bf, size, "%*s", width, self->thread->comm);
|
||||
}
|
||||
|
||||
/* --sort dso */
|
||||
|
@ -149,16 +153,16 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||
return strcmp(dso_name_l, dso_name_r);
|
||||
}
|
||||
|
||||
size_t
|
||||
sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
|
||||
static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
|
||||
size_t size, unsigned int width)
|
||||
{
|
||||
if (self->ms.map && self->ms.map->dso) {
|
||||
const char *dso_name = !verbose ? self->ms.map->dso->short_name :
|
||||
self->ms.map->dso->long_name;
|
||||
return repsep_fprintf(fp, "%-*s", width, dso_name);
|
||||
return repsep_snprintf(bf, size, "%-*s", width, dso_name);
|
||||
}
|
||||
|
||||
return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
|
||||
return repsep_snprintf(bf, size, "%*Lx", width, self->ip);
|
||||
}
|
||||
|
||||
/* --sort symbol */
|
||||
|
@ -177,22 +181,22 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||
return (int64_t)(ip_r - ip_l);
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
|
||||
static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
|
||||
size_t size, unsigned int width __used)
|
||||
{
|
||||
size_t ret = 0;
|
||||
|
||||
if (verbose) {
|
||||
char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!';
|
||||
ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip, o);
|
||||
ret += repsep_snprintf(bf, size, "%#018llx %c ", self->ip, o);
|
||||
}
|
||||
|
||||
ret += repsep_fprintf(fp, "[%c] ", self->level);
|
||||
ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", self->level);
|
||||
if (self->ms.sym)
|
||||
ret += repsep_fprintf(fp, "%s", self->ms.sym->name);
|
||||
ret += repsep_snprintf(bf + ret, size - ret, "%s",
|
||||
self->ms.sym->name);
|
||||
else
|
||||
ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
|
||||
ret += repsep_snprintf(bf + ret, size - ret, "%#016llx", self->ip);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -231,10 +235,10 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||
return strcmp(sym_l->name, sym_r->name);
|
||||
}
|
||||
|
||||
size_t
|
||||
sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
|
||||
static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
|
||||
size_t size, unsigned int width)
|
||||
{
|
||||
return repsep_fprintf(fp, "%-*s", width,
|
||||
return repsep_snprintf(bf, size, "%-*s", width,
|
||||
self->parent ? self->parent->name : "[other]");
|
||||
}
|
||||
|
||||
|
@ -260,9 +264,8 @@ int sort_dimension__add(const char *tok)
|
|||
char err[BUFSIZ];
|
||||
|
||||
regerror(ret, &parent_regex, err, sizeof(err));
|
||||
fprintf(stderr, "Invalid regex: %s\n%s",
|
||||
parent_pattern, err);
|
||||
exit(-1);
|
||||
pr_err("Invalid regex: %s\n%s", parent_pattern, err);
|
||||
return -EINVAL;
|
||||
}
|
||||
sort__has_parent = 1;
|
||||
}
|
||||
|
|
|
@ -49,12 +49,12 @@ struct hist_entry {
|
|||
u64 ip;
|
||||
char level;
|
||||
struct symbol *parent;
|
||||
struct callchain_node callchain;
|
||||
union {
|
||||
unsigned long position;
|
||||
struct hist_entry *pair;
|
||||
struct rb_root sorted_chain;
|
||||
};
|
||||
struct callchain_node callchain[0];
|
||||
};
|
||||
|
||||
enum sort_type {
|
||||
|
@ -76,7 +76,8 @@ struct sort_entry {
|
|||
|
||||
int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
|
||||
int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
|
||||
size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width);
|
||||
int (*snprintf)(struct hist_entry *self, char *bf, size_t size,
|
||||
unsigned int width);
|
||||
unsigned int *width;
|
||||
bool elide;
|
||||
};
|
||||
|
@ -86,7 +87,6 @@ extern struct list_head hist_entry__sort_list;
|
|||
|
||||
void setup_sorting(const char * const usagestr[], const struct option *opts);
|
||||
|
||||
extern int repsep_fprintf(FILE *fp, const char *fmt, ...);
|
||||
extern size_t sort__thread_print(FILE *, struct hist_entry *, unsigned int);
|
||||
extern size_t sort__comm_print(FILE *, struct hist_entry *, unsigned int);
|
||||
extern size_t sort__dso_print(FILE *, struct hist_entry *, unsigned int);
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef __PERF_STRING_H_
|
||||
#define __PERF_STRING_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "types.h"
|
||||
|
||||
s64 perf_atoll(const char *str);
|
||||
char **argv_split(const char *str, int *argcp);
|
||||
void argv_free(char **argv);
|
||||
bool strglobmatch(const char *str, const char *pat);
|
||||
bool strlazymatch(const char *str, const char *pat);
|
||||
|
||||
#define _STR(x) #x
|
||||
#define STR(x) _STR(x)
|
||||
|
||||
#endif /* __PERF_STRING_H */
|
|
@ -38,15 +38,6 @@ int find_all_tid(int pid, pid_t ** all_tid)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void map_groups__init(struct map_groups *self)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAP__NR_TYPES; ++i) {
|
||||
self->maps[i] = RB_ROOT;
|
||||
INIT_LIST_HEAD(&self->removed_maps[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static struct thread *thread__new(pid_t pid)
|
||||
{
|
||||
struct thread *self = zalloc(sizeof(*self));
|
||||
|
@ -62,28 +53,6 @@ static struct thread *thread__new(pid_t pid)
|
|||
return self;
|
||||
}
|
||||
|
||||
static void map_groups__flush(struct map_groups *self)
|
||||
{
|
||||
int type;
|
||||
|
||||
for (type = 0; type < MAP__NR_TYPES; type++) {
|
||||
struct rb_root *root = &self->maps[type];
|
||||
struct rb_node *next = rb_first(root);
|
||||
|
||||
while (next) {
|
||||
struct map *pos = rb_entry(next, struct map, rb_node);
|
||||
next = rb_next(&pos->rb_node);
|
||||
rb_erase(&pos->rb_node, root);
|
||||
/*
|
||||
* We may have references to this map, for
|
||||
* instance in some hist_entry instances, so
|
||||
* just move them to a separate list.
|
||||
*/
|
||||
list_add_tail(&pos->node, &self->removed_maps[pos->type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int thread__set_comm(struct thread *self, const char *comm)
|
||||
{
|
||||
int err;
|
||||
|
@ -110,69 +79,10 @@ int thread__comm_len(struct thread *self)
|
|||
return self->comm_len;
|
||||
}
|
||||
|
||||
size_t __map_groups__fprintf_maps(struct map_groups *self,
|
||||
enum map_type type, FILE *fp)
|
||||
{
|
||||
size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
|
||||
struct rb_node *nd;
|
||||
|
||||
for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
|
||||
struct map *pos = rb_entry(nd, struct map, rb_node);
|
||||
printed += fprintf(fp, "Map:");
|
||||
printed += map__fprintf(pos, fp);
|
||||
if (verbose > 2) {
|
||||
printed += dso__fprintf(pos->dso, type, fp);
|
||||
printed += fprintf(fp, "--\n");
|
||||
}
|
||||
}
|
||||
|
||||
return printed;
|
||||
}
|
||||
|
||||
size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp)
|
||||
{
|
||||
size_t printed = 0, i;
|
||||
for (i = 0; i < MAP__NR_TYPES; ++i)
|
||||
printed += __map_groups__fprintf_maps(self, i, fp);
|
||||
return printed;
|
||||
}
|
||||
|
||||
static size_t __map_groups__fprintf_removed_maps(struct map_groups *self,
|
||||
enum map_type type, FILE *fp)
|
||||
{
|
||||
struct map *pos;
|
||||
size_t printed = 0;
|
||||
|
||||
list_for_each_entry(pos, &self->removed_maps[type], node) {
|
||||
printed += fprintf(fp, "Map:");
|
||||
printed += map__fprintf(pos, fp);
|
||||
if (verbose > 1) {
|
||||
printed += dso__fprintf(pos->dso, type, fp);
|
||||
printed += fprintf(fp, "--\n");
|
||||
}
|
||||
}
|
||||
return printed;
|
||||
}
|
||||
|
||||
static size_t map_groups__fprintf_removed_maps(struct map_groups *self, FILE *fp)
|
||||
{
|
||||
size_t printed = 0, i;
|
||||
for (i = 0; i < MAP__NR_TYPES; ++i)
|
||||
printed += __map_groups__fprintf_removed_maps(self, i, fp);
|
||||
return printed;
|
||||
}
|
||||
|
||||
static size_t map_groups__fprintf(struct map_groups *self, FILE *fp)
|
||||
{
|
||||
size_t printed = map_groups__fprintf_maps(self, fp);
|
||||
printed += fprintf(fp, "Removed maps:\n");
|
||||
return printed + map_groups__fprintf_removed_maps(self, fp);
|
||||
}
|
||||
|
||||
static size_t thread__fprintf(struct thread *self, FILE *fp)
|
||||
{
|
||||
return fprintf(fp, "Thread %d %s\n", self->pid, self->comm) +
|
||||
map_groups__fprintf(&self->mg, fp);
|
||||
map_groups__fprintf(&self->mg, verbose, fp);
|
||||
}
|
||||
|
||||
struct thread *perf_session__findnew(struct perf_session *self, pid_t pid)
|
||||
|
@ -214,87 +124,12 @@ struct thread *perf_session__findnew(struct perf_session *self, pid_t pid)
|
|||
return th;
|
||||
}
|
||||
|
||||
static int map_groups__fixup_overlappings(struct map_groups *self,
|
||||
struct map *map)
|
||||
{
|
||||
struct rb_root *root = &self->maps[map->type];
|
||||
struct rb_node *next = rb_first(root);
|
||||
|
||||
while (next) {
|
||||
struct map *pos = rb_entry(next, struct map, rb_node);
|
||||
next = rb_next(&pos->rb_node);
|
||||
|
||||
if (!map__overlap(pos, map))
|
||||
continue;
|
||||
|
||||
if (verbose >= 2) {
|
||||
fputs("overlapping maps:\n", stderr);
|
||||
map__fprintf(map, stderr);
|
||||
map__fprintf(pos, stderr);
|
||||
}
|
||||
|
||||
rb_erase(&pos->rb_node, root);
|
||||
/*
|
||||
* We may have references to this map, for instance in some
|
||||
* hist_entry instances, so just move them to a separate
|
||||
* list.
|
||||
*/
|
||||
list_add_tail(&pos->node, &self->removed_maps[map->type]);
|
||||
/*
|
||||
* Now check if we need to create new maps for areas not
|
||||
* overlapped by the new map:
|
||||
*/
|
||||
if (map->start > pos->start) {
|
||||
struct map *before = map__clone(pos);
|
||||
|
||||
if (before == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
before->end = map->start - 1;
|
||||
map_groups__insert(self, before);
|
||||
if (verbose >= 2)
|
||||
map__fprintf(before, stderr);
|
||||
}
|
||||
|
||||
if (map->end < pos->end) {
|
||||
struct map *after = map__clone(pos);
|
||||
|
||||
if (after == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
after->start = map->end + 1;
|
||||
map_groups__insert(self, after);
|
||||
if (verbose >= 2)
|
||||
map__fprintf(after, stderr);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void thread__insert_map(struct thread *self, struct map *map)
|
||||
{
|
||||
map_groups__fixup_overlappings(&self->mg, map);
|
||||
map_groups__fixup_overlappings(&self->mg, map, verbose, stderr);
|
||||
map_groups__insert(&self->mg, map);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX This should not really _copy_ te maps, but refcount them.
|
||||
*/
|
||||
static int map_groups__clone(struct map_groups *self,
|
||||
struct map_groups *parent, enum map_type type)
|
||||
{
|
||||
struct rb_node *nd;
|
||||
for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) {
|
||||
struct map *map = rb_entry(nd, struct map, rb_node);
|
||||
struct map *new = map__clone(map);
|
||||
if (new == NULL)
|
||||
return -ENOMEM;
|
||||
map_groups__insert(self, new);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int thread__fork(struct thread *self, struct thread *parent)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -42,12 +42,14 @@
|
|||
#define _ALL_SOURCE 1
|
||||
#define _GNU_SOURCE 1
|
||||
#define _BSD_SOURCE 1
|
||||
#define HAS_BOOL
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statfs.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -78,6 +80,7 @@
|
|||
#include <pwd.h>
|
||||
#include <inttypes.h>
|
||||
#include "../../../include/linux/magic.h"
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#ifndef NO_ICONV
|
||||
|
@ -415,4 +418,13 @@ void git_qsort(void *base, size_t nmemb, size_t size,
|
|||
int mkdir_p(char *path, mode_t mode);
|
||||
int copyfile(const char *from, const char *to);
|
||||
|
||||
s64 perf_atoll(const char *str);
|
||||
char **argv_split(const char *str, int *argcp);
|
||||
void argv_free(char **argv);
|
||||
bool strglobmatch(const char *str, const char *pat);
|
||||
bool strlazymatch(const char *str, const char *pat);
|
||||
|
||||
#define _STR(x) #x
|
||||
#define STR(x) _STR(x)
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue