aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-record.txt60
-rw-r--r--tools/perf/Documentation/perf-report.txt15
-rw-r--r--tools/perf/Makefile49
-rw-r--r--tools/perf/builtin-annotate.c93
-rw-r--r--tools/perf/builtin-help.c6
-rw-r--r--tools/perf/builtin-list.c2
-rw-r--r--tools/perf/builtin-record.c18
-rw-r--r--tools/perf/builtin-report.c652
-rw-r--r--tools/perf/builtin-stat.c54
-rw-r--r--tools/perf/builtin-top.c77
-rw-r--r--tools/perf/perf.c82
-rw-r--r--tools/perf/perf.h10
-rw-r--r--tools/perf/util/alias.c2
-rw-r--r--tools/perf/util/cache.h2
-rw-r--r--tools/perf/util/callchain.c255
-rw-r--r--tools/perf/util/callchain.h41
-rw-r--r--tools/perf/util/color.c37
-rw-r--r--tools/perf/util/color.h5
-rw-r--r--tools/perf/util/config.c18
-rw-r--r--tools/perf/util/exec_cmd.c5
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/help.c26
-rw-r--r--tools/perf/util/help.h6
-rw-r--r--tools/perf/util/include/asm/system.h1
-rw-r--r--tools/perf/util/include/linux/kernel.h29
-rw-r--r--tools/perf/util/include/linux/list.h18
-rw-r--r--tools/perf/util/include/linux/module.h6
-rw-r--r--tools/perf/util/include/linux/poison.h1
-rw-r--r--tools/perf/util/include/linux/prefetch.h6
-rw-r--r--tools/perf/util/include/linux/rbtree.h1
-rw-r--r--tools/perf/util/list.h603
-rw-r--r--tools/perf/util/module.c509
-rw-r--r--tools/perf/util/module.h53
-rw-r--r--tools/perf/util/parse-events.c431
-rw-r--r--tools/perf/util/parse-events.h5
-rw-r--r--tools/perf/util/parse-options.c5
-rw-r--r--tools/perf/util/parse-options.h27
-rw-r--r--tools/perf/util/quote.c48
-rw-r--r--tools/perf/util/quote.h2
-rw-r--r--tools/perf/util/rbtree.c383
-rw-r--r--tools/perf/util/rbtree.h171
-rw-r--r--tools/perf/util/strbuf.c13
-rw-r--r--tools/perf/util/strbuf.h10
-rw-r--r--tools/perf/util/string.h3
-rw-r--r--tools/perf/util/strlist.c20
-rw-r--r--tools/perf/util/strlist.h13
-rw-r--r--tools/perf/util/symbol.c405
-rw-r--r--tools/perf/util/symbol.h12
-rw-r--r--tools/perf/util/util.h2
-rw-r--r--tools/perf/util/wrapper.c5
50 files changed, 2546 insertions, 1753 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 1dbc1eeb4c01..6be696b0a2bb 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -29,13 +29,67 @@ OPTIONS
29 Select the PMU event. Selection can be a symbolic event name 29 Select the PMU event. Selection can be a symbolic event name
30 (use 'perf list' to list all events) or a raw PMU 30 (use 'perf list' to list all events) or a raw PMU
31 event (eventsel+umask) in the form of rNNN where NNN is a 31 event (eventsel+umask) in the form of rNNN where NNN is a
32 hexadecimal event descriptor. 32 hexadecimal event descriptor.
33 33
34-a:: 34-a::
35 system-wide collection 35 System-wide collection.
36 36
37-l:: 37-l::
38 scale counter values 38 Scale counter values.
39
40-p::
41--pid=::
42 Record events on existing pid.
43
44-r::
45--realtime=::
46 Collect data with this RT SCHED_FIFO priority.
47-A::
48--append::
49 Append to the output file to do incremental profiling.
50
51-f::
52--force::
53 Overwrite existing data file.
54
55-c::
56--count=::
57 Event period to sample.
58
59-o::
60--output=::
61 Output file name.
62
63-i::
64--inherit::
65 Child tasks inherit counters.
66-F::
67--freq=::
68 Profile at this frequency.
69
70-m::
71--mmap-pages=::
72 Number of mmap data pages.
73
74-g::
75--call-graph::
76 Do call-graph (stack chain/backtrace) recording.
77
78-v::
79--verbose::
80 Be more verbose (show counter open errors, etc).
81
82-s::
83--stat::
84 Per thread counts.
85
86-d::
87--data::
88 Sample addresses.
89
90-n::
91--no-samples::
92 Don't sample.
39 93
40SEE ALSO 94SEE ALSO
41-------- 95--------
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 8aa3f8c88707..e72e93110782 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -24,6 +24,9 @@ OPTIONS
24--dsos=:: 24--dsos=::
25 Only consider symbols in these dsos. CSV that understands 25 Only consider symbols in these dsos. CSV that understands
26 file://filename entries. 26 file://filename entries.
27-n
28--show-nr-samples
29 Show the number of samples for each symbol
27-C:: 30-C::
28--comms=:: 31--comms=::
29 Only consider symbols in these comms. CSV that understands 32 Only consider symbols in these comms. CSV that understands
@@ -33,6 +36,18 @@ OPTIONS
33 Only consider these symbols. CSV that understands 36 Only consider these symbols. CSV that understands
34 file://filename entries. 37 file://filename entries.
35 38
39-w::
40--field-width=::
41 Force each column width to the provided list, for large terminal
42 readability.
43
44-t::
45--field-separator=::
46
47 Use a special separator character and don't pad with spaces, replacing
48 all occurances of this separator in symbol names (and other output)
49 with a '.' character, that thus it's the only non valid separator.
50
36SEE ALSO 51SEE ALSO
37-------- 52--------
38linkperf:perf-stat[1] 53linkperf:perf-stat[1]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 9c6d0ae3708e..1916e44b9bb0 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -158,13 +158,15 @@ uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
158uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not') 158uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
159 159
160# If we're on a 64-bit kernel, use -m64 160# If we're on a 64-bit kernel, use -m64
161ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M)) 161ifndef NO_64BIT
162 M64 := -m64 162 ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M))
163 M64 := -m64
164 endif
163endif 165endif
164 166
165# CFLAGS and LDFLAGS are for the users to override from the command line. 167# CFLAGS and LDFLAGS are for the users to override from the command line.
166 168
167CFLAGS = $(M64) -ggdb3 -Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6 169CFLAGS = $(M64) -ggdb3 -Wall -Wextra -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6
168LDFLAGS = -lpthread -lrt -lelf -lm 170LDFLAGS = -lpthread -lrt -lelf -lm
169ALL_CFLAGS = $(CFLAGS) 171ALL_CFLAGS = $(CFLAGS)
170ALL_LDFLAGS = $(LDFLAGS) 172ALL_LDFLAGS = $(LDFLAGS)
@@ -223,7 +225,7 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
223# Those must not be GNU-specific; they are shared with perl/ which may 225# Those must not be GNU-specific; they are shared with perl/ which may
224# be built by a different compiler. (Note that this is an artifact now 226# be built by a different compiler. (Note that this is an artifact now
225# but it still might be nice to keep that distinction.) 227# but it still might be nice to keep that distinction.)
226BASIC_CFLAGS = 228BASIC_CFLAGS = -Iutil/include
227BASIC_LDFLAGS = 229BASIC_LDFLAGS =
228 230
229# Guard against environment variables 231# Guard against environment variables
@@ -289,10 +291,11 @@ export PERL_PATH
289LIB_FILE=libperf.a 291LIB_FILE=libperf.a
290 292
291LIB_H += ../../include/linux/perf_counter.h 293LIB_H += ../../include/linux/perf_counter.h
294LIB_H += ../../include/linux/rbtree.h
295LIB_H += ../../include/linux/list.h
296LIB_H += util/include/linux/list.h
292LIB_H += perf.h 297LIB_H += perf.h
293LIB_H += util/types.h 298LIB_H += util/types.h
294LIB_H += util/list.h
295LIB_H += util/rbtree.h
296LIB_H += util/levenshtein.h 299LIB_H += util/levenshtein.h
297LIB_H += util/parse-options.h 300LIB_H += util/parse-options.h
298LIB_H += util/parse-events.h 301LIB_H += util/parse-events.h
@@ -305,6 +308,7 @@ LIB_H += util/strlist.h
305LIB_H += util/run-command.h 308LIB_H += util/run-command.h
306LIB_H += util/sigchain.h 309LIB_H += util/sigchain.h
307LIB_H += util/symbol.h 310LIB_H += util/symbol.h
311LIB_H += util/module.h
308LIB_H += util/color.h 312LIB_H += util/color.h
309 313
310LIB_OBJS += util/abspath.o 314LIB_OBJS += util/abspath.o
@@ -328,6 +332,7 @@ LIB_OBJS += util/usage.o
328LIB_OBJS += util/wrapper.o 332LIB_OBJS += util/wrapper.o
329LIB_OBJS += util/sigchain.o 333LIB_OBJS += util/sigchain.o
330LIB_OBJS += util/symbol.o 334LIB_OBJS += util/symbol.o
335LIB_OBJS += util/module.o
331LIB_OBJS += util/color.o 336LIB_OBJS += util/color.o
332LIB_OBJS += util/pager.o 337LIB_OBJS += util/pager.o
333LIB_OBJS += util/header.o 338LIB_OBJS += util/header.o
@@ -342,7 +347,6 @@ BUILTIN_OBJS += builtin-stat.o
342BUILTIN_OBJS += builtin-top.o 347BUILTIN_OBJS += builtin-top.o
343 348
344PERFLIBS = $(LIB_FILE) 349PERFLIBS = $(LIB_FILE)
345EXTLIBS =
346 350
347# 351#
348# Platform specific tweaks 352# Platform specific tweaks
@@ -371,6 +375,28 @@ ifeq ($(uname_S),Darwin)
371 PTHREAD_LIBS = 375 PTHREAD_LIBS =
372endif 376endif
373 377
378ifneq ($(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) > /dev/null 2>&1 && echo y"), y)
379 msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel);
380endif
381
382ifdef NO_DEMANGLE
383 BASIC_CFLAGS += -DNO_DEMANGLE
384else
385
386 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) -lbfd > /dev/null 2>&1 && echo y")
387
388 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) -lbfd -liberty > /dev/null 2>&1 && echo y")
389
390 ifeq ($(has_bfd),y)
391 EXTLIBS += -lbfd
392 else ifeq ($(has_bfd_iberty),y)
393 EXTLIBS += -lbfd -liberty
394 else
395 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el] to gain symbol demangling)
396 BASIC_CFLAGS += -DNO_DEMANGLE
397 endif
398endif
399
374ifndef CC_LD_DYNPATH 400ifndef CC_LD_DYNPATH
375 ifdef NO_R_TO_GCC_LINKER 401 ifdef NO_R_TO_GCC_LINKER
376 # Some gcc does not accept and pass -R to the linker to specify 402 # Some gcc does not accept and pass -R to the linker to specify
@@ -381,12 +407,6 @@ ifndef CC_LD_DYNPATH
381 endif 407 endif
382endif 408endif
383 409
384ifdef ZLIB_PATH
385 BASIC_CFLAGS += -I$(ZLIB_PATH)/include
386 EXTLIBS += -L$(ZLIB_PATH)/$(lib) $(CC_LD_DYNPATH)$(ZLIB_PATH)/$(lib)
387endif
388EXTLIBS += -lz
389
390ifdef NEEDS_SOCKET 410ifdef NEEDS_SOCKET
391 EXTLIBS += -lsocket 411 EXTLIBS += -lsocket
392endif 412endif
@@ -697,6 +717,9 @@ builtin-init-db.o: builtin-init-db.c PERF-CFLAGS
697util/config.o: util/config.c PERF-CFLAGS 717util/config.o: util/config.c PERF-CFLAGS
698 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 718 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
699 719
720util/rbtree.o: ../../lib/rbtree.c PERF-CFLAGS
721 $(QUIET_CC)$(CC) -o util/rbtree.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
722
700perf-%$X: %.o $(PERFLIBS) 723perf-%$X: %.o $(PERFLIBS)
701 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) 724 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
702 725
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 722c0f54e549..1dba568e1941 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -10,9 +10,9 @@
10#include "util/util.h" 10#include "util/util.h"
11 11
12#include "util/color.h" 12#include "util/color.h"
13#include "util/list.h" 13#include <linux/list.h>
14#include "util/cache.h" 14#include "util/cache.h"
15#include "util/rbtree.h" 15#include <linux/rbtree.h>
16#include "util/symbol.h" 16#include "util/symbol.h"
17#include "util/string.h" 17#include "util/string.h"
18 18
@@ -25,10 +25,6 @@
25#define SHOW_USER 2 25#define SHOW_USER 2
26#define SHOW_HV 4 26#define SHOW_HV 4
27 27
28#define MIN_GREEN 0.5
29#define MIN_RED 5.0
30
31
32static char const *input_name = "perf.data"; 28static char const *input_name = "perf.data";
33static char *vmlinux = "vmlinux"; 29static char *vmlinux = "vmlinux";
34 30
@@ -43,6 +39,10 @@ static int dump_trace = 0;
43 39
44static int verbose; 40static int verbose;
45 41
42static int modules;
43
44static int full_paths;
45
46static int print_line; 46static int print_line;
47 47
48static unsigned long page_size; 48static unsigned long page_size;
@@ -74,20 +74,12 @@ struct fork_event {
74 u32 pid, ppid; 74 u32 pid, ppid;
75}; 75};
76 76
77struct period_event {
78 struct perf_event_header header;
79 u64 time;
80 u64 id;
81 u64 sample_period;
82};
83
84typedef union event_union { 77typedef union event_union {
85 struct perf_event_header header; 78 struct perf_event_header header;
86 struct ip_event ip; 79 struct ip_event ip;
87 struct mmap_event mmap; 80 struct mmap_event mmap;
88 struct comm_event comm; 81 struct comm_event comm;
89 struct fork_event fork; 82 struct fork_event fork;
90 struct period_event period;
91} event_t; 83} event_t;
92 84
93 85
@@ -160,7 +152,7 @@ static void dsos__fprintf(FILE *fp)
160 152
161static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 153static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
162{ 154{
163 return dso__find_symbol(kernel_dso, ip); 155 return dso__find_symbol(dso, ip);
164} 156}
165 157
166static int load_kernel(void) 158static int load_kernel(void)
@@ -171,8 +163,8 @@ static int load_kernel(void)
171 if (!kernel_dso) 163 if (!kernel_dso)
172 return -1; 164 return -1;
173 165
174 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); 166 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules);
175 if (err) { 167 if (err <= 0) {
176 dso__delete(kernel_dso); 168 dso__delete(kernel_dso);
177 kernel_dso = NULL; 169 kernel_dso = NULL;
178 } else 170 } else
@@ -203,7 +195,7 @@ static u64 map__map_ip(struct map *map, u64 ip)
203 return ip - map->start + map->pgoff; 195 return ip - map->start + map->pgoff;
204} 196}
205 197
206static u64 vdso__map_ip(struct map *map, u64 ip) 198static u64 vdso__map_ip(struct map *map __used, u64 ip)
207{ 199{
208 return ip; 200 return ip;
209} 201}
@@ -600,7 +592,7 @@ static LIST_HEAD(hist_entry__sort_list);
600 592
601static int sort_dimension__add(char *tok) 593static int sort_dimension__add(char *tok)
602{ 594{
603 int i; 595 unsigned int i;
604 596
605 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { 597 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
606 struct sort_dimension *sd = &sort_dimensions[i]; 598 struct sort_dimension *sd = &sort_dimensions[i];
@@ -998,19 +990,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
998} 990}
999 991
1000static int 992static int
1001process_period_event(event_t *event, unsigned long offset, unsigned long head)
1002{
1003 dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
1004 (void *)(offset + head),
1005 (void *)(long)(event->header.size),
1006 event->period.time,
1007 event->period.id,
1008 event->period.sample_period);
1009
1010 return 0;
1011}
1012
1013static int
1014process_event(event_t *event, unsigned long offset, unsigned long head) 993process_event(event_t *event, unsigned long offset, unsigned long head)
1015{ 994{
1016 switch (event->header.type) { 995 switch (event->header.type) {
@@ -1025,9 +1004,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1025 1004
1026 case PERF_EVENT_FORK: 1005 case PERF_EVENT_FORK:
1027 return process_fork_event(event, offset, head); 1006 return process_fork_event(event, offset, head);
1028
1029 case PERF_EVENT_PERIOD:
1030 return process_period_event(event, offset, head);
1031 /* 1007 /*
1032 * We dont process them right now but they are fine: 1008 * We dont process them right now but they are fine:
1033 */ 1009 */
@@ -1043,24 +1019,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1043 return 0; 1019 return 0;
1044} 1020}
1045 1021
1046static char *get_color(double percent)
1047{
1048 char *color = PERF_COLOR_NORMAL;
1049
1050 /*
1051 * We color high-overhead entries in red, mid-overhead
1052 * entries in green - and keep the low overhead places
1053 * normal:
1054 */
1055 if (percent >= MIN_RED)
1056 color = PERF_COLOR_RED;
1057 else {
1058 if (percent > MIN_GREEN)
1059 color = PERF_COLOR_GREEN;
1060 }
1061 return color;
1062}
1063
1064static int 1022static int
1065parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) 1023parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1066{ 1024{
@@ -1069,7 +1027,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1069 static const char *prev_color; 1027 static const char *prev_color;
1070 unsigned int offset; 1028 unsigned int offset;
1071 size_t line_len; 1029 size_t line_len;
1072 u64 line_ip; 1030 s64 line_ip;
1073 int ret; 1031 int ret;
1074 char *c; 1032 char *c;
1075 1033
@@ -1122,7 +1080,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1122 } else if (sym->hist_sum) 1080 } else if (sym->hist_sum)
1123 percent = 100.0 * hits / sym->hist_sum; 1081 percent = 100.0 * hits / sym->hist_sum;
1124 1082
1125 color = get_color(percent); 1083 color = get_percent_color(percent);
1126 1084
1127 /* 1085 /*
1128 * Also color the filename and line if needed, with 1086 * Also color the filename and line if needed, with
@@ -1258,7 +1216,7 @@ static void print_summary(char *filename)
1258 1216
1259 sym_ext = rb_entry(node, struct sym_ext, node); 1217 sym_ext = rb_entry(node, struct sym_ext, node);
1260 percent = sym_ext->percent; 1218 percent = sym_ext->percent;
1261 color = get_color(percent); 1219 color = get_percent_color(percent);
1262 path = sym_ext->path; 1220 path = sym_ext->path;
1263 1221
1264 color_fprintf(stdout, color, " %7.2f %s", percent, path); 1222 color_fprintf(stdout, color, " %7.2f %s", percent, path);
@@ -1268,19 +1226,25 @@ static void print_summary(char *filename)
1268 1226
1269static void annotate_sym(struct dso *dso, struct symbol *sym) 1227static void annotate_sym(struct dso *dso, struct symbol *sym)
1270{ 1228{
1271 char *filename = dso->name; 1229 char *filename = dso->name, *d_filename;
1272 u64 start, end, len; 1230 u64 start, end, len;
1273 char command[PATH_MAX*2]; 1231 char command[PATH_MAX*2];
1274 FILE *file; 1232 FILE *file;
1275 1233
1276 if (!filename) 1234 if (!filename)
1277 return; 1235 return;
1278 if (dso == kernel_dso) 1236 if (sym->module)
1237 filename = sym->module->path;
1238 else if (dso == kernel_dso)
1279 filename = vmlinux; 1239 filename = vmlinux;
1280 1240
1281 start = sym->obj_start; 1241 start = sym->obj_start;
1282 if (!start) 1242 if (!start)
1283 start = sym->start; 1243 start = sym->start;
1244 if (full_paths)
1245 d_filename = filename;
1246 else
1247 d_filename = basename(filename);
1284 1248
1285 end = start + sym->end - sym->start + 1; 1249 end = start + sym->end - sym->start + 1;
1286 len = sym->end - sym->start; 1250 len = sym->end - sym->start;
@@ -1291,13 +1255,14 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
1291 } 1255 }
1292 1256
1293 printf("\n\n------------------------------------------------\n"); 1257 printf("\n\n------------------------------------------------\n");
1294 printf(" Percent | Source code & Disassembly of %s\n", filename); 1258 printf(" Percent | Source code & Disassembly of %s\n", d_filename);
1295 printf("------------------------------------------------\n"); 1259 printf("------------------------------------------------\n");
1296 1260
1297 if (verbose >= 2) 1261 if (verbose >= 2)
1298 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 1262 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);
1299 1263
1300 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (u64)start, (u64)end, filename); 1264 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
1265 (u64)start, (u64)end, filename, filename);
1301 1266
1302 if (verbose >= 3) 1267 if (verbose >= 3)
1303 printf("doing: %s\n", command); 1268 printf("doing: %s\n", command);
@@ -1428,7 +1393,7 @@ more:
1428 1393
1429 head += size; 1394 head += size;
1430 1395
1431 if (offset + head < stat.st_size) 1396 if (offset + head < (unsigned long)stat.st_size)
1432 goto more; 1397 goto more;
1433 1398
1434 rc = EXIT_SUCCESS; 1399 rc = EXIT_SUCCESS;
@@ -1472,8 +1437,12 @@ static const struct option options[] = {
1472 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1437 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1473 "dump raw trace in ASCII"), 1438 "dump raw trace in ASCII"),
1474 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1439 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1440 OPT_BOOLEAN('m', "modules", &modules,
1441 "load module symbols - WARNING: use only with -k and LIVE kernel"),
1475 OPT_BOOLEAN('l', "print-line", &print_line, 1442 OPT_BOOLEAN('l', "print-line", &print_line,
1476 "print matching source lines (may be slow)"), 1443 "print matching source lines (may be slow)"),
1444 OPT_BOOLEAN('P', "full-paths", &full_paths,
1445 "Don't shorten the displayed pathnames"),
1477 OPT_END() 1446 OPT_END()
1478}; 1447};
1479 1448
@@ -1492,7 +1461,7 @@ static void setup_sorting(void)
1492 free(str); 1461 free(str);
1493} 1462}
1494 1463
1495int cmd_annotate(int argc, const char **argv, const char *prefix) 1464int cmd_annotate(int argc, const char **argv, const char *prefix __used)
1496{ 1465{
1497 symbol__init(); 1466 symbol__init();
1498 1467
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 0f32dc3f3c4c..2599d86a733b 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Builtin help command 4 * Builtin help command
5 */ 5 */
6#include "perf.h"
6#include "util/cache.h" 7#include "util/cache.h"
7#include "builtin.h" 8#include "builtin.h"
8#include "util/exec_cmd.h" 9#include "util/exec_cmd.h"
@@ -277,7 +278,7 @@ static struct cmdnames main_cmds, other_cmds;
277 278
278void list_common_cmds_help(void) 279void list_common_cmds_help(void)
279{ 280{
280 int i, longest = 0; 281 unsigned int i, longest = 0;
281 282
282 for (i = 0; i < ARRAY_SIZE(common_cmds); i++) { 283 for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
283 if (longest < strlen(common_cmds[i].name)) 284 if (longest < strlen(common_cmds[i].name))
@@ -415,9 +416,10 @@ static void show_html_page(const char *perf_cmd)
415 open_html(page_path.buf); 416 open_html(page_path.buf);
416} 417}
417 418
418int cmd_help(int argc, const char **argv, const char *prefix) 419int cmd_help(int argc, const char **argv, const char *prefix __used)
419{ 420{
420 const char *alias; 421 const char *alias;
422
421 load_command_list("perf-", &main_cmds, &other_cmds); 423 load_command_list("perf-", &main_cmds, &other_cmds);
422 424
423 perf_config(perf_help_config, NULL); 425 perf_config(perf_help_config, NULL);
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index fe60e37c96ef..f990fa8a35c9 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -13,7 +13,7 @@
13#include "util/parse-options.h" 13#include "util/parse-options.h"
14#include "util/parse-events.h" 14#include "util/parse-events.h"
15 15
16int cmd_list(int argc, const char **argv, const char *prefix) 16int cmd_list(int argc __used, const char **argv __used, const char *prefix __used)
17{ 17{
18 print_events(); 18 print_events();
19 return 0; 19 return 0;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index d18546f37d7c..90c98082af10 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -43,6 +43,7 @@ static int call_graph = 0;
43static int verbose = 0; 43static int verbose = 0;
44static int inherit_stat = 0; 44static int inherit_stat = 0;
45static int no_samples = 0; 45static int no_samples = 0;
46static int sample_address = 0;
46 47
47static long samples; 48static long samples;
48static struct timeval last_read; 49static struct timeval last_read;
@@ -294,7 +295,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
294 while (1) { 295 while (1) {
295 char bf[BUFSIZ], *pbf = bf; 296 char bf[BUFSIZ], *pbf = bf;
296 struct mmap_event mmap_ev = { 297 struct mmap_event mmap_ev = {
297 .header.type = PERF_EVENT_MMAP, 298 .header = { .type = PERF_EVENT_MMAP },
298 }; 299 };
299 int n; 300 int n;
300 size_t size; 301 size_t size;
@@ -313,6 +314,10 @@ static void pid_synthesize_mmap_samples(pid_t pid)
313 if (*pbf == 'x') { /* vm_exec */ 314 if (*pbf == 'x') { /* vm_exec */
314 char *execname = strchr(bf, '/'); 315 char *execname = strchr(bf, '/');
315 316
317 /* Catch VDSO */
318 if (execname == NULL)
319 execname = strstr(bf, "[vdso]");
320
316 if (execname == NULL) 321 if (execname == NULL)
317 continue; 322 continue;
318 323
@@ -401,9 +406,13 @@ static void create_counter(int counter, int cpu, pid_t pid)
401 if (inherit_stat) 406 if (inherit_stat)
402 attr->inherit_stat = 1; 407 attr->inherit_stat = 1;
403 408
409 if (sample_address)
410 attr->sample_type |= PERF_SAMPLE_ADDR;
411
404 if (call_graph) 412 if (call_graph)
405 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 413 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
406 414
415
407 attr->mmap = track; 416 attr->mmap = track;
408 attr->comm = track; 417 attr->comm = track;
409 attr->inherit = (cpu < 0) && inherit; 418 attr->inherit = (cpu < 0) && inherit;
@@ -645,16 +654,19 @@ static const struct option options[] = {
645 "be more verbose (show counter open errors, etc)"), 654 "be more verbose (show counter open errors, etc)"),
646 OPT_BOOLEAN('s', "stat", &inherit_stat, 655 OPT_BOOLEAN('s', "stat", &inherit_stat,
647 "per thread counts"), 656 "per thread counts"),
657 OPT_BOOLEAN('d', "data", &sample_address,
658 "Sample addresses"),
648 OPT_BOOLEAN('n', "no-samples", &no_samples, 659 OPT_BOOLEAN('n', "no-samples", &no_samples,
649 "don't sample"), 660 "don't sample"),
650 OPT_END() 661 OPT_END()
651}; 662};
652 663
653int cmd_record(int argc, const char **argv, const char *prefix) 664int cmd_record(int argc, const char **argv, const char *prefix __used)
654{ 665{
655 int counter; 666 int counter;
656 667
657 argc = parse_options(argc, argv, options, record_usage, 0); 668 argc = parse_options(argc, argv, options, record_usage,
669 PARSE_OPT_STOP_AT_NON_OPTION);
658 if (!argc && target_pid == -1 && !system_wide) 670 if (!argc && target_pid == -1 && !system_wide)
659 usage_with_options(record_usage, options); 671 usage_with_options(record_usage, options);
660 672
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 135b7837e6bf..8cb58d68a006 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -10,9 +10,9 @@
10#include "util/util.h" 10#include "util/util.h"
11 11
12#include "util/color.h" 12#include "util/color.h"
13#include "util/list.h" 13#include <linux/list.h>
14#include "util/cache.h" 14#include "util/cache.h"
15#include "util/rbtree.h" 15#include <linux/rbtree.h>
16#include "util/symbol.h" 16#include "util/symbol.h"
17#include "util/string.h" 17#include "util/string.h"
18#include "util/callchain.h" 18#include "util/callchain.h"
@@ -31,10 +31,12 @@
31static char const *input_name = "perf.data"; 31static char const *input_name = "perf.data";
32static char *vmlinux = NULL; 32static char *vmlinux = NULL;
33 33
34static char default_sort_order[] = "comm,dso"; 34static char default_sort_order[] = "comm,dso,symbol";
35static char *sort_order = default_sort_order; 35static char *sort_order = default_sort_order;
36static char *dso_list_str, *comm_list_str, *sym_list_str; 36static char *dso_list_str, *comm_list_str, *sym_list_str,
37 *col_width_list_str;
37static struct strlist *dso_list, *comm_list, *sym_list; 38static struct strlist *dso_list, *comm_list, *sym_list;
39static char *field_sep;
38 40
39static int input; 41static int input;
40static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; 42static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -46,7 +48,10 @@ static int dump_trace = 0;
46static int verbose; 48static int verbose;
47#define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0) 49#define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0)
48 50
51static int modules;
52
49static int full_paths; 53static int full_paths;
54static int show_nr_samples;
50 55
51static unsigned long page_size; 56static unsigned long page_size;
52static unsigned long mmap_window = 32; 57static unsigned long mmap_window = 32;
@@ -56,8 +61,17 @@ static char *parent_pattern = default_parent_pattern;
56static regex_t parent_regex; 61static regex_t parent_regex;
57 62
58static int exclude_other = 1; 63static int exclude_other = 1;
64
65static char callchain_default_opt[] = "fractal,0.5";
66
59static int callchain; 67static int callchain;
60 68
69static
70struct callchain_param callchain_param = {
71 .mode = CHAIN_GRAPH_ABS,
72 .min_percent = 0.5
73};
74
61static u64 sample_type; 75static u64 sample_type;
62 76
63struct ip_event { 77struct ip_event {
@@ -85,13 +99,7 @@ struct comm_event {
85struct fork_event { 99struct fork_event {
86 struct perf_event_header header; 100 struct perf_event_header header;
87 u32 pid, ppid; 101 u32 pid, ppid;
88}; 102 u32 tid, ptid;
89
90struct period_event {
91 struct perf_event_header header;
92 u64 time;
93 u64 id;
94 u64 sample_period;
95}; 103};
96 104
97struct lost_event { 105struct lost_event {
@@ -113,14 +121,41 @@ typedef union event_union {
113 struct mmap_event mmap; 121 struct mmap_event mmap;
114 struct comm_event comm; 122 struct comm_event comm;
115 struct fork_event fork; 123 struct fork_event fork;
116 struct period_event period;
117 struct lost_event lost; 124 struct lost_event lost;
118 struct read_event read; 125 struct read_event read;
119} event_t; 126} event_t;
120 127
128static int repsep_fprintf(FILE *fp, const char *fmt, ...)
129{
130 int n;
131 va_list ap;
132
133 va_start(ap, fmt);
134 if (!field_sep)
135 n = vfprintf(fp, fmt, ap);
136 else {
137 char *bf = NULL;
138 n = vasprintf(&bf, fmt, ap);
139 if (n > 0) {
140 char *sep = bf;
141 while (1) {
142 sep = strchr(sep, *field_sep);
143 if (sep == NULL)
144 break;
145 *sep = '.';
146 }
147 }
148 fputs(bf, fp);
149 free(bf);
150 }
151 va_end(ap);
152 return n;
153}
154
121static LIST_HEAD(dsos); 155static LIST_HEAD(dsos);
122static struct dso *kernel_dso; 156static struct dso *kernel_dso;
123static struct dso *vdso; 157static struct dso *vdso;
158static struct dso *hypervisor_dso;
124 159
125static void dsos__add(struct dso *dso) 160static void dsos__add(struct dso *dso)
126{ 161{
@@ -176,7 +211,7 @@ static void dsos__fprintf(FILE *fp)
176 211
177static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 212static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
178{ 213{
179 return dso__find_symbol(kernel_dso, ip); 214 return dso__find_symbol(dso, ip);
180} 215}
181 216
182static int load_kernel(void) 217static int load_kernel(void)
@@ -187,8 +222,8 @@ static int load_kernel(void)
187 if (!kernel_dso) 222 if (!kernel_dso)
188 return -1; 223 return -1;
189 224
190 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); 225 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules);
191 if (err) { 226 if (err <= 0) {
192 dso__delete(kernel_dso); 227 dso__delete(kernel_dso);
193 kernel_dso = NULL; 228 kernel_dso = NULL;
194 } else 229 } else
@@ -202,6 +237,11 @@ static int load_kernel(void)
202 237
203 dsos__add(vdso); 238 dsos__add(vdso);
204 239
240 hypervisor_dso = dso__new("[hypervisor]", 0);
241 if (!hypervisor_dso)
242 return -1;
243 dsos__add(hypervisor_dso);
244
205 return err; 245 return err;
206} 246}
207 247
@@ -213,7 +253,7 @@ static int strcommon(const char *pathname)
213{ 253{
214 int n = 0; 254 int n = 0;
215 255
216 while (pathname[n] == cwd[n] && n < cwdlen) 256 while (n < cwdlen && pathname[n] == cwd[n])
217 ++n; 257 ++n;
218 258
219 return n; 259 return n;
@@ -233,7 +273,7 @@ static u64 map__map_ip(struct map *map, u64 ip)
233 return ip - map->start + map->pgoff; 273 return ip - map->start + map->pgoff;
234} 274}
235 275
236static u64 vdso__map_ip(struct map *map, u64 ip) 276static u64 vdso__map_ip(struct map *map __used, u64 ip)
237{ 277{
238 return ip; 278 return ip;
239} 279}
@@ -343,12 +383,28 @@ static struct thread *thread__new(pid_t pid)
343 return self; 383 return self;
344} 384}
345 385
386static unsigned int dsos__col_width,
387 comms__col_width,
388 threads__col_width;
389
346static int thread__set_comm(struct thread *self, const char *comm) 390static int thread__set_comm(struct thread *self, const char *comm)
347{ 391{
348 if (self->comm) 392 if (self->comm)
349 free(self->comm); 393 free(self->comm);
350 self->comm = strdup(comm); 394 self->comm = strdup(comm);
351 return self->comm ? 0 : -ENOMEM; 395 if (!self->comm)
396 return -ENOMEM;
397
398 if (!col_width_list_str && !field_sep &&
399 (!comm_list || strlist__has_entry(comm_list, comm))) {
400 unsigned int slen = strlen(comm);
401 if (slen > comms__col_width) {
402 comms__col_width = slen;
403 threads__col_width = slen + 6;
404 }
405 }
406
407 return 0;
352} 408}
353 409
354static size_t thread__fprintf(struct thread *self, FILE *fp) 410static size_t thread__fprintf(struct thread *self, FILE *fp)
@@ -519,7 +575,9 @@ struct sort_entry {
519 575
520 int64_t (*cmp)(struct hist_entry *, struct hist_entry *); 576 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
521 int64_t (*collapse)(struct hist_entry *, struct hist_entry *); 577 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
522 size_t (*print)(FILE *fp, struct hist_entry *); 578 size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width);
579 unsigned int *width;
580 bool elide;
523}; 581};
524 582
525static int64_t cmp_null(void *l, void *r) 583static int64_t cmp_null(void *l, void *r)
@@ -541,15 +599,17 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
541} 599}
542 600
543static size_t 601static size_t
544sort__thread_print(FILE *fp, struct hist_entry *self) 602sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
545{ 603{
546 return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid); 604 return repsep_fprintf(fp, "%*s:%5d", width - 6,
605 self->thread->comm ?: "", self->thread->pid);
547} 606}
548 607
549static struct sort_entry sort_thread = { 608static struct sort_entry sort_thread = {
550 .header = " Command: Pid", 609 .header = "Command: Pid",
551 .cmp = sort__thread_cmp, 610 .cmp = sort__thread_cmp,
552 .print = sort__thread_print, 611 .print = sort__thread_print,
612 .width = &threads__col_width,
553}; 613};
554 614
555/* --sort comm */ 615/* --sort comm */
@@ -573,16 +633,17 @@ sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
573} 633}
574 634
575static size_t 635static size_t
576sort__comm_print(FILE *fp, struct hist_entry *self) 636sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
577{ 637{
578 return fprintf(fp, "%16s", self->thread->comm); 638 return repsep_fprintf(fp, "%*s", width, self->thread->comm);
579} 639}
580 640
581static struct sort_entry sort_comm = { 641static struct sort_entry sort_comm = {
582 .header = " Command", 642 .header = "Command",
583 .cmp = sort__comm_cmp, 643 .cmp = sort__comm_cmp,
584 .collapse = sort__comm_collapse, 644 .collapse = sort__comm_collapse,
585 .print = sort__comm_print, 645 .print = sort__comm_print,
646 .width = &comms__col_width,
586}; 647};
587 648
588/* --sort dso */ 649/* --sort dso */
@@ -600,18 +661,19 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
600} 661}
601 662
602static size_t 663static size_t
603sort__dso_print(FILE *fp, struct hist_entry *self) 664sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
604{ 665{
605 if (self->dso) 666 if (self->dso)
606 return fprintf(fp, "%-25s", self->dso->name); 667 return repsep_fprintf(fp, "%-*s", width, self->dso->name);
607 668
608 return fprintf(fp, "%016llx ", (u64)self->ip); 669 return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
609} 670}
610 671
611static struct sort_entry sort_dso = { 672static struct sort_entry sort_dso = {
612 .header = "Shared Object ", 673 .header = "Shared Object",
613 .cmp = sort__dso_cmp, 674 .cmp = sort__dso_cmp,
614 .print = sort__dso_print, 675 .print = sort__dso_print,
676 .width = &dsos__col_width,
615}; 677};
616 678
617/* --sort symbol */ 679/* --sort symbol */
@@ -631,18 +693,22 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
631} 693}
632 694
633static size_t 695static size_t
634sort__sym_print(FILE *fp, struct hist_entry *self) 696sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
635{ 697{
636 size_t ret = 0; 698 size_t ret = 0;
637 699
638 if (verbose) 700 if (verbose)
639 ret += fprintf(fp, "%#018llx ", (u64)self->ip); 701 ret += repsep_fprintf(fp, "%#018llx ", (u64)self->ip);
640 702
703 ret += repsep_fprintf(fp, "[%c] ", self->level);
641 if (self->sym) { 704 if (self->sym) {
642 ret += fprintf(fp, "[%c] %s", 705 ret += repsep_fprintf(fp, "%s", self->sym->name);
643 self->dso == kernel_dso ? 'k' : '.', self->sym->name); 706
707 if (self->sym->module)
708 ret += repsep_fprintf(fp, "\t[%s]",
709 self->sym->module->name);
644 } else { 710 } else {
645 ret += fprintf(fp, "%#016llx", (u64)self->ip); 711 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
646 } 712 }
647 713
648 return ret; 714 return ret;
@@ -669,19 +735,19 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
669} 735}
670 736
671static size_t 737static size_t
672sort__parent_print(FILE *fp, struct hist_entry *self) 738sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
673{ 739{
674 size_t ret = 0; 740 return repsep_fprintf(fp, "%-*s", width,
675 741 self->parent ? self->parent->name : "[other]");
676 ret += fprintf(fp, "%-20s", self->parent ? self->parent->name : "[other]");
677
678 return ret;
679} 742}
680 743
744static unsigned int parent_symbol__col_width;
745
681static struct sort_entry sort_parent = { 746static struct sort_entry sort_parent = {
682 .header = "Parent symbol ", 747 .header = "Parent symbol",
683 .cmp = sort__parent_cmp, 748 .cmp = sort__parent_cmp,
684 .print = sort__parent_print, 749 .print = sort__parent_print,
750 .width = &parent_symbol__col_width,
685}; 751};
686 752
687static int sort__need_collapse = 0; 753static int sort__need_collapse = 0;
@@ -705,7 +771,7 @@ static LIST_HEAD(hist_entry__sort_list);
705 771
706static int sort_dimension__add(char *tok) 772static int sort_dimension__add(char *tok)
707{ 773{
708 int i; 774 unsigned int i;
709 775
710 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { 776 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
711 struct sort_dimension *sd = &sort_dimensions[i]; 777 struct sort_dimension *sd = &sort_dimensions[i];
@@ -775,8 +841,109 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
775 return cmp; 841 return cmp;
776} 842}
777 843
844static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask)
845{
846 int i;
847 size_t ret = 0;
848
849 ret += fprintf(fp, "%s", " ");
850
851 for (i = 0; i < depth; i++)
852 if (depth_mask & (1 << i))
853 ret += fprintf(fp, "| ");
854 else
855 ret += fprintf(fp, " ");
856
857 ret += fprintf(fp, "\n");
858
859 return ret;
860}
778static size_t 861static size_t
779callchain__fprintf(FILE *fp, struct callchain_node *self, u64 total_samples) 862ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
863 int depth_mask, int count, u64 total_samples,
864 int hits)
865{
866 int i;
867 size_t ret = 0;
868
869 ret += fprintf(fp, "%s", " ");
870 for (i = 0; i < depth; i++) {
871 if (depth_mask & (1 << i))
872 ret += fprintf(fp, "|");
873 else
874 ret += fprintf(fp, " ");
875 if (!count && i == depth - 1) {
876 double percent;
877
878 percent = hits * 100.0 / total_samples;
879 ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
880 } else
881 ret += fprintf(fp, "%s", " ");
882 }
883 if (chain->sym)
884 ret += fprintf(fp, "%s\n", chain->sym->name);
885 else
886 ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
887
888 return ret;
889}
890
891static size_t
892callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
893 u64 total_samples, int depth, int depth_mask)
894{
895 struct rb_node *node, *next;
896 struct callchain_node *child;
897 struct callchain_list *chain;
898 int new_depth_mask = depth_mask;
899 u64 new_total;
900 size_t ret = 0;
901 int i;
902
903 if (callchain_param.mode == CHAIN_GRAPH_REL)
904 new_total = self->cumul_hit;
905 else
906 new_total = total_samples;
907
908 node = rb_first(&self->rb_root);
909 while (node) {
910 child = rb_entry(node, struct callchain_node, rb_node);
911
912 /*
913 * The depth mask manages the output of pipes that show
914 * the depth. We don't want to keep the pipes of the current
915 * level for the last child of this depth
916 */
917 next = rb_next(node);
918 if (!next)
919 new_depth_mask &= ~(1 << (depth - 1));
920
921 /*
922 * But we keep the older depth mask for the line seperator
923 * to keep the level link until we reach the last child
924 */
925 ret += ipchain__fprintf_graph_line(fp, depth, depth_mask);
926 i = 0;
927 list_for_each_entry(chain, &child->val, list) {
928 if (chain->ip >= PERF_CONTEXT_MAX)
929 continue;
930 ret += ipchain__fprintf_graph(fp, chain, depth,
931 new_depth_mask, i++,
932 new_total,
933 child->cumul_hit);
934 }
935 ret += callchain__fprintf_graph(fp, child, new_total,
936 depth + 1,
937 new_depth_mask | (1 << depth));
938 node = next;
939 }
940
941 return ret;
942}
943
944static size_t
945callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
946 u64 total_samples)
780{ 947{
781 struct callchain_list *chain; 948 struct callchain_list *chain;
782 size_t ret = 0; 949 size_t ret = 0;
@@ -784,11 +951,18 @@ callchain__fprintf(FILE *fp, struct callchain_node *self, u64 total_samples)
784 if (!self) 951 if (!self)
785 return 0; 952 return 0;
786 953
787 ret += callchain__fprintf(fp, self->parent, total_samples); 954 ret += callchain__fprintf_flat(fp, self->parent, total_samples);
788 955
789 956
790 list_for_each_entry(chain, &self->val, list) 957 list_for_each_entry(chain, &self->val, list) {
791 ret += fprintf(fp, " %p\n", (void *)chain->ip); 958 if (chain->ip >= PERF_CONTEXT_MAX)
959 continue;
960 if (chain->sym)
961 ret += fprintf(fp, " %s\n", chain->sym->name);
962 else
963 ret += fprintf(fp, " %p\n",
964 (void *)(long)chain->ip);
965 }
792 966
793 return ret; 967 return ret;
794} 968}
@@ -807,8 +981,19 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
807 981
808 chain = rb_entry(rb_node, struct callchain_node, rb_node); 982 chain = rb_entry(rb_node, struct callchain_node, rb_node);
809 percent = chain->hit * 100.0 / total_samples; 983 percent = chain->hit * 100.0 / total_samples;
810 ret += fprintf(fp, " %6.2f%%\n", percent); 984 switch (callchain_param.mode) {
811 ret += callchain__fprintf(fp, chain, total_samples); 985 case CHAIN_FLAT:
986 ret += percent_color_fprintf(fp, " %6.2f%%\n",
987 percent);
988 ret += callchain__fprintf_flat(fp, chain, total_samples);
989 break;
990 case CHAIN_GRAPH_ABS: /* Falldown */
991 case CHAIN_GRAPH_REL:
992 ret += callchain__fprintf_graph(fp, chain,
993 total_samples, 1, 1);
994 default:
995 break;
996 }
812 ret += fprintf(fp, "\n"); 997 ret += fprintf(fp, "\n");
813 rb_node = rb_next(rb_node); 998 rb_node = rb_next(rb_node);
814 } 999 }
@@ -826,33 +1011,26 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
826 if (exclude_other && !self->parent) 1011 if (exclude_other && !self->parent)
827 return 0; 1012 return 0;
828 1013
829 if (total_samples) { 1014 if (total_samples)
830 double percent = self->count * 100.0 / total_samples; 1015 ret = percent_color_fprintf(fp,
831 char *color = PERF_COLOR_NORMAL; 1016 field_sep ? "%.2f" : " %6.2f%%",
832 1017 (self->count * 100.0) / total_samples);
833 /* 1018 else
834 * We color high-overhead entries in red, mid-overhead 1019 ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count);
835 * entries in green - and keep the low overhead places
836 * normal:
837 */
838 if (percent >= 5.0) {
839 color = PERF_COLOR_RED;
840 } else {
841 if (percent >= 0.5)
842 color = PERF_COLOR_GREEN;
843 }
844 1020
845 ret = color_fprintf(fp, color, " %6.2f%%", 1021 if (show_nr_samples) {
846 (self->count * 100.0) / total_samples); 1022 if (field_sep)
847 } else 1023 fprintf(fp, "%c%lld", *field_sep, self->count);
848 ret = fprintf(fp, "%12Ld ", self->count); 1024 else
1025 fprintf(fp, "%11lld", self->count);
1026 }
849 1027
850 list_for_each_entry(se, &hist_entry__sort_list, list) { 1028 list_for_each_entry(se, &hist_entry__sort_list, list) {
851 if (exclude_other && (se == &sort_parent)) 1029 if (se->elide)
852 continue; 1030 continue;
853 1031
854 fprintf(fp, " "); 1032 fprintf(fp, "%s", field_sep ?: " ");
855 ret += se->print(fp, self); 1033 ret += se->print(fp, self, se->width ? *se->width : 0);
856 } 1034 }
857 1035
858 ret += fprintf(fp, "\n"); 1036 ret += fprintf(fp, "\n");
@@ -867,6 +1045,18 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
867 * 1045 *
868 */ 1046 */
869 1047
1048static void dso__calc_col_width(struct dso *self)
1049{
1050 if (!col_width_list_str && !field_sep &&
1051 (!dso_list || strlist__has_entry(dso_list, self->name))) {
1052 unsigned int slen = strlen(self->name);
1053 if (slen > dsos__col_width)
1054 dsos__col_width = slen;
1055 }
1056
1057 self->slen_calculated = 1;
1058}
1059
870static struct symbol * 1060static struct symbol *
871resolve_symbol(struct thread *thread, struct map **mapp, 1061resolve_symbol(struct thread *thread, struct map **mapp,
872 struct dso **dsop, u64 *ipp) 1062 struct dso **dsop, u64 *ipp)
@@ -886,6 +1076,14 @@ resolve_symbol(struct thread *thread, struct map **mapp,
886 1076
887 map = thread__find_map(thread, ip); 1077 map = thread__find_map(thread, ip);
888 if (map != NULL) { 1078 if (map != NULL) {
1079 /*
1080 * We have to do this here as we may have a dso
1081 * with no symbol hit that has a name longer than
1082 * the ones with symbols sampled.
1083 */
1084 if (!sort_dso.elide && !map->dso->slen_calculated)
1085 dso__calc_col_width(map->dso);
1086
889 if (mapp) 1087 if (mapp)
890 *mapp = map; 1088 *mapp = map;
891got_map: 1089got_map:
@@ -923,6 +1121,58 @@ static int call__match(struct symbol *sym)
923 return 0; 1121 return 0;
924} 1122}
925 1123
1124static struct symbol **
1125resolve_callchain(struct thread *thread, struct map *map __used,
1126 struct ip_callchain *chain, struct hist_entry *entry)
1127{
1128 u64 context = PERF_CONTEXT_MAX;
1129 struct symbol **syms = NULL;
1130 unsigned int i;
1131
1132 if (callchain) {
1133 syms = calloc(chain->nr, sizeof(*syms));
1134 if (!syms) {
1135 fprintf(stderr, "Can't allocate memory for symbols\n");
1136 exit(-1);
1137 }
1138 }
1139
1140 for (i = 0; i < chain->nr; i++) {
1141 u64 ip = chain->ips[i];
1142 struct dso *dso = NULL;
1143 struct symbol *sym;
1144
1145 if (ip >= PERF_CONTEXT_MAX) {
1146 context = ip;
1147 continue;
1148 }
1149
1150 switch (context) {
1151 case PERF_CONTEXT_HV:
1152 dso = hypervisor_dso;
1153 break;
1154 case PERF_CONTEXT_KERNEL:
1155 dso = kernel_dso;
1156 break;
1157 default:
1158 break;
1159 }
1160
1161 sym = resolve_symbol(thread, NULL, &dso, &ip);
1162
1163 if (sym) {
1164 if (sort__has_parent && call__match(sym) &&
1165 !entry->parent)
1166 entry->parent = sym;
1167 if (!callchain)
1168 break;
1169 syms[i] = sym;
1170 }
1171 }
1172
1173 return syms;
1174}
1175
926/* 1176/*
927 * collect histogram counts 1177 * collect histogram counts
928 */ 1178 */
@@ -935,6 +1185,7 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
935 struct rb_node **p = &hist.rb_node; 1185 struct rb_node **p = &hist.rb_node;
936 struct rb_node *parent = NULL; 1186 struct rb_node *parent = NULL;
937 struct hist_entry *he; 1187 struct hist_entry *he;
1188 struct symbol **syms = NULL;
938 struct hist_entry entry = { 1189 struct hist_entry entry = {
939 .thread = thread, 1190 .thread = thread,
940 .map = map, 1191 .map = map,
@@ -948,36 +1199,8 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
948 }; 1199 };
949 int cmp; 1200 int cmp;
950 1201
951 if (sort__has_parent && chain) { 1202 if ((sort__has_parent || callchain) && chain)
952 u64 context = PERF_CONTEXT_MAX; 1203 syms = resolve_callchain(thread, map, chain, &entry);
953 int i;
954
955 for (i = 0; i < chain->nr; i++) {
956 u64 ip = chain->ips[i];
957 struct dso *dso = NULL;
958 struct symbol *sym;
959
960 if (ip >= PERF_CONTEXT_MAX) {
961 context = ip;
962 continue;
963 }
964
965 switch (context) {
966 case PERF_CONTEXT_KERNEL:
967 dso = kernel_dso;
968 break;
969 default:
970 break;
971 }
972
973 sym = resolve_symbol(thread, NULL, &dso, &ip);
974
975 if (sym && call__match(sym)) {
976 entry.parent = sym;
977 break;
978 }
979 }
980 }
981 1204
982 while (*p != NULL) { 1205 while (*p != NULL) {
983 parent = *p; 1206 parent = *p;
@@ -987,8 +1210,10 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
987 1210
988 if (!cmp) { 1211 if (!cmp) {
989 he->count += count; 1212 he->count += count;
990 if (callchain) 1213 if (callchain) {
991 append_chain(&he->callchain, chain); 1214 append_chain(&he->callchain, chain, syms);
1215 free(syms);
1216 }
992 return 0; 1217 return 0;
993 } 1218 }
994 1219
@@ -1004,7 +1229,8 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
1004 *he = entry; 1229 *he = entry;
1005 if (callchain) { 1230 if (callchain) {
1006 callchain_init(&he->callchain); 1231 callchain_init(&he->callchain);
1007 append_chain(&he->callchain, chain); 1232 append_chain(&he->callchain, chain, syms);
1233 free(syms);
1008 } 1234 }
1009 rb_link_node(&he->rb_node, parent, p); 1235 rb_link_node(&he->rb_node, parent, p);
1010 rb_insert_color(&he->rb_node, &hist); 1236 rb_insert_color(&he->rb_node, &hist);
@@ -1076,14 +1302,15 @@ static void collapse__resort(void)
1076 1302
1077static struct rb_root output_hists; 1303static struct rb_root output_hists;
1078 1304
1079static void output__insert_entry(struct hist_entry *he) 1305static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
1080{ 1306{
1081 struct rb_node **p = &output_hists.rb_node; 1307 struct rb_node **p = &output_hists.rb_node;
1082 struct rb_node *parent = NULL; 1308 struct rb_node *parent = NULL;
1083 struct hist_entry *iter; 1309 struct hist_entry *iter;
1084 1310
1085 if (callchain) 1311 if (callchain)
1086 sort_chain_to_rbtree(&he->sorted_chain, &he->callchain); 1312 callchain_param.sort(&he->sorted_chain, &he->callchain,
1313 min_callchain_hits, &callchain_param);
1087 1314
1088 while (*p != NULL) { 1315 while (*p != NULL) {
1089 parent = *p; 1316 parent = *p;
@@ -1099,11 +1326,14 @@ static void output__insert_entry(struct hist_entry *he)
1099 rb_insert_color(&he->rb_node, &output_hists); 1326 rb_insert_color(&he->rb_node, &output_hists);
1100} 1327}
1101 1328
1102static void output__resort(void) 1329static void output__resort(u64 total_samples)
1103{ 1330{
1104 struct rb_node *next; 1331 struct rb_node *next;
1105 struct hist_entry *n; 1332 struct hist_entry *n;
1106 struct rb_root *tree = &hist; 1333 struct rb_root *tree = &hist;
1334 u64 min_callchain_hits;
1335
1336 min_callchain_hits = total_samples * (callchain_param.min_percent / 100);
1107 1337
1108 if (sort__need_collapse) 1338 if (sort__need_collapse)
1109 tree = &collapse_hists; 1339 tree = &collapse_hists;
@@ -1115,7 +1345,7 @@ static void output__resort(void)
1115 next = rb_next(&n->rb_node); 1345 next = rb_next(&n->rb_node);
1116 1346
1117 rb_erase(&n->rb_node, tree); 1347 rb_erase(&n->rb_node, tree);
1118 output__insert_entry(n); 1348 output__insert_entry(n, min_callchain_hits);
1119 } 1349 }
1120} 1350}
1121 1351
@@ -1125,35 +1355,67 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
1125 struct sort_entry *se; 1355 struct sort_entry *se;
1126 struct rb_node *nd; 1356 struct rb_node *nd;
1127 size_t ret = 0; 1357 size_t ret = 0;
1358 unsigned int width;
1359 char *col_width = col_width_list_str;
1128 1360
1129 fprintf(fp, "\n"); 1361 fprintf(fp, "# Samples: %Ld\n", (u64)total_samples);
1130 fprintf(fp, "#\n");
1131 fprintf(fp, "# (%Ld samples)\n", (u64)total_samples);
1132 fprintf(fp, "#\n"); 1362 fprintf(fp, "#\n");
1133 1363
1134 fprintf(fp, "# Overhead"); 1364 fprintf(fp, "# Overhead");
1365 if (show_nr_samples) {
1366 if (field_sep)
1367 fprintf(fp, "%cSamples", *field_sep);
1368 else
1369 fputs(" Samples ", fp);
1370 }
1135 list_for_each_entry(se, &hist_entry__sort_list, list) { 1371 list_for_each_entry(se, &hist_entry__sort_list, list) {
1136 if (exclude_other && (se == &sort_parent)) 1372 if (se->elide)
1373 continue;
1374 if (field_sep) {
1375 fprintf(fp, "%c%s", *field_sep, se->header);
1137 continue; 1376 continue;
1138 fprintf(fp, " %s", se->header); 1377 }
1378 width = strlen(se->header);
1379 if (se->width) {
1380 if (col_width_list_str) {
1381 if (col_width) {
1382 *se->width = atoi(col_width);
1383 col_width = strchr(col_width, ',');
1384 if (col_width)
1385 ++col_width;
1386 }
1387 }
1388 width = *se->width = max(*se->width, width);
1389 }
1390 fprintf(fp, " %*s", width, se->header);
1139 } 1391 }
1140 fprintf(fp, "\n"); 1392 fprintf(fp, "\n");
1141 1393
1394 if (field_sep)
1395 goto print_entries;
1396
1142 fprintf(fp, "# ........"); 1397 fprintf(fp, "# ........");
1398 if (show_nr_samples)
1399 fprintf(fp, " ..........");
1143 list_for_each_entry(se, &hist_entry__sort_list, list) { 1400 list_for_each_entry(se, &hist_entry__sort_list, list) {
1144 int i; 1401 unsigned int i;
1145 1402
1146 if (exclude_other && (se == &sort_parent)) 1403 if (se->elide)
1147 continue; 1404 continue;
1148 1405
1149 fprintf(fp, " "); 1406 fprintf(fp, " ");
1150 for (i = 0; i < strlen(se->header); i++) 1407 if (se->width)
1408 width = *se->width;
1409 else
1410 width = strlen(se->header);
1411 for (i = 0; i < width; i++)
1151 fprintf(fp, "."); 1412 fprintf(fp, ".");
1152 } 1413 }
1153 fprintf(fp, "\n"); 1414 fprintf(fp, "\n");
1154 1415
1155 fprintf(fp, "#\n"); 1416 fprintf(fp, "#\n");
1156 1417
1418print_entries:
1157 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) { 1419 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
1158 pos = rb_entry(nd, struct hist_entry, rb_node); 1420 pos = rb_entry(nd, struct hist_entry, rb_node);
1159 ret += hist_entry__fprintf(fp, pos, total_samples); 1421 ret += hist_entry__fprintf(fp, pos, total_samples);
@@ -1162,7 +1424,7 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
1162 if (sort_order == default_sort_order && 1424 if (sort_order == default_sort_order &&
1163 parent_pattern == default_parent_pattern) { 1425 parent_pattern == default_parent_pattern) {
1164 fprintf(fp, "#\n"); 1426 fprintf(fp, "#\n");
1165 fprintf(fp, "# (For more details, try: perf report --sort comm,dso,symbol)\n"); 1427 fprintf(fp, "# (For a higher level overview, try: perf report --sort comm,dso)\n");
1166 fprintf(fp, "#\n"); 1428 fprintf(fp, "#\n");
1167 } 1429 }
1168 fprintf(fp, "\n"); 1430 fprintf(fp, "\n");
@@ -1213,6 +1475,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1213 struct map *map = NULL; 1475 struct map *map = NULL;
1214 void *more_data = event->ip.__more_data; 1476 void *more_data = event->ip.__more_data;
1215 struct ip_callchain *chain = NULL; 1477 struct ip_callchain *chain = NULL;
1478 int cpumode;
1216 1479
1217 if (sample_type & PERF_SAMPLE_PERIOD) { 1480 if (sample_type & PERF_SAMPLE_PERIOD) {
1218 period = *(u64 *)more_data; 1481 period = *(u64 *)more_data;
@@ -1228,7 +1491,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1228 (long long)period); 1491 (long long)period);
1229 1492
1230 if (sample_type & PERF_SAMPLE_CALLCHAIN) { 1493 if (sample_type & PERF_SAMPLE_CALLCHAIN) {
1231 int i; 1494 unsigned int i;
1232 1495
1233 chain = (void *)more_data; 1496 chain = (void *)more_data;
1234 1497
@@ -1256,7 +1519,9 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1256 if (comm_list && !strlist__has_entry(comm_list, thread->comm)) 1519 if (comm_list && !strlist__has_entry(comm_list, thread->comm))
1257 return 0; 1520 return 0;
1258 1521
1259 if (event->header.misc & PERF_EVENT_MISC_KERNEL) { 1522 cpumode = event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK;
1523
1524 if (cpumode == PERF_EVENT_MISC_KERNEL) {
1260 show = SHOW_KERNEL; 1525 show = SHOW_KERNEL;
1261 level = 'k'; 1526 level = 'k';
1262 1527
@@ -1264,7 +1529,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1264 1529
1265 dprintf(" ...... dso: %s\n", dso->name); 1530 dprintf(" ...... dso: %s\n", dso->name);
1266 1531
1267 } else if (event->header.misc & PERF_EVENT_MISC_USER) { 1532 } else if (cpumode == PERF_EVENT_MISC_USER) {
1268 1533
1269 show = SHOW_USER; 1534 show = SHOW_USER;
1270 level = '.'; 1535 level = '.';
@@ -1272,6 +1537,9 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1272 } else { 1537 } else {
1273 show = SHOW_HV; 1538 show = SHOW_HV;
1274 level = 'H'; 1539 level = 'H';
1540
1541 dso = hypervisor_dso;
1542
1275 dprintf(" ...... dso: [hypervisor]\n"); 1543 dprintf(" ...... dso: [hypervisor]\n");
1276 } 1544 }
1277 1545
@@ -1341,15 +1609,27 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
1341} 1609}
1342 1610
1343static int 1611static int
1344process_fork_event(event_t *event, unsigned long offset, unsigned long head) 1612process_task_event(event_t *event, unsigned long offset, unsigned long head)
1345{ 1613{
1346 struct thread *thread = threads__findnew(event->fork.pid); 1614 struct thread *thread = threads__findnew(event->fork.pid);
1347 struct thread *parent = threads__findnew(event->fork.ppid); 1615 struct thread *parent = threads__findnew(event->fork.ppid);
1348 1616
1349 dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n", 1617 dprintf("%p [%p]: PERF_EVENT_%s: (%d:%d):(%d:%d)\n",
1350 (void *)(offset + head), 1618 (void *)(offset + head),
1351 (void *)(long)(event->header.size), 1619 (void *)(long)(event->header.size),
1352 event->fork.pid, event->fork.ppid); 1620 event->header.type == PERF_EVENT_FORK ? "FORK" : "EXIT",
1621 event->fork.pid, event->fork.tid,
1622 event->fork.ppid, event->fork.ptid);
1623
1624 /*
1625 * A thread clone will have the same PID for both
1626 * parent and child.
1627 */
1628 if (thread == parent)
1629 return 0;
1630
1631 if (event->header.type == PERF_EVENT_EXIT)
1632 return 0;
1353 1633
1354 if (!thread || !parent || thread__fork(thread, parent)) { 1634 if (!thread || !parent || thread__fork(thread, parent)) {
1355 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); 1635 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
@@ -1361,19 +1641,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
1361} 1641}
1362 1642
1363static int 1643static int
1364process_period_event(event_t *event, unsigned long offset, unsigned long head)
1365{
1366 dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
1367 (void *)(offset + head),
1368 (void *)(long)(event->header.size),
1369 event->period.time,
1370 event->period.id,
1371 event->period.sample_period);
1372
1373 return 0;
1374}
1375
1376static int
1377process_lost_event(event_t *event, unsigned long offset, unsigned long head) 1644process_lost_event(event_t *event, unsigned long offset, unsigned long head)
1378{ 1645{
1379 dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", 1646 dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n",
@@ -1452,10 +1719,8 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1452 return process_comm_event(event, offset, head); 1719 return process_comm_event(event, offset, head);
1453 1720
1454 case PERF_EVENT_FORK: 1721 case PERF_EVENT_FORK:
1455 return process_fork_event(event, offset, head); 1722 case PERF_EVENT_EXIT:
1456 1723 return process_task_event(event, offset, head);
1457 case PERF_EVENT_PERIOD:
1458 return process_period_event(event, offset, head);
1459 1724
1460 case PERF_EVENT_LOST: 1725 case PERF_EVENT_LOST:
1461 return process_lost_event(event, offset, head); 1726 return process_lost_event(event, offset, head);
@@ -1534,9 +1799,19 @@ static int __cmd_report(void)
1534 1799
1535 sample_type = perf_header__sample_type(); 1800 sample_type = perf_header__sample_type();
1536 1801
1537 if (sort__has_parent && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { 1802 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
1538 fprintf(stderr, "selected --sort parent, but no callchain data\n"); 1803 if (sort__has_parent) {
1539 exit(-1); 1804 fprintf(stderr, "selected --sort parent, but no"
1805 " callchain data. Did you call"
1806 " perf record without -g?\n");
1807 exit(-1);
1808 }
1809 if (callchain) {
1810 fprintf(stderr, "selected -c but no callchain data."
1811 " Did you call perf record without"
1812 " -g?\n");
1813 exit(-1);
1814 }
1540 } 1815 }
1541 1816
1542 if (load_kernel() < 0) { 1817 if (load_kernel() < 0) {
@@ -1619,7 +1894,7 @@ more:
1619 if (offset + head >= header->data_offset + header->data_size) 1894 if (offset + head >= header->data_offset + header->data_size)
1620 goto done; 1895 goto done;
1621 1896
1622 if (offset + head < stat.st_size) 1897 if (offset + head < (unsigned long)stat.st_size)
1623 goto more; 1898 goto more;
1624 1899
1625done: 1900done:
@@ -1643,12 +1918,58 @@ done:
1643 dsos__fprintf(stdout); 1918 dsos__fprintf(stdout);
1644 1919
1645 collapse__resort(); 1920 collapse__resort();
1646 output__resort(); 1921 output__resort(total);
1647 output__fprintf(stdout, total); 1922 output__fprintf(stdout, total);
1648 1923
1649 return rc; 1924 return rc;
1650} 1925}
1651 1926
1927static int
1928parse_callchain_opt(const struct option *opt __used, const char *arg,
1929 int unset __used)
1930{
1931 char *tok;
1932 char *endptr;
1933
1934 callchain = 1;
1935
1936 if (!arg)
1937 return 0;
1938
1939 tok = strtok((char *)arg, ",");
1940 if (!tok)
1941 return -1;
1942
1943 /* get the output mode */
1944 if (!strncmp(tok, "graph", strlen(arg)))
1945 callchain_param.mode = CHAIN_GRAPH_ABS;
1946
1947 else if (!strncmp(tok, "flat", strlen(arg)))
1948 callchain_param.mode = CHAIN_FLAT;
1949
1950 else if (!strncmp(tok, "fractal", strlen(arg)))
1951 callchain_param.mode = CHAIN_GRAPH_REL;
1952
1953 else
1954 return -1;
1955
1956 /* get the min percentage */
1957 tok = strtok(NULL, ",");
1958 if (!tok)
1959 goto setup;
1960
1961 callchain_param.min_percent = strtod(tok, &endptr);
1962 if (tok == endptr)
1963 return -1;
1964
1965setup:
1966 if (register_callchain_param(&callchain_param) < 0) {
1967 fprintf(stderr, "Can't register callchain params\n");
1968 return -1;
1969 }
1970 return 0;
1971}
1972
1652static const char * const report_usage[] = { 1973static const char * const report_usage[] = {
1653 "perf report [<options>] <command>", 1974 "perf report [<options>] <command>",
1654 NULL 1975 NULL
@@ -1662,6 +1983,10 @@ static const struct option options[] = {
1662 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1983 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1663 "dump raw trace in ASCII"), 1984 "dump raw trace in ASCII"),
1664 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1985 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1986 OPT_BOOLEAN('m', "modules", &modules,
1987 "load module symbols - WARNING: use only with -k and LIVE kernel"),
1988 OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,
1989 "Show a column with the number of samples"),
1665 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1990 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1666 "sort by key(s): pid, comm, dso, symbol, parent"), 1991 "sort by key(s): pid, comm, dso, symbol, parent"),
1667 OPT_BOOLEAN('P', "full-paths", &full_paths, 1992 OPT_BOOLEAN('P', "full-paths", &full_paths,
@@ -1670,13 +1995,21 @@ static const struct option options[] = {
1670 "regex filter to identify parent, see: '--sort parent'"), 1995 "regex filter to identify parent, see: '--sort parent'"),
1671 OPT_BOOLEAN('x', "exclude-other", &exclude_other, 1996 OPT_BOOLEAN('x', "exclude-other", &exclude_other,
1672 "Only display entries with parent-match"), 1997 "Only display entries with parent-match"),
1673 OPT_BOOLEAN('c', "callchain", &callchain, "Display callchains"), 1998 OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent",
1999 "Display callchains using output_type and min percent threshold. "
2000 "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt),
1674 OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]", 2001 OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
1675 "only consider symbols in these dsos"), 2002 "only consider symbols in these dsos"),
1676 OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]", 2003 OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]",
1677 "only consider symbols in these comms"), 2004 "only consider symbols in these comms"),
1678 OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]", 2005 OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]",
1679 "only consider these symbols"), 2006 "only consider these symbols"),
2007 OPT_STRING('w', "column-widths", &col_width_list_str,
2008 "width[,width...]",
2009 "don't try to adjust column width, use these fixed values"),
2010 OPT_STRING('t', "field-separator", &field_sep, "separator",
2011 "separator for columns, no spaces will be added between "
2012 "columns '.' is reserved."),
1680 OPT_END() 2013 OPT_END()
1681}; 2014};
1682 2015
@@ -1696,7 +2029,8 @@ static void setup_sorting(void)
1696} 2029}
1697 2030
1698static void setup_list(struct strlist **list, const char *list_str, 2031static void setup_list(struct strlist **list, const char *list_str,
1699 const char *list_name) 2032 struct sort_entry *se, const char *list_name,
2033 FILE *fp)
1700{ 2034{
1701 if (list_str) { 2035 if (list_str) {
1702 *list = strlist__new(true, list_str); 2036 *list = strlist__new(true, list_str);
@@ -1705,10 +2039,15 @@ static void setup_list(struct strlist **list, const char *list_str,
1705 list_name); 2039 list_name);
1706 exit(129); 2040 exit(129);
1707 } 2041 }
2042 if (strlist__nr_entries(*list) == 1) {
2043 fprintf(fp, "# %s: %s\n", list_name,
2044 strlist__entry(*list, 0)->s);
2045 se->elide = true;
2046 }
1708 } 2047 }
1709} 2048}
1710 2049
1711int cmd_report(int argc, const char **argv, const char *prefix) 2050int cmd_report(int argc, const char **argv, const char *prefix __used)
1712{ 2051{
1713 symbol__init(); 2052 symbol__init();
1714 2053
@@ -1718,9 +2057,10 @@ int cmd_report(int argc, const char **argv, const char *prefix)
1718 2057
1719 setup_sorting(); 2058 setup_sorting();
1720 2059
1721 if (parent_pattern != default_parent_pattern) 2060 if (parent_pattern != default_parent_pattern) {
1722 sort_dimension__add("parent"); 2061 sort_dimension__add("parent");
1723 else 2062 sort_parent.elide = 1;
2063 } else
1724 exclude_other = 0; 2064 exclude_other = 0;
1725 2065
1726 /* 2066 /*
@@ -1729,11 +2069,17 @@ int cmd_report(int argc, const char **argv, const char *prefix)
1729 if (argc) 2069 if (argc)
1730 usage_with_options(report_usage, options); 2070 usage_with_options(report_usage, options);
1731 2071
1732 setup_list(&dso_list, dso_list_str, "dso");
1733 setup_list(&comm_list, comm_list_str, "comm");
1734 setup_list(&sym_list, sym_list_str, "symbol");
1735
1736 setup_pager(); 2072 setup_pager();
1737 2073
2074 setup_list(&dso_list, dso_list_str, &sort_dso, "dso", stdout);
2075 setup_list(&comm_list, comm_list_str, &sort_comm, "comm", stdout);
2076 setup_list(&sym_list, sym_list_str, &sort_sym, "symbol", stdout);
2077
2078 if (field_sep && *field_sep == '.') {
2079 fputs("'.' is the only non valid --field-separator argument\n",
2080 stderr);
2081 exit(129);
2082 }
2083
1738 return __cmd_report(); 2084 return __cmd_report();
1739} 2085}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 2e03524a1de0..f9510eeeb6c7 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -64,7 +64,7 @@ static struct perf_counter_attr default_attrs[] = {
64 64
65static int system_wide = 0; 65static int system_wide = 0;
66static int verbose = 0; 66static int verbose = 0;
67static int nr_cpus = 0; 67static unsigned int nr_cpus = 0;
68static int run_idx = 0; 68static int run_idx = 0;
69 69
70static int run_count = 1; 70static int run_count = 1;
@@ -96,6 +96,10 @@ static u64 walltime_nsecs_noise;
96static u64 runtime_cycles_avg; 96static u64 runtime_cycles_avg;
97static u64 runtime_cycles_noise; 97static u64 runtime_cycles_noise;
98 98
99#define MATCH_EVENT(t, c, counter) \
100 (attrs[counter].type == PERF_TYPE_##t && \
101 attrs[counter].config == PERF_COUNT_##c)
102
99#define ERR_PERF_OPEN \ 103#define ERR_PERF_OPEN \
100"Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n" 104"Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n"
101 105
@@ -108,7 +112,8 @@ static void create_perf_stat_counter(int counter, int pid)
108 PERF_FORMAT_TOTAL_TIME_RUNNING; 112 PERF_FORMAT_TOTAL_TIME_RUNNING;
109 113
110 if (system_wide) { 114 if (system_wide) {
111 int cpu; 115 unsigned int cpu;
116
112 for (cpu = 0; cpu < nr_cpus; cpu++) { 117 for (cpu = 0; cpu < nr_cpus; cpu++) {
113 fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0); 118 fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0);
114 if (fd[cpu][counter] < 0 && verbose) 119 if (fd[cpu][counter] < 0 && verbose)
@@ -132,13 +137,8 @@ static void create_perf_stat_counter(int counter, int pid)
132 */ 137 */
133static inline int nsec_counter(int counter) 138static inline int nsec_counter(int counter)
134{ 139{
135 if (attrs[counter].type != PERF_TYPE_SOFTWARE) 140 if (MATCH_EVENT(SOFTWARE, SW_CPU_CLOCK, counter) ||
136 return 0; 141 MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
137
138 if (attrs[counter].config == PERF_COUNT_SW_CPU_CLOCK)
139 return 1;
140
141 if (attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
142 return 1; 142 return 1;
143 143
144 return 0; 144 return 0;
@@ -150,8 +150,8 @@ static inline int nsec_counter(int counter)
150static void read_counter(int counter) 150static void read_counter(int counter)
151{ 151{
152 u64 *count, single_count[3]; 152 u64 *count, single_count[3];
153 ssize_t res; 153 unsigned int cpu;
154 int cpu, nv; 154 size_t res, nv;
155 int scaled; 155 int scaled;
156 156
157 count = event_res[run_idx][counter]; 157 count = event_res[run_idx][counter];
@@ -165,6 +165,7 @@ static void read_counter(int counter)
165 165
166 res = read(fd[cpu][counter], single_count, nv * sizeof(u64)); 166 res = read(fd[cpu][counter], single_count, nv * sizeof(u64));
167 assert(res == nv * sizeof(u64)); 167 assert(res == nv * sizeof(u64));
168
168 close(fd[cpu][counter]); 169 close(fd[cpu][counter]);
169 fd[cpu][counter] = -1; 170 fd[cpu][counter] = -1;
170 171
@@ -192,15 +193,13 @@ static void read_counter(int counter)
192 /* 193 /*
193 * Save the full runtime - to allow normalization during printout: 194 * Save the full runtime - to allow normalization during printout:
194 */ 195 */
195 if (attrs[counter].type == PERF_TYPE_SOFTWARE && 196 if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
196 attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
197 runtime_nsecs[run_idx] = count[0]; 197 runtime_nsecs[run_idx] = count[0];
198 if (attrs[counter].type == PERF_TYPE_HARDWARE && 198 if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter))
199 attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES)
200 runtime_cycles[run_idx] = count[0]; 199 runtime_cycles[run_idx] = count[0];
201} 200}
202 201
203static int run_perf_stat(int argc, const char **argv) 202static int run_perf_stat(int argc __used, const char **argv)
204{ 203{
205 unsigned long long t0, t1; 204 unsigned long long t0, t1;
206 int status = 0; 205 int status = 0;
@@ -240,7 +239,8 @@ static int run_perf_stat(int argc, const char **argv)
240 /* 239 /*
241 * Wait until the parent tells us to go. 240 * Wait until the parent tells us to go.
242 */ 241 */
243 read(go_pipe[0], &buf, 1); 242 if (read(go_pipe[0], &buf, 1) == -1)
243 perror("unable to read pipe");
244 244
245 execvp(argv[0], (char **)argv); 245 execvp(argv[0], (char **)argv);
246 246
@@ -253,7 +253,8 @@ static int run_perf_stat(int argc, const char **argv)
253 */ 253 */
254 close(child_ready_pipe[1]); 254 close(child_ready_pipe[1]);
255 close(go_pipe[0]); 255 close(go_pipe[0]);
256 read(child_ready_pipe[0], &buf, 1); 256 if (read(child_ready_pipe[0], &buf, 1) == -1)
257 perror("unable to read pipe");
257 close(child_ready_pipe[0]); 258 close(child_ready_pipe[0]);
258 259
259 for (counter = 0; counter < nr_counters; counter++) 260 for (counter = 0; counter < nr_counters; counter++)
@@ -290,9 +291,7 @@ static void nsec_printout(int counter, u64 *count, u64 *noise)
290 291
291 fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter)); 292 fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter));
292 293
293 if (attrs[counter].type == PERF_TYPE_SOFTWARE && 294 if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) {
294 attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) {
295
296 if (walltime_nsecs_avg) 295 if (walltime_nsecs_avg)
297 fprintf(stderr, " # %10.3f CPUs ", 296 fprintf(stderr, " # %10.3f CPUs ",
298 (double)count[0] / (double)walltime_nsecs_avg); 297 (double)count[0] / (double)walltime_nsecs_avg);
@@ -305,9 +304,7 @@ static void abs_printout(int counter, u64 *count, u64 *noise)
305 fprintf(stderr, " %14Ld %-24s", count[0], event_name(counter)); 304 fprintf(stderr, " %14Ld %-24s", count[0], event_name(counter));
306 305
307 if (runtime_cycles_avg && 306 if (runtime_cycles_avg &&
308 attrs[counter].type == PERF_TYPE_HARDWARE && 307 MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) {
309 attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) {
310
311 fprintf(stderr, " # %10.3f IPC ", 308 fprintf(stderr, " # %10.3f IPC ",
312 (double)count[0] / (double)runtime_cycles_avg); 309 (double)count[0] / (double)runtime_cycles_avg);
313 } else { 310 } else {
@@ -390,7 +387,7 @@ static void calc_avg(void)
390 event_res_avg[j]+1, event_res[i][j]+1); 387 event_res_avg[j]+1, event_res[i][j]+1);
391 update_avg("counter/2", j, 388 update_avg("counter/2", j,
392 event_res_avg[j]+2, event_res[i][j]+2); 389 event_res_avg[j]+2, event_res[i][j]+2);
393 if (event_scaled[i][j] != -1) 390 if (event_scaled[i][j] != (u64)-1)
394 update_avg("scaled", j, 391 update_avg("scaled", j,
395 event_scaled_avg + j, event_scaled[i]+j); 392 event_scaled_avg + j, event_scaled[i]+j);
396 else 393 else
@@ -510,11 +507,12 @@ static const struct option options[] = {
510 OPT_END() 507 OPT_END()
511}; 508};
512 509
513int cmd_stat(int argc, const char **argv, const char *prefix) 510int cmd_stat(int argc, const char **argv, const char *prefix __used)
514{ 511{
515 int status; 512 int status;
516 513
517 argc = parse_options(argc, argv, options, stat_usage, 0); 514 argc = parse_options(argc, argv, options, stat_usage,
515 PARSE_OPT_STOP_AT_NON_OPTION);
518 if (!argc) 516 if (!argc)
519 usage_with_options(stat_usage, options); 517 usage_with_options(stat_usage, options);
520 if (run_count <= 0 || run_count > MAX_RUN) 518 if (run_count <= 0 || run_count > MAX_RUN)
@@ -528,7 +526,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix)
528 526
529 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 527 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
530 assert(nr_cpus <= MAX_NR_CPUS); 528 assert(nr_cpus <= MAX_NR_CPUS);
531 assert(nr_cpus >= 0); 529 assert((int)nr_cpus >= 0);
532 530
533 /* 531 /*
534 * We dont want to block the signals - that would cause 532 * We dont want to block the signals - that would cause
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index cf0d21f1ae10..f139f1ab9333 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -23,7 +23,7 @@
23#include "util/symbol.h" 23#include "util/symbol.h"
24#include "util/color.h" 24#include "util/color.h"
25#include "util/util.h" 25#include "util/util.h"
26#include "util/rbtree.h" 26#include <linux/rbtree.h>
27#include "util/parse-options.h" 27#include "util/parse-options.h"
28#include "util/parse-events.h" 28#include "util/parse-events.h"
29 29
@@ -58,6 +58,7 @@ static u64 count_filter = 5;
58static int print_entries = 15; 58static int print_entries = 15;
59 59
60static int target_pid = -1; 60static int target_pid = -1;
61static int inherit = 0;
61static int profile_cpu = -1; 62static int profile_cpu = -1;
62static int nr_cpus = 0; 63static int nr_cpus = 0;
63static unsigned int realtime_prio = 0; 64static unsigned int realtime_prio = 0;
@@ -66,6 +67,7 @@ static unsigned int page_size;
66static unsigned int mmap_pages = 16; 67static unsigned int mmap_pages = 16;
67static int freq = 0; 68static int freq = 0;
68static int verbose = 0; 69static int verbose = 0;
70static char *vmlinux = NULL;
69 71
70static char *sym_filter; 72static char *sym_filter;
71static unsigned long filter_start; 73static unsigned long filter_start;
@@ -238,7 +240,6 @@ static void print_sym_table(void)
238 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { 240 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
239 struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node); 241 struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node);
240 struct symbol *sym = (struct symbol *)(syme + 1); 242 struct symbol *sym = (struct symbol *)(syme + 1);
241 char *color = PERF_COLOR_NORMAL;
242 double pcnt; 243 double pcnt;
243 244
244 if (++printed > print_entries || syme->snap_count < count_filter) 245 if (++printed > print_entries || syme->snap_count < count_filter)
@@ -247,29 +248,20 @@ static void print_sym_table(void)
247 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) / 248 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
248 sum_ksamples)); 249 sum_ksamples));
249 250
250 /*
251 * We color high-overhead entries in red, mid-overhead
252 * entries in green - and keep the low overhead places
253 * normal:
254 */
255 if (pcnt >= 5.0) {
256 color = PERF_COLOR_RED;
257 } else {
258 if (pcnt >= 0.5)
259 color = PERF_COLOR_GREEN;
260 }
261
262 if (nr_counters == 1) 251 if (nr_counters == 1)
263 printf("%20.2f - ", syme->weight); 252 printf("%20.2f - ", syme->weight);
264 else 253 else
265 printf("%9.1f %10ld - ", syme->weight, syme->snap_count); 254 printf("%9.1f %10ld - ", syme->weight, syme->snap_count);
266 255
267 color_fprintf(stdout, color, "%4.1f%%", pcnt); 256 percent_color_fprintf(stdout, "%4.1f%%", pcnt);
268 printf(" - %016llx : %s\n", sym->start, sym->name); 257 printf(" - %016llx : %s", sym->start, sym->name);
258 if (sym->module)
259 printf("\t[%s]", sym->module->name);
260 printf("\n");
269 } 261 }
270} 262}
271 263
272static void *display_thread(void *arg) 264static void *display_thread(void *arg __used)
273{ 265{
274 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 266 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
275 int delay_msecs = delay_secs * 1000; 267 int delay_msecs = delay_secs * 1000;
@@ -286,11 +278,32 @@ static void *display_thread(void *arg)
286 return NULL; 278 return NULL;
287} 279}
288 280
281/* Tag samples to be skipped. */
282static const char *skip_symbols[] = {
283 "default_idle",
284 "cpu_idle",
285 "enter_idle",
286 "exit_idle",
287 "mwait_idle",
288 "mwait_idle_with_hints",
289 "ppc64_runlatch_off",
290 "pseries_dedicated_idle_sleep",
291 NULL
292};
293
289static int symbol_filter(struct dso *self, struct symbol *sym) 294static int symbol_filter(struct dso *self, struct symbol *sym)
290{ 295{
291 static int filter_match; 296 static int filter_match;
292 struct sym_entry *syme; 297 struct sym_entry *syme;
293 const char *name = sym->name; 298 const char *name = sym->name;
299 int i;
300
301 /*
302 * ppc64 uses function descriptors and appends a '.' to the
303 * start of every instruction address. Remove it.
304 */
305 if (name[0] == '.')
306 name++;
294 307
295 if (!strcmp(name, "_text") || 308 if (!strcmp(name, "_text") ||
296 !strcmp(name, "_etext") || 309 !strcmp(name, "_etext") ||
@@ -302,13 +315,12 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
302 return 1; 315 return 1;
303 316
304 syme = dso__sym_priv(self, sym); 317 syme = dso__sym_priv(self, sym);
305 /* Tag samples to be skipped. */ 318 for (i = 0; skip_symbols[i]; i++) {
306 if (!strcmp("default_idle", name) || 319 if (!strcmp(skip_symbols[i], name)) {
307 !strcmp("cpu_idle", name) || 320 syme->skip = 1;
308 !strcmp("enter_idle", name) || 321 break;
309 !strcmp("exit_idle", name) || 322 }
310 !strcmp("mwait_idle", name)) 323 }
311 syme->skip = 1;
312 324
313 if (filter_match == 1) { 325 if (filter_match == 1) {
314 filter_end = sym->start; 326 filter_end = sym->start;
@@ -340,12 +352,13 @@ static int parse_symbols(void)
340{ 352{
341 struct rb_node *node; 353 struct rb_node *node;
342 struct symbol *sym; 354 struct symbol *sym;
355 int modules = vmlinux ? 1 : 0;
343 356
344 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry)); 357 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry));
345 if (kernel_dso == NULL) 358 if (kernel_dso == NULL)
346 return -1; 359 return -1;
347 360
348 if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1) != 0) 361 if (dso__load_kernel(kernel_dso, vmlinux, symbol_filter, verbose, modules) <= 0)
349 goto out_delete_dso; 362 goto out_delete_dso;
350 363
351 node = rb_first(&kernel_dso->syms); 364 node = rb_first(&kernel_dso->syms);
@@ -407,7 +420,7 @@ static void process_event(u64 ip, int counter, int user)
407struct mmap_data { 420struct mmap_data {
408 int counter; 421 int counter;
409 void *base; 422 void *base;
410 unsigned int mask; 423 int mask;
411 unsigned int prev; 424 unsigned int prev;
412}; 425};
413 426
@@ -538,7 +551,7 @@ int group_fd;
538static void start_counter(int i, int counter) 551static void start_counter(int i, int counter)
539{ 552{
540 struct perf_counter_attr *attr; 553 struct perf_counter_attr *attr;
541 unsigned int cpu; 554 int cpu;
542 555
543 cpu = profile_cpu; 556 cpu = profile_cpu;
544 if (target_pid == -1 && profile_cpu == -1) 557 if (target_pid == -1 && profile_cpu == -1)
@@ -548,6 +561,7 @@ static void start_counter(int i, int counter)
548 561
549 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 562 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
550 attr->freq = freq; 563 attr->freq = freq;
564 attr->inherit = (cpu < 0) && inherit;
551 565
552try_again: 566try_again:
553 fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0); 567 fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0);
@@ -661,6 +675,7 @@ static const struct option options[] = {
661 "system-wide collection from all CPUs"), 675 "system-wide collection from all CPUs"),
662 OPT_INTEGER('C', "CPU", &profile_cpu, 676 OPT_INTEGER('C', "CPU", &profile_cpu,
663 "CPU to profile on"), 677 "CPU to profile on"),
678 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
664 OPT_INTEGER('m', "mmap-pages", &mmap_pages, 679 OPT_INTEGER('m', "mmap-pages", &mmap_pages,
665 "number of mmap data pages"), 680 "number of mmap data pages"),
666 OPT_INTEGER('r', "realtime", &realtime_prio, 681 OPT_INTEGER('r', "realtime", &realtime_prio,
@@ -673,9 +688,11 @@ static const struct option options[] = {
673 "only display functions with more events than this"), 688 "only display functions with more events than this"),
674 OPT_BOOLEAN('g', "group", &group, 689 OPT_BOOLEAN('g', "group", &group,
675 "put the counters into a counter group"), 690 "put the counters into a counter group"),
691 OPT_BOOLEAN('i', "inherit", &inherit,
692 "child tasks inherit counters"),
676 OPT_STRING('s', "sym-filter", &sym_filter, "pattern", 693 OPT_STRING('s', "sym-filter", &sym_filter, "pattern",
677 "only display symbols matchig this pattern"), 694 "only display symbols matchig this pattern"),
678 OPT_BOOLEAN('z', "zero", &group, 695 OPT_BOOLEAN('z', "zero", &zero,
679 "zero history across updates"), 696 "zero history across updates"),
680 OPT_INTEGER('F', "freq", &freq, 697 OPT_INTEGER('F', "freq", &freq,
681 "profile at this frequency"), 698 "profile at this frequency"),
@@ -686,10 +703,12 @@ static const struct option options[] = {
686 OPT_END() 703 OPT_END()
687}; 704};
688 705
689int cmd_top(int argc, const char **argv, const char *prefix) 706int cmd_top(int argc, const char **argv, const char *prefix __used)
690{ 707{
691 int counter; 708 int counter;
692 709
710 symbol__init();
711
693 page_size = sysconf(_SC_PAGE_SIZE); 712 page_size = sysconf(_SC_PAGE_SIZE);
694 713
695 argc = parse_options(argc, argv, options, top_usage, 0); 714 argc = parse_options(argc, argv, options, top_usage, 0);
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 4eb725933703..31982ad064b4 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -12,6 +12,8 @@
12#include "util/cache.h" 12#include "util/cache.h"
13#include "util/quote.h" 13#include "util/quote.h"
14#include "util/run-command.h" 14#include "util/run-command.h"
15#include "util/parse-events.h"
16#include "util/string.h"
15 17
16const char perf_usage_string[] = 18const char perf_usage_string[] =
17 "perf [--version] [--help] COMMAND [ARGS]"; 19 "perf [--version] [--help] COMMAND [ARGS]";
@@ -25,6 +27,8 @@ struct pager_config {
25 int val; 27 int val;
26}; 28};
27 29
30static char debugfs_mntpt[MAXPATHLEN];
31
28static int pager_command_config(const char *var, const char *value, void *data) 32static int pager_command_config(const char *var, const char *value, void *data)
29{ 33{
30 struct pager_config *c = data; 34 struct pager_config *c = data;
@@ -56,6 +60,15 @@ static void commit_pager_choice(void) {
56 } 60 }
57} 61}
58 62
63static void set_debugfs_path(void)
64{
65 char *path;
66
67 path = getenv(PERF_DEBUGFS_ENVIRONMENT);
68 snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt,
69 "tracing/events");
70}
71
59static int handle_options(const char*** argv, int* argc, int* envchanged) 72static int handle_options(const char*** argv, int* argc, int* envchanged)
60{ 73{
61 int handled = 0; 74 int handled = 0;
@@ -122,6 +135,22 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
122 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1); 135 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
123 if (envchanged) 136 if (envchanged)
124 *envchanged = 1; 137 *envchanged = 1;
138 } else if (!strcmp(cmd, "--debugfs-dir")) {
139 if (*argc < 2) {
140 fprintf(stderr, "No directory given for --debugfs-dir.\n");
141 usage(perf_usage_string);
142 }
143 strncpy(debugfs_mntpt, (*argv)[1], MAXPATHLEN);
144 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
145 if (envchanged)
146 *envchanged = 1;
147 (*argv)++;
148 (*argc)--;
149 } else if (!prefixcmp(cmd, "--debugfs-dir=")) {
150 strncpy(debugfs_mntpt, cmd + 14, MAXPATHLEN);
151 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
152 if (envchanged)
153 *envchanged = 1;
125 } else { 154 } else {
126 fprintf(stderr, "Unknown option: %s\n", cmd); 155 fprintf(stderr, "Unknown option: %s\n", cmd);
127 usage(perf_usage_string); 156 usage(perf_usage_string);
@@ -228,9 +257,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
228 if (use_pager == -1 && p->option & USE_PAGER) 257 if (use_pager == -1 && p->option & USE_PAGER)
229 use_pager = 1; 258 use_pager = 1;
230 commit_pager_choice(); 259 commit_pager_choice();
231 260 set_debugfs_path();
232 if (p->option & NEED_WORK_TREE)
233 /* setup_work_tree() */;
234 261
235 status = p->fn(argc, argv, prefix); 262 status = p->fn(argc, argv, prefix);
236 if (status) 263 if (status)
@@ -266,7 +293,7 @@ static void handle_internal_command(int argc, const char **argv)
266 { "annotate", cmd_annotate, 0 }, 293 { "annotate", cmd_annotate, 0 },
267 { "version", cmd_version, 0 }, 294 { "version", cmd_version, 0 },
268 }; 295 };
269 int i; 296 unsigned int i;
270 static const char ext[] = STRIP_EXTENSION; 297 static const char ext[] = STRIP_EXTENSION;
271 298
272 if (sizeof(ext) > 1) { 299 if (sizeof(ext) > 1) {
@@ -349,6 +376,49 @@ static int run_argv(int *argcp, const char ***argv)
349 return done_alias; 376 return done_alias;
350} 377}
351 378
379/* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */
380static void get_debugfs_mntpt(void)
381{
382 FILE *file;
383 char fs_type[100];
384 char debugfs[MAXPATHLEN];
385
386 /*
387 * try the standard location
388 */
389 if (valid_debugfs_mount("/sys/kernel/debug/") == 0) {
390 strcpy(debugfs_mntpt, "/sys/kernel/debug/");
391 return;
392 }
393
394 /*
395 * try the sane location
396 */
397 if (valid_debugfs_mount("/debug/") == 0) {
398 strcpy(debugfs_mntpt, "/debug/");
399 return;
400 }
401
402 /*
403 * give up and parse /proc/mounts
404 */
405 file = fopen("/proc/mounts", "r");
406 if (file == NULL)
407 return;
408
409 while (fscanf(file, "%*s %"
410 STR(MAXPATHLEN)
411 "s %99s %*s %*d %*d\n",
412 debugfs, fs_type) == 2) {
413 if (strcmp(fs_type, "debugfs") == 0)
414 break;
415 }
416 fclose(file);
417 if (strcmp(fs_type, "debugfs") == 0) {
418 strncpy(debugfs_mntpt, debugfs, MAXPATHLEN);
419 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
420 }
421}
352 422
353int main(int argc, const char **argv) 423int main(int argc, const char **argv)
354{ 424{
@@ -357,7 +427,8 @@ int main(int argc, const char **argv)
357 cmd = perf_extract_argv0_path(argv[0]); 427 cmd = perf_extract_argv0_path(argv[0]);
358 if (!cmd) 428 if (!cmd)
359 cmd = "perf-help"; 429 cmd = "perf-help";
360 430 /* get debugfs mount point from /proc/mounts */
431 get_debugfs_mntpt();
361 /* 432 /*
362 * "perf-xxxx" is the same as "perf xxxx", but we obviously: 433 * "perf-xxxx" is the same as "perf xxxx", but we obviously:
363 * 434 *
@@ -380,6 +451,7 @@ int main(int argc, const char **argv)
380 argc--; 451 argc--;
381 handle_options(&argv, &argc, NULL); 452 handle_options(&argv, &argc, NULL);
382 commit_pager_choice(); 453 commit_pager_choice();
454 set_debugfs_path();
383 if (argc > 0) { 455 if (argc > 0) {
384 if (!prefixcmp(argv[0], "--")) 456 if (!prefixcmp(argv[0], "--"))
385 argv[0] += 2; 457 argv[0] += 2;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index d3042a6ba03d..e5148e2b6134 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -1,7 +1,13 @@
1#ifndef _PERF_PERF_H 1#ifndef _PERF_PERF_H
2#define _PERF_PERF_H 2#define _PERF_PERF_H
3 3
4#if defined(__x86_64__) || defined(__i386__) 4#if defined(__i386__)
5#include "../../arch/x86/include/asm/unistd.h"
6#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
7#define cpu_relax() asm volatile("rep; nop" ::: "memory");
8#endif
9
10#if defined(__x86_64__)
5#include "../../arch/x86/include/asm/unistd.h" 11#include "../../arch/x86/include/asm/unistd.h"
6#define rmb() asm volatile("lfence" ::: "memory") 12#define rmb() asm volatile("lfence" ::: "memory")
7#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 13#define cpu_relax() asm volatile("rep; nop" ::: "memory");
@@ -68,6 +74,8 @@ static inline unsigned long long rdclock(void)
68#define __user 74#define __user
69#define asmlinkage 75#define asmlinkage
70 76
77#define __used __attribute__((__unused__))
78
71#define unlikely(x) __builtin_expect(!!(x), 0) 79#define unlikely(x) __builtin_expect(!!(x), 0)
72#define min(x, y) ({ \ 80#define min(x, y) ({ \
73 typeof(x) _min1 = (x); \ 81 typeof(x) _min1 = (x); \
diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c
index 9b3dd2b428df..b8144e80bb1e 100644
--- a/tools/perf/util/alias.c
+++ b/tools/perf/util/alias.c
@@ -3,7 +3,7 @@
3static const char *alias_key; 3static const char *alias_key;
4static char *alias_val; 4static char *alias_val;
5 5
6static int alias_lookup_cb(const char *k, const char *v, void *cb) 6static int alias_lookup_cb(const char *k, const char *v, void *cb __used)
7{ 7{
8 if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) { 8 if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) {
9 if (!v) 9 if (!v)
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 393d6146d13b..4b50c412b9c5 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -3,6 +3,7 @@
3 3
4#include "util.h" 4#include "util.h"
5#include "strbuf.h" 5#include "strbuf.h"
6#include "../perf.h"
6 7
7#define PERF_DIR_ENVIRONMENT "PERF_DIR" 8#define PERF_DIR_ENVIRONMENT "PERF_DIR"
8#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE" 9#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE"
@@ -17,6 +18,7 @@
17#define PERFATTRIBUTES_FILE ".perfattributes" 18#define PERFATTRIBUTES_FILE ".perfattributes"
18#define INFOATTRIBUTES_FILE "info/attributes" 19#define INFOATTRIBUTES_FILE "info/attributes"
19#define ATTRIBUTE_MACRO_PREFIX "[attr]" 20#define ATTRIBUTE_MACRO_PREFIX "[attr]"
21#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
20 22
21typedef int (*config_fn_t)(const char *, const char *, void *); 23typedef int (*config_fn_t)(const char *, const char *, void *);
22extern int perf_default_config(const char *, const char *, void *); 24extern int perf_default_config(const char *, const char *, void *);
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index ad3c28578961..9d3c8141b8c1 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -4,6 +4,9 @@
4 * Handle the callchains from the stream in an ad-hoc radix tree and then 4 * Handle the callchains from the stream in an ad-hoc radix tree and then
5 * sort them in an rbtree. 5 * sort them in an rbtree.
6 * 6 *
7 * Using a radix for code path provides a fast retrieval and factorizes
8 * memory use. Also that lets us use the paths in a hierarchical graph view.
9 *
7 */ 10 */
8 11
9#include <stdlib.h> 12#include <stdlib.h>
@@ -13,8 +16,12 @@
13 16
14#include "callchain.h" 17#include "callchain.h"
15 18
19#define chain_for_each_child(child, parent) \
20 list_for_each_entry(child, &parent->children, brothers)
16 21
17static void rb_insert_callchain(struct rb_root *root, struct callchain_node *chain) 22static void
23rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
24 enum chain_mode mode)
18{ 25{
19 struct rb_node **p = &root->rb_node; 26 struct rb_node **p = &root->rb_node;
20 struct rb_node *parent = NULL; 27 struct rb_node *parent = NULL;
@@ -24,32 +31,125 @@ static void rb_insert_callchain(struct rb_root *root, struct callchain_node *cha
24 parent = *p; 31 parent = *p;
25 rnode = rb_entry(parent, struct callchain_node, rb_node); 32 rnode = rb_entry(parent, struct callchain_node, rb_node);
26 33
27 if (rnode->hit < chain->hit) 34 switch (mode) {
28 p = &(*p)->rb_left; 35 case CHAIN_FLAT:
29 else 36 if (rnode->hit < chain->hit)
30 p = &(*p)->rb_right; 37 p = &(*p)->rb_left;
38 else
39 p = &(*p)->rb_right;
40 break;
41 case CHAIN_GRAPH_ABS: /* Falldown */
42 case CHAIN_GRAPH_REL:
43 if (rnode->cumul_hit < chain->cumul_hit)
44 p = &(*p)->rb_left;
45 else
46 p = &(*p)->rb_right;
47 break;
48 default:
49 break;
50 }
31 } 51 }
32 52
33 rb_link_node(&chain->rb_node, parent, p); 53 rb_link_node(&chain->rb_node, parent, p);
34 rb_insert_color(&chain->rb_node, root); 54 rb_insert_color(&chain->rb_node, root);
35} 55}
36 56
57static void
58__sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
59 u64 min_hit)
60{
61 struct callchain_node *child;
62
63 chain_for_each_child(child, node)
64 __sort_chain_flat(rb_root, child, min_hit);
65
66 if (node->hit && node->hit >= min_hit)
67 rb_insert_callchain(rb_root, node, CHAIN_FLAT);
68}
69
37/* 70/*
38 * Once we get every callchains from the stream, we can now 71 * Once we get every callchains from the stream, we can now
39 * sort them by hit 72 * sort them by hit
40 */ 73 */
41void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node) 74static void
75sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
76 u64 min_hit, struct callchain_param *param __used)
77{
78 __sort_chain_flat(rb_root, node, min_hit);
79}
80
81static void __sort_chain_graph_abs(struct callchain_node *node,
82 u64 min_hit)
83{
84 struct callchain_node *child;
85
86 node->rb_root = RB_ROOT;
87
88 chain_for_each_child(child, node) {
89 __sort_chain_graph_abs(child, min_hit);
90 if (child->cumul_hit >= min_hit)
91 rb_insert_callchain(&node->rb_root, child,
92 CHAIN_GRAPH_ABS);
93 }
94}
95
96static void
97sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_node *chain_root,
98 u64 min_hit, struct callchain_param *param __used)
99{
100 __sort_chain_graph_abs(chain_root, min_hit);
101 rb_root->rb_node = chain_root->rb_root.rb_node;
102}
103
104static void __sort_chain_graph_rel(struct callchain_node *node,
105 double min_percent)
42{ 106{
43 struct callchain_node *child; 107 struct callchain_node *child;
108 u64 min_hit;
44 109
45 list_for_each_entry(child, &node->children, brothers) 110 node->rb_root = RB_ROOT;
46 sort_chain_to_rbtree(rb_root, child); 111 min_hit = node->cumul_hit * min_percent / 100.0;
47 112
48 if (node->hit) 113 chain_for_each_child(child, node) {
49 rb_insert_callchain(rb_root, node); 114 __sort_chain_graph_rel(child, min_percent);
115 if (child->cumul_hit >= min_hit)
116 rb_insert_callchain(&node->rb_root, child,
117 CHAIN_GRAPH_REL);
118 }
50} 119}
51 120
52static struct callchain_node *create_child(struct callchain_node *parent) 121static void
122sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_node *chain_root,
123 u64 min_hit __used, struct callchain_param *param)
124{
125 __sort_chain_graph_rel(chain_root, param->min_percent);
126 rb_root->rb_node = chain_root->rb_root.rb_node;
127}
128
129int register_callchain_param(struct callchain_param *param)
130{
131 switch (param->mode) {
132 case CHAIN_GRAPH_ABS:
133 param->sort = sort_chain_graph_abs;
134 break;
135 case CHAIN_GRAPH_REL:
136 param->sort = sort_chain_graph_rel;
137 break;
138 case CHAIN_FLAT:
139 param->sort = sort_chain_flat;
140 break;
141 default:
142 return -1;
143 }
144 return 0;
145}
146
147/*
148 * Create a child for a parent. If inherit_children, then the new child
149 * will become the new parent of it's parent children
150 */
151static struct callchain_node *
152create_child(struct callchain_node *parent, bool inherit_children)
53{ 153{
54 struct callchain_node *new; 154 struct callchain_node *new;
55 155
@@ -61,91 +161,147 @@ static struct callchain_node *create_child(struct callchain_node *parent)
61 new->parent = parent; 161 new->parent = parent;
62 INIT_LIST_HEAD(&new->children); 162 INIT_LIST_HEAD(&new->children);
63 INIT_LIST_HEAD(&new->val); 163 INIT_LIST_HEAD(&new->val);
164
165 if (inherit_children) {
166 struct callchain_node *next;
167
168 list_splice(&parent->children, &new->children);
169 INIT_LIST_HEAD(&parent->children);
170
171 chain_for_each_child(next, new)
172 next->parent = new;
173 }
64 list_add_tail(&new->brothers, &parent->children); 174 list_add_tail(&new->brothers, &parent->children);
65 175
66 return new; 176 return new;
67} 177}
68 178
179/*
180 * Fill the node with callchain values
181 */
69static void 182static void
70fill_node(struct callchain_node *node, struct ip_callchain *chain, int start) 183fill_node(struct callchain_node *node, struct ip_callchain *chain,
184 int start, struct symbol **syms)
71{ 185{
72 int i; 186 unsigned int i;
73 187
74 for (i = start; i < chain->nr; i++) { 188 for (i = start; i < chain->nr; i++) {
75 struct callchain_list *call; 189 struct callchain_list *call;
76 190
77 call = malloc(sizeof(*chain)); 191 call = malloc(sizeof(*call));
78 if (!call) { 192 if (!call) {
79 perror("not enough memory for the code path tree"); 193 perror("not enough memory for the code path tree");
80 return; 194 return;
81 } 195 }
82 call->ip = chain->ips[i]; 196 call->ip = chain->ips[i];
197 call->sym = syms[i];
83 list_add_tail(&call->list, &node->val); 198 list_add_tail(&call->list, &node->val);
84 } 199 }
85 node->val_nr = i - start; 200 node->val_nr = chain->nr - start;
201 if (!node->val_nr)
202 printf("Warning: empty node in callchain tree\n");
86} 203}
87 204
88static void add_child(struct callchain_node *parent, struct ip_callchain *chain) 205static void
206add_child(struct callchain_node *parent, struct ip_callchain *chain,
207 int start, struct symbol **syms)
89{ 208{
90 struct callchain_node *new; 209 struct callchain_node *new;
91 210
92 new = create_child(parent); 211 new = create_child(parent, false);
93 fill_node(new, chain, parent->val_nr); 212 fill_node(new, chain, start, syms);
94 213
95 new->hit = 1; 214 new->cumul_hit = new->hit = 1;
96} 215}
97 216
217/*
218 * Split the parent in two parts (a new child is created) and
219 * give a part of its callchain to the created child.
220 * Then create another child to host the given callchain of new branch
221 */
98static void 222static void
99split_add_child(struct callchain_node *parent, struct ip_callchain *chain, 223split_add_child(struct callchain_node *parent, struct ip_callchain *chain,
100 struct callchain_list *to_split, int idx) 224 struct callchain_list *to_split, int idx_parents, int idx_local,
225 struct symbol **syms)
101{ 226{
102 struct callchain_node *new; 227 struct callchain_node *new;
228 struct list_head *old_tail;
229 unsigned int idx_total = idx_parents + idx_local;
103 230
104 /* split */ 231 /* split */
105 new = create_child(parent); 232 new = create_child(parent, true);
106 list_move_tail(&to_split->list, &new->val);
107 new->hit = parent->hit;
108 parent->hit = 0;
109 parent->val_nr = idx;
110 233
111 /* create the new one */ 234 /* split the callchain and move a part to the new child */
112 add_child(parent, chain); 235 old_tail = parent->val.prev;
236 list_del_range(&to_split->list, old_tail);
237 new->val.next = &to_split->list;
238 new->val.prev = old_tail;
239 to_split->list.prev = &new->val;
240 old_tail->next = &new->val;
241
242 /* split the hits */
243 new->hit = parent->hit;
244 new->cumul_hit = parent->cumul_hit;
245 new->val_nr = parent->val_nr - idx_local;
246 parent->val_nr = idx_local;
247
248 /* create a new child for the new branch if any */
249 if (idx_total < chain->nr) {
250 parent->hit = 0;
251 add_child(parent, chain, idx_total, syms);
252 } else {
253 parent->hit = 1;
254 }
113} 255}
114 256
115static int 257static int
116__append_chain(struct callchain_node *root, struct ip_callchain *chain, 258__append_chain(struct callchain_node *root, struct ip_callchain *chain,
117 int start); 259 unsigned int start, struct symbol **syms);
118 260
119static int 261static void
120__append_chain_children(struct callchain_node *root, struct ip_callchain *chain) 262__append_chain_children(struct callchain_node *root, struct ip_callchain *chain,
263 struct symbol **syms, unsigned int start)
121{ 264{
122 struct callchain_node *rnode; 265 struct callchain_node *rnode;
123 266
124 /* lookup in childrens */ 267 /* lookup in childrens */
125 list_for_each_entry(rnode, &root->children, brothers) { 268 chain_for_each_child(rnode, root) {
126 int ret = __append_chain(rnode, chain, root->val_nr); 269 unsigned int ret = __append_chain(rnode, chain, start, syms);
270
127 if (!ret) 271 if (!ret)
128 return 0; 272 goto cumul;
129 } 273 }
130 return -1; 274 /* nothing in children, add to the current node */
275 add_child(root, chain, start, syms);
276
277cumul:
278 root->cumul_hit++;
131} 279}
132 280
133static int 281static int
134__append_chain(struct callchain_node *root, struct ip_callchain *chain, 282__append_chain(struct callchain_node *root, struct ip_callchain *chain,
135 int start) 283 unsigned int start, struct symbol **syms)
136{ 284{
137 struct callchain_list *cnode; 285 struct callchain_list *cnode;
138 int i = start; 286 unsigned int i = start;
139 bool found = false; 287 bool found = false;
140 288
141 /* lookup in the current node */ 289 /*
290 * Lookup in the current node
291 * If we have a symbol, then compare the start to match
292 * anywhere inside a function.
293 */
142 list_for_each_entry(cnode, &root->val, list) { 294 list_for_each_entry(cnode, &root->val, list) {
143 if (cnode->ip != chain->ips[i++]) 295 if (i == chain->nr)
296 break;
297 if (cnode->sym && syms[i]) {
298 if (cnode->sym->start != syms[i]->start)
299 break;
300 } else if (cnode->ip != chain->ips[i])
144 break; 301 break;
145 if (!found) 302 if (!found)
146 found = true; 303 found = true;
147 if (i == chain->nr) 304 i++;
148 break;
149 } 305 }
150 306
151 /* matches not, relay on the parent */ 307 /* matches not, relay on the parent */
@@ -153,22 +309,27 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain,
153 return -1; 309 return -1;
154 310
155 /* we match only a part of the node. Split it and add the new chain */ 311 /* we match only a part of the node. Split it and add the new chain */
156 if (i < root->val_nr) { 312 if (i - start < root->val_nr) {
157 split_add_child(root, chain, cnode, i); 313 split_add_child(root, chain, cnode, start, i - start, syms);
158 return 0; 314 return 0;
159 } 315 }
160 316
161 /* we match 100% of the path, increment the hit */ 317 /* we match 100% of the path, increment the hit */
162 if (i == root->val_nr) { 318 if (i - start == root->val_nr && i == chain->nr) {
163 root->hit++; 319 root->hit++;
320 root->cumul_hit++;
321
164 return 0; 322 return 0;
165 } 323 }
166 324
167 return __append_chain_children(root, chain); 325 /* We match the node and still have a part remaining */
326 __append_chain_children(root, chain, syms, i);
327
328 return 0;
168} 329}
169 330
170void append_chain(struct callchain_node *root, struct ip_callchain *chain) 331void append_chain(struct callchain_node *root, struct ip_callchain *chain,
332 struct symbol **syms)
171{ 333{
172 if (__append_chain_children(root, chain) == -1) 334 __append_chain_children(root, chain, syms, 0);
173 add_child(root, chain);
174} 335}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index fa1cd2f71fd3..7812122bea1d 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -2,22 +2,42 @@
2#define __PERF_CALLCHAIN_H 2#define __PERF_CALLCHAIN_H
3 3
4#include "../perf.h" 4#include "../perf.h"
5#include "list.h" 5#include <linux/list.h>
6#include "rbtree.h" 6#include <linux/rbtree.h>
7#include "symbol.h"
7 8
9enum chain_mode {
10 CHAIN_FLAT,
11 CHAIN_GRAPH_ABS,
12 CHAIN_GRAPH_REL
13};
8 14
9struct callchain_node { 15struct callchain_node {
10 struct callchain_node *parent; 16 struct callchain_node *parent;
11 struct list_head brothers; 17 struct list_head brothers;
12 struct list_head children; 18 struct list_head children;
13 struct list_head val; 19 struct list_head val;
14 struct rb_node rb_node; 20 struct rb_node rb_node; /* to sort nodes in an rbtree */
15 int val_nr; 21 struct rb_root rb_root; /* sorted tree of children */
16 int hit; 22 unsigned int val_nr;
23 u64 hit;
24 u64 cumul_hit; /* hit + hits of children */
25};
26
27struct callchain_param;
28
29typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *,
30 u64, struct callchain_param *);
31
32struct callchain_param {
33 enum chain_mode mode;
34 double min_percent;
35 sort_chain_func_t sort;
17}; 36};
18 37
19struct callchain_list { 38struct callchain_list {
20 unsigned long ip; 39 u64 ip;
40 struct symbol *sym;
21 struct list_head list; 41 struct list_head list;
22}; 42};
23 43
@@ -28,6 +48,7 @@ static inline void callchain_init(struct callchain_node *node)
28 INIT_LIST_HEAD(&node->val); 48 INIT_LIST_HEAD(&node->val);
29} 49}
30 50
31void append_chain(struct callchain_node *root, struct ip_callchain *chain); 51int register_callchain_param(struct callchain_param *param);
32void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node); 52void append_chain(struct callchain_node *root, struct ip_callchain *chain,
53 struct symbol **syms);
33#endif 54#endif
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 9a8c20ccc53e..90a044d1fe7d 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -11,7 +11,8 @@ static int parse_color(const char *name, int len)
11 }; 11 };
12 char *end; 12 char *end;
13 int i; 13 int i;
14 for (i = 0; i < ARRAY_SIZE(color_names); i++) { 14
15 for (i = 0; i < (int)ARRAY_SIZE(color_names); i++) {
15 const char *str = color_names[i]; 16 const char *str = color_names[i];
16 if (!strncasecmp(name, str, len) && !str[len]) 17 if (!strncasecmp(name, str, len) && !str[len])
17 return i - 1; 18 return i - 1;
@@ -28,7 +29,8 @@ static int parse_attr(const char *name, int len)
28 static const char * const attr_names[] = { 29 static const char * const attr_names[] = {
29 "bold", "dim", "ul", "blink", "reverse" 30 "bold", "dim", "ul", "blink", "reverse"
30 }; 31 };
31 int i; 32 unsigned int i;
33
32 for (i = 0; i < ARRAY_SIZE(attr_names); i++) { 34 for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
33 const char *str = attr_names[i]; 35 const char *str = attr_names[i];
34 if (!strncasecmp(name, str, len) && !str[len]) 36 if (!strncasecmp(name, str, len) && !str[len])
@@ -222,10 +224,12 @@ int color_fwrite_lines(FILE *fp, const char *color,
222{ 224{
223 if (!*color) 225 if (!*color)
224 return fwrite(buf, count, 1, fp) != 1; 226 return fwrite(buf, count, 1, fp) != 1;
227
225 while (count) { 228 while (count) {
226 char *p = memchr(buf, '\n', count); 229 char *p = memchr(buf, '\n', count);
230
227 if (p != buf && (fputs(color, fp) < 0 || 231 if (p != buf && (fputs(color, fp) < 0 ||
228 fwrite(buf, p ? p - buf : count, 1, fp) != 1 || 232 fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 ||
229 fputs(PERF_COLOR_RESET, fp) < 0)) 233 fputs(PERF_COLOR_RESET, fp) < 0))
230 return -1; 234 return -1;
231 if (!p) 235 if (!p)
@@ -238,4 +242,31 @@ int color_fwrite_lines(FILE *fp, const char *color,
238 return 0; 242 return 0;
239} 243}
240 244
245char *get_percent_color(double percent)
246{
247 char *color = PERF_COLOR_NORMAL;
241 248
249 /*
250 * We color high-overhead entries in red, mid-overhead
251 * entries in green - and keep the low overhead places
252 * normal:
253 */
254 if (percent >= MIN_RED)
255 color = PERF_COLOR_RED;
256 else {
257 if (percent > MIN_GREEN)
258 color = PERF_COLOR_GREEN;
259 }
260 return color;
261}
262
263int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
264{
265 int r;
266 char *color;
267
268 color = get_percent_color(percent);
269 r = color_fprintf(fp, color, fmt, percent);
270
271 return r;
272}
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 5abfd379582b..706cec50bd25 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -15,6 +15,9 @@
15#define PERF_COLOR_CYAN "\033[36m" 15#define PERF_COLOR_CYAN "\033[36m"
16#define PERF_COLOR_BG_RED "\033[41m" 16#define PERF_COLOR_BG_RED "\033[41m"
17 17
18#define MIN_GREEN 0.5
19#define MIN_RED 5.0
20
18/* 21/*
19 * This variable stores the value of color.ui 22 * This variable stores the value of color.ui
20 */ 23 */
@@ -32,5 +35,7 @@ void color_parse_mem(const char *value, int len, const char *var, char *dst);
32int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); 35int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
33int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); 36int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
34int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); 37int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
38int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
39char *get_percent_color(double percent);
35 40
36#endif /* COLOR_H */ 41#endif /* COLOR_H */
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 3dd13faa6a27..780df541006d 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -47,10 +47,12 @@ static int get_next_char(void)
47static char *parse_value(void) 47static char *parse_value(void)
48{ 48{
49 static char value[1024]; 49 static char value[1024];
50 int quote = 0, comment = 0, len = 0, space = 0; 50 int quote = 0, comment = 0, space = 0;
51 size_t len = 0;
51 52
52 for (;;) { 53 for (;;) {
53 int c = get_next_char(); 54 int c = get_next_char();
55
54 if (len >= sizeof(value) - 1) 56 if (len >= sizeof(value) - 1)
55 return NULL; 57 return NULL;
56 if (c == '\n') { 58 if (c == '\n') {
@@ -353,13 +355,13 @@ int perf_config_string(const char **dest, const char *var, const char *value)
353 return 0; 355 return 0;
354} 356}
355 357
356static int perf_default_core_config(const char *var, const char *value) 358static int perf_default_core_config(const char *var __used, const char *value __used)
357{ 359{
358 /* Add other config variables here and to Documentation/config.txt. */ 360 /* Add other config variables here and to Documentation/config.txt. */
359 return 0; 361 return 0;
360} 362}
361 363
362int perf_default_config(const char *var, const char *value, void *dummy) 364int perf_default_config(const char *var, const char *value, void *dummy __used)
363{ 365{
364 if (!prefixcmp(var, "core.")) 366 if (!prefixcmp(var, "core."))
365 return perf_default_core_config(var, value); 367 return perf_default_core_config(var, value);
@@ -471,10 +473,10 @@ static int matches(const char* key, const char* value)
471 !regexec(store.value_regex, value, 0, NULL, 0))); 473 !regexec(store.value_regex, value, 0, NULL, 0)));
472} 474}
473 475
474static int store_aux(const char* key, const char* value, void *cb) 476static int store_aux(const char* key, const char* value, void *cb __used)
475{ 477{
478 int section_len;
476 const char *ep; 479 const char *ep;
477 size_t section_len;
478 480
479 switch (store.state) { 481 switch (store.state) {
480 case KEY_SEEN: 482 case KEY_SEEN:
@@ -551,7 +553,7 @@ static int store_write_section(int fd, const char* key)
551 strbuf_addf(&sb, "[%.*s]\n", store.baselen, key); 553 strbuf_addf(&sb, "[%.*s]\n", store.baselen, key);
552 } 554 }
553 555
554 success = write_in_full(fd, sb.buf, sb.len) == sb.len; 556 success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len);
555 strbuf_release(&sb); 557 strbuf_release(&sb);
556 558
557 return success; 559 return success;
@@ -599,7 +601,7 @@ static int store_write_pair(int fd, const char* key, const char* value)
599 } 601 }
600 strbuf_addf(&sb, "%s\n", quote); 602 strbuf_addf(&sb, "%s\n", quote);
601 603
602 success = write_in_full(fd, sb.buf, sb.len) == sb.len; 604 success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len);
603 strbuf_release(&sb); 605 strbuf_release(&sb);
604 606
605 return success; 607 return success;
@@ -741,7 +743,7 @@ int perf_config_set_multivar(const char* key, const char* value,
741 } else { 743 } else {
742 struct stat st; 744 struct stat st;
743 char* contents; 745 char* contents;
744 size_t contents_sz, copy_begin, copy_end; 746 ssize_t contents_sz, copy_begin, copy_end;
745 int i, new_line = 0; 747 int i, new_line = 0;
746 748
747 if (value_regex == NULL) 749 if (value_regex == NULL)
diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
index d39292263153..34a352867382 100644
--- a/tools/perf/util/exec_cmd.c
+++ b/tools/perf/util/exec_cmd.c
@@ -1,6 +1,9 @@
1#include "cache.h" 1#include "cache.h"
2#include "exec_cmd.h" 2#include "exec_cmd.h"
3#include "quote.h" 3#include "quote.h"
4
5#include <string.h>
6
4#define MAX_ARGS 32 7#define MAX_ARGS 32
5 8
6extern char **environ; 9extern char **environ;
@@ -51,7 +54,7 @@ const char *perf_extract_argv0_path(const char *argv0)
51 slash--; 54 slash--;
52 55
53 if (slash >= argv0) { 56 if (slash >= argv0) {
54 argv0_path = strndup(argv0, slash - argv0); 57 argv0_path = xstrndup(argv0, slash - argv0);
55 return slash + 1; 58 return slash + 1;
56 } 59 }
57 60
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index b5ef53ad4c7a..bf280449fcfd 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -16,7 +16,7 @@ struct perf_header {
16 int frozen; 16 int frozen;
17 int attrs, size; 17 int attrs, size;
18 struct perf_header_attr **attr; 18 struct perf_header_attr **attr;
19 off_t attr_offset; 19 s64 attr_offset;
20 u64 data_offset; 20 u64 data_offset;
21 u64 data_size; 21 u64 data_size;
22}; 22};
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
index 17a00e0df2c4..fbb00978b2e2 100644
--- a/tools/perf/util/help.c
+++ b/tools/perf/util/help.c
@@ -26,7 +26,7 @@ static int term_columns(void)
26 return 80; 26 return 80;
27} 27}
28 28
29void add_cmdname(struct cmdnames *cmds, const char *name, int len) 29void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
30{ 30{
31 struct cmdname *ent = malloc(sizeof(*ent) + len + 1); 31 struct cmdname *ent = malloc(sizeof(*ent) + len + 1);
32 32
@@ -40,7 +40,8 @@ void add_cmdname(struct cmdnames *cmds, const char *name, int len)
40 40
41static void clean_cmdnames(struct cmdnames *cmds) 41static void clean_cmdnames(struct cmdnames *cmds)
42{ 42{
43 int i; 43 unsigned int i;
44
44 for (i = 0; i < cmds->cnt; ++i) 45 for (i = 0; i < cmds->cnt; ++i)
45 free(cmds->names[i]); 46 free(cmds->names[i]);
46 free(cmds->names); 47 free(cmds->names);
@@ -57,7 +58,7 @@ static int cmdname_compare(const void *a_, const void *b_)
57 58
58static void uniq(struct cmdnames *cmds) 59static void uniq(struct cmdnames *cmds)
59{ 60{
60 int i, j; 61 unsigned int i, j;
61 62
62 if (!cmds->cnt) 63 if (!cmds->cnt)
63 return; 64 return;
@@ -71,7 +72,7 @@ static void uniq(struct cmdnames *cmds)
71 72
72void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) 73void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
73{ 74{
74 int ci, cj, ei; 75 size_t ci, cj, ei;
75 int cmp; 76 int cmp;
76 77
77 ci = cj = ei = 0; 78 ci = cj = ei = 0;
@@ -106,8 +107,9 @@ static void pretty_print_string_list(struct cmdnames *cmds, int longest)
106 printf(" "); 107 printf(" ");
107 108
108 for (j = 0; j < cols; j++) { 109 for (j = 0; j < cols; j++) {
109 int n = j * rows + i; 110 unsigned int n = j * rows + i;
110 int size = space; 111 unsigned int size = space;
112
111 if (n >= cmds->cnt) 113 if (n >= cmds->cnt)
112 break; 114 break;
113 if (j == cols-1 || n + rows >= cmds->cnt) 115 if (j == cols-1 || n + rows >= cmds->cnt)
@@ -208,7 +210,7 @@ void load_command_list(const char *prefix,
208void list_commands(const char *title, struct cmdnames *main_cmds, 210void list_commands(const char *title, struct cmdnames *main_cmds,
209 struct cmdnames *other_cmds) 211 struct cmdnames *other_cmds)
210{ 212{
211 int i, longest = 0; 213 unsigned int i, longest = 0;
212 214
213 for (i = 0; i < main_cmds->cnt; i++) 215 for (i = 0; i < main_cmds->cnt; i++)
214 if (longest < main_cmds->names[i]->len) 216 if (longest < main_cmds->names[i]->len)
@@ -239,7 +241,8 @@ void list_commands(const char *title, struct cmdnames *main_cmds,
239 241
240int is_in_cmdlist(struct cmdnames *c, const char *s) 242int is_in_cmdlist(struct cmdnames *c, const char *s)
241{ 243{
242 int i; 244 unsigned int i;
245
243 for (i = 0; i < c->cnt; i++) 246 for (i = 0; i < c->cnt; i++)
244 if (!strcmp(s, c->names[i]->name)) 247 if (!strcmp(s, c->names[i]->name))
245 return 1; 248 return 1;
@@ -271,7 +274,8 @@ static int levenshtein_compare(const void *p1, const void *p2)
271 274
272static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) 275static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
273{ 276{
274 int i; 277 unsigned int i;
278
275 ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc); 279 ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc);
276 280
277 for (i = 0; i < old->cnt; i++) 281 for (i = 0; i < old->cnt; i++)
@@ -283,7 +287,7 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
283 287
284const char *help_unknown_cmd(const char *cmd) 288const char *help_unknown_cmd(const char *cmd)
285{ 289{
286 int i, n = 0, best_similarity = 0; 290 unsigned int i, n = 0, best_similarity = 0;
287 struct cmdnames main_cmds, other_cmds; 291 struct cmdnames main_cmds, other_cmds;
288 292
289 memset(&main_cmds, 0, sizeof(main_cmds)); 293 memset(&main_cmds, 0, sizeof(main_cmds));
@@ -345,7 +349,7 @@ const char *help_unknown_cmd(const char *cmd)
345 exit(1); 349 exit(1);
346} 350}
347 351
348int cmd_version(int argc, const char **argv, const char *prefix) 352int cmd_version(int argc __used, const char **argv __used, const char *prefix __used)
349{ 353{
350 printf("perf version %s\n", perf_version_string); 354 printf("perf version %s\n", perf_version_string);
351 return 0; 355 return 0;
diff --git a/tools/perf/util/help.h b/tools/perf/util/help.h
index 56bc15406ffc..7128783637b4 100644
--- a/tools/perf/util/help.h
+++ b/tools/perf/util/help.h
@@ -2,8 +2,8 @@
2#define HELP_H 2#define HELP_H
3 3
4struct cmdnames { 4struct cmdnames {
5 int alloc; 5 size_t alloc;
6 int cnt; 6 size_t cnt;
7 struct cmdname { 7 struct cmdname {
8 size_t len; /* also used for similarity index in help.c */ 8 size_t len; /* also used for similarity index in help.c */
9 char name[FLEX_ARRAY]; 9 char name[FLEX_ARRAY];
@@ -19,7 +19,7 @@ static inline void mput_char(char c, unsigned int num)
19void load_command_list(const char *prefix, 19void load_command_list(const char *prefix,
20 struct cmdnames *main_cmds, 20 struct cmdnames *main_cmds,
21 struct cmdnames *other_cmds); 21 struct cmdnames *other_cmds);
22void add_cmdname(struct cmdnames *cmds, const char *name, int len); 22void add_cmdname(struct cmdnames *cmds, const char *name, size_t len);
23/* Here we require that excludes is a sorted list. */ 23/* Here we require that excludes is a sorted list. */
24void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes); 24void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes);
25int is_in_cmdlist(struct cmdnames *c, const char *s); 25int is_in_cmdlist(struct cmdnames *c, const char *s);
diff --git a/tools/perf/util/include/asm/system.h b/tools/perf/util/include/asm/system.h
new file mode 100644
index 000000000000..710cecca972d
--- /dev/null
+++ b/tools/perf/util/include/asm/system.h
@@ -0,0 +1 @@
/* Empty */
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
new file mode 100644
index 000000000000..a6b87390cb52
--- /dev/null
+++ b/tools/perf/util/include/linux/kernel.h
@@ -0,0 +1,29 @@
1#ifndef PERF_LINUX_KERNEL_H_
2#define PERF_LINUX_KERNEL_H_
3
4#ifndef offsetof
5#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
6#endif
7
8#ifndef container_of
9/**
10 * container_of - cast a member of a structure out to the containing structure
11 * @ptr: the pointer to the member.
12 * @type: the type of the container struct this is embedded in.
13 * @member: the name of the member within the struct.
14 *
15 */
16#define container_of(ptr, type, member) ({ \
17 const typeof(((type *)0)->member) * __mptr = (ptr); \
18 (type *)((char *)__mptr - offsetof(type, member)); })
19#endif
20
21#ifndef max
22#define max(x, y) ({ \
23 typeof(x) _max1 = (x); \
24 typeof(y) _max2 = (y); \
25 (void) (&_max1 == &_max2); \
26 _max1 > _max2 ? _max1 : _max2; })
27#endif
28
29#endif
diff --git a/tools/perf/util/include/linux/list.h b/tools/perf/util/include/linux/list.h
new file mode 100644
index 000000000000..dbe4b814382a
--- /dev/null
+++ b/tools/perf/util/include/linux/list.h
@@ -0,0 +1,18 @@
1#include "../../../../include/linux/list.h"
2
3#ifndef PERF_LIST_H
4#define PERF_LIST_H
5/**
6 * list_del_range - deletes range of entries from list.
7 * @begin: first element in the range to delete from the list.
8 * @end: last element in the range to delete from the list.
9 * Note: list_empty on the range of entries does not return true after this,
10 * the entries is in an undefined state.
11 */
12static inline void list_del_range(struct list_head *begin,
13 struct list_head *end)
14{
15 begin->prev->next = end->next;
16 end->next->prev = begin->prev;
17}
18#endif
diff --git a/tools/perf/util/include/linux/module.h b/tools/perf/util/include/linux/module.h
new file mode 100644
index 000000000000..b43e2dc21e04
--- /dev/null
+++ b/tools/perf/util/include/linux/module.h
@@ -0,0 +1,6 @@
1#ifndef PERF_LINUX_MODULE_H
2#define PERF_LINUX_MODULE_H
3
4#define EXPORT_SYMBOL(name)
5
6#endif
diff --git a/tools/perf/util/include/linux/poison.h b/tools/perf/util/include/linux/poison.h
new file mode 100644
index 000000000000..fef6dbc9ce13
--- /dev/null
+++ b/tools/perf/util/include/linux/poison.h
@@ -0,0 +1 @@
#include "../../../../include/linux/poison.h"
diff --git a/tools/perf/util/include/linux/prefetch.h b/tools/perf/util/include/linux/prefetch.h
new file mode 100644
index 000000000000..7841e485d8c3
--- /dev/null
+++ b/tools/perf/util/include/linux/prefetch.h
@@ -0,0 +1,6 @@
1#ifndef PERF_LINUX_PREFETCH_H
2#define PERF_LINUX_PREFETCH_H
3
4static inline void prefetch(void *a __attribute__((unused))) { }
5
6#endif
diff --git a/tools/perf/util/include/linux/rbtree.h b/tools/perf/util/include/linux/rbtree.h
new file mode 100644
index 000000000000..7a243a143037
--- /dev/null
+++ b/tools/perf/util/include/linux/rbtree.h
@@ -0,0 +1 @@
#include "../../../../include/linux/rbtree.h"
diff --git a/tools/perf/util/list.h b/tools/perf/util/list.h
deleted file mode 100644
index e2548e8072cf..000000000000
--- a/tools/perf/util/list.h
+++ /dev/null
@@ -1,603 +0,0 @@
1#ifndef _LINUX_LIST_H
2#define _LINUX_LIST_H
3/*
4 Copyright (C) Cast of dozens, comes from the Linux kernel
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation.
9*/
10
11#include <stddef.h>
12
13/*
14 * These are non-NULL pointers that will result in page faults
15 * under normal circumstances, used to verify that nobody uses
16 * non-initialized list entries.
17 */
18#define LIST_POISON1 ((void *)0x00100100)
19#define LIST_POISON2 ((void *)0x00200200)
20
21/**
22 * container_of - cast a member of a structure out to the containing structure
23 * @ptr: the pointer to the member.
24 * @type: the type of the container struct this is embedded in.
25 * @member: the name of the member within the struct.
26 *
27 */
28#define container_of(ptr, type, member) ({ \
29 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
30 (type *)( (char *)__mptr - offsetof(type,member) );})
31
32/*
33 * Simple doubly linked list implementation.
34 *
35 * Some of the internal functions ("__xxx") are useful when
36 * manipulating whole lists rather than single entries, as
37 * sometimes we already know the next/prev entries and we can
38 * generate better code by using them directly rather than
39 * using the generic single-entry routines.
40 */
41
42struct list_head {
43 struct list_head *next, *prev;
44};
45
46#define LIST_HEAD_INIT(name) { &(name), &(name) }
47
48#define LIST_HEAD(name) \
49 struct list_head name = LIST_HEAD_INIT(name)
50
51static inline void INIT_LIST_HEAD(struct list_head *list)
52{
53 list->next = list;
54 list->prev = list;
55}
56
57/*
58 * Insert a new entry between two known consecutive entries.
59 *
60 * This is only for internal list manipulation where we know
61 * the prev/next entries already!
62 */
63static inline void __list_add(struct list_head *new,
64 struct list_head *prev,
65 struct list_head *next)
66{
67 next->prev = new;
68 new->next = next;
69 new->prev = prev;
70 prev->next = new;
71}
72
73/**
74 * list_add - add a new entry
75 * @new: new entry to be added
76 * @head: list head to add it after
77 *
78 * Insert a new entry after the specified head.
79 * This is good for implementing stacks.
80 */
81static inline void list_add(struct list_head *new, struct list_head *head)
82{
83 __list_add(new, head, head->next);
84}
85
86/**
87 * list_add_tail - add a new entry
88 * @new: new entry to be added
89 * @head: list head to add it before
90 *
91 * Insert a new entry before the specified head.
92 * This is useful for implementing queues.
93 */
94static inline void list_add_tail(struct list_head *new, struct list_head *head)
95{
96 __list_add(new, head->prev, head);
97}
98
99/*
100 * Delete a list entry by making the prev/next entries
101 * point to each other.
102 *
103 * This is only for internal list manipulation where we know
104 * the prev/next entries already!
105 */
106static inline void __list_del(struct list_head * prev, struct list_head * next)
107{
108 next->prev = prev;
109 prev->next = next;
110}
111
112/**
113 * list_del - deletes entry from list.
114 * @entry: the element to delete from the list.
115 * Note: list_empty on entry does not return true after this, the entry is
116 * in an undefined state.
117 */
118static inline void list_del(struct list_head *entry)
119{
120 __list_del(entry->prev, entry->next);
121 entry->next = LIST_POISON1;
122 entry->prev = LIST_POISON2;
123}
124
125/**
126 * list_del_range - deletes range of entries from list.
127 * @beging: first element in the range to delete from the list.
128 * @beging: first element in the range to delete from the list.
129 * Note: list_empty on the range of entries does not return true after this,
130 * the entries is in an undefined state.
131 */
132static inline void list_del_range(struct list_head *begin,
133 struct list_head *end)
134{
135 begin->prev->next = end->next;
136 end->next->prev = begin->prev;
137}
138
139/**
140 * list_replace - replace old entry by new one
141 * @old : the element to be replaced
142 * @new : the new element to insert
143 * Note: if 'old' was empty, it will be overwritten.
144 */
145static inline void list_replace(struct list_head *old,
146 struct list_head *new)
147{
148 new->next = old->next;
149 new->next->prev = new;
150 new->prev = old->prev;
151 new->prev->next = new;
152}
153
154static inline void list_replace_init(struct list_head *old,
155 struct list_head *new)
156{
157 list_replace(old, new);
158 INIT_LIST_HEAD(old);
159}
160
161/**
162 * list_del_init - deletes entry from list and reinitialize it.
163 * @entry: the element to delete from the list.
164 */
165static inline void list_del_init(struct list_head *entry)
166{
167 __list_del(entry->prev, entry->next);
168 INIT_LIST_HEAD(entry);
169}
170
171/**
172 * list_move - delete from one list and add as another's head
173 * @list: the entry to move
174 * @head: the head that will precede our entry
175 */
176static inline void list_move(struct list_head *list, struct list_head *head)
177{
178 __list_del(list->prev, list->next);
179 list_add(list, head);
180}
181
182/**
183 * list_move_tail - delete from one list and add as another's tail
184 * @list: the entry to move
185 * @head: the head that will follow our entry
186 */
187static inline void list_move_tail(struct list_head *list,
188 struct list_head *head)
189{
190 __list_del(list->prev, list->next);
191 list_add_tail(list, head);
192}
193
194/**
195 * list_is_last - tests whether @list is the last entry in list @head
196 * @list: the entry to test
197 * @head: the head of the list
198 */
199static inline int list_is_last(const struct list_head *list,
200 const struct list_head *head)
201{
202 return list->next == head;
203}
204
205/**
206 * list_empty - tests whether a list is empty
207 * @head: the list to test.
208 */
209static inline int list_empty(const struct list_head *head)
210{
211 return head->next == head;
212}
213
214/**
215 * list_empty_careful - tests whether a list is empty and not being modified
216 * @head: the list to test
217 *
218 * Description:
219 * tests whether a list is empty _and_ checks that no other CPU might be
220 * in the process of modifying either member (next or prev)
221 *
222 * NOTE: using list_empty_careful() without synchronization
223 * can only be safe if the only activity that can happen
224 * to the list entry is list_del_init(). Eg. it cannot be used
225 * if another CPU could re-list_add() it.
226 */
227static inline int list_empty_careful(const struct list_head *head)
228{
229 struct list_head *next = head->next;
230 return (next == head) && (next == head->prev);
231}
232
233static inline void __list_splice(struct list_head *list,
234 struct list_head *head)
235{
236 struct list_head *first = list->next;
237 struct list_head *last = list->prev;
238 struct list_head *at = head->next;
239
240 first->prev = head;
241 head->next = first;
242
243 last->next = at;
244 at->prev = last;
245}
246
247/**
248 * list_splice - join two lists
249 * @list: the new list to add.
250 * @head: the place to add it in the first list.
251 */
252static inline void list_splice(struct list_head *list, struct list_head *head)
253{
254 if (!list_empty(list))
255 __list_splice(list, head);
256}
257
258/**
259 * list_splice_init - join two lists and reinitialise the emptied list.
260 * @list: the new list to add.
261 * @head: the place to add it in the first list.
262 *
263 * The list at @list is reinitialised
264 */
265static inline void list_splice_init(struct list_head *list,
266 struct list_head *head)
267{
268 if (!list_empty(list)) {
269 __list_splice(list, head);
270 INIT_LIST_HEAD(list);
271 }
272}
273
274/**
275 * list_entry - get the struct for this entry
276 * @ptr: the &struct list_head pointer.
277 * @type: the type of the struct this is embedded in.
278 * @member: the name of the list_struct within the struct.
279 */
280#define list_entry(ptr, type, member) \
281 container_of(ptr, type, member)
282
283/**
284 * list_first_entry - get the first element from a list
285 * @ptr: the list head to take the element from.
286 * @type: the type of the struct this is embedded in.
287 * @member: the name of the list_struct within the struct.
288 *
289 * Note, that list is expected to be not empty.
290 */
291#define list_first_entry(ptr, type, member) \
292 list_entry((ptr)->next, type, member)
293
294/**
295 * list_for_each - iterate over a list
296 * @pos: the &struct list_head to use as a loop cursor.
297 * @head: the head for your list.
298 */
299#define list_for_each(pos, head) \
300 for (pos = (head)->next; pos != (head); \
301 pos = pos->next)
302
303/**
304 * __list_for_each - iterate over a list
305 * @pos: the &struct list_head to use as a loop cursor.
306 * @head: the head for your list.
307 *
308 * This variant differs from list_for_each() in that it's the
309 * simplest possible list iteration code, no prefetching is done.
310 * Use this for code that knows the list to be very short (empty
311 * or 1 entry) most of the time.
312 */
313#define __list_for_each(pos, head) \
314 for (pos = (head)->next; pos != (head); pos = pos->next)
315
316/**
317 * list_for_each_prev - iterate over a list backwards
318 * @pos: the &struct list_head to use as a loop cursor.
319 * @head: the head for your list.
320 */
321#define list_for_each_prev(pos, head) \
322 for (pos = (head)->prev; pos != (head); \
323 pos = pos->prev)
324
325/**
326 * list_for_each_safe - iterate over a list safe against removal of list entry
327 * @pos: the &struct list_head to use as a loop cursor.
328 * @n: another &struct list_head to use as temporary storage
329 * @head: the head for your list.
330 */
331#define list_for_each_safe(pos, n, head) \
332 for (pos = (head)->next, n = pos->next; pos != (head); \
333 pos = n, n = pos->next)
334
335/**
336 * list_for_each_entry - iterate over list of given type
337 * @pos: the type * to use as a loop cursor.
338 * @head: the head for your list.
339 * @member: the name of the list_struct within the struct.
340 */
341#define list_for_each_entry(pos, head, member) \
342 for (pos = list_entry((head)->next, typeof(*pos), member); \
343 &pos->member != (head); \
344 pos = list_entry(pos->member.next, typeof(*pos), member))
345
346/**
347 * list_for_each_entry_reverse - iterate backwards over list of given type.
348 * @pos: the type * to use as a loop cursor.
349 * @head: the head for your list.
350 * @member: the name of the list_struct within the struct.
351 */
352#define list_for_each_entry_reverse(pos, head, member) \
353 for (pos = list_entry((head)->prev, typeof(*pos), member); \
354 &pos->member != (head); \
355 pos = list_entry(pos->member.prev, typeof(*pos), member))
356
357/**
358 * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue
359 * @pos: the type * to use as a start point
360 * @head: the head of the list
361 * @member: the name of the list_struct within the struct.
362 *
363 * Prepares a pos entry for use as a start point in list_for_each_entry_continue.
364 */
365#define list_prepare_entry(pos, head, member) \
366 ((pos) ? : list_entry(head, typeof(*pos), member))
367
368/**
369 * list_for_each_entry_continue - continue iteration over list of given type
370 * @pos: the type * to use as a loop cursor.
371 * @head: the head for your list.
372 * @member: the name of the list_struct within the struct.
373 *
374 * Continue to iterate over list of given type, continuing after
375 * the current position.
376 */
377#define list_for_each_entry_continue(pos, head, member) \
378 for (pos = list_entry(pos->member.next, typeof(*pos), member); \
379 &pos->member != (head); \
380 pos = list_entry(pos->member.next, typeof(*pos), member))
381
382/**
383 * list_for_each_entry_from - iterate over list of given type from the current point
384 * @pos: the type * to use as a loop cursor.
385 * @head: the head for your list.
386 * @member: the name of the list_struct within the struct.
387 *
388 * Iterate over list of given type, continuing from current position.
389 */
390#define list_for_each_entry_from(pos, head, member) \
391 for (; &pos->member != (head); \
392 pos = list_entry(pos->member.next, typeof(*pos), member))
393
394/**
395 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
396 * @pos: the type * to use as a loop cursor.
397 * @n: another type * to use as temporary storage
398 * @head: the head for your list.
399 * @member: the name of the list_struct within the struct.
400 */
401#define list_for_each_entry_safe(pos, n, head, member) \
402 for (pos = list_entry((head)->next, typeof(*pos), member), \
403 n = list_entry(pos->member.next, typeof(*pos), member); \
404 &pos->member != (head); \
405 pos = n, n = list_entry(n->member.next, typeof(*n), member))
406
407/**
408 * list_for_each_entry_safe_continue
409 * @pos: the type * to use as a loop cursor.
410 * @n: another type * to use as temporary storage
411 * @head: the head for your list.
412 * @member: the name of the list_struct within the struct.
413 *
414 * Iterate over list of given type, continuing after current point,
415 * safe against removal of list entry.
416 */
417#define list_for_each_entry_safe_continue(pos, n, head, member) \
418 for (pos = list_entry(pos->member.next, typeof(*pos), member), \
419 n = list_entry(pos->member.next, typeof(*pos), member); \
420 &pos->member != (head); \
421 pos = n, n = list_entry(n->member.next, typeof(*n), member))
422
423/**
424 * list_for_each_entry_safe_from
425 * @pos: the type * to use as a loop cursor.
426 * @n: another type * to use as temporary storage
427 * @head: the head for your list.
428 * @member: the name of the list_struct within the struct.
429 *
430 * Iterate over list of given type from current point, safe against
431 * removal of list entry.
432 */
433#define list_for_each_entry_safe_from(pos, n, head, member) \
434 for (n = list_entry(pos->member.next, typeof(*pos), member); \
435 &pos->member != (head); \
436 pos = n, n = list_entry(n->member.next, typeof(*n), member))
437
438/**
439 * list_for_each_entry_safe_reverse
440 * @pos: the type * to use as a loop cursor.
441 * @n: another type * to use as temporary storage
442 * @head: the head for your list.
443 * @member: the name of the list_struct within the struct.
444 *
445 * Iterate backwards over list of given type, safe against removal
446 * of list entry.
447 */
448#define list_for_each_entry_safe_reverse(pos, n, head, member) \
449 for (pos = list_entry((head)->prev, typeof(*pos), member), \
450 n = list_entry(pos->member.prev, typeof(*pos), member); \
451 &pos->member != (head); \
452 pos = n, n = list_entry(n->member.prev, typeof(*n), member))
453
454/*
455 * Double linked lists with a single pointer list head.
456 * Mostly useful for hash tables where the two pointer list head is
457 * too wasteful.
458 * You lose the ability to access the tail in O(1).
459 */
460
461struct hlist_head {
462 struct hlist_node *first;
463};
464
465struct hlist_node {
466 struct hlist_node *next, **pprev;
467};
468
469#define HLIST_HEAD_INIT { .first = NULL }
470#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
471#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
472static inline void INIT_HLIST_NODE(struct hlist_node *h)
473{
474 h->next = NULL;
475 h->pprev = NULL;
476}
477
478static inline int hlist_unhashed(const struct hlist_node *h)
479{
480 return !h->pprev;
481}
482
483static inline int hlist_empty(const struct hlist_head *h)
484{
485 return !h->first;
486}
487
488static inline void __hlist_del(struct hlist_node *n)
489{
490 struct hlist_node *next = n->next;
491 struct hlist_node **pprev = n->pprev;
492 *pprev = next;
493 if (next)
494 next->pprev = pprev;
495}
496
497static inline void hlist_del(struct hlist_node *n)
498{
499 __hlist_del(n);
500 n->next = LIST_POISON1;
501 n->pprev = LIST_POISON2;
502}
503
504static inline void hlist_del_init(struct hlist_node *n)
505{
506 if (!hlist_unhashed(n)) {
507 __hlist_del(n);
508 INIT_HLIST_NODE(n);
509 }
510}
511
512static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
513{
514 struct hlist_node *first = h->first;
515 n->next = first;
516 if (first)
517 first->pprev = &n->next;
518 h->first = n;
519 n->pprev = &h->first;
520}
521
522/* next must be != NULL */
523static inline void hlist_add_before(struct hlist_node *n,
524 struct hlist_node *next)
525{
526 n->pprev = next->pprev;
527 n->next = next;
528 next->pprev = &n->next;
529 *(n->pprev) = n;
530}
531
532static inline void hlist_add_after(struct hlist_node *n,
533 struct hlist_node *next)
534{
535 next->next = n->next;
536 n->next = next;
537 next->pprev = &n->next;
538
539 if(next->next)
540 next->next->pprev = &next->next;
541}
542
543#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
544
545#define hlist_for_each(pos, head) \
546 for (pos = (head)->first; pos; \
547 pos = pos->next)
548
549#define hlist_for_each_safe(pos, n, head) \
550 for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
551 pos = n)
552
553/**
554 * hlist_for_each_entry - iterate over list of given type
555 * @tpos: the type * to use as a loop cursor.
556 * @pos: the &struct hlist_node to use as a loop cursor.
557 * @head: the head for your list.
558 * @member: the name of the hlist_node within the struct.
559 */
560#define hlist_for_each_entry(tpos, pos, head, member) \
561 for (pos = (head)->first; \
562 pos && \
563 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
564 pos = pos->next)
565
566/**
567 * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
568 * @tpos: the type * to use as a loop cursor.
569 * @pos: the &struct hlist_node to use as a loop cursor.
570 * @member: the name of the hlist_node within the struct.
571 */
572#define hlist_for_each_entry_continue(tpos, pos, member) \
573 for (pos = (pos)->next; \
574 pos && \
575 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
576 pos = pos->next)
577
578/**
579 * hlist_for_each_entry_from - iterate over a hlist continuing from current point
580 * @tpos: the type * to use as a loop cursor.
581 * @pos: the &struct hlist_node to use as a loop cursor.
582 * @member: the name of the hlist_node within the struct.
583 */
584#define hlist_for_each_entry_from(tpos, pos, member) \
585 for (; pos && \
586 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
587 pos = pos->next)
588
589/**
590 * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
591 * @tpos: the type * to use as a loop cursor.
592 * @pos: the &struct hlist_node to use as a loop cursor.
593 * @n: another &struct hlist_node to use as temporary storage
594 * @head: the head for your list.
595 * @member: the name of the hlist_node within the struct.
596 */
597#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
598 for (pos = (head)->first; \
599 pos && ({ n = pos->next; 1; }) && \
600 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
601 pos = n)
602
603#endif
diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c
new file mode 100644
index 000000000000..ddabe925d65d
--- /dev/null
+++ b/tools/perf/util/module.c
@@ -0,0 +1,509 @@
1#include "util.h"
2#include "../perf.h"
3#include "string.h"
4#include "module.h"
5
6#include <libelf.h>
7#include <gelf.h>
8#include <elf.h>
9#include <dirent.h>
10#include <sys/utsname.h>
11
12static unsigned int crc32(const char *p, unsigned int len)
13{
14 int i;
15 unsigned int crc = 0;
16
17 while (len--) {
18 crc ^= *p++;
19 for (i = 0; i < 8; i++)
20 crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
21 }
22 return crc;
23}
24
25/* module section methods */
26
27struct sec_dso *sec_dso__new_dso(const char *name)
28{
29 struct sec_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
30
31 if (self != NULL) {
32 strcpy(self->name, name);
33 self->secs = RB_ROOT;
34 self->find_section = sec_dso__find_section;
35 }
36
37 return self;
38}
39
40static void sec_dso__delete_section(struct section *self)
41{
42 free(((void *)self));
43}
44
45void sec_dso__delete_sections(struct sec_dso *self)
46{
47 struct section *pos;
48 struct rb_node *next = rb_first(&self->secs);
49
50 while (next) {
51 pos = rb_entry(next, struct section, rb_node);
52 next = rb_next(&pos->rb_node);
53 rb_erase(&pos->rb_node, &self->secs);
54 sec_dso__delete_section(pos);
55 }
56}
57
58void sec_dso__delete_self(struct sec_dso *self)
59{
60 sec_dso__delete_sections(self);
61 free(self);
62}
63
64static void sec_dso__insert_section(struct sec_dso *self, struct section *sec)
65{
66 struct rb_node **p = &self->secs.rb_node;
67 struct rb_node *parent = NULL;
68 const u64 hash = sec->hash;
69 struct section *s;
70
71 while (*p != NULL) {
72 parent = *p;
73 s = rb_entry(parent, struct section, rb_node);
74 if (hash < s->hash)
75 p = &(*p)->rb_left;
76 else
77 p = &(*p)->rb_right;
78 }
79 rb_link_node(&sec->rb_node, parent, p);
80 rb_insert_color(&sec->rb_node, &self->secs);
81}
82
83struct section *sec_dso__find_section(struct sec_dso *self, const char *name)
84{
85 struct rb_node *n;
86 u64 hash;
87 int len;
88
89 if (self == NULL)
90 return NULL;
91
92 len = strlen(name);
93 hash = crc32(name, len);
94
95 n = self->secs.rb_node;
96
97 while (n) {
98 struct section *s = rb_entry(n, struct section, rb_node);
99
100 if (hash < s->hash)
101 n = n->rb_left;
102 else if (hash > s->hash)
103 n = n->rb_right;
104 else {
105 if (!strcmp(name, s->name))
106 return s;
107 else
108 n = rb_next(&s->rb_node);
109 }
110 }
111
112 return NULL;
113}
114
115static size_t sec_dso__fprintf_section(struct section *self, FILE *fp)
116{
117 return fprintf(fp, "name:%s vma:%llx path:%s\n",
118 self->name, self->vma, self->path);
119}
120
121size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp)
122{
123 size_t ret = fprintf(fp, "dso: %s\n", self->name);
124
125 struct rb_node *nd;
126 for (nd = rb_first(&self->secs); nd; nd = rb_next(nd)) {
127 struct section *pos = rb_entry(nd, struct section, rb_node);
128 ret += sec_dso__fprintf_section(pos, fp);
129 }
130
131 return ret;
132}
133
134static struct section *section__new(const char *name, const char *path)
135{
136 struct section *self = calloc(1, sizeof(*self));
137
138 if (!self)
139 goto out_failure;
140
141 self->name = calloc(1, strlen(name) + 1);
142 if (!self->name)
143 goto out_failure;
144
145 self->path = calloc(1, strlen(path) + 1);
146 if (!self->path)
147 goto out_failure;
148
149 strcpy(self->name, name);
150 strcpy(self->path, path);
151 self->hash = crc32(self->name, strlen(name));
152
153 return self;
154
155out_failure:
156 if (self) {
157 if (self->name)
158 free(self->name);
159 if (self->path)
160 free(self->path);
161 free(self);
162 }
163
164 return NULL;
165}
166
167/* module methods */
168
169struct mod_dso *mod_dso__new_dso(const char *name)
170{
171 struct mod_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
172
173 if (self != NULL) {
174 strcpy(self->name, name);
175 self->mods = RB_ROOT;
176 self->find_module = mod_dso__find_module;
177 }
178
179 return self;
180}
181
182static void mod_dso__delete_module(struct module *self)
183{
184 free(((void *)self));
185}
186
187void mod_dso__delete_modules(struct mod_dso *self)
188{
189 struct module *pos;
190 struct rb_node *next = rb_first(&self->mods);
191
192 while (next) {
193 pos = rb_entry(next, struct module, rb_node);
194 next = rb_next(&pos->rb_node);
195 rb_erase(&pos->rb_node, &self->mods);
196 mod_dso__delete_module(pos);
197 }
198}
199
200void mod_dso__delete_self(struct mod_dso *self)
201{
202 mod_dso__delete_modules(self);
203 free(self);
204}
205
206static void mod_dso__insert_module(struct mod_dso *self, struct module *mod)
207{
208 struct rb_node **p = &self->mods.rb_node;
209 struct rb_node *parent = NULL;
210 const u64 hash = mod->hash;
211 struct module *m;
212
213 while (*p != NULL) {
214 parent = *p;
215 m = rb_entry(parent, struct module, rb_node);
216 if (hash < m->hash)
217 p = &(*p)->rb_left;
218 else
219 p = &(*p)->rb_right;
220 }
221 rb_link_node(&mod->rb_node, parent, p);
222 rb_insert_color(&mod->rb_node, &self->mods);
223}
224
225struct module *mod_dso__find_module(struct mod_dso *self, const char *name)
226{
227 struct rb_node *n;
228 u64 hash;
229 int len;
230
231 if (self == NULL)
232 return NULL;
233
234 len = strlen(name);
235 hash = crc32(name, len);
236
237 n = self->mods.rb_node;
238
239 while (n) {
240 struct module *m = rb_entry(n, struct module, rb_node);
241
242 if (hash < m->hash)
243 n = n->rb_left;
244 else if (hash > m->hash)
245 n = n->rb_right;
246 else {
247 if (!strcmp(name, m->name))
248 return m;
249 else
250 n = rb_next(&m->rb_node);
251 }
252 }
253
254 return NULL;
255}
256
257static size_t mod_dso__fprintf_module(struct module *self, FILE *fp)
258{
259 return fprintf(fp, "name:%s path:%s\n", self->name, self->path);
260}
261
262size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp)
263{
264 struct rb_node *nd;
265 size_t ret;
266
267 ret = fprintf(fp, "dso: %s\n", self->name);
268
269 for (nd = rb_first(&self->mods); nd; nd = rb_next(nd)) {
270 struct module *pos = rb_entry(nd, struct module, rb_node);
271
272 ret += mod_dso__fprintf_module(pos, fp);
273 }
274
275 return ret;
276}
277
278static struct module *module__new(const char *name, const char *path)
279{
280 struct module *self = calloc(1, sizeof(*self));
281
282 if (!self)
283 goto out_failure;
284
285 self->name = calloc(1, strlen(name) + 1);
286 if (!self->name)
287 goto out_failure;
288
289 self->path = calloc(1, strlen(path) + 1);
290 if (!self->path)
291 goto out_failure;
292
293 strcpy(self->name, name);
294 strcpy(self->path, path);
295 self->hash = crc32(self->name, strlen(name));
296
297 return self;
298
299out_failure:
300 if (self) {
301 if (self->name)
302 free(self->name);
303 if (self->path)
304 free(self->path);
305 free(self);
306 }
307
308 return NULL;
309}
310
311static int mod_dso__load_sections(struct module *mod)
312{
313 int count = 0, path_len;
314 struct dirent *entry;
315 char *line = NULL;
316 char *dir_path;
317 DIR *dir;
318 size_t n;
319
320 path_len = strlen("/sys/module/");
321 path_len += strlen(mod->name);
322 path_len += strlen("/sections/");
323
324 dir_path = calloc(1, path_len + 1);
325 if (dir_path == NULL)
326 goto out_failure;
327
328 strcat(dir_path, "/sys/module/");
329 strcat(dir_path, mod->name);
330 strcat(dir_path, "/sections/");
331
332 dir = opendir(dir_path);
333 if (dir == NULL)
334 goto out_free;
335
336 while ((entry = readdir(dir))) {
337 struct section *section;
338 char *path, *vma;
339 int line_len;
340 FILE *file;
341
342 if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name))
343 continue;
344
345 path = calloc(1, path_len + strlen(entry->d_name) + 1);
346 if (path == NULL)
347 break;
348 strcat(path, dir_path);
349 strcat(path, entry->d_name);
350
351 file = fopen(path, "r");
352 if (file == NULL) {
353 free(path);
354 break;
355 }
356
357 line_len = getline(&line, &n, file);
358 if (line_len < 0) {
359 free(path);
360 fclose(file);
361 break;
362 }
363
364 if (!line) {
365 free(path);
366 fclose(file);
367 break;
368 }
369
370 line[--line_len] = '\0'; /* \n */
371
372 vma = strstr(line, "0x");
373 if (!vma) {
374 free(path);
375 fclose(file);
376 break;
377 }
378 vma += 2;
379
380 section = section__new(entry->d_name, path);
381 if (!section) {
382 fprintf(stderr, "load_sections: allocation error\n");
383 free(path);
384 fclose(file);
385 break;
386 }
387
388 hex2u64(vma, &section->vma);
389 sec_dso__insert_section(mod->sections, section);
390
391 free(path);
392 fclose(file);
393 count++;
394 }
395
396 closedir(dir);
397 free(line);
398 free(dir_path);
399
400 return count;
401
402out_free:
403 free(dir_path);
404
405out_failure:
406 return count;
407}
408
409static int mod_dso__load_module_paths(struct mod_dso *self)
410{
411 struct utsname uts;
412 int count = 0, len;
413 char *line = NULL;
414 FILE *file;
415 char *path;
416 size_t n;
417
418 if (uname(&uts) < 0)
419 goto out_failure;
420
421 len = strlen("/lib/modules/");
422 len += strlen(uts.release);
423 len += strlen("/modules.dep");
424
425 path = calloc(1, len);
426 if (path == NULL)
427 goto out_failure;
428
429 strcat(path, "/lib/modules/");
430 strcat(path, uts.release);
431 strcat(path, "/modules.dep");
432
433 file = fopen(path, "r");
434 free(path);
435 if (file == NULL)
436 goto out_failure;
437
438 while (!feof(file)) {
439 char *path, *name, *tmp;
440 struct module *module;
441 int line_len, len;
442
443 line_len = getline(&line, &n, file);
444 if (line_len < 0)
445 break;
446
447 if (!line)
448 goto out_failure;
449
450 line[--line_len] = '\0'; /* \n */
451
452 path = strtok(line, ":");
453 if (!path)
454 goto out_failure;
455
456 name = strdup(path);
457 name = strtok(name, "/");
458
459 tmp = name;
460
461 while (tmp) {
462 tmp = strtok(NULL, "/");
463 if (tmp)
464 name = tmp;
465 }
466 name = strsep(&name, ".");
467
468 /* Quirk: replace '-' with '_' in sound modules */
469 for (len = strlen(name); len; len--) {
470 if (*(name+len) == '-')
471 *(name+len) = '_';
472 }
473
474 module = module__new(name, path);
475 if (!module) {
476 fprintf(stderr, "load_module_paths: allocation error\n");
477 goto out_failure;
478 }
479 mod_dso__insert_module(self, module);
480
481 module->sections = sec_dso__new_dso("sections");
482 if (!module->sections) {
483 fprintf(stderr, "load_module_paths: allocation error\n");
484 goto out_failure;
485 }
486
487 module->active = mod_dso__load_sections(module);
488
489 if (module->active > 0)
490 count++;
491 }
492
493 free(line);
494 fclose(file);
495
496 return count;
497
498out_failure:
499 return -1;
500}
501
502int mod_dso__load_modules(struct mod_dso *dso)
503{
504 int err;
505
506 err = mod_dso__load_module_paths(dso);
507
508 return err;
509}
diff --git a/tools/perf/util/module.h b/tools/perf/util/module.h
new file mode 100644
index 000000000000..8a592ef641ca
--- /dev/null
+++ b/tools/perf/util/module.h
@@ -0,0 +1,53 @@
1#ifndef _PERF_MODULE_
2#define _PERF_MODULE_ 1
3
4#include <linux/types.h>
5#include "../types.h"
6#include <linux/list.h>
7#include <linux/rbtree.h>
8
9struct section {
10 struct rb_node rb_node;
11 u64 hash;
12 u64 vma;
13 char *name;
14 char *path;
15};
16
17struct sec_dso {
18 struct list_head node;
19 struct rb_root secs;
20 struct section *(*find_section)(struct sec_dso *, const char *name);
21 char name[0];
22};
23
24struct module {
25 struct rb_node rb_node;
26 u64 hash;
27 char *name;
28 char *path;
29 struct sec_dso *sections;
30 int active;
31};
32
33struct mod_dso {
34 struct list_head node;
35 struct rb_root mods;
36 struct module *(*find_module)(struct mod_dso *, const char *name);
37 char name[0];
38};
39
40struct sec_dso *sec_dso__new_dso(const char *name);
41void sec_dso__delete_sections(struct sec_dso *self);
42void sec_dso__delete_self(struct sec_dso *self);
43size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp);
44struct section *sec_dso__find_section(struct sec_dso *self, const char *name);
45
46struct mod_dso *mod_dso__new_dso(const char *name);
47void mod_dso__delete_modules(struct mod_dso *self);
48void mod_dso__delete_self(struct mod_dso *self);
49size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp);
50struct module *mod_dso__find_module(struct mod_dso *self, const char *name);
51int mod_dso__load_modules(struct mod_dso *dso);
52
53#endif /* _PERF_MODULE_ */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4d042f104cdc..7bdad8df22a6 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -5,6 +5,7 @@
5#include "parse-events.h" 5#include "parse-events.h"
6#include "exec_cmd.h" 6#include "exec_cmd.h"
7#include "string.h" 7#include "string.h"
8#include "cache.h"
8 9
9extern char *strcasestr(const char *haystack, const char *needle); 10extern char *strcasestr(const char *haystack, const char *needle);
10 11
@@ -19,6 +20,8 @@ struct event_symbol {
19 char *alias; 20 char *alias;
20}; 21};
21 22
23char debugfs_path[MAXPATHLEN];
24
22#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 25#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
23#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 26#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
24 27
@@ -71,8 +74,8 @@ static char *sw_event_names[] = {
71#define MAX_ALIASES 8 74#define MAX_ALIASES 8
72 75
73static char *hw_cache[][MAX_ALIASES] = { 76static char *hw_cache[][MAX_ALIASES] = {
74 { "L1-d$", "l1-d", "l1d", "L1-data", }, 77 { "L1-dcache", "l1-d", "l1d", "L1-data", },
75 { "L1-i$", "l1-i", "l1i", "L1-instruction", }, 78 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
76 { "LLC", "L2" }, 79 { "LLC", "L2" },
77 { "dTLB", "d-tlb", "Data-TLB", }, 80 { "dTLB", "d-tlb", "Data-TLB", },
78 { "iTLB", "i-tlb", "Instruction-TLB", }, 81 { "iTLB", "i-tlb", "Instruction-TLB", },
@@ -110,6 +113,88 @@ static unsigned long hw_cache_stat[C(MAX)] = {
110 [C(BPU)] = (CACHE_READ), 113 [C(BPU)] = (CACHE_READ),
111}; 114};
112 115
116#define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st) \
117 while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \
118 if (snprintf(file, MAXPATHLEN, "%s/%s", debugfs_path, \
119 sys_dirent.d_name) && \
120 (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \
121 (strcmp(sys_dirent.d_name, ".")) && \
122 (strcmp(sys_dirent.d_name, "..")))
123
124#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st) \
125 while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \
126 if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path, \
127 sys_dirent.d_name, evt_dirent.d_name) && \
128 (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \
129 (strcmp(evt_dirent.d_name, ".")) && \
130 (strcmp(evt_dirent.d_name, "..")))
131
132#define MAX_EVENT_LENGTH 30
133
134int valid_debugfs_mount(const char *debugfs)
135{
136 struct statfs st_fs;
137
138 if (statfs(debugfs, &st_fs) < 0)
139 return -ENOENT;
140 else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
141 return -ENOENT;
142 return 0;
143}
144
145static char *tracepoint_id_to_name(u64 config)
146{
147 static char tracepoint_name[2 * MAX_EVENT_LENGTH];
148 DIR *sys_dir, *evt_dir;
149 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
150 struct stat st;
151 char id_buf[4];
152 int fd;
153 u64 id;
154 char evt_path[MAXPATHLEN];
155
156 if (valid_debugfs_mount(debugfs_path))
157 return "unkown";
158
159 sys_dir = opendir(debugfs_path);
160 if (!sys_dir)
161 goto cleanup;
162
163 for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
164 evt_dir = opendir(evt_path);
165 if (!evt_dir)
166 goto cleanup;
167 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
168 evt_path, st) {
169 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id",
170 debugfs_path, sys_dirent.d_name,
171 evt_dirent.d_name);
172 fd = open(evt_path, O_RDONLY);
173 if (fd < 0)
174 continue;
175 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
176 close(fd);
177 continue;
178 }
179 close(fd);
180 id = atoll(id_buf);
181 if (id == config) {
182 closedir(evt_dir);
183 closedir(sys_dir);
184 snprintf(tracepoint_name, 2 * MAX_EVENT_LENGTH,
185 "%s:%s", sys_dirent.d_name,
186 evt_dirent.d_name);
187 return tracepoint_name;
188 }
189 }
190 closedir(evt_dir);
191 }
192
193cleanup:
194 closedir(sys_dir);
195 return "unkown";
196}
197
113static int is_cache_op_valid(u8 cache_type, u8 cache_op) 198static int is_cache_op_valid(u8 cache_type, u8 cache_op)
114{ 199{
115 if (hw_cache_stat[cache_type] & COP(cache_op)) 200 if (hw_cache_stat[cache_type] & COP(cache_op))
@@ -177,6 +262,9 @@ char *event_name(int counter)
177 return sw_event_names[config]; 262 return sw_event_names[config];
178 return "unknown-software"; 263 return "unknown-software";
179 264
265 case PERF_TYPE_TRACEPOINT:
266 return tracepoint_id_to_name(config);
267
180 default: 268 default:
181 break; 269 break;
182 } 270 }
@@ -184,16 +272,20 @@ char *event_name(int counter)
184 return "unknown"; 272 return "unknown";
185} 273}
186 274
187static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size) 275static int parse_aliases(const char **str, char *names[][MAX_ALIASES], int size)
188{ 276{
189 int i, j; 277 int i, j;
278 int n, longest = -1;
190 279
191 for (i = 0; i < size; i++) { 280 for (i = 0; i < size; i++) {
192 for (j = 0; j < MAX_ALIASES; j++) { 281 for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
193 if (!names[i][j]) 282 n = strlen(names[i][j]);
194 break; 283 if (n > longest && !strncasecmp(*str, names[i][j], n))
195 if (strcasestr(str, names[i][j])) 284 longest = n;
196 return i; 285 }
286 if (longest > 0) {
287 *str += longest;
288 return i;
197 } 289 }
198 } 290 }
199 291
@@ -201,30 +293,53 @@ static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size)
201} 293}
202 294
203static int 295static int
204parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr) 296parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
205{ 297{
206 int cache_type = -1, cache_op = 0, cache_result = 0; 298 const char *s = *str;
299 int cache_type = -1, cache_op = -1, cache_result = -1;
207 300
208 cache_type = parse_aliases(str, hw_cache, PERF_COUNT_HW_CACHE_MAX); 301 cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
209 /* 302 /*
210 * No fallback - if we cannot get a clear cache type 303 * No fallback - if we cannot get a clear cache type
211 * then bail out: 304 * then bail out:
212 */ 305 */
213 if (cache_type == -1) 306 if (cache_type == -1)
214 return -EINVAL; 307 return 0;
308
309 while ((cache_op == -1 || cache_result == -1) && *s == '-') {
310 ++s;
311
312 if (cache_op == -1) {
313 cache_op = parse_aliases(&s, hw_cache_op,
314 PERF_COUNT_HW_CACHE_OP_MAX);
315 if (cache_op >= 0) {
316 if (!is_cache_op_valid(cache_type, cache_op))
317 return 0;
318 continue;
319 }
320 }
321
322 if (cache_result == -1) {
323 cache_result = parse_aliases(&s, hw_cache_result,
324 PERF_COUNT_HW_CACHE_RESULT_MAX);
325 if (cache_result >= 0)
326 continue;
327 }
328
329 /*
330 * Can't parse this as a cache op or result, so back up
331 * to the '-'.
332 */
333 --s;
334 break;
335 }
215 336
216 cache_op = parse_aliases(str, hw_cache_op, PERF_COUNT_HW_CACHE_OP_MAX);
217 /* 337 /*
218 * Fall back to reads: 338 * Fall back to reads:
219 */ 339 */
220 if (cache_op == -1) 340 if (cache_op == -1)
221 cache_op = PERF_COUNT_HW_CACHE_OP_READ; 341 cache_op = PERF_COUNT_HW_CACHE_OP_READ;
222 342
223 if (!is_cache_op_valid(cache_type, cache_op))
224 return -EINVAL;
225
226 cache_result = parse_aliases(str, hw_cache_result,
227 PERF_COUNT_HW_CACHE_RESULT_MAX);
228 /* 343 /*
229 * Fall back to accesses: 344 * Fall back to accesses:
230 */ 345 */
@@ -234,93 +349,202 @@ parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr)
234 attr->config = cache_type | (cache_op << 8) | (cache_result << 16); 349 attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
235 attr->type = PERF_TYPE_HW_CACHE; 350 attr->type = PERF_TYPE_HW_CACHE;
236 351
237 return 0; 352 *str = s;
353 return 1;
354}
355
356static int parse_tracepoint_event(const char **strp,
357 struct perf_counter_attr *attr)
358{
359 const char *evt_name;
360 char sys_name[MAX_EVENT_LENGTH];
361 char id_buf[4];
362 int fd;
363 unsigned int sys_length, evt_length;
364 u64 id;
365 char evt_path[MAXPATHLEN];
366
367 if (valid_debugfs_mount(debugfs_path))
368 return 0;
369
370 evt_name = strchr(*strp, ':');
371 if (!evt_name)
372 return 0;
373
374 sys_length = evt_name - *strp;
375 if (sys_length >= MAX_EVENT_LENGTH)
376 return 0;
377
378 strncpy(sys_name, *strp, sys_length);
379 sys_name[sys_length] = '\0';
380 evt_name = evt_name + 1;
381 evt_length = strlen(evt_name);
382 if (evt_length >= MAX_EVENT_LENGTH)
383 return 0;
384
385 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
386 sys_name, evt_name);
387 fd = open(evt_path, O_RDONLY);
388 if (fd < 0)
389 return 0;
390
391 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
392 close(fd);
393 return 0;
394 }
395 close(fd);
396 id = atoll(id_buf);
397 attr->config = id;
398 attr->type = PERF_TYPE_TRACEPOINT;
399 *strp = evt_name + evt_length;
400 return 1;
238} 401}
239 402
240static int check_events(const char *str, unsigned int i) 403static int check_events(const char *str, unsigned int i)
241{ 404{
242 if (!strncmp(str, event_symbols[i].symbol, 405 int n;
243 strlen(event_symbols[i].symbol)))
244 return 1;
245 406
246 if (strlen(event_symbols[i].alias)) 407 n = strlen(event_symbols[i].symbol);
247 if (!strncmp(str, event_symbols[i].alias, 408 if (!strncmp(str, event_symbols[i].symbol, n))
248 strlen(event_symbols[i].alias))) 409 return n;
249 return 1; 410
411 n = strlen(event_symbols[i].alias);
412 if (n)
413 if (!strncmp(str, event_symbols[i].alias, n))
414 return n;
250 return 0; 415 return 0;
251} 416}
252 417
253/* 418static int
254 * Each event can have multiple symbolic names. 419parse_symbolic_event(const char **strp, struct perf_counter_attr *attr)
255 * Symbolic names are (almost) exactly matched.
256 */
257static int parse_event_symbols(const char *str, struct perf_counter_attr *attr)
258{ 420{
259 u64 config, id; 421 const char *str = *strp;
260 int type;
261 unsigned int i; 422 unsigned int i;
262 const char *sep, *pstr; 423 int n;
263 424
264 if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) { 425 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
265 attr->type = PERF_TYPE_RAW; 426 n = check_events(str, i);
266 attr->config = config; 427 if (n > 0) {
428 attr->type = event_symbols[i].type;
429 attr->config = event_symbols[i].config;
430 *strp = str + n;
431 return 1;
432 }
433 }
434 return 0;
435}
436
437static int parse_raw_event(const char **strp, struct perf_counter_attr *attr)
438{
439 const char *str = *strp;
440 u64 config;
441 int n;
267 442
443 if (*str != 'r')
268 return 0; 444 return 0;
445 n = hex2u64(str + 1, &config);
446 if (n > 0) {
447 *strp = str + n + 1;
448 attr->type = PERF_TYPE_RAW;
449 attr->config = config;
450 return 1;
269 } 451 }
452 return 0;
453}
270 454
271 pstr = str; 455static int
272 sep = strchr(pstr, ':'); 456parse_numeric_event(const char **strp, struct perf_counter_attr *attr)
273 if (sep) { 457{
274 type = atoi(pstr); 458 const char *str = *strp;
275 pstr = sep + 1; 459 char *endp;
276 id = atoi(pstr); 460 unsigned long type;
277 sep = strchr(pstr, ':'); 461 u64 config;
278 if (sep) { 462
279 pstr = sep + 1; 463 type = strtoul(str, &endp, 0);
280 if (strchr(pstr, 'k')) 464 if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
281 attr->exclude_user = 1; 465 str = endp + 1;
282 if (strchr(pstr, 'u')) 466 config = strtoul(str, &endp, 0);
283 attr->exclude_kernel = 1; 467 if (endp > str) {
468 attr->type = type;
469 attr->config = config;
470 *strp = endp;
471 return 1;
284 } 472 }
285 attr->type = type; 473 }
286 attr->config = id; 474 return 0;
475}
287 476
477static int
478parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
479{
480 const char *str = *strp;
481 int eu = 1, ek = 1, eh = 1;
482
483 if (*str++ != ':')
288 return 0; 484 return 0;
485 while (*str) {
486 if (*str == 'u')
487 eu = 0;
488 else if (*str == 'k')
489 ek = 0;
490 else if (*str == 'h')
491 eh = 0;
492 else
493 break;
494 ++str;
495 }
496 if (str >= *strp + 2) {
497 *strp = str;
498 attr->exclude_user = eu;
499 attr->exclude_kernel = ek;
500 attr->exclude_hv = eh;
501 return 1;
289 } 502 }
503 return 0;
504}
290 505
291 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { 506/*
292 if (check_events(str, i)) { 507 * Each event can have multiple symbolic names.
293 attr->type = event_symbols[i].type; 508 * Symbolic names are (almost) exactly matched.
294 attr->config = event_symbols[i].config; 509 */
510static int parse_event_symbols(const char **str, struct perf_counter_attr *attr)
511{
512 if (!(parse_tracepoint_event(str, attr) ||
513 parse_raw_event(str, attr) ||
514 parse_numeric_event(str, attr) ||
515 parse_symbolic_event(str, attr) ||
516 parse_generic_hw_event(str, attr)))
517 return 0;
295 518
296 return 0; 519 parse_event_modifier(str, attr);
297 }
298 }
299 520
300 return parse_generic_hw_symbols(str, attr); 521 return 1;
301} 522}
302 523
303int parse_events(const struct option *opt, const char *str, int unset) 524int parse_events(const struct option *opt __used, const char *str, int unset __used)
304{ 525{
305 struct perf_counter_attr attr; 526 struct perf_counter_attr attr;
306 int ret;
307 527
308 memset(&attr, 0, sizeof(attr)); 528 for (;;) {
309again: 529 if (nr_counters == MAX_COUNTERS)
310 if (nr_counters == MAX_COUNTERS) 530 return -1;
311 return -1; 531
532 memset(&attr, 0, sizeof(attr));
533 if (!parse_event_symbols(&str, &attr))
534 return -1;
312 535
313 ret = parse_event_symbols(str, &attr); 536 if (!(*str == 0 || *str == ',' || isspace(*str)))
314 if (ret < 0) 537 return -1;
315 return ret;
316 538
317 attrs[nr_counters] = attr; 539 attrs[nr_counters] = attr;
318 nr_counters++; 540 nr_counters++;
319 541
320 str = strstr(str, ","); 542 if (*str == 0)
321 if (str) { 543 break;
322 str++; 544 if (*str == ',')
323 goto again; 545 ++str;
546 while (isspace(*str))
547 ++str;
324 } 548 }
325 549
326 return 0; 550 return 0;
@@ -335,12 +559,48 @@ static const char * const event_type_descriptors[] = {
335}; 559};
336 560
337/* 561/*
562 * Print the events from <debugfs_mount_point>/tracing/events
563 */
564
565static void print_tracepoint_events(void)
566{
567 DIR *sys_dir, *evt_dir;
568 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
569 struct stat st;
570 char evt_path[MAXPATHLEN];
571
572 if (valid_debugfs_mount(debugfs_path))
573 return;
574
575 sys_dir = opendir(debugfs_path);
576 if (!sys_dir)
577 goto cleanup;
578
579 for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
580 evt_dir = opendir(evt_path);
581 if (!evt_dir)
582 goto cleanup;
583 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
584 evt_path, st) {
585 snprintf(evt_path, MAXPATHLEN, "%s:%s",
586 sys_dirent.d_name, evt_dirent.d_name);
587 fprintf(stderr, " %-40s [%s]\n", evt_path,
588 event_type_descriptors[PERF_TYPE_TRACEPOINT+1]);
589 }
590 closedir(evt_dir);
591 }
592
593cleanup:
594 closedir(sys_dir);
595}
596
597/*
338 * Print the help text for the event symbols: 598 * Print the help text for the event symbols:
339 */ 599 */
340void print_events(void) 600void print_events(void)
341{ 601{
342 struct event_symbol *syms = event_symbols; 602 struct event_symbol *syms = event_symbols;
343 unsigned int i, type, prev_type = -1; 603 unsigned int i, type, op, prev_type = -1;
344 char name[40]; 604 char name[40];
345 605
346 fprintf(stderr, "\n"); 606 fprintf(stderr, "\n");
@@ -348,7 +608,7 @@ void print_events(void)
348 608
349 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 609 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
350 type = syms->type + 1; 610 type = syms->type + 1;
351 if (type > ARRAY_SIZE(event_type_descriptors)) 611 if (type >= ARRAY_SIZE(event_type_descriptors))
352 type = 0; 612 type = 0;
353 613
354 if (type != prev_type) 614 if (type != prev_type)
@@ -365,9 +625,26 @@ void print_events(void)
365 } 625 }
366 626
367 fprintf(stderr, "\n"); 627 fprintf(stderr, "\n");
628 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
629 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
630 /* skip invalid cache type */
631 if (!is_cache_op_valid(type, op))
632 continue;
633
634 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
635 fprintf(stderr, " %-40s [%s]\n",
636 event_cache_name(type, op, i),
637 event_type_descriptors[4]);
638 }
639 }
640 }
641
642 fprintf(stderr, "\n");
368 fprintf(stderr, " %-40s [raw hardware event descriptor]\n", 643 fprintf(stderr, " %-40s [raw hardware event descriptor]\n",
369 "rNNN"); 644 "rNNN");
370 fprintf(stderr, "\n"); 645 fprintf(stderr, "\n");
371 646
647 print_tracepoint_events();
648
372 exit(129); 649 exit(129);
373} 650}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index e3d552908e60..1ea5d09b6eb1 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -3,6 +3,8 @@
3 * Parse symbolic events/counts passed in as options: 3 * Parse symbolic events/counts passed in as options:
4 */ 4 */
5 5
6struct option;
7
6extern int nr_counters; 8extern int nr_counters;
7 9
8extern struct perf_counter_attr attrs[MAX_COUNTERS]; 10extern struct perf_counter_attr attrs[MAX_COUNTERS];
@@ -15,3 +17,6 @@ extern int parse_events(const struct option *opt, const char *str, int unset);
15 17
16extern void print_events(void); 18extern void print_events(void);
17 19
20extern char debugfs_path[];
21extern int valid_debugfs_mount(const char *debugfs);
22
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index b3affb1658d2..1bf67190c820 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -20,7 +20,8 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
20 if (p->opt) { 20 if (p->opt) {
21 *arg = p->opt; 21 *arg = p->opt;
22 p->opt = NULL; 22 p->opt = NULL;
23 } else if (p->argc == 1 && (opt->flags & PARSE_OPT_LASTARG_DEFAULT)) { 23 } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
24 **(p->argv + 1) == '-')) {
24 *arg = (const char *)opt->defval; 25 *arg = (const char *)opt->defval;
25 } else if (p->argc > 1) { 26 } else if (p->argc > 1) {
26 p->argc--; 27 p->argc--;
@@ -485,7 +486,7 @@ int parse_options_usage(const char * const *usagestr,
485} 486}
486 487
487 488
488int parse_opt_verbosity_cb(const struct option *opt, const char *arg, 489int parse_opt_verbosity_cb(const struct option *opt, const char *arg __used,
489 int unset) 490 int unset)
490{ 491{
491 int *target = opt->value; 492 int *target = opt->value;
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index a1039a6ce0eb..8aa3464c7090 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -90,21 +90,22 @@ struct option {
90 intptr_t defval; 90 intptr_t defval;
91}; 91};
92 92
93#define OPT_END() { OPTION_END } 93#define OPT_END() { .type = OPTION_END }
94#define OPT_ARGUMENT(l, h) { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) } 94#define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) }
95#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) } 95#define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) }
96#define OPT_BIT(s, l, v, h, b) { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) } 96#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (b) }
97#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) } 97#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = (v), .help = (h) }
98#define OPT_SET_INT(s, l, v, h, i) { OPTION_SET_INT, (s), (l), (v), NULL, (h), 0, NULL, (i) } 98#define OPT_SET_INT(s, l, v, h, i) { .type = OPTION_SET_INT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (i) }
99#define OPT_SET_PTR(s, l, v, h, p) { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) } 99#define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) }
100#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), NULL, (h) } 100#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = (v), .help = (h) }
101#define OPT_LONG(s, l, v, h) { OPTION_LONG, (s), (l), (v), NULL, (h) } 101#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = (v), .help = (h) }
102#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) } 102#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h) }
103#define OPT_DATE(s, l, v, h) \ 103#define OPT_DATE(s, l, v, h) \
104 { OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \ 104 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
105 parse_opt_approxidate_cb }
106#define OPT_CALLBACK(s, l, v, a, h, f) \ 105#define OPT_CALLBACK(s, l, v, a, h, f) \
107 { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) } 106 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) }
107#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
108 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }
108 109
109/* parse_options() will filter out the processed options and leave the 110/* parse_options() will filter out the processed options and leave the
110 * non-option argments in argv[]. 111 * non-option argments in argv[].
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c
index f18c5212bc92..2726fe40eb5d 100644
--- a/tools/perf/util/quote.c
+++ b/tools/perf/util/quote.c
@@ -162,12 +162,16 @@ static inline int sq_must_quote(char c)
162 return sq_lookup[(unsigned char)c] + quote_path_fully > 0; 162 return sq_lookup[(unsigned char)c] + quote_path_fully > 0;
163} 163}
164 164
165/* returns the longest prefix not needing a quote up to maxlen if positive. 165/*
166 This stops at the first \0 because it's marked as a character needing an 166 * Returns the longest prefix not needing a quote up to maxlen if
167 escape */ 167 * positive.
168static size_t next_quote_pos(const char *s, ssize_t maxlen) 168 * This stops at the first \0 because it's marked as a character
169 * needing an escape.
170 */
171static ssize_t next_quote_pos(const char *s, ssize_t maxlen)
169{ 172{
170 size_t len; 173 ssize_t len;
174
171 if (maxlen < 0) { 175 if (maxlen < 0) {
172 for (len = 0; !sq_must_quote(s[len]); len++); 176 for (len = 0; !sq_must_quote(s[len]); len++);
173 } else { 177 } else {
@@ -192,22 +196,22 @@ static size_t next_quote_pos(const char *s, ssize_t maxlen)
192static size_t quote_c_style_counted(const char *name, ssize_t maxlen, 196static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
193 struct strbuf *sb, FILE *fp, int no_dq) 197 struct strbuf *sb, FILE *fp, int no_dq)
194{ 198{
195#undef EMIT 199#define EMIT(c) \
196#define EMIT(c) \ 200 do { \
197 do { \ 201 if (sb) strbuf_addch(sb, (c)); \
198 if (sb) strbuf_addch(sb, (c)); \ 202 if (fp) fputc((c), fp); \
199 if (fp) fputc((c), fp); \ 203 count++; \
200 count++; \
201 } while (0) 204 } while (0)
202#define EMITBUF(s, l) \ 205
203 do { \ 206#define EMITBUF(s, l) \
204 int __ret; \ 207 do { \
205 if (sb) strbuf_add(sb, (s), (l)); \ 208 int __ret; \
206 if (fp) __ret = fwrite((s), (l), 1, fp); \ 209 if (sb) strbuf_add(sb, (s), (l)); \
207 count += (l); \ 210 if (fp) __ret = fwrite((s), (l), 1, fp); \
211 count += (l); \
208 } while (0) 212 } while (0)
209 213
210 size_t len, count = 0; 214 ssize_t len, count = 0;
211 const char *p = name; 215 const char *p = name;
212 216
213 for (;;) { 217 for (;;) {
@@ -273,8 +277,8 @@ void write_name_quoted(const char *name, FILE *fp, int terminator)
273 fputc(terminator, fp); 277 fputc(terminator, fp);
274} 278}
275 279
276extern void write_name_quotedpfx(const char *pfx, size_t pfxlen, 280void write_name_quotedpfx(const char *pfx, ssize_t pfxlen,
277 const char *name, FILE *fp, int terminator) 281 const char *name, FILE *fp, int terminator)
278{ 282{
279 int needquote = 0; 283 int needquote = 0;
280 284
@@ -306,7 +310,7 @@ char *quote_path_relative(const char *in, int len,
306 len = strlen(in); 310 len = strlen(in);
307 311
308 /* "../" prefix itself does not need quoting, but "in" might. */ 312 /* "../" prefix itself does not need quoting, but "in" might. */
309 needquote = next_quote_pos(in, len) < len; 313 needquote = (next_quote_pos(in, len) < len);
310 strbuf_setlen(out, 0); 314 strbuf_setlen(out, 0);
311 strbuf_grow(out, len); 315 strbuf_grow(out, len);
312 316
@@ -314,7 +318,7 @@ char *quote_path_relative(const char *in, int len,
314 strbuf_addch(out, '"'); 318 strbuf_addch(out, '"');
315 if (prefix) { 319 if (prefix) {
316 int off = 0; 320 int off = 0;
317 while (prefix[off] && off < len && prefix[off] == in[off]) 321 while (off < len && prefix[off] && prefix[off] == in[off])
318 if (prefix[off] == '/') { 322 if (prefix[off] == '/') {
319 prefix += off + 1; 323 prefix += off + 1;
320 in += off + 1; 324 in += off + 1;
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h
index 5dfad89816db..a5454a1d1c13 100644
--- a/tools/perf/util/quote.h
+++ b/tools/perf/util/quote.h
@@ -53,7 +53,7 @@ extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq
53extern void quote_two_c_style(struct strbuf *, const char *, const char *, int); 53extern void quote_two_c_style(struct strbuf *, const char *, const char *, int);
54 54
55extern void write_name_quoted(const char *name, FILE *, int terminator); 55extern void write_name_quoted(const char *name, FILE *, int terminator);
56extern void write_name_quotedpfx(const char *pfx, size_t pfxlen, 56extern void write_name_quotedpfx(const char *pfx, ssize_t pfxlen,
57 const char *name, FILE *, int terminator); 57 const char *name, FILE *, int terminator);
58 58
59/* quote path as relative to the given prefix */ 59/* quote path as relative to the given prefix */
diff --git a/tools/perf/util/rbtree.c b/tools/perf/util/rbtree.c
deleted file mode 100644
index b15ba9c7cb3f..000000000000
--- a/tools/perf/util/rbtree.c
+++ /dev/null
@@ -1,383 +0,0 @@
1/*
2 Red Black Trees
3 (C) 1999 Andrea Arcangeli <andrea@suse.de>
4 (C) 2002 David Woodhouse <dwmw2@infradead.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 linux/lib/rbtree.c
21*/
22
23#include "rbtree.h"
24
25static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
26{
27 struct rb_node *right = node->rb_right;
28 struct rb_node *parent = rb_parent(node);
29
30 if ((node->rb_right = right->rb_left))
31 rb_set_parent(right->rb_left, node);
32 right->rb_left = node;
33
34 rb_set_parent(right, parent);
35
36 if (parent)
37 {
38 if (node == parent->rb_left)
39 parent->rb_left = right;
40 else
41 parent->rb_right = right;
42 }
43 else
44 root->rb_node = right;
45 rb_set_parent(node, right);
46}
47
48static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
49{
50 struct rb_node *left = node->rb_left;
51 struct rb_node *parent = rb_parent(node);
52
53 if ((node->rb_left = left->rb_right))
54 rb_set_parent(left->rb_right, node);
55 left->rb_right = node;
56
57 rb_set_parent(left, parent);
58
59 if (parent)
60 {
61 if (node == parent->rb_right)
62 parent->rb_right = left;
63 else
64 parent->rb_left = left;
65 }
66 else
67 root->rb_node = left;
68 rb_set_parent(node, left);
69}
70
71void rb_insert_color(struct rb_node *node, struct rb_root *root)
72{
73 struct rb_node *parent, *gparent;
74
75 while ((parent = rb_parent(node)) && rb_is_red(parent))
76 {
77 gparent = rb_parent(parent);
78
79 if (parent == gparent->rb_left)
80 {
81 {
82 register struct rb_node *uncle = gparent->rb_right;
83 if (uncle && rb_is_red(uncle))
84 {
85 rb_set_black(uncle);
86 rb_set_black(parent);
87 rb_set_red(gparent);
88 node = gparent;
89 continue;
90 }
91 }
92
93 if (parent->rb_right == node)
94 {
95 register struct rb_node *tmp;
96 __rb_rotate_left(parent, root);
97 tmp = parent;
98 parent = node;
99 node = tmp;
100 }
101
102 rb_set_black(parent);
103 rb_set_red(gparent);
104 __rb_rotate_right(gparent, root);
105 } else {
106 {
107 register struct rb_node *uncle = gparent->rb_left;
108 if (uncle && rb_is_red(uncle))
109 {
110 rb_set_black(uncle);
111 rb_set_black(parent);
112 rb_set_red(gparent);
113 node = gparent;
114 continue;
115 }
116 }
117
118 if (parent->rb_left == node)
119 {
120 register struct rb_node *tmp;
121 __rb_rotate_right(parent, root);
122 tmp = parent;
123 parent = node;
124 node = tmp;
125 }
126
127 rb_set_black(parent);
128 rb_set_red(gparent);
129 __rb_rotate_left(gparent, root);
130 }
131 }
132
133 rb_set_black(root->rb_node);
134}
135
136static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
137 struct rb_root *root)
138{
139 struct rb_node *other;
140
141 while ((!node || rb_is_black(node)) && node != root->rb_node)
142 {
143 if (parent->rb_left == node)
144 {
145 other = parent->rb_right;
146 if (rb_is_red(other))
147 {
148 rb_set_black(other);
149 rb_set_red(parent);
150 __rb_rotate_left(parent, root);
151 other = parent->rb_right;
152 }
153 if ((!other->rb_left || rb_is_black(other->rb_left)) &&
154 (!other->rb_right || rb_is_black(other->rb_right)))
155 {
156 rb_set_red(other);
157 node = parent;
158 parent = rb_parent(node);
159 }
160 else
161 {
162 if (!other->rb_right || rb_is_black(other->rb_right))
163 {
164 rb_set_black(other->rb_left);
165 rb_set_red(other);
166 __rb_rotate_right(other, root);
167 other = parent->rb_right;
168 }
169 rb_set_color(other, rb_color(parent));
170 rb_set_black(parent);
171 rb_set_black(other->rb_right);
172 __rb_rotate_left(parent, root);
173 node = root->rb_node;
174 break;
175 }
176 }
177 else
178 {
179 other = parent->rb_left;
180 if (rb_is_red(other))
181 {
182 rb_set_black(other);
183 rb_set_red(parent);
184 __rb_rotate_right(parent, root);
185 other = parent->rb_left;
186 }
187 if ((!other->rb_left || rb_is_black(other->rb_left)) &&
188 (!other->rb_right || rb_is_black(other->rb_right)))
189 {
190 rb_set_red(other);
191 node = parent;
192 parent = rb_parent(node);
193 }
194 else
195 {
196 if (!other->rb_left || rb_is_black(other->rb_left))
197 {
198 rb_set_black(other->rb_right);
199 rb_set_red(other);
200 __rb_rotate_left(other, root);
201 other = parent->rb_left;
202 }
203 rb_set_color(other, rb_color(parent));
204 rb_set_black(parent);
205 rb_set_black(other->rb_left);
206 __rb_rotate_right(parent, root);
207 node = root->rb_node;
208 break;
209 }
210 }
211 }
212 if (node)
213 rb_set_black(node);
214}
215
216void rb_erase(struct rb_node *node, struct rb_root *root)
217{
218 struct rb_node *child, *parent;
219 int color;
220
221 if (!node->rb_left)
222 child = node->rb_right;
223 else if (!node->rb_right)
224 child = node->rb_left;
225 else
226 {
227 struct rb_node *old = node, *left;
228
229 node = node->rb_right;
230 while ((left = node->rb_left) != NULL)
231 node = left;
232 child = node->rb_right;
233 parent = rb_parent(node);
234 color = rb_color(node);
235
236 if (child)
237 rb_set_parent(child, parent);
238 if (parent == old) {
239 parent->rb_right = child;
240 parent = node;
241 } else
242 parent->rb_left = child;
243
244 node->rb_parent_color = old->rb_parent_color;
245 node->rb_right = old->rb_right;
246 node->rb_left = old->rb_left;
247
248 if (rb_parent(old))
249 {
250 if (rb_parent(old)->rb_left == old)
251 rb_parent(old)->rb_left = node;
252 else
253 rb_parent(old)->rb_right = node;
254 } else
255 root->rb_node = node;
256
257 rb_set_parent(old->rb_left, node);
258 if (old->rb_right)
259 rb_set_parent(old->rb_right, node);
260 goto color;
261 }
262
263 parent = rb_parent(node);
264 color = rb_color(node);
265
266 if (child)
267 rb_set_parent(child, parent);
268 if (parent)
269 {
270 if (parent->rb_left == node)
271 parent->rb_left = child;
272 else
273 parent->rb_right = child;
274 }
275 else
276 root->rb_node = child;
277
278 color:
279 if (color == RB_BLACK)
280 __rb_erase_color(child, parent, root);
281}
282
283/*
284 * This function returns the first node (in sort order) of the tree.
285 */
286struct rb_node *rb_first(const struct rb_root *root)
287{
288 struct rb_node *n;
289
290 n = root->rb_node;
291 if (!n)
292 return NULL;
293 while (n->rb_left)
294 n = n->rb_left;
295 return n;
296}
297
298struct rb_node *rb_last(const struct rb_root *root)
299{
300 struct rb_node *n;
301
302 n = root->rb_node;
303 if (!n)
304 return NULL;
305 while (n->rb_right)
306 n = n->rb_right;
307 return n;
308}
309
310struct rb_node *rb_next(const struct rb_node *node)
311{
312 struct rb_node *parent;
313
314 if (rb_parent(node) == node)
315 return NULL;
316
317 /* If we have a right-hand child, go down and then left as far
318 as we can. */
319 if (node->rb_right) {
320 node = node->rb_right;
321 while (node->rb_left)
322 node=node->rb_left;
323 return (struct rb_node *)node;
324 }
325
326 /* No right-hand children. Everything down and left is
327 smaller than us, so any 'next' node must be in the general
328 direction of our parent. Go up the tree; any time the
329 ancestor is a right-hand child of its parent, keep going
330 up. First time it's a left-hand child of its parent, said
331 parent is our 'next' node. */
332 while ((parent = rb_parent(node)) && node == parent->rb_right)
333 node = parent;
334
335 return parent;
336}
337
338struct rb_node *rb_prev(const struct rb_node *node)
339{
340 struct rb_node *parent;
341
342 if (rb_parent(node) == node)
343 return NULL;
344
345 /* If we have a left-hand child, go down and then right as far
346 as we can. */
347 if (node->rb_left) {
348 node = node->rb_left;
349 while (node->rb_right)
350 node=node->rb_right;
351 return (struct rb_node *)node;
352 }
353
354 /* No left-hand children. Go up till we find an ancestor which
355 is a right-hand child of its parent */
356 while ((parent = rb_parent(node)) && node == parent->rb_left)
357 node = parent;
358
359 return parent;
360}
361
362void rb_replace_node(struct rb_node *victim, struct rb_node *new,
363 struct rb_root *root)
364{
365 struct rb_node *parent = rb_parent(victim);
366
367 /* Set the surrounding nodes to point to the replacement */
368 if (parent) {
369 if (victim == parent->rb_left)
370 parent->rb_left = new;
371 else
372 parent->rb_right = new;
373 } else {
374 root->rb_node = new;
375 }
376 if (victim->rb_left)
377 rb_set_parent(victim->rb_left, new);
378 if (victim->rb_right)
379 rb_set_parent(victim->rb_right, new);
380
381 /* Copy the pointers/colour from the victim to the replacement */
382 *new = *victim;
383}
diff --git a/tools/perf/util/rbtree.h b/tools/perf/util/rbtree.h
deleted file mode 100644
index 6bdc488a47fb..000000000000
--- a/tools/perf/util/rbtree.h
+++ /dev/null
@@ -1,171 +0,0 @@
1/*
2 Red Black Trees
3 (C) 1999 Andrea Arcangeli <andrea@suse.de>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 linux/include/linux/rbtree.h
20
21 To use rbtrees you'll have to implement your own insert and search cores.
22 This will avoid us to use callbacks and to drop drammatically performances.
23 I know it's not the cleaner way, but in C (not in C++) to get
24 performances and genericity...
25
26 Some example of insert and search follows here. The search is a plain
27 normal search over an ordered tree. The insert instead must be implemented
28 int two steps: as first thing the code must insert the element in
29 order as a red leaf in the tree, then the support library function
30 rb_insert_color() must be called. Such function will do the
31 not trivial work to rebalance the rbtree if necessary.
32
33-----------------------------------------------------------------------
34static inline struct page * rb_search_page_cache(struct inode * inode,
35 unsigned long offset)
36{
37 struct rb_node * n = inode->i_rb_page_cache.rb_node;
38 struct page * page;
39
40 while (n)
41 {
42 page = rb_entry(n, struct page, rb_page_cache);
43
44 if (offset < page->offset)
45 n = n->rb_left;
46 else if (offset > page->offset)
47 n = n->rb_right;
48 else
49 return page;
50 }
51 return NULL;
52}
53
54static inline struct page * __rb_insert_page_cache(struct inode * inode,
55 unsigned long offset,
56 struct rb_node * node)
57{
58 struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
59 struct rb_node * parent = NULL;
60 struct page * page;
61
62 while (*p)
63 {
64 parent = *p;
65 page = rb_entry(parent, struct page, rb_page_cache);
66
67 if (offset < page->offset)
68 p = &(*p)->rb_left;
69 else if (offset > page->offset)
70 p = &(*p)->rb_right;
71 else
72 return page;
73 }
74
75 rb_link_node(node, parent, p);
76
77 return NULL;
78}
79
80static inline struct page * rb_insert_page_cache(struct inode * inode,
81 unsigned long offset,
82 struct rb_node * node)
83{
84 struct page * ret;
85 if ((ret = __rb_insert_page_cache(inode, offset, node)))
86 goto out;
87 rb_insert_color(node, &inode->i_rb_page_cache);
88 out:
89 return ret;
90}
91-----------------------------------------------------------------------
92*/
93
94#ifndef _LINUX_RBTREE_H
95#define _LINUX_RBTREE_H
96
97#include <stddef.h>
98
99/**
100 * container_of - cast a member of a structure out to the containing structure
101 * @ptr: the pointer to the member.
102 * @type: the type of the container struct this is embedded in.
103 * @member: the name of the member within the struct.
104 *
105 */
106#define container_of(ptr, type, member) ({ \
107 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
108 (type *)( (char *)__mptr - offsetof(type,member) );})
109
110struct rb_node
111{
112 unsigned long rb_parent_color;
113#define RB_RED 0
114#define RB_BLACK 1
115 struct rb_node *rb_right;
116 struct rb_node *rb_left;
117} __attribute__((aligned(sizeof(long))));
118 /* The alignment might seem pointless, but allegedly CRIS needs it */
119
120struct rb_root
121{
122 struct rb_node *rb_node;
123};
124
125
126#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
127#define rb_color(r) ((r)->rb_parent_color & 1)
128#define rb_is_red(r) (!rb_color(r))
129#define rb_is_black(r) rb_color(r)
130#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
131#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
132
133static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
134{
135 rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
136}
137static inline void rb_set_color(struct rb_node *rb, int color)
138{
139 rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
140}
141
142#define RB_ROOT (struct rb_root) { NULL, }
143#define rb_entry(ptr, type, member) container_of(ptr, type, member)
144
145#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
146#define RB_EMPTY_NODE(node) (rb_parent(node) == node)
147#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
148
149extern void rb_insert_color(struct rb_node *, struct rb_root *);
150extern void rb_erase(struct rb_node *, struct rb_root *);
151
152/* Find logical next and previous nodes in a tree */
153extern struct rb_node *rb_next(const struct rb_node *);
154extern struct rb_node *rb_prev(const struct rb_node *);
155extern struct rb_node *rb_first(const struct rb_root *);
156extern struct rb_node *rb_last(const struct rb_root *);
157
158/* Fast replacement of a single node without remove/rebalance/add/rebalance */
159extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
160 struct rb_root *root);
161
162static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
163 struct rb_node ** rb_link)
164{
165 node->rb_parent_color = (unsigned long )parent;
166 node->rb_left = node->rb_right = NULL;
167
168 *rb_link = node;
169}
170
171#endif /* _LINUX_RBTREE_H */
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 464e7ca898cf..5249d5a1b0c2 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -16,7 +16,7 @@ int prefixcmp(const char *str, const char *prefix)
16 */ 16 */
17char strbuf_slopbuf[1]; 17char strbuf_slopbuf[1];
18 18
19void strbuf_init(struct strbuf *sb, size_t hint) 19void strbuf_init(struct strbuf *sb, ssize_t hint)
20{ 20{
21 sb->alloc = sb->len = 0; 21 sb->alloc = sb->len = 0;
22 sb->buf = strbuf_slopbuf; 22 sb->buf = strbuf_slopbuf;
@@ -92,7 +92,8 @@ void strbuf_ltrim(struct strbuf *sb)
92 92
93void strbuf_tolower(struct strbuf *sb) 93void strbuf_tolower(struct strbuf *sb)
94{ 94{
95 int i; 95 unsigned int i;
96
96 for (i = 0; i < sb->len; i++) 97 for (i = 0; i < sb->len; i++)
97 sb->buf[i] = tolower(sb->buf[i]); 98 sb->buf[i] = tolower(sb->buf[i]);
98} 99}
@@ -264,7 +265,7 @@ size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
264 return res; 265 return res;
265} 266}
266 267
267ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint) 268ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
268{ 269{
269 size_t oldlen = sb->len; 270 size_t oldlen = sb->len;
270 size_t oldalloc = sb->alloc; 271 size_t oldalloc = sb->alloc;
@@ -293,7 +294,7 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
293 294
294#define STRBUF_MAXLINK (2*PATH_MAX) 295#define STRBUF_MAXLINK (2*PATH_MAX)
295 296
296int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint) 297int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint)
297{ 298{
298 size_t oldalloc = sb->alloc; 299 size_t oldalloc = sb->alloc;
299 300
@@ -301,7 +302,7 @@ int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
301 hint = 32; 302 hint = 32;
302 303
303 while (hint < STRBUF_MAXLINK) { 304 while (hint < STRBUF_MAXLINK) {
304 int len; 305 ssize_t len;
305 306
306 strbuf_grow(sb, hint); 307 strbuf_grow(sb, hint);
307 len = readlink(path, sb->buf, hint); 308 len = readlink(path, sb->buf, hint);
@@ -343,7 +344,7 @@ int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
343 return 0; 344 return 0;
344} 345}
345 346
346int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint) 347int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint)
347{ 348{
348 int fd, len; 349 int fd, len;
349 350
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index 9ee908a3ec5d..d2aa86c014c1 100644
--- a/tools/perf/util/strbuf.h
+++ b/tools/perf/util/strbuf.h
@@ -50,7 +50,7 @@ struct strbuf {
50#define STRBUF_INIT { 0, 0, strbuf_slopbuf } 50#define STRBUF_INIT { 0, 0, strbuf_slopbuf }
51 51
52/*----- strbuf life cycle -----*/ 52/*----- strbuf life cycle -----*/
53extern void strbuf_init(struct strbuf *, size_t); 53extern void strbuf_init(struct strbuf *buf, ssize_t hint);
54extern void strbuf_release(struct strbuf *); 54extern void strbuf_release(struct strbuf *);
55extern char *strbuf_detach(struct strbuf *, size_t *); 55extern char *strbuf_detach(struct strbuf *, size_t *);
56extern void strbuf_attach(struct strbuf *, void *, size_t, size_t); 56extern void strbuf_attach(struct strbuf *, void *, size_t, size_t);
@@ -61,7 +61,7 @@ static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) {
61} 61}
62 62
63/*----- strbuf size related -----*/ 63/*----- strbuf size related -----*/
64static inline size_t strbuf_avail(const struct strbuf *sb) { 64static inline ssize_t strbuf_avail(const struct strbuf *sb) {
65 return sb->alloc ? sb->alloc - sb->len - 1 : 0; 65 return sb->alloc ? sb->alloc - sb->len - 1 : 0;
66} 66}
67 67
@@ -122,9 +122,9 @@ extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
122 122
123extern size_t strbuf_fread(struct strbuf *, size_t, FILE *); 123extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
124/* XXX: if read fails, any partial read is undone */ 124/* XXX: if read fails, any partial read is undone */
125extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint); 125extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
126extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint); 126extern int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint);
127extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint); 127extern int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint);
128 128
129extern int strbuf_getline(struct strbuf *, FILE *, int); 129extern int strbuf_getline(struct strbuf *, FILE *, int);
130 130
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h
index 3dca2f654cd0..bf39dfadfd24 100644
--- a/tools/perf/util/string.h
+++ b/tools/perf/util/string.h
@@ -5,4 +5,7 @@
5 5
6int hex2u64(const char *ptr, u64 *val); 6int hex2u64(const char *ptr, u64 *val);
7 7
8#define _STR(x) #x
9#define STR(x) _STR(x)
10
8#endif 11#endif
diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c
index 025a78edfffe..7ad38171dc2b 100644
--- a/tools/perf/util/strlist.c
+++ b/tools/perf/util/strlist.c
@@ -64,6 +64,7 @@ int strlist__add(struct strlist *self, const char *new_entry)
64 64
65 rb_link_node(&sn->rb_node, parent, p); 65 rb_link_node(&sn->rb_node, parent, p);
66 rb_insert_color(&sn->rb_node, &self->entries); 66 rb_insert_color(&sn->rb_node, &self->entries);
67 ++self->nr_entries;
67 68
68 return 0; 69 return 0;
69} 70}
@@ -155,8 +156,9 @@ struct strlist *strlist__new(bool dupstr, const char *slist)
155 struct strlist *self = malloc(sizeof(*self)); 156 struct strlist *self = malloc(sizeof(*self));
156 157
157 if (self != NULL) { 158 if (self != NULL) {
158 self->entries = RB_ROOT; 159 self->entries = RB_ROOT;
159 self->dupstr = dupstr; 160 self->dupstr = dupstr;
161 self->nr_entries = 0;
160 if (slist && strlist__parse_list(self, slist) != 0) 162 if (slist && strlist__parse_list(self, slist) != 0)
161 goto out_error; 163 goto out_error;
162 } 164 }
@@ -182,3 +184,17 @@ void strlist__delete(struct strlist *self)
182 free(self); 184 free(self);
183 } 185 }
184} 186}
187
188struct str_node *strlist__entry(const struct strlist *self, unsigned int idx)
189{
190 struct rb_node *nd;
191
192 for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
193 struct str_node *pos = rb_entry(nd, struct str_node, rb_node);
194
195 if (!idx--)
196 return pos;
197 }
198
199 return NULL;
200}
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h
index 2fb117fb4b67..921818e44a54 100644
--- a/tools/perf/util/strlist.h
+++ b/tools/perf/util/strlist.h
@@ -1,7 +1,7 @@
1#ifndef STRLIST_H_ 1#ifndef STRLIST_H_
2#define STRLIST_H_ 2#define STRLIST_H_
3 3
4#include "rbtree.h" 4#include <linux/rbtree.h>
5#include <stdbool.h> 5#include <stdbool.h>
6 6
7struct str_node { 7struct str_node {
@@ -11,7 +11,8 @@ struct str_node {
11 11
12struct strlist { 12struct strlist {
13 struct rb_root entries; 13 struct rb_root entries;
14 bool dupstr; 14 unsigned int nr_entries;
15 bool dupstr;
15}; 16};
16 17
17struct strlist *strlist__new(bool dupstr, const char *slist); 18struct strlist *strlist__new(bool dupstr, const char *slist);
@@ -21,11 +22,17 @@ void strlist__remove(struct strlist *self, struct str_node *sn);
21int strlist__load(struct strlist *self, const char *filename); 22int strlist__load(struct strlist *self, const char *filename);
22int strlist__add(struct strlist *self, const char *str); 23int strlist__add(struct strlist *self, const char *str);
23 24
25struct str_node *strlist__entry(const struct strlist *self, unsigned int idx);
24bool strlist__has_entry(struct strlist *self, const char *entry); 26bool strlist__has_entry(struct strlist *self, const char *entry);
25 27
26static inline bool strlist__empty(const struct strlist *self) 28static inline bool strlist__empty(const struct strlist *self)
27{ 29{
28 return rb_first(&self->entries) == NULL; 30 return self->nr_entries == 0;
31}
32
33static inline unsigned int strlist__nr_entries(const struct strlist *self)
34{
35 return self->nr_entries;
29} 36}
30 37
31int strlist__parse_list(struct strlist *self, const char *s); 38int strlist__parse_list(struct strlist *self, const char *s);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 78c2efde01b7..16ddca202948 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -7,8 +7,23 @@
7#include <gelf.h> 7#include <gelf.h>
8#include <elf.h> 8#include <elf.h>
9 9
10#ifndef NO_DEMANGLE
11#include <bfd.h>
12#else
13static inline
14char *bfd_demangle(void __used *v, const char __used *c, int __used i)
15{
16 return NULL;
17}
18#endif
19
10const char *sym_hist_filter; 20const char *sym_hist_filter;
11 21
22#ifndef DMGL_PARAMS
23#define DMGL_PARAMS (1 << 0) /* Include function args */
24#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
25#endif
26
12static struct symbol *symbol__new(u64 start, u64 len, 27static struct symbol *symbol__new(u64 start, u64 len,
13 const char *name, unsigned int priv_size, 28 const char *name, unsigned int priv_size,
14 u64 obj_start, int verbose) 29 u64 obj_start, int verbose)
@@ -35,7 +50,7 @@ static struct symbol *symbol__new(u64 start, u64 len,
35 self = ((void *)self) + priv_size; 50 self = ((void *)self) + priv_size;
36 } 51 }
37 self->start = start; 52 self->start = start;
38 self->end = start + len - 1; 53 self->end = len ? start + len - 1 : start;
39 memcpy(self->name, name, namelen); 54 memcpy(self->name, name, namelen);
40 55
41 return self; 56 return self;
@@ -48,8 +63,12 @@ static void symbol__delete(struct symbol *self, unsigned int priv_size)
48 63
49static size_t symbol__fprintf(struct symbol *self, FILE *fp) 64static size_t symbol__fprintf(struct symbol *self, FILE *fp)
50{ 65{
51 return fprintf(fp, " %llx-%llx %s\n", 66 if (!self->module)
67 return fprintf(fp, " %llx-%llx %s\n",
52 self->start, self->end, self->name); 68 self->start, self->end, self->name);
69 else
70 return fprintf(fp, " %llx-%llx %s \t[%s]\n",
71 self->start, self->end, self->name, self->module->name);
53} 72}
54 73
55struct dso *dso__new(const char *name, unsigned int sym_priv_size) 74struct dso *dso__new(const char *name, unsigned int sym_priv_size)
@@ -61,6 +80,7 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
61 self->syms = RB_ROOT; 80 self->syms = RB_ROOT;
62 self->sym_priv_size = sym_priv_size; 81 self->sym_priv_size = sym_priv_size;
63 self->find_symbol = dso__find_symbol; 82 self->find_symbol = dso__find_symbol;
83 self->slen_calculated = 0;
64 } 84 }
65 85
66 return self; 86 return self;
@@ -146,6 +166,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
146 char *line = NULL; 166 char *line = NULL;
147 size_t n; 167 size_t n;
148 FILE *file = fopen("/proc/kallsyms", "r"); 168 FILE *file = fopen("/proc/kallsyms", "r");
169 int count = 0;
149 170
150 if (file == NULL) 171 if (file == NULL)
151 goto out_failure; 172 goto out_failure;
@@ -188,8 +209,10 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
188 209
189 if (filter && filter(self, sym)) 210 if (filter && filter(self, sym))
190 symbol__delete(sym, self->sym_priv_size); 211 symbol__delete(sym, self->sym_priv_size);
191 else 212 else {
192 dso__insert_symbol(self, sym); 213 dso__insert_symbol(self, sym);
214 count++;
215 }
193 } 216 }
194 217
195 /* 218 /*
@@ -212,7 +235,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
212 free(line); 235 free(line);
213 fclose(file); 236 fclose(file);
214 237
215 return 0; 238 return count;
216 239
217out_delete_line: 240out_delete_line:
218 free(line); 241 free(line);
@@ -307,6 +330,26 @@ static inline int elf_sym__is_function(const GElf_Sym *sym)
307 sym->st_size != 0; 330 sym->st_size != 0;
308} 331}
309 332
333static inline int elf_sym__is_label(const GElf_Sym *sym)
334{
335 return elf_sym__type(sym) == STT_NOTYPE &&
336 sym->st_name != 0 &&
337 sym->st_shndx != SHN_UNDEF &&
338 sym->st_shndx != SHN_ABS;
339}
340
341static inline const char *elf_sec__name(const GElf_Shdr *shdr,
342 const Elf_Data *secstrs)
343{
344 return secstrs->d_buf + shdr->sh_name;
345}
346
347static inline int elf_sec__is_text(const GElf_Shdr *shdr,
348 const Elf_Data *secstrs)
349{
350 return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
351}
352
310static inline const char *elf_sym__name(const GElf_Sym *sym, 353static inline const char *elf_sym__name(const GElf_Sym *sym,
311 const Elf_Data *symstrs) 354 const Elf_Data *symstrs)
312{ 355{
@@ -346,36 +389,61 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
346 idx < nr_entries; \ 389 idx < nr_entries; \
347 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) 390 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
348 391
349static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, 392/*
350 GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym, 393 * We need to check if we have a .dynsym, so that we can handle the
351 GElf_Shdr *shdr_dynsym, 394 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
352 size_t dynsym_idx, int verbose) 395 * .dynsym or .symtab).
396 * And always look at the original dso, not at debuginfo packages, that
397 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
398 */
399static int dso__synthesize_plt_symbols(struct dso *self, int verbose)
353{ 400{
354 uint32_t nr_rel_entries, idx; 401 uint32_t nr_rel_entries, idx;
355 GElf_Sym sym; 402 GElf_Sym sym;
356 u64 plt_offset; 403 u64 plt_offset;
357 GElf_Shdr shdr_plt; 404 GElf_Shdr shdr_plt;
358 struct symbol *f; 405 struct symbol *f;
359 GElf_Shdr shdr_rel_plt; 406 GElf_Shdr shdr_rel_plt, shdr_dynsym;
360 Elf_Data *reldata, *syms, *symstrs; 407 Elf_Data *reldata, *syms, *symstrs;
361 Elf_Scn *scn_plt_rel, *scn_symstrs; 408 Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
409 size_t dynsym_idx;
410 GElf_Ehdr ehdr;
362 char sympltname[1024]; 411 char sympltname[1024];
363 int nr = 0, symidx; 412 Elf *elf;
413 int nr = 0, symidx, fd, err = 0;
414
415 fd = open(self->name, O_RDONLY);
416 if (fd < 0)
417 goto out;
418
419 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
420 if (elf == NULL)
421 goto out_close;
364 422
365 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 423 if (gelf_getehdr(elf, &ehdr) == NULL)
424 goto out_elf_end;
425
426 scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
427 ".dynsym", &dynsym_idx);
428 if (scn_dynsym == NULL)
429 goto out_elf_end;
430
431 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
366 ".rela.plt", NULL); 432 ".rela.plt", NULL);
367 if (scn_plt_rel == NULL) { 433 if (scn_plt_rel == NULL) {
368 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 434 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
369 ".rel.plt", NULL); 435 ".rel.plt", NULL);
370 if (scn_plt_rel == NULL) 436 if (scn_plt_rel == NULL)
371 return 0; 437 goto out_elf_end;
372 } 438 }
373 439
440 err = -1;
441
374 if (shdr_rel_plt.sh_link != dynsym_idx) 442 if (shdr_rel_plt.sh_link != dynsym_idx)
375 return 0; 443 goto out_elf_end;
376 444
377 if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL) 445 if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
378 return 0; 446 goto out_elf_end;
379 447
380 /* 448 /*
381 * Fetch the relocation section to find the indexes to the GOT 449 * Fetch the relocation section to find the indexes to the GOT
@@ -383,19 +451,19 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
383 */ 451 */
384 reldata = elf_getdata(scn_plt_rel, NULL); 452 reldata = elf_getdata(scn_plt_rel, NULL);
385 if (reldata == NULL) 453 if (reldata == NULL)
386 return -1; 454 goto out_elf_end;
387 455
388 syms = elf_getdata(scn_dynsym, NULL); 456 syms = elf_getdata(scn_dynsym, NULL);
389 if (syms == NULL) 457 if (syms == NULL)
390 return -1; 458 goto out_elf_end;
391 459
392 scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link); 460 scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
393 if (scn_symstrs == NULL) 461 if (scn_symstrs == NULL)
394 return -1; 462 goto out_elf_end;
395 463
396 symstrs = elf_getdata(scn_symstrs, NULL); 464 symstrs = elf_getdata(scn_symstrs, NULL);
397 if (symstrs == NULL) 465 if (symstrs == NULL)
398 return -1; 466 goto out_elf_end;
399 467
400 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; 468 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
401 plt_offset = shdr_plt.sh_offset; 469 plt_offset = shdr_plt.sh_offset;
@@ -414,7 +482,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
414 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 482 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
415 sympltname, self->sym_priv_size, 0, verbose); 483 sympltname, self->sym_priv_size, 0, verbose);
416 if (!f) 484 if (!f)
417 return -1; 485 goto out_elf_end;
418 486
419 dso__insert_symbol(self, f); 487 dso__insert_symbol(self, f);
420 ++nr; 488 ++nr;
@@ -432,25 +500,31 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
432 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 500 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
433 sympltname, self->sym_priv_size, 0, verbose); 501 sympltname, self->sym_priv_size, 0, verbose);
434 if (!f) 502 if (!f)
435 return -1; 503 goto out_elf_end;
436 504
437 dso__insert_symbol(self, f); 505 dso__insert_symbol(self, f);
438 ++nr; 506 ++nr;
439 } 507 }
440 } else {
441 /*
442 * TODO: There are still one more shdr_rel_plt.sh_type
443 * I have to investigate, but probably should be ignored.
444 */
445 } 508 }
446 509
447 return nr; 510 err = 0;
511out_elf_end:
512 elf_end(elf);
513out_close:
514 close(fd);
515
516 if (err == 0)
517 return nr;
518out:
519 fprintf(stderr, "%s: problems reading %s PLT info.\n",
520 __func__, self->name);
521 return 0;
448} 522}
449 523
450static int dso__load_sym(struct dso *self, int fd, const char *name, 524static int dso__load_sym(struct dso *self, int fd, const char *name,
451 symbol_filter_t filter, int verbose) 525 symbol_filter_t filter, int verbose, struct module *mod)
452{ 526{
453 Elf_Data *symstrs; 527 Elf_Data *symstrs, *secstrs;
454 uint32_t nr_syms; 528 uint32_t nr_syms;
455 int err = -1; 529 int err = -1;
456 uint32_t index; 530 uint32_t index;
@@ -458,10 +532,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
458 GElf_Shdr shdr; 532 GElf_Shdr shdr;
459 Elf_Data *syms; 533 Elf_Data *syms;
460 GElf_Sym sym; 534 GElf_Sym sym;
461 Elf_Scn *sec, *sec_dynsym; 535 Elf_Scn *sec, *sec_strndx;
462 Elf *elf; 536 Elf *elf;
463 size_t dynsym_idx; 537 int nr = 0, kernel = !strcmp("[kernel]", self->name);
464 int nr = 0;
465 538
466 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 539 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
467 if (elf == NULL) { 540 if (elf == NULL) {
@@ -477,32 +550,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
477 goto out_elf_end; 550 goto out_elf_end;
478 } 551 }
479 552
480 /*
481 * We need to check if we have a .dynsym, so that we can handle the
482 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
483 * .dynsym or .symtab)
484 */
485 sec_dynsym = elf_section_by_name(elf, &ehdr, &shdr,
486 ".dynsym", &dynsym_idx);
487 if (sec_dynsym != NULL) {
488 nr = dso__synthesize_plt_symbols(self, elf, &ehdr,
489 sec_dynsym, &shdr,
490 dynsym_idx, verbose);
491 if (nr < 0)
492 goto out_elf_end;
493 }
494
495 /*
496 * But if we have a full .symtab (that is a superset of .dynsym) we
497 * should add the symbols not in the .dynsyn
498 */
499 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); 553 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
500 if (sec == NULL) { 554 if (sec == NULL) {
501 if (sec_dynsym == NULL) 555 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
556 if (sec == NULL)
502 goto out_elf_end; 557 goto out_elf_end;
503
504 sec = sec_dynsym;
505 gelf_getshdr(sec, &shdr);
506 } 558 }
507 559
508 syms = elf_getdata(sec, NULL); 560 syms = elf_getdata(sec, NULL);
@@ -517,17 +569,34 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
517 if (symstrs == NULL) 569 if (symstrs == NULL)
518 goto out_elf_end; 570 goto out_elf_end;
519 571
572 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
573 if (sec_strndx == NULL)
574 goto out_elf_end;
575
576 secstrs = elf_getdata(sec_strndx, NULL);
577 if (secstrs == NULL)
578 goto out_elf_end;
579
520 nr_syms = shdr.sh_size / shdr.sh_entsize; 580 nr_syms = shdr.sh_size / shdr.sh_entsize;
521 581
522 memset(&sym, 0, sizeof(sym)); 582 memset(&sym, 0, sizeof(sym));
523 self->prelinked = elf_section_by_name(elf, &ehdr, &shdr, 583 if (!kernel) {
524 ".gnu.prelink_undo", 584 self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
525 NULL) != NULL; 585 elf_section_by_name(elf, &ehdr, &shdr,
586 ".gnu.prelink_undo",
587 NULL) != NULL);
588 } else self->adjust_symbols = 0;
589
526 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 590 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
527 struct symbol *f; 591 struct symbol *f;
592 const char *name;
593 char *demangled;
528 u64 obj_start; 594 u64 obj_start;
595 struct section *section = NULL;
596 int is_label = elf_sym__is_label(&sym);
597 const char *section_name;
529 598
530 if (!elf_sym__is_function(&sym)) 599 if (!is_label && !elf_sym__is_function(&sym))
531 continue; 600 continue;
532 601
533 sec = elf_getscn(elf, sym.st_shndx); 602 sec = elf_getscn(elf, sym.st_shndx);
@@ -535,9 +604,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
535 goto out_elf_end; 604 goto out_elf_end;
536 605
537 gelf_getshdr(sec, &shdr); 606 gelf_getshdr(sec, &shdr);
607
608 if (is_label && !elf_sec__is_text(&shdr, secstrs))
609 continue;
610
611 section_name = elf_sec__name(&shdr, secstrs);
538 obj_start = sym.st_value; 612 obj_start = sym.st_value;
539 613
540 if (self->prelinked) { 614 if (self->adjust_symbols) {
541 if (verbose >= 2) 615 if (verbose >= 2)
542 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", 616 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
543 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 617 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
@@ -545,15 +619,36 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
545 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 619 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
546 } 620 }
547 621
548 f = symbol__new(sym.st_value, sym.st_size, 622 if (mod) {
549 elf_sym__name(&sym, symstrs), 623 section = mod->sections->find_section(mod->sections, section_name);
624 if (section)
625 sym.st_value += section->vma;
626 else {
627 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
628 mod->name, section_name);
629 goto out_elf_end;
630 }
631 }
632 /*
633 * We need to figure out if the object was created from C++ sources
634 * DWARF DW_compile_unit has this, but we don't always have access
635 * to it...
636 */
637 name = elf_sym__name(&sym, symstrs);
638 demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI);
639 if (demangled != NULL)
640 name = demangled;
641
642 f = symbol__new(sym.st_value, sym.st_size, name,
550 self->sym_priv_size, obj_start, verbose); 643 self->sym_priv_size, obj_start, verbose);
644 free(demangled);
551 if (!f) 645 if (!f)
552 goto out_elf_end; 646 goto out_elf_end;
553 647
554 if (filter && filter(self, f)) 648 if (filter && filter(self, f))
555 symbol__delete(f, self->sym_priv_size); 649 symbol__delete(f, self->sym_priv_size);
556 else { 650 else {
651 f->module = mod;
557 dso__insert_symbol(self, f); 652 dso__insert_symbol(self, f);
558 nr++; 653 nr++;
559 } 654 }
@@ -566,10 +661,69 @@ out_close:
566 return err; 661 return err;
567} 662}
568 663
664#define BUILD_ID_SIZE 128
665
666static char *dso__read_build_id(struct dso *self, int verbose)
667{
668 int i;
669 GElf_Ehdr ehdr;
670 GElf_Shdr shdr;
671 Elf_Data *build_id_data;
672 Elf_Scn *sec;
673 char *build_id = NULL, *bid;
674 unsigned char *raw;
675 Elf *elf;
676 int fd = open(self->name, O_RDONLY);
677
678 if (fd < 0)
679 goto out;
680
681 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
682 if (elf == NULL) {
683 if (verbose)
684 fprintf(stderr, "%s: cannot read %s ELF file.\n",
685 __func__, self->name);
686 goto out_close;
687 }
688
689 if (gelf_getehdr(elf, &ehdr) == NULL) {
690 if (verbose)
691 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
692 goto out_elf_end;
693 }
694
695 sec = elf_section_by_name(elf, &ehdr, &shdr, ".note.gnu.build-id", NULL);
696 if (sec == NULL)
697 goto out_elf_end;
698
699 build_id_data = elf_getdata(sec, NULL);
700 if (build_id_data == NULL)
701 goto out_elf_end;
702 build_id = malloc(BUILD_ID_SIZE);
703 if (build_id == NULL)
704 goto out_elf_end;
705 raw = build_id_data->d_buf + 16;
706 bid = build_id;
707
708 for (i = 0; i < 20; ++i) {
709 sprintf(bid, "%02x", *raw);
710 ++raw;
711 bid += 2;
712 }
713 if (verbose)
714 printf("%s(%s): %s\n", __func__, self->name, build_id);
715out_elf_end:
716 elf_end(elf);
717out_close:
718 close(fd);
719out:
720 return build_id;
721}
722
569int dso__load(struct dso *self, symbol_filter_t filter, int verbose) 723int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
570{ 724{
571 int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug"); 725 int size = PATH_MAX;
572 char *name = malloc(size); 726 char *name = malloc(size), *build_id = NULL;
573 int variant = 0; 727 int variant = 0;
574 int ret = -1; 728 int ret = -1;
575 int fd; 729 int fd;
@@ -577,7 +731,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
577 if (!name) 731 if (!name)
578 return -1; 732 return -1;
579 733
580 self->prelinked = 0; 734 self->adjust_symbols = 0;
581 735
582 if (strncmp(self->name, "/tmp/perf-", 10) == 0) 736 if (strncmp(self->name, "/tmp/perf-", 10) == 0)
583 return dso__load_perf_map(self, filter, verbose); 737 return dso__load_perf_map(self, filter, verbose);
@@ -591,7 +745,18 @@ more:
591 case 1: /* Ubuntu */ 745 case 1: /* Ubuntu */
592 snprintf(name, size, "/usr/lib/debug%s", self->name); 746 snprintf(name, size, "/usr/lib/debug%s", self->name);
593 break; 747 break;
594 case 2: /* Sane people */ 748 case 2:
749 build_id = dso__read_build_id(self, verbose);
750 if (build_id != NULL) {
751 snprintf(name, size,
752 "/usr/lib/debug/.build-id/%.2s/%s.debug",
753 build_id, build_id + 2);
754 free(build_id);
755 break;
756 }
757 variant++;
758 /* Fall thru */
759 case 3: /* Sane people */
595 snprintf(name, size, "%s", self->name); 760 snprintf(name, size, "%s", self->name);
596 break; 761 break;
597 762
@@ -603,7 +768,7 @@ more:
603 fd = open(name, O_RDONLY); 768 fd = open(name, O_RDONLY);
604 } while (fd < 0); 769 } while (fd < 0);
605 770
606 ret = dso__load_sym(self, fd, name, filter, verbose); 771 ret = dso__load_sym(self, fd, name, filter, verbose, NULL);
607 close(fd); 772 close(fd);
608 773
609 /* 774 /*
@@ -612,11 +777,96 @@ more:
612 if (!ret) 777 if (!ret)
613 goto more; 778 goto more;
614 779
780 if (ret > 0) {
781 int nr_plt = dso__synthesize_plt_symbols(self, verbose);
782 if (nr_plt > 0)
783 ret += nr_plt;
784 }
615out: 785out:
616 free(name); 786 free(name);
617 return ret; 787 return ret;
618} 788}
619 789
790static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name,
791 symbol_filter_t filter, int verbose)
792{
793 struct module *mod = mod_dso__find_module(mods, name);
794 int err = 0, fd;
795
796 if (mod == NULL || !mod->active)
797 return err;
798
799 fd = open(mod->path, O_RDONLY);
800
801 if (fd < 0)
802 return err;
803
804 err = dso__load_sym(self, fd, name, filter, verbose, mod);
805 close(fd);
806
807 return err;
808}
809
810int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose)
811{
812 struct mod_dso *mods = mod_dso__new_dso("modules");
813 struct module *pos;
814 struct rb_node *next;
815 int err;
816
817 err = mod_dso__load_modules(mods);
818
819 if (err <= 0)
820 return err;
821
822 /*
823 * Iterate over modules, and load active symbols.
824 */
825 next = rb_first(&mods->mods);
826 while (next) {
827 pos = rb_entry(next, struct module, rb_node);
828 err = dso__load_module(self, mods, pos->name, filter, verbose);
829
830 if (err < 0)
831 break;
832
833 next = rb_next(&pos->rb_node);
834 }
835
836 if (err < 0) {
837 mod_dso__delete_modules(mods);
838 mod_dso__delete_self(mods);
839 }
840
841 return err;
842}
843
844static inline void dso__fill_symbol_holes(struct dso *self)
845{
846 struct symbol *prev = NULL;
847 struct rb_node *nd;
848
849 for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) {
850 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
851
852 if (prev) {
853 u64 hole = 0;
854 int alias = pos->start == prev->start;
855
856 if (!alias)
857 hole = prev->start - pos->end - 1;
858
859 if (hole || alias) {
860 if (alias)
861 pos->end = prev->end;
862 else if (hole)
863 pos->end = prev->start - 1;
864 }
865 }
866 prev = pos;
867 }
868}
869
620static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 870static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
621 symbol_filter_t filter, int verbose) 871 symbol_filter_t filter, int verbose)
622{ 872{
@@ -625,21 +875,28 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
625 if (fd < 0) 875 if (fd < 0)
626 return -1; 876 return -1;
627 877
628 err = dso__load_sym(self, fd, vmlinux, filter, verbose); 878 err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL);
879
880 if (err > 0)
881 dso__fill_symbol_holes(self);
882
629 close(fd); 883 close(fd);
630 884
631 return err; 885 return err;
632} 886}
633 887
634int dso__load_kernel(struct dso *self, const char *vmlinux, 888int dso__load_kernel(struct dso *self, const char *vmlinux,
635 symbol_filter_t filter, int verbose) 889 symbol_filter_t filter, int verbose, int modules)
636{ 890{
637 int err = -1; 891 int err = -1;
638 892
639 if (vmlinux) 893 if (vmlinux) {
640 err = dso__load_vmlinux(self, vmlinux, filter, verbose); 894 err = dso__load_vmlinux(self, vmlinux, filter, verbose);
895 if (err > 0 && modules)
896 err = dso__load_modules(self, filter, verbose);
897 }
641 898
642 if (err < 0) 899 if (err <= 0)
643 err = dso__load_kallsyms(self, filter, verbose); 900 err = dso__load_kallsyms(self, filter, verbose);
644 901
645 return err; 902 return err;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 2c48ace8203b..2f92b21c712d 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -3,8 +3,9 @@
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include "types.h" 5#include "types.h"
6#include "list.h" 6#include <linux/list.h>
7#include "rbtree.h" 7#include <linux/rbtree.h>
8#include "module.h"
8 9
9struct symbol { 10struct symbol {
10 struct rb_node rb_node; 11 struct rb_node rb_node;
@@ -13,6 +14,7 @@ struct symbol {
13 u64 obj_start; 14 u64 obj_start;
14 u64 hist_sum; 15 u64 hist_sum;
15 u64 *hist; 16 u64 *hist;
17 struct module *module;
16 void *priv; 18 void *priv;
17 char name[0]; 19 char name[0];
18}; 20};
@@ -22,7 +24,8 @@ struct dso {
22 struct rb_root syms; 24 struct rb_root syms;
23 struct symbol *(*find_symbol)(struct dso *, u64 ip); 25 struct symbol *(*find_symbol)(struct dso *, u64 ip);
24 unsigned int sym_priv_size; 26 unsigned int sym_priv_size;
25 unsigned char prelinked; 27 unsigned char adjust_symbols;
28 unsigned char slen_calculated;
26 char name[0]; 29 char name[0];
27}; 30};
28 31
@@ -41,7 +44,8 @@ static inline void *dso__sym_priv(struct dso *self, struct symbol *sym)
41struct symbol *dso__find_symbol(struct dso *self, u64 ip); 44struct symbol *dso__find_symbol(struct dso *self, u64 ip);
42 45
43int dso__load_kernel(struct dso *self, const char *vmlinux, 46int dso__load_kernel(struct dso *self, const char *vmlinux,
44 symbol_filter_t filter, int verbose); 47 symbol_filter_t filter, int verbose, int modules);
48int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose);
45int dso__load(struct dso *self, symbol_filter_t filter, int verbose); 49int dso__load(struct dso *self, symbol_filter_t filter, int verbose);
46 50
47size_t dso__fprintf(struct dso *self, FILE *fp); 51size_t dso__fprintf(struct dso *self, FILE *fp);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b4be6071c105..68fe157d72fb 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -50,6 +50,7 @@
50#include <unistd.h> 50#include <unistd.h>
51#include <stdio.h> 51#include <stdio.h>
52#include <sys/stat.h> 52#include <sys/stat.h>
53#include <sys/statfs.h>
53#include <fcntl.h> 54#include <fcntl.h>
54#include <stddef.h> 55#include <stddef.h>
55#include <stdlib.h> 56#include <stdlib.h>
@@ -80,6 +81,7 @@
80#include <netdb.h> 81#include <netdb.h>
81#include <pwd.h> 82#include <pwd.h>
82#include <inttypes.h> 83#include <inttypes.h>
84#include "../../../include/linux/magic.h"
83 85
84#ifndef NO_ICONV 86#ifndef NO_ICONV
85#include <iconv.h> 87#include <iconv.h>
diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c
index 6350d65f6d9e..4574ac28396f 100644
--- a/tools/perf/util/wrapper.c
+++ b/tools/perf/util/wrapper.c
@@ -7,7 +7,7 @@
7 * There's no pack memory to release - but stay close to the Git 7 * There's no pack memory to release - but stay close to the Git
8 * version so wrap this away: 8 * version so wrap this away:
9 */ 9 */
10static inline void release_pack_memory(size_t size, int flag) 10static inline void release_pack_memory(size_t size __used, int flag __used)
11{ 11{
12} 12}
13 13
@@ -59,7 +59,8 @@ void *xmemdupz(const void *data, size_t len)
59char *xstrndup(const char *str, size_t len) 59char *xstrndup(const char *str, size_t len)
60{ 60{
61 char *p = memchr(str, '\0', len); 61 char *p = memchr(str, '\0', len);
62 return xmemdupz(str, p ? p - str : len); 62
63 return xmemdupz(str, p ? (size_t)(p - str) : len);
63} 64}
64 65
65void *xrealloc(void *ptr, size_t size) 66void *xrealloc(void *ptr, size_t size)