diff options
Diffstat (limited to 'tools')
53 files changed, 2393 insertions, 1458 deletions
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore index fe08660ce0b..124760bb37b 100644 --- a/tools/perf/.gitignore +++ b/tools/perf/.gitignore @@ -13,6 +13,7 @@ perf*.xml perf*.html common-cmds.h perf.data +perf.data.old tags TAGS cscope* diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt new file mode 100644 index 00000000000..8974e208cba --- /dev/null +++ b/tools/perf/Documentation/perf-diff.txt @@ -0,0 +1,55 @@ +perf-diff(1) +============== + +NAME +---- +perf-diff - Read two perf.data files and display the differential profile + +SYNOPSIS +-------- +[verse] +'perf diff' [oldfile] [newfile] + +DESCRIPTION +----------- +This command displays the performance difference amongst two perf.data files +captured via perf record. + +If no parameters are passed it will assume perf.data.old and perf.data. + +OPTIONS +------- +-d:: +--dsos=:: + Only consider symbols in these dsos. CSV that understands + file://filename entries. + +-C:: +--comms=:: + Only consider symbols in these comms. CSV that understands + file://filename entries. + +-S:: +--symbols=:: + Only consider these symbols. CSV that understands + file://filename entries. + +-s:: +--sort=:: + Sort by key(s): pid, comm, dso, symbol. + +-t:: +--field-separator=:: + + Use a special separator character and don't pad with spaces, replacing + all occurances of this separator in symbol names (and other output) + with a '.' character, that thus it's the only non valid separator. + +-v:: +--verbose:: + Be verbose, for instance, show the raw counts in addition to the + diff. + +SEE ALSO +-------- +linkperf:perf-record[1] diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 8fa6bf99fcb..250e391b4bc 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt @@ -49,8 +49,9 @@ PROBE SYNTAX ------------ Probe points are defined by following syntax. - "FUNC[+OFFS|:RLN|%return][@SRC]|SRC:ALN [ARG ...]" + "[EVENT=]FUNC[+OFFS|:RLN|%return][@SRC]|SRC:ALN [ARG ...]" +'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. Currently, event group name is set as 'probe'. 'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, 'RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. In addition, 'SRC' specifies a source file which has that function. It is also possible to specify a probe point by the source line number by using 'SRC:ALN' syntax, where 'SRC' is the source file path and 'ALN' is the line number. 'ARG' specifies the arguments of this probe point. You can use the name of local variable, or kprobe-tracer argument format (e.g. $retval, %ax, etc). diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 9dccb180b7a..abfabe9147a 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -39,6 +39,10 @@ OPTIONS Only consider these symbols. CSV that understands file://filename entries. +-s:: +--sort=:: + Sort by key(s): pid, comm, dso, symbol, parent. + -w:: --field-width=:: Force each column width to the provided list, for large terminal diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 07065efa60e..60e5900da48 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -8,18 +8,43 @@ perf-trace - Read perf.data (created by perf record) and display trace output SYNOPSIS -------- [verse] -'perf trace' [-i <file> | --input=file] symbol_name +'perf trace' {record <script> | report <script> [args] } DESCRIPTION ----------- This command reads the input file and displays the trace recorded. +There are several variants of perf trace: + + 'perf trace' to see a detailed trace of the workload that was + recorded. + + 'perf trace record <script>' to record the events required for 'perf + trace report'. <script> is the name displayed in the output of + 'perf trace --list' i.e. the actual script name minus any language + extension. + + 'perf trace report <script>' to run and display the results of + <script>. <script> is the name displayed in the output of 'perf + trace --list' i.e. the actual script name minus any language + extension. The perf.data output from a previous run of 'perf trace + record <script>' is used and should be present for this command to + succeed. + OPTIONS ------- -D:: --dump-raw-trace=:: Display verbose dump of the trace data. +-L:: +--Latency=:: + Show latency attributes (irqs/preemption disabled, etc). + +-l:: +--list=:: + Display a list of available trace scripts. + -s:: --script=:: Process trace data with the given script ([lang]:script[.ext]). diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 406999668ca..2e7fa3a0680 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -250,7 +250,19 @@ PTHREAD_LIBS = -lpthread # explicitly what architecture to check for. Fix this up for yours.. SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ -ifeq ($(shell sh -c "echo 'int foo(void) {char X[2]; return 3;}' | $(CC) -x c -c -Werror -fstack-protector-all - -o /dev/null "$(QUIET_STDERR)" && echo y"), y) +ifeq ($(V), 2) + QUIET_STDERR = ">/dev/null" +else + QUIET_STDERR = ">/dev/null 2>&1" +endif + +BITBUCKET = "/dev/null" + +ifneq ($(shell sh -c "(echo '\#include <stdio.h>'; echo 'int main(void) { return puts(\"hi\"); }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) "$(QUIET_STDERR)" && echo y"), y) + BITBUCKET = .perf.dev.null +endif + +ifeq ($(shell sh -c "echo 'int foo(void) {char X[2]; return 3;}' | $(CC) -x c -c -Werror -fstack-protector-all - -o $(BITBUCKET) "$(QUIET_STDERR)" && echo y"), y) CFLAGS := $(CFLAGS) -fstack-protector-all endif @@ -343,13 +355,18 @@ LIB_H += util/include/linux/string.h LIB_H += util/include/linux/types.h LIB_H += util/include/asm/asm-offsets.h LIB_H += util/include/asm/bitops.h +LIB_H += util/include/asm/bug.h LIB_H += util/include/asm/byteorder.h LIB_H += util/include/asm/swab.h LIB_H += util/include/asm/system.h LIB_H += util/include/asm/uaccess.h LIB_H += perf.h +LIB_H += util/cache.h +LIB_H += util/callchain.h +LIB_H += util/debug.h LIB_H += util/debugfs.h LIB_H += util/event.h +LIB_H += util/exec_cmd.h LIB_H += util/types.h LIB_H += util/levenshtein.h LIB_H += util/parse-options.h @@ -362,6 +379,7 @@ 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 LIB_H += util/sigchain.h LIB_H += util/symbol.h @@ -370,7 +388,8 @@ LIB_H += util/values.h LIB_H += util/sort.h LIB_H += util/hist.h LIB_H += util/thread.h -LIB_H += util/data_map.h +LIB_H += util/trace-event.h +LIB_H += util/trace-event-perl.h LIB_H += util/probe-finder.h LIB_H += util/probe-event.h @@ -428,6 +447,7 @@ BUILTIN_OBJS += bench/sched-messaging.o BUILTIN_OBJS += bench/sched-pipe.o BUILTIN_OBJS += 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 @@ -443,11 +463,6 @@ BUILTIN_OBJS += builtin-kmem.o PERFLIBS = $(LIB_FILE) -ifeq ($(V), 2) - QUIET_STDERR = ">/dev/null" -else - QUIET_STDERR = ">/dev/null 2>&1" -endif # # Platform specific tweaks # @@ -475,22 +490,23 @@ ifeq ($(uname_S),Darwin) PTHREAD_LIBS = 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 /dev/null $(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 /dev/null $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) +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); endif - ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) + ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 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) BASIC_CFLAGS += -DLIBELF_NO_MMAP endif else msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]); endif -ifneq ($(shell sh -c "(echo '\#include <libdwarf/dwarf.h>'; echo '\#include <libdwarf/libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; Dwarf_Ranges *rng; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); dwarf_get_ranges(dbg, 0, &rng, 0, 0, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -ldwarf -lelf -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) +ifneq ($(shell sh -c "(echo '\#ifndef _MIPS_SZLONG'; echo '\#define _MIPS_SZLONG 0'; echo '\#endif'; echo '\#include <dwarf.h>'; echo '\#include <libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; Dwarf_Ranges *rng; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); dwarf_get_ranges(dbg, 0, &rng, 0, 0, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/libdwarf -ldwarf -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) msg := $(warning No libdwarf.h found or old libdwarf.h found, disables dwarf support. Please install libdwarf-dev/libdwarf-devel >= 20081231); BASIC_CFLAGS += -DNO_LIBDWARF else + BASIC_CFLAGS += -I/usr/include/libdwarf EXTLIBS += -lelf -ldwarf LIB_OBJS += util/probe-finder.o endif @@ -500,7 +516,7 @@ PERL_EMBED_LDOPTS = `perl -MExtUtils::Embed -e ldopts 2>/dev/null` PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` endif -ifneq ($(shell sh -c "(echo '\#include <EXTERN.h>'; echo '\#include <perl.h>'; echo 'int main(void) { perl_alloc(); return 0; }') | $(CC) -x c - $(PERL_EMBED_CCOPTS) -o /dev/null $(PERL_EMBED_LDOPTS) > /dev/null 2>&1 && echo y"), y) +ifneq ($(shell sh -c "(echo '\#include <EXTERN.h>'; echo '\#include <perl.h>'; echo 'int main(void) { perl_alloc(); return 0; }') | $(CC) -x c - $(PERL_EMBED_CCOPTS) -o $(BITBUCKET) $(PERL_EMBED_LDOPTS) > /dev/null 2>&1 && echo y"), y) BASIC_CFLAGS += -DNO_LIBPERL else ALL_LDFLAGS += $(PERL_EMBED_LDOPTS) @@ -510,20 +526,20 @@ endif ifdef NO_DEMANGLE BASIC_CFLAGS += -DNO_DEMANGLE else - has_bfd := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) -lbfd "$(QUIET_STDERR)" && echo y") + has_bfd := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd "$(QUIET_STDERR)" && echo y") ifeq ($(has_bfd),y) EXTLIBS += -lbfd else - has_bfd_iberty := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) -lbfd -liberty "$(QUIET_STDERR)" && echo y") + has_bfd_iberty := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd -liberty "$(QUIET_STDERR)" && echo y") ifeq ($(has_bfd_iberty),y) EXTLIBS += -lbfd -liberty else - has_bfd_iberty_z := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) -lbfd -liberty -lz "$(QUIET_STDERR)" && echo y") + has_bfd_iberty_z := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd -liberty -lz "$(QUIET_STDERR)" && echo y") ifeq ($(has_bfd_iberty_z),y) EXTLIBS += -lbfd -liberty -lz else - has_cplus_demangle := $(shell sh -c "(echo 'extern char *cplus_demangle(const char *, int);'; echo 'int main(void) { cplus_demangle(0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) -liberty "$(QUIET_STDERR)" && echo y") + has_cplus_demangle := $(shell sh -c "(echo 'extern char *cplus_demangle(const char *, int);'; echo 'int main(void) { cplus_demangle(0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -liberty "$(QUIET_STDERR)" && echo y") ifeq ($(has_cplus_demangle),y) EXTLIBS += -liberty BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE @@ -771,7 +787,7 @@ export TAR INSTALL DESTDIR SHELL_PATH SHELL = $(SHELL_PATH) -all:: 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) 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 @@ -996,8 +1012,6 @@ install: all $(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' - $(INSTALL) scripts/perl/Perf-Trace-Util/Makefile.PL -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util' - $(INSTALL) scripts/perl/Perf-Trace-Util/README -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util' ifdef BUILT_INS $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' $(INSTALL) $(BUILT_INS) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' @@ -1100,6 +1114,11 @@ clean: .PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS .PHONY: .FORCE-PERF-BUILD-OPTIONS +.perf.dev.null: + touch .perf.dev.null + +.INTERMEDIATE: .perf.dev.null + ### Make sure built-ins do not have dups and listed in perf.c # check-builtins:: diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 21a78d30d53..593ff25006d 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -26,7 +26,6 @@ #include "util/sort.h" #include "util/hist.h" #include "util/session.h" -#include "util/data_map.h" static char const *input_name = "perf.data"; @@ -52,11 +51,6 @@ struct sym_priv { struct sym_ext *ext; }; -static struct symbol_conf symbol_conf = { - .priv_size = sizeof(struct sym_priv), - .try_vmlinux_path = true, -}; - static const char *sym_hist_filter; static int symbol_filter(struct map *map __used, struct symbol *sym) @@ -122,30 +116,32 @@ static void hist_hit(struct hist_entry *he, u64 ip) h->ip[offset]); } -static int hist_entry__add(struct addr_location *al, u64 count) +static int perf_session__add_hist_entry(struct perf_session *self, + struct addr_location *al, u64 count) { bool hit; - struct hist_entry *he = __hist_entry__add(al, NULL, count, &hit); + struct hist_entry *he = __perf_session__add_hist_entry(self, al, NULL, + count, &hit); if (he == NULL) return -ENOMEM; hist_hit(he, al->addr); return 0; } -static int process_sample_event(event_t *event) +static int process_sample_event(event_t *event, struct perf_session *session) { struct addr_location al; dump_printf("(IP, %d): %d: %p\n", event->header.misc, event->ip.pid, (void *)(long)event->ip.ip); - if (event__preprocess_sample(event, &al, symbol_filter) < 0) { + if (event__preprocess_sample(event, session, &al, symbol_filter) < 0) { fprintf(stderr, "problem processing %d event, skipping it.\n", event->header.type); return -1; } - if (hist_entry__add(&al, 1)) { + if (!al.filtered && perf_session__add_hist_entry(session, &al, 1)) { fprintf(stderr, "problem incrementing symbol count, " "skipping event\n"); return -1; @@ -429,11 +425,11 @@ static void annotate_sym(struct hist_entry *he) free_source_line(he, len); } -static void find_annotations(void) +static void perf_session__find_annotations(struct perf_session *self) { struct rb_node *nd; - for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) { + for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) { struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); struct sym_priv *priv; @@ -454,7 +450,7 @@ static void find_annotations(void) } } -static struct perf_file_handler file_handler = { +static struct perf_event_ops event_ops = { .process_sample_event = process_sample_event, .process_mmap_event = event__process_mmap, .process_comm_event = event__process_comm, @@ -463,17 +459,14 @@ static struct perf_file_handler file_handler = { static int __cmd_annotate(void) { - struct perf_session *session = perf_session__new(input_name, O_RDONLY, force); - struct thread *idle; int ret; + struct perf_session *session; + session = perf_session__new(input_name, O_RDONLY, force); if (session == NULL) return -ENOMEM; - idle = register_idle_thread(); - register_perf_file_handler(&file_handler); - - ret = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd); + ret = perf_session__process_events(session, &event_ops); if (ret) goto out_delete; @@ -483,15 +476,14 @@ static int __cmd_annotate(void) } if (verbose > 3) - threads__fprintf(stdout); + perf_session__fprintf(session, stdout); if (verbose > 2) dsos__fprintf(stdout); - collapse__resort(); - output__resort(event__total[0]); - - find_annotations(); + perf_session__collapse_resort(session); + perf_session__output_resort(session, session->event_total[0]); + perf_session__find_annotations(session); out_delete: perf_session__delete(session); @@ -524,29 +516,17 @@ static const struct option options[] = { OPT_END() }; -static void setup_sorting(void) +int cmd_annotate(int argc, const char **argv, const char *prefix __used) { - char *tmp, *tok, *str = strdup(sort_order); - - for (tok = strtok_r(str, ", ", &tmp); - tok; tok = strtok_r(NULL, ", ", &tmp)) { - if (sort_dimension__add(tok) < 0) { - error("Unknown --sort key: `%s'", tok); - usage_with_options(annotate_usage, options); - } - } + argc = parse_options(argc, argv, options, annotate_usage, 0); - free(str); -} + symbol_conf.priv_size = sizeof(struct sym_priv); + symbol_conf.try_vmlinux_path = true; -int cmd_annotate(int argc, const char **argv, const char *prefix __used) -{ - if (symbol__init(&symbol_conf) < 0) + if (symbol__init() < 0) return -1; - argc = parse_options(argc, argv, options, annotate_usage, 0); - - setup_sorting(); + setup_sorting(annotate_usage, options); if (argc) { /* diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index bfd16a1594e..1e99ac80691 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c @@ -9,7 +9,6 @@ #include "builtin.h" #include "perf.h" #include "util/cache.h" -#include "util/data_map.h" #include "util/debug.h" #include "util/parse-options.h" #include "util/session.h" @@ -18,7 +17,7 @@ static char const *input_name = "perf.data"; static int force; -static const char *const buildid_list_usage[] = { +static const char * const buildid_list_usage[] = { "perf buildid-list [<options>]", NULL }; @@ -55,8 +54,9 @@ static int perf_file_section__process_buildids(struct perf_file_section *self, static int __cmd_buildid_list(void) { int err = -1; - struct perf_session *session = perf_session__new(input_name, O_RDONLY, force); + struct perf_session *session; + session = perf_session__new(input_name, O_RDONLY, force); if (session == NULL) return -1; diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c new file mode 100644 index 00000000000..bd71b8ceafb --- /dev/null +++ b/tools/perf/builtin-diff.c @@ -0,0 +1,249 @@ +/* + * builtin-diff.c + * + * Builtin diff command: Analyze two perf.data input files, look up and read + * DSOs and symbol information, sort them and produce a diff. + */ +#include "builtin.h" + +#include "util/debug.h" +#include "util/event.h" +#include "util/hist.h" +#include "util/session.h" +#include "util/sort.h" +#include "util/symbol.h" +#include "util/util.h" + +#include <stdlib.h> + +static char const *input_old = "perf.data.old", + *input_new = "perf.data"; +static char diff__default_sort_order[] = "dso,symbol"; +static int force; +static bool show_displacement; + +static int perf_session__add_hist_entry(struct perf_session *self, + struct addr_location *al, u64 count) +{ + bool hit; + struct hist_entry *he = __perf_session__add_hist_entry(self, al, NULL, + count, &hit); + if (he == NULL) + return -ENOMEM; + + if (hit) + he->count += count; + + return 0; +} + +static int diff__process_sample_event(event_t *event, struct perf_session *session) +{ + struct addr_location al; + struct sample_data data = { .period = 1, }; + + dump_printf("(IP, %d): %d: %p\n", event->header.misc, + event->ip.pid, (void *)(long)event->ip.ip); + + if (event__preprocess_sample(event, session, &al, NULL) < 0) { + pr_warning("problem processing %d event, skipping it.\n", + event->header.type); + return -1; + } + + if (al.filtered) + return 0; + + event__parse_sample(event, session->sample_type, &data); + + if (al.sym && perf_session__add_hist_entry(session, &al, data.period)) { + pr_warning("problem incrementing symbol count, skipping event\n"); + return -1; + } + + session->events_stats.total += data.period; + return 0; +} + +static struct perf_event_ops event_ops = { + .process_sample_event = diff__process_sample_event, + .process_mmap_event = event__process |