aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-timechart.txt3
-rw-r--r--tools/perf/Makefile33
-rw-r--r--tools/perf/builtin-annotate.c526
-rw-r--r--tools/perf/builtin-record.c77
-rw-r--r--tools/perf/builtin-report.c864
-rw-r--r--tools/perf/builtin-sched.c306
-rw-r--r--tools/perf/builtin-stat.c8
-rw-r--r--tools/perf/builtin-timechart.c10
-rw-r--r--tools/perf/builtin-top.c171
-rw-r--r--tools/perf/builtin-trace.c174
-rw-r--r--tools/perf/design.txt3
-rw-r--r--tools/perf/perf.c16
-rw-r--r--tools/perf/util/cache.h11
-rw-r--r--tools/perf/util/callchain.h2
-rw-r--r--tools/perf/util/color.h6
-rw-r--r--tools/perf/util/data_map.c222
-rw-r--r--tools/perf/util/data_map.h31
-rw-r--r--tools/perf/util/debug.h4
-rw-r--r--tools/perf/util/event.h15
-rw-r--r--tools/perf/util/exec_cmd.h6
-rw-r--r--tools/perf/util/header.c50
-rw-r--r--tools/perf/util/header.h10
-rw-r--r--tools/perf/util/help.h6
-rw-r--r--tools/perf/util/hist.c210
-rw-r--r--tools/perf/util/hist.h50
-rw-r--r--tools/perf/util/levenshtein.h6
-rw-r--r--tools/perf/util/module.c545
-rw-r--r--tools/perf/util/module.h53
-rw-r--r--tools/perf/util/parse-events.c5
-rw-r--r--tools/perf/util/parse-events.h6
-rw-r--r--tools/perf/util/parse-options.h6
-rw-r--r--tools/perf/util/quote.h6
-rw-r--r--tools/perf/util/run-command.h6
-rw-r--r--tools/perf/util/sigchain.h6
-rw-r--r--tools/perf/util/sort.c276
-rw-r--r--tools/perf/util/sort.h90
-rw-r--r--tools/perf/util/strbuf.h6
-rw-r--r--tools/perf/util/string.c11
-rw-r--r--tools/perf/util/string.h7
-rw-r--r--tools/perf/util/strlist.h6
-rw-r--r--tools/perf/util/svghelper.c14
-rw-r--r--tools/perf/util/svghelper.h6
-rw-r--r--tools/perf/util/symbol.c724
-rw-r--r--tools/perf/util/symbol.h24
-rw-r--r--tools/perf/util/thread.c156
-rw-r--r--tools/perf/util/thread.h29
-rw-r--r--tools/perf/util/trace-event-info.c6
-rw-r--r--tools/perf/util/trace-event-parse.c551
-rw-r--r--tools/perf/util/trace-event-read.c7
-rw-r--r--tools/perf/util/trace-event.h41
-rw-r--r--tools/perf/util/types.h6
-rw-r--r--tools/perf/util/values.h6
52 files changed, 2631 insertions, 2788 deletions
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 1c2ed3090cce..a7910099d6fd 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -31,6 +31,9 @@ OPTIONS
31-w:: 31-w::
32--width=:: 32--width=::
33 Select the width of the SVG file (default: 1000) 33 Select the width of the SVG file (default: 1000)
34-p::
35--power-only::
36 Only output the CPU power section of the diagram
34 37
35 38
36SEE ALSO 39SEE ALSO
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index b5f1953b6144..106c15055b50 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -157,11 +157,18 @@ uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
157uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not') 157uname_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#
161ifndef NO_64BIT 161# Add -m32 for cross-builds:
162 ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M)) 162#
163 M64 := -m64 163ifdef NO_64BIT
164 endif 164 MBITS := -m32
165else
166 #
167 # If we're on a 64-bit kernel, use -m64:
168 #
169 ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M))
170 MBITS := -m64
171 endif
165endif 172endif
166 173
167# CFLAGS and LDFLAGS are for the users to override from the command line. 174# CFLAGS and LDFLAGS are for the users to override from the command line.
@@ -194,7 +201,7 @@ EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wold-style-definition
194EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-prototypes 201EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-prototypes
195EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wdeclaration-after-statement 202EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wdeclaration-after-statement
196 203
197CFLAGS = $(M64) -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -fstack-protector-all -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) 204CFLAGS = $(MBITS) -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -fstack-protector-all -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS)
198LDFLAGS = -lpthread -lrt -lelf -lm 205LDFLAGS = -lpthread -lrt -lelf -lm
199ALL_CFLAGS = $(CFLAGS) 206ALL_CFLAGS = $(CFLAGS)
200ALL_LDFLAGS = $(LDFLAGS) 207ALL_LDFLAGS = $(LDFLAGS)
@@ -323,6 +330,7 @@ LIB_H += ../../include/linux/rbtree.h
323LIB_H += ../../include/linux/list.h 330LIB_H += ../../include/linux/list.h
324LIB_H += util/include/linux/list.h 331LIB_H += util/include/linux/list.h
325LIB_H += perf.h 332LIB_H += perf.h
333LIB_H += util/event.h
326LIB_H += util/types.h 334LIB_H += util/types.h
327LIB_H += util/levenshtein.h 335LIB_H += util/levenshtein.h
328LIB_H += util/parse-options.h 336LIB_H += util/parse-options.h
@@ -336,9 +344,12 @@ LIB_H += util/strlist.h
336LIB_H += util/run-command.h 344LIB_H += util/run-command.h
337LIB_H += util/sigchain.h 345LIB_H += util/sigchain.h
338LIB_H += util/symbol.h 346LIB_H += util/symbol.h
339LIB_H += util/module.h
340LIB_H += util/color.h 347LIB_H += util/color.h
341LIB_H += util/values.h 348LIB_H += util/values.h
349LIB_H += util/sort.h
350LIB_H += util/hist.h
351LIB_H += util/thread.h
352LIB_H += util/data_map.h
342 353
343LIB_OBJS += util/abspath.o 354LIB_OBJS += util/abspath.o
344LIB_OBJS += util/alias.o 355LIB_OBJS += util/alias.o
@@ -361,7 +372,6 @@ LIB_OBJS += util/usage.o
361LIB_OBJS += util/wrapper.o 372LIB_OBJS += util/wrapper.o
362LIB_OBJS += util/sigchain.o 373LIB_OBJS += util/sigchain.o
363LIB_OBJS += util/symbol.o 374LIB_OBJS += util/symbol.o
364LIB_OBJS += util/module.o
365LIB_OBJS += util/color.o 375LIB_OBJS += util/color.o
366LIB_OBJS += util/pager.o 376LIB_OBJS += util/pager.o
367LIB_OBJS += util/header.o 377LIB_OBJS += util/header.o
@@ -374,6 +384,9 @@ LIB_OBJS += util/trace-event-parse.o
374LIB_OBJS += util/trace-event-read.o 384LIB_OBJS += util/trace-event-read.o
375LIB_OBJS += util/trace-event-info.o 385LIB_OBJS += util/trace-event-info.o
376LIB_OBJS += util/svghelper.o 386LIB_OBJS += util/svghelper.o
387LIB_OBJS += util/sort.o
388LIB_OBJS += util/hist.o
389LIB_OBJS += util/data_map.o
377 390
378BUILTIN_OBJS += builtin-annotate.o 391BUILTIN_OBJS += builtin-annotate.o
379BUILTIN_OBJS += builtin-help.o 392BUILTIN_OBJS += builtin-help.o
@@ -416,7 +429,7 @@ ifeq ($(uname_S),Darwin)
416endif 429endif
417 430
418ifneq ($(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) 431ifneq ($(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)
419 msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel); 432 msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]);
420endif 433endif
421 434
422ifdef NO_DEMANGLE 435ifdef NO_DEMANGLE
@@ -728,7 +741,7 @@ $(BUILT_INS): perf$X
728common-cmds.h: util/generate-cmdlist.sh command-list.txt 741common-cmds.h: util/generate-cmdlist.sh command-list.txt
729 742
730common-cmds.h: $(wildcard Documentation/perf-*.txt) 743common-cmds.h: $(wildcard Documentation/perf-*.txt)
731 $(QUIET_GEN)util/generate-cmdlist.sh > $@+ && mv $@+ $@ 744 $(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@
732 745
733$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh 746$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
734 $(QUIET_GEN)$(RM) $@ $@+ && \ 747 $(QUIET_GEN)$(RM) $@ $@+ && \
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 1ec741615814..3fe0de03004d 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -22,15 +22,13 @@
22#include "util/parse-options.h" 22#include "util/parse-options.h"
23#include "util/parse-events.h" 23#include "util/parse-events.h"
24#include "util/thread.h" 24#include "util/thread.h"
25#include "util/sort.h"
26#include "util/hist.h"
25 27
26static char const *input_name = "perf.data"; 28static char const *input_name = "perf.data";
27 29
28static char default_sort_order[] = "comm,symbol";
29static char *sort_order = default_sort_order;
30
31static int force; 30static int force;
32static int input; 31static int input;
33static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
34 32
35static int full_paths; 33static int full_paths;
36 34
@@ -39,258 +37,12 @@ static int print_line;
39static unsigned long page_size; 37static unsigned long page_size;
40static unsigned long mmap_window = 32; 38static unsigned long mmap_window = 32;
41 39
42static struct rb_root threads;
43static struct thread *last_match;
44
45
46struct sym_ext { 40struct sym_ext {
47 struct rb_node node; 41 struct rb_node node;
48 double percent; 42 double percent;
49 char *path; 43 char *path;
50}; 44};
51 45
52/*
53 * histogram, sorted on item, collects counts
54 */
55
56static struct rb_root hist;
57
58struct hist_entry {
59 struct rb_node rb_node;
60
61 struct thread *thread;
62 struct map *map;
63 struct dso *dso;
64 struct symbol *sym;
65 u64 ip;
66 char level;
67
68 uint32_t count;
69};
70
71/*
72 * configurable sorting bits
73 */
74
75struct sort_entry {
76 struct list_head list;
77
78 const char *header;
79
80 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
81 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
82 size_t (*print)(FILE *fp, struct hist_entry *);
83};
84
85/* --sort pid */
86
87static int64_t
88sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
89{
90 return right->thread->pid - left->thread->pid;
91}
92
93static size_t
94sort__thread_print(FILE *fp, struct hist_entry *self)
95{
96 return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid);
97}
98
99static struct sort_entry sort_thread = {
100 .header = " Command: Pid",
101 .cmp = sort__thread_cmp,
102 .print = sort__thread_print,
103};
104
105/* --sort comm */
106
107static int64_t
108sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
109{
110 return right->thread->pid - left->thread->pid;
111}
112
113static int64_t
114sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
115{
116 char *comm_l = left->thread->comm;
117 char *comm_r = right->thread->comm;
118
119 if (!comm_l || !comm_r) {
120 if (!comm_l && !comm_r)
121 return 0;
122 else if (!comm_l)
123 return -1;
124 else
125 return 1;
126 }
127
128 return strcmp(comm_l, comm_r);
129}
130
131static size_t
132sort__comm_print(FILE *fp, struct hist_entry *self)
133{
134 return fprintf(fp, "%16s", self->thread->comm);
135}
136
137static struct sort_entry sort_comm = {
138 .header = " Command",
139 .cmp = sort__comm_cmp,
140 .collapse = sort__comm_collapse,
141 .print = sort__comm_print,
142};
143
144/* --sort dso */
145
146static int64_t
147sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
148{
149 struct dso *dso_l = left->dso;
150 struct dso *dso_r = right->dso;
151
152 if (!dso_l || !dso_r) {
153 if (!dso_l && !dso_r)
154 return 0;
155 else if (!dso_l)
156 return -1;
157 else
158 return 1;
159 }
160
161 return strcmp(dso_l->name, dso_r->name);
162}
163
164static size_t
165sort__dso_print(FILE *fp, struct hist_entry *self)
166{
167 if (self->dso)
168 return fprintf(fp, "%-25s", self->dso->name);
169
170 return fprintf(fp, "%016llx ", (u64)self->ip);
171}
172
173static struct sort_entry sort_dso = {
174 .header = "Shared Object ",
175 .cmp = sort__dso_cmp,
176 .print = sort__dso_print,
177};
178
179/* --sort symbol */
180
181static int64_t
182sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
183{
184 u64 ip_l, ip_r;
185
186 if (left->sym == right->sym)
187 return 0;
188
189 ip_l = left->sym ? left->sym->start : left->ip;
190 ip_r = right->sym ? right->sym->start : right->ip;
191
192 return (int64_t)(ip_r - ip_l);
193}
194
195static size_t
196sort__sym_print(FILE *fp, struct hist_entry *self)
197{
198 size_t ret = 0;
199
200 if (verbose)
201 ret += fprintf(fp, "%#018llx ", (u64)self->ip);
202
203 if (self->sym) {
204 ret += fprintf(fp, "[%c] %s",
205 self->dso == kernel_dso ? 'k' : '.', self->sym->name);
206 } else {
207 ret += fprintf(fp, "%#016llx", (u64)self->ip);
208 }
209
210 return ret;
211}
212
213static struct sort_entry sort_sym = {
214 .header = "Symbol",
215 .cmp = sort__sym_cmp,
216 .print = sort__sym_print,
217};
218
219static int sort__need_collapse = 0;
220
221struct sort_dimension {
222 const char *name;
223 struct sort_entry *entry;
224 int taken;
225};
226
227static struct sort_dimension sort_dimensions[] = {
228 { .name = "pid", .entry = &sort_thread, },
229 { .name = "comm", .entry = &sort_comm, },
230 { .name = "dso", .entry = &sort_dso, },
231 { .name = "symbol", .entry = &sort_sym, },
232};
233
234static LIST_HEAD(hist_entry__sort_list);
235
236static int sort_dimension__add(char *tok)
237{
238 unsigned int i;
239
240 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
241 struct sort_dimension *sd = &sort_dimensions[i];
242
243 if (sd->taken)
244 continue;
245
246 if (strncasecmp(tok, sd->name, strlen(tok)))
247 continue;
248
249 if (sd->entry->collapse)
250 sort__need_collapse = 1;
251
252 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
253 sd->taken = 1;
254
255 return 0;
256 }
257
258 return -ESRCH;
259}
260
261static int64_t
262hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
263{
264 struct sort_entry *se;
265 int64_t cmp = 0;
266
267 list_for_each_entry(se, &hist_entry__sort_list, list) {
268 cmp = se->cmp(left, right);
269 if (cmp)
270 break;
271 }
272
273 return cmp;
274}
275
276static int64_t
277hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
278{
279 struct sort_entry *se;
280 int64_t cmp = 0;
281
282 list_for_each_entry(se, &hist_entry__sort_list, list) {
283 int64_t (*f)(struct hist_entry *, struct hist_entry *);
284
285 f = se->collapse ?: se->cmp;
286
287 cmp = f(left, right);
288 if (cmp)
289 break;
290 }
291
292 return cmp;
293}
294 46
295/* 47/*
296 * collect histogram counts 48 * collect histogram counts
@@ -306,6 +58,7 @@ static void hist_hit(struct hist_entry *he, u64 ip)
306 return; 58 return;
307 59
308 sym_size = sym->end - sym->start; 60 sym_size = sym->end - sym->start;
61 ip = he->map->map_ip(he->map, ip);
309 offset = ip - sym->start; 62 offset = ip - sym->start;
310 63
311 if (offset >= sym_size) 64 if (offset >= sym_size)
@@ -322,173 +75,27 @@ static void hist_hit(struct hist_entry *he, u64 ip)
322 sym->hist[offset]); 75 sym->hist[offset]);
323} 76}
324 77
325static int 78static int hist_entry__add(struct thread *thread, struct map *map,
326hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 79 struct symbol *sym, u64 ip, u64 count, char level)
327 struct symbol *sym, u64 ip, char level)
328{ 80{
329 struct rb_node **p = &hist.rb_node; 81 bool hit;
330 struct rb_node *parent = NULL; 82 struct hist_entry *he = __hist_entry__add(thread, map, sym, NULL, ip,
331 struct hist_entry *he; 83 count, level, &hit);
332 struct hist_entry entry = { 84 if (he == NULL)
333 .thread = thread,
334 .map = map,
335 .dso = dso,
336 .sym = sym,
337 .ip = ip,
338 .level = level,
339 .count = 1,
340 };
341 int cmp;
342
343 while (*p != NULL) {
344 parent = *p;
345 he = rb_entry(parent, struct hist_entry, rb_node);
346
347 cmp = hist_entry__cmp(&entry, he);
348
349 if (!cmp) {
350 hist_hit(he, ip);
351
352 return 0;
353 }
354
355 if (cmp < 0)
356 p = &(*p)->rb_left;
357 else
358 p = &(*p)->rb_right;
359 }
360
361 he = malloc(sizeof(*he));
362 if (!he)
363 return -ENOMEM; 85 return -ENOMEM;
364 *he = entry; 86 if (hit)
365 rb_link_node(&he->rb_node, parent, p); 87 hist_hit(he, ip);
366 rb_insert_color(&he->rb_node, &hist);
367
368 return 0; 88 return 0;
369} 89}
370 90
371static void hist_entry__free(struct hist_entry *he)
372{
373 free(he);
374}
375
376/*
377 * collapse the histogram
378 */
379
380static struct rb_root collapse_hists;
381
382static void collapse__insert_entry(struct hist_entry *he)
383{
384 struct rb_node **p = &collapse_hists.rb_node;
385 struct rb_node *parent = NULL;
386 struct hist_entry *iter;
387 int64_t cmp;
388
389 while (*p != NULL) {
390 parent = *p;
391 iter = rb_entry(parent, struct hist_entry, rb_node);
392
393 cmp = hist_entry__collapse(iter, he);
394
395 if (!cmp) {
396 iter->count += he->count;
397 hist_entry__free(he);
398 return;
399 }
400
401 if (cmp < 0)
402 p = &(*p)->rb_left;
403 else
404 p = &(*p)->rb_right;
405 }
406
407 rb_link_node(&he->rb_node, parent, p);
408 rb_insert_color(&he->rb_node, &collapse_hists);
409}
410
411static void collapse__resort(void)
412{
413 struct rb_node *next;
414 struct hist_entry *n;
415
416 if (!sort__need_collapse)
417 return;
418
419 next = rb_first(&hist);
420 while (next) {
421 n = rb_entry(next, struct hist_entry, rb_node);
422 next = rb_next(&n->rb_node);
423
424 rb_erase(&n->rb_node, &hist);
425 collapse__insert_entry(n);
426 }
427}
428
429/*
430 * reverse the map, sort on count.
431 */
432
433static struct rb_root output_hists;
434
435static void output__insert_entry(struct hist_entry *he)
436{
437 struct rb_node **p = &output_hists.rb_node;
438 struct rb_node *parent = NULL;
439 struct hist_entry *iter;
440
441 while (*p != NULL) {
442 parent = *p;
443 iter = rb_entry(parent, struct hist_entry, rb_node);
444
445 if (he->count > iter->count)
446 p = &(*p)->rb_left;
447 else
448 p = &(*p)->rb_right;
449 }
450
451 rb_link_node(&he->rb_node, parent, p);
452 rb_insert_color(&he->rb_node, &output_hists);
453}
454
455static void output__resort(void)
456{
457 struct rb_node *next;
458 struct hist_entry *n;
459 struct rb_root *tree = &hist;
460
461 if (sort__need_collapse)
462 tree = &collapse_hists;
463
464 next = rb_first(tree);
465
466 while (next) {
467 n = rb_entry(next, struct hist_entry, rb_node);
468 next = rb_next(&n->rb_node);
469
470 rb_erase(&n->rb_node, tree);
471 output__insert_entry(n);
472 }
473}
474
475static unsigned long total = 0,
476 total_mmap = 0,
477 total_comm = 0,
478 total_fork = 0,
479 total_unknown = 0;
480
481static int 91static int
482process_sample_event(event_t *event, unsigned long offset, unsigned long head) 92process_sample_event(event_t *event, unsigned long offset, unsigned long head)
483{ 93{
484 char level; 94 char level;
485 int show = 0;
486 struct dso *dso = NULL;
487 struct thread *thread;
488 u64 ip = event->ip.ip; 95 u64 ip = event->ip.ip;
489 struct map *map = NULL; 96 struct map *map = NULL;
490 97 struct symbol *sym = NULL;
491 thread = threads__findnew(event->ip.pid, &threads, &last_match); 98 struct thread *thread = threads__findnew(event->ip.pid);
492 99
493 dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", 100 dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
494 (void *)(offset + head), 101 (void *)(offset + head),
@@ -506,51 +113,44 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
506 } 113 }
507 114
508 if (event->header.misc & PERF_RECORD_MISC_KERNEL) { 115 if (event->header.misc & PERF_RECORD_MISC_KERNEL) {
509 show = SHOW_KERNEL;
510 level = 'k'; 116 level = 'k';
511 117 sym = kernel_maps__find_symbol(ip, &map);
512 dso = kernel_dso; 118 dump_printf(" ...... dso: %s\n",
513 119 map ? map->dso->long_name : "<not found>");
514 dump_printf(" ...... dso: %s\n", dso->name);
515
516 } else if (event->header.misc & PERF_RECORD_MISC_USER) { 120 } else if (event->header.misc & PERF_RECORD_MISC_USER) {
517
518 show = SHOW_USER;
519 level = '.'; 121 level = '.';
520
521 map = thread__find_map(thread, ip); 122 map = thread__find_map(thread, ip);
522 if (map != NULL) { 123 if (map != NULL) {
124got_map:
523 ip = map->map_ip(map, ip); 125 ip = map->map_ip(map, ip);
524 dso = map->dso; 126 sym = map->dso->find_symbol(map->dso, ip);
525 } else { 127 } else {
526 /* 128 /*
527 * If this is outside of all known maps, 129 * If this is outside of all known maps,
528 * and is a negative address, try to look it 130 * and is a negative address, try to look it
529 * up in the kernel dso, as it might be a 131 * up in the kernel dso, as it might be a
530 * vsyscall (which executes in user-mode): 132 * vsyscall or vdso (which executes in user-mode).
133 *
134 * XXX This is nasty, we should have a symbol list in
135 * the "[vdso]" dso, but for now lets use the old
136 * trick of looking in the whole kernel symbol list.
531 */ 137 */
532 if ((long long)ip < 0) 138 if ((long long)ip < 0) {
533 dso = kernel_dso; 139 map = kernel_map;
140 goto got_map;
141 }
534 } 142 }
535 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 143 dump_printf(" ...... dso: %s\n",
536 144 map ? map->dso->long_name : "<not found>");
537 } else { 145 } else {
538 show = SHOW_HV;
539 level = 'H'; 146 level = 'H';
540 dump_printf(" ...... dso: [hypervisor]\n"); 147 dump_printf(" ...... dso: [hypervisor]\n");
541 } 148 }
542 149
543 if (show & show_mask) { 150 if (hist_entry__add(thread, map, sym, ip, 1, level)) {
544 struct symbol *sym = NULL; 151 fprintf(stderr, "problem incrementing symbol count, "
545 152 "skipping event\n");
546 if (dso) 153 return -1;
547 sym = dso->find_symbol(dso, ip);
548
549 if (hist_entry__add(thread, map, dso, sym, ip, level)) {
550 fprintf(stderr,
551 "problem incrementing symbol count, skipping event\n");
552 return -1;
553 }
554 } 154 }
555 total++; 155 total++;
556 156
@@ -560,10 +160,8 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
560static int 160static int
561process_mmap_event(event_t *event, unsigned long offset, unsigned long head) 161process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
562{ 162{
563 struct thread *thread;
564 struct map *map = map__new(&event->mmap, NULL, 0); 163 struct map *map = map__new(&event->mmap, NULL, 0);
565 164 struct thread *thread = threads__findnew(event->mmap.pid);
566 thread = threads__findnew(event->mmap.pid, &threads, &last_match);
567 165
568 dump_printf("%p [%p]: PERF_RECORD_MMAP %d: [%p(%p) @ %p]: %s\n", 166 dump_printf("%p [%p]: PERF_RECORD_MMAP %d: [%p(%p) @ %p]: %s\n",
569 (void *)(offset + head), 167 (void *)(offset + head),
@@ -588,9 +186,8 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
588static int 186static int
589process_comm_event(event_t *event, unsigned long offset, unsigned long head) 187process_comm_event(event_t *event, unsigned long offset, unsigned long head)
590{ 188{
591 struct thread *thread; 189 struct thread *thread = threads__findnew(event->comm.pid);
592 190
593 thread = threads__findnew(event->comm.pid, &threads, &last_match);
594 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n", 191 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
595 (void *)(offset + head), 192 (void *)(offset + head),
596 (void *)(long)(event->header.size), 193 (void *)(long)(event->header.size),
@@ -609,11 +206,9 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
609static int 206static int
610process_fork_event(event_t *event, unsigned long offset, unsigned long head) 207process_fork_event(event_t *event, unsigned long offset, unsigned long head)
611{ 208{
612 struct thread *thread; 209 struct thread *thread = threads__findnew(event->fork.pid);
613 struct thread *parent; 210 struct thread *parent = threads__findnew(event->fork.ppid);
614 211
615 thread = threads__findnew(event->fork.pid, &threads, &last_match);
616 parent = threads__findnew(event->fork.ppid, &threads, &last_match);
617 dump_printf("%p [%p]: PERF_RECORD_FORK: %d:%d\n", 212 dump_printf("%p [%p]: PERF_RECORD_FORK: %d:%d\n",
618 (void *)(offset + head), 213 (void *)(offset + head),
619 (void *)(long)(event->header.size), 214 (void *)(long)(event->header.size),
@@ -666,7 +261,7 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
666} 261}
667 262
668static int 263static int
669parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) 264parse_line(FILE *file, struct symbol *sym, u64 len)
670{ 265{
671 char *line = NULL, *tmp, *tmp2; 266 char *line = NULL, *tmp, *tmp2;
672 static const char *prev_line; 267 static const char *prev_line;
@@ -716,7 +311,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
716 const char *color; 311 const char *color;
717 struct sym_ext *sym_ext = sym->priv; 312 struct sym_ext *sym_ext = sym->priv;
718 313
719 offset = line_ip - start; 314 offset = line_ip - sym->start;
720 if (offset < len) 315 if (offset < len)
721 hits = sym->hist[offset]; 316 hits = sym->hist[offset];
722 317
@@ -795,7 +390,7 @@ static void free_source_line(struct symbol *sym, int len)
795 390
796/* Get the filename:line for the colored entries */ 391/* Get the filename:line for the colored entries */
797static void 392static void
798get_source_line(struct symbol *sym, u64 start, int len, const char *filename) 393get_source_line(struct symbol *sym, int len, const char *filename)
799{ 394{
800 int i; 395 int i;
801 char cmd[PATH_MAX * 2]; 396 char cmd[PATH_MAX * 2];
@@ -820,7 +415,7 @@ get_source_line(struct symbol *sym, u64 start, int len, const char *filename)
820 if (sym_ext[i].percent <= 0.5) 415 if (sym_ext[i].percent <= 0.5)
821 continue; 416 continue;
822 417
823 offset = start + i; 418 offset = sym->start + i;
824 sprintf(cmd, "addr2line -e %s %016llx", filename, offset); 419 sprintf(cmd, "addr2line -e %s %016llx", filename, offset);
825 fp = popen(cmd, "r"); 420 fp = popen(cmd, "r");
826 if (!fp) 421 if (!fp)
@@ -872,31 +467,23 @@ static void print_summary(const char *filename)
872 467
873static void annotate_sym(struct dso *dso, struct symbol *sym) 468static void annotate_sym(struct dso *dso, struct symbol *sym)
874{ 469{
875 const char *filename = dso->name, *d_filename; 470 const char *filename = dso->long_name, *d_filename;
876 u64 start, end, len; 471 u64 len;
877 char command[PATH_MAX*2]; 472 char command[PATH_MAX*2];
878 FILE *file; 473 FILE *file;
879 474
880 if (!filename) 475 if (!filename)
881 return; 476 return;
882 if (sym->module) 477
883 filename = sym->module->path;
884 else if (dso == kernel_dso)
885 filename = vmlinux_name;
886
887 start = sym->obj_start;
888 if (!start)
889 start = sym->start;
890 if (full_paths) 478 if (full_paths)
891 d_filename = filename; 479 d_filename = filename;
892 else 480 else
893 d_filename = basename(filename); 481 d_filename = basename(filename);
894 482
895 end = start + sym->end - sym->start + 1;
896 len = sym->end - sym->start; 483 len = sym->end - sym->start;
897 484
898 if (print_line) { 485 if (print_line) {
899 get_source_line(sym, start, len, filename); 486 get_source_line(sym, len, filename);
900 print_summary(filename); 487 print_summary(filename);
901 } 488 }
902 489
@@ -905,10 +492,11 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
905 printf("------------------------------------------------\n"); 492 printf("------------------------------------------------\n");
906 493
907 if (verbose >= 2) 494 if (verbose >= 2)
908 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 495 printf("annotating [%p] %30s : [%p] %30s\n",
496 dso, dso->long_name, sym, sym->name);
909 497
910 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", 498 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
911 (u64)start, (u64)end, filename, filename); 499 sym->start, sym->end, filename, filename);
912 500
913 if (verbose >= 3) 501 if (verbose >= 3)
914 printf("doing: %s\n", command); 502 printf("doing: %s\n", command);
@@ -918,7 +506,7 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
918 return; 506 return;
919 507
920 while (!feof(file)) { 508 while (!feof(file)) {
921 if (parse_line(file, sym, start, len) < 0) 509 if (parse_line(file, sym, len) < 0)
922 break; 510 break;
923 } 511 }
924 512
@@ -959,7 +547,7 @@ static int __cmd_annotate(void)
959 uint32_t size; 547 uint32_t size;
960 char *buf; 548 char *buf;
961 549
962 register_idle_thread(&threads, &last_match); 550 register_idle_thread();
963 551
964 input = open(input_name, O_RDONLY); 552 input = open(input_name, O_RDONLY);
965 if (input < 0) { 553 if (input < 0) {
@@ -1059,14 +647,14 @@ more:
1059 if (dump_trace) 647 if (dump_trace)
1060 return 0; 648 return 0;
1061 649
1062 if (verbose >= 3) 650 if (verbose > 3)
1063 threads__fprintf(stdout, &threads); 651 threads__fprintf(stdout);
1064 652
1065 if (verbose >= 2) 653 if (verbose > 2)
1066 dsos__fprintf(stdout); 654 dsos__fprintf(stdout);
1067 655
1068 collapse__resort(); 656 collapse__resort();
1069 output__resort(); 657 output__resort(total);
1070 658
1071 find_annotations(); 659 find_annotations();
1072 660
@@ -1139,5 +727,11 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
1139 727
1140 setup_pager(); 728 setup_pager();
1141 729
730 if (field_sep && *field_sep == '.') {
731 fputs("'.' is the only non valid --field-separator argument\n",
732 stderr);
733 exit(129);
734 }
735
1142 return __cmd_annotate(); 736 return __cmd_annotate();
1143} 737}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a5a050af8e7d..4e3a374e7aa7 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -17,7 +17,6 @@
17#include "util/header.h" 17#include "util/header.h"
18#include "util/event.h" 18#include "util/event.h"
19#include "util/debug.h" 19#include "util/debug.h"
20#include "util/trace-event.h"
21 20
22#include <unistd.h> 21#include <unistd.h>
23#include <sched.h> 22#include <sched.h>
@@ -27,44 +26,45 @@
27 26
28static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 27static int fd[MAX_NR_CPUS][MAX_COUNTERS];
29 28
30static long default_interval = 100000; 29static long default_interval = 0;
31 30
32static int nr_cpus = 0; 31static int nr_cpus = 0;
33static unsigned int page_size; 32static unsigned int page_size;
34static unsigned int mmap_pages = 128; 33static unsigned int mmap_pages = 128;
35static int freq = 0; 34static int freq = 1000;
36static int output; 35static int output;
37static const char *output_name = "perf.data"; 36static const char *output_name = "perf.data";
38static int group = 0; 37static int group = 0;
39static unsigned int realtime_prio = 0; 38static unsigned int realtime_prio = 0;
40static int raw_samples = 0; 39static int raw_samples = 0;
41static int system_wide = 0; 40static int system_wide = 0;
42static int profile_cpu = -1; 41static int profile_cpu = -1;
43static pid_t target_pid = -1; 42static pid_t target_pid = -1;
44static int inherit = 1; 43static pid_t child_pid = -1;
45static int force = 0; 44static int inherit = 1;
46static int append_file = 0; 45static int force = 0;
47static int call_graph = 0; 46static int append_file = 0;
48static int inherit_stat = 0; 47static int call_graph = 0;
49static int no_samples = 0; 48static int inherit_stat = 0;
50static int sample_address = 0; 49static int no_samples = 0;
51static int multiplex = 0; 50static int sample_address = 0;
52static int multiplex_fd = -1; 51static int multiplex = 0;
53 52static int multiplex_fd = -1;
54static long samples; 53
54static long samples = 0;
55static struct timeval last_read; 55static struct timeval last_read;
56static struct timeval this_read; 56static struct timeval this_read;
57 57
58static u64 bytes_written; 58static u64 bytes_written = 0;
59 59
60static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS]; 60static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS];
61 61
62static int nr_poll; 62static int nr_poll = 0;
63static int nr_cpu; 63static int nr_cpu = 0;
64 64
65static int file_new = 1; 65static int file_new = 1;
66 66
67struct perf_header *header; 67struct perf_header *header = NULL;
68 68
69struct mmap_data { 69struct mmap_data {
70 int counter; 70 int counter;
@@ -184,6 +184,9 @@ static void sig_handler(int sig)
184 184
185static void sig_atexit(void) 185static void sig_atexit(void)
186{ 186{
187 if (child_pid != -1)
188 kill(child_pid, SIGTERM);
189
187 if (signr == -1) 190 if (signr == -1)
188 return; 191 return;
189 192
@@ -562,17 +565,17 @@ static int __cmd_record(int argc, const char **argv)
562 else 565 else
563 header = perf_header__new(); 566 header = perf_header__new();
564 567
565
566 if (raw_samples) { 568 if (raw_samples) {
567 read_tracing_data(attrs, nr_counters); 569 perf_header__set_trace_info();
568 } else { 570 } else {
569 for (i = 0; i < nr_counters; i++) { 571 for (i = 0; i < nr_counters; i++) {
570 if (attrs[i].sample_type & PERF_SAMPLE_RAW) { 572 if (attrs[i].sample_type & PERF_SAMPLE_RAW) {
571 read_tracing_data(attrs, nr_counters); 573 perf_header__set_trace_info();
572 break; 574 break;
573 } 575 }
574 } 576 }
575 } 577 }
578
576 atexit(atexit_header); 579 atexit(atexit_header);
577 580
578 if (!system_wide) { 581 if (!system_wide) {
@@ -610,6 +613,8 @@ static int __cmd_record(int argc, const char **argv)
610 exit(-1); 613 exit(-1);
611 } 614 }
612 } 615 }
616
617 child_pid = pid;
613 } 618 }
614 619
615 if (realtime_prio) { 620 if (realtime_prio) {
@@ -725,6 +730,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
725 attrs[0].config = PERF_COUNT_HW_CPU_CYCLES; 730 attrs[0].config = PERF_COUNT_HW_CPU_CYCLES;
726 } 731 }
727 732
733 /*
734 * User specified count overrides default frequency.
735 */
736 if (default_interval)
737 freq = 0;
738 else if (freq) {
739 default_interval = freq;
740 } else {
741 fprintf(stderr, "frequency and count are zero, aborting\n");
742 exit(EXIT_FAILURE);
743 }
744
728 for (counter = 0; counter < nr_counters; counter++) { 745 for (counter = 0; counter < nr_counters; counter++) {
729 if (attrs[counter].sample_period) 746 if (attrs[counter].sample_period)
730 continue; 747 continue;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 19669c20088e..015c79745966 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -26,20 +26,18 @@
26#include "util/parse-options.h" 26#include "util/parse-options.h"
27#include "util/parse-events.h" 27#include "util/parse-events.h"
28 28
29#include "util/data_map.h"
29#include "util/thread.h" 30#include "util/thread.h"
31#include "util/sort.h"
32#include "util/hist.h"
30 33
31static char const *input_name = "perf.data"; 34static char const *input_name = "perf.data";
32 35
33static char default_sort_order[] = "comm,dso,symbol";
34static char *sort_order = default_sort_order;
35static char *dso_list_str, *comm_list_str, *sym_list_str, 36static char *dso_list_str, *comm_list_str, *sym_list_str,
36 *col_width_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;
38static char *field_sep;
39 39
40static int force; 40static int force;
41static int input;
42static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
43 41
44static int full_paths; 42static int full_paths;
45static int show_nr_samples; 43static int show_nr_samples;
@@ -50,368 +48,17 @@ static struct perf_read_values show_threads_values;
50static char default_pretty_printing_style[] = "normal"; 48static char default_pretty_printing_style[] = "normal";
51static char *pretty_printing_style = default_pretty_printing_style; 49static char *pretty_printing_style = default_pretty_printing_style;
52 50
53static unsigned long page_size;
54static unsigned long mmap_window = 32;
55
56static char default_parent_pattern[] = "^sys_|^do_page_fault";
57static char *parent_pattern = default_parent_pattern;
58static regex_t parent_regex;
59
60static int exclude_other = 1; 51static int exclude_other = 1;
61 52
62static char callchain_default_opt[] = "fractal,0.5"; 53static char callchain_default_opt[] = "fractal,0.5";
63 54
64static int callchain; 55static char *cwd;
65
66static char __cwd[PATH_MAX];
67static char *cwd = __cwd;
68static int cwdlen; 56static int cwdlen;
69 57
70static struct rb_root threads;
71static struct thread *last_match;
72
73static struct perf_header *header; 58static struct perf_header *header;
74 59
75static
76struct callchain_param callchain_param = {
77 .mode = CHAIN_GRAPH_REL,
78 .min_percent = 0.5
79};
80
81static u64 sample_type; 60static u64 sample_type;
82 61
83static int repsep_fprintf(FILE *fp, const char *fmt, ...)
84{
85 int n;
86 va_list ap;
87
88 va_start(ap, fmt);
89 if (!field_sep)
90 n = vfprintf(fp, fmt, ap);
91 else {
92 char *bf = NULL;
93 n = vasprintf(&bf, fmt, ap);
94 if (n > 0) {
95 char *sep = bf;
96
97 while (1) {
98 sep = strchr(sep, *field_sep);
99 if (sep == NULL)
100 break;
101 *sep = '.';
102 }
103 }
104 fputs(bf, fp);
105 free(bf);
106 }
107 va_end(ap);
108 return n;
109}
110
111static unsigned int dsos__col_width,
112 comms__col_width,
113 threads__col_width;
114
115/*
116 * histogram, sorted on item, collects counts
117 */
118
119static struct rb_root hist;
120
121struct hist_entry {
122 struct rb_node rb_node;
123
124 struct thread *thread;
125 struct map *map;
126 struct dso *dso;
127 struct symbol *sym;
128 struct symbol *parent;
129 u64 ip;
130 char level;
131 struct callchain_node callchain;
132 struct rb_root sorted_chain;
133
134 u64 count;
135};
136
137/*
138 * configurable sorting bits
139 */
140
141struct sort_entry {
142 struct list_head list;
143
144 const char *header;
145
146 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
147 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
148 size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width);
149 unsigned int *width;
150 bool elide;
151};
152
153static int64_t cmp_null(void *l, void *r)
154{
155 if (!l && !r)
156 return 0;
157 else if (!l)
158 return -1;
159 else
160 return 1;
161}
162
163/* --sort pid */
164
165static int64_t
166sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
167{
168 return right->thread->pid - left->thread->pid;
169}
170
171static size_t
172sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
173{
174 return repsep_fprintf(fp, "%*s:%5d", width - 6,
175 self->thread->comm ?: "", self->thread->pid);
176}
177
178static struct sort_entry sort_thread = {
179 .header = "Command: Pid",
180 .cmp = sort__thread_cmp,
181 .print = sort__thread_print,
182 .width = &threads__col_width,
183};
184
185/* --sort comm */
186
187static int64_t
188sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
189{
190 return right->thread->pid - left->thread->pid;
191}
192
193static int64_t
194sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
195{
196 char *comm_l = left->thread->comm;
197 char *comm_r = right->thread->comm;
198
199 if (!comm_l || !comm_r)
200 return cmp_null(comm_l, comm_r);
201
202 return strcmp(comm_l, comm_r);
203}
204
205static size_t
206sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
207{
208 return repsep_fprintf(fp, "%*s", width, self->thread->comm);
209}
210
211static struct sort_entry sort_comm = {
212 .header = "Command",
213 .cmp = sort__comm_cmp,
214 .collapse = sort__comm_collapse,
215 .print = sort__comm_print,
216 .width = &comms__col_width,
217};
218
219/* --sort dso */
220
221static int64_t
222sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
223{
224 struct dso *dso_l = left->dso;
225 struct dso *dso_r = right->dso;
226
227 if (!dso_l || !dso_r)
228 return cmp_null(dso_l, dso_r);
229
230 return strcmp(dso_l->name, dso_r->name);
231}
232
233static size_t
234sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
235{
236 if (self->dso)
237 return repsep_fprintf(fp, "%-*s", width, self->dso->name);
238
239 return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
240}
241
242static struct sort_entry sort_dso = {
243 .header = "Shared Object",
244 .cmp = sort__dso_cmp,
245 .print = sort__dso_print,
246 .width = &dsos__col_width,
247};
248
249/* --sort symbol */
250
251static int64_t
252sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
253{
254 u64 ip_l, ip_r;
255
256 if (left->sym == right->sym)
257 return 0;
258
259 ip_l = left->sym ? left->sym->start : left->ip;
260 ip_r = right->sym ? right->sym->start : right->ip;
261
262 return (int64_t)(ip_r - ip_l);
263}
264
265static size_t
266sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
267{
268 size_t ret = 0;
269
270 if (verbose)
271 ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip,
272 dso__symtab_origin(self->dso));
273
274 ret += repsep_fprintf(fp, "[%c] ", self->level);
275 if (self->sym) {
276 ret += repsep_fprintf(fp, "%s", self->sym->name);
277
278 if (self->sym->module)
279 ret += repsep_fprintf(fp, "\t[%s]",
280 self->sym->module->name);
281 } else {
282 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
283 }
284
285 return ret;
286}
287
288static struct sort_entry sort_sym = {
289 .header = "Symbol",
290 .cmp = sort__sym_cmp,
291 .print = sort__sym_print,
292};
293
294/* --sort parent */
295
296static int64_t
297sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
298{
299 struct symbol *sym_l = left->parent;
300 struct symbol *sym_r = right->parent;
301
302 if (!sym_l || !sym_r)
303 return cmp_null(sym_l, sym_r);
304
305 return strcmp(sym_l->name, sym_r->name);
306}
307
308static size_t
309sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
310{
311 return repsep_fprintf(fp, "%-*s", width,
312 self->parent ? self->parent->name : "[other]");
313}
314
315static unsigned int parent_symbol__col_width;
316
317static struct sort_entry sort_parent = {
318 .header = "Parent symbol",
319 .cmp = sort__parent_cmp,
320 .print = sort__parent_print,
321 .width = &parent_symbol__col_width,
322};
323
324static int sort__need_collapse = 0;
325static int sort__has_parent = 0;
326
327struct sort_dimension {
328 const char *name;
329 struct sort_entry *entry;
330 int taken;
331};
332
333static struct sort_dimension sort_dimensions[] = {
334 { .name = "pid", .entry = &sort_thread, },
335 { .name = "comm", .entry = &sort_comm, },
336 { .name = "dso", .entry = &sort_dso, },
337 { .name = "symbol", .entry = &sort_sym, },
338 { .name = "parent", .entry = &sort_parent, },
339};
340
341static LIST_HEAD(hist_entry__sort_list);
342
343static int sort_dimension__add(const char *tok)
344{
345 unsigned int i;
346
347 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
348 struct sort_dimension *sd = &sort_dimensions[i];
349
350 if (sd->taken)
351 continue;
352
353 if (strncasecmp(tok, sd->name, strlen(tok)))
354 continue;
355
356 if (sd->entry->collapse)
357 sort__need_collapse = 1;
358
359 if (sd->entry == &sort_parent) {
360 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
361 if (ret) {
362 char err[BUFSIZ];
363
364 regerror(ret, &parent_regex, err, sizeof(err));
365 fprintf(stderr, "Invalid regex: %s\n%s",
366 parent_pattern, err);
367 exit(-1);
368 }
369 sort__has_parent = 1;
370 }
371
372 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
373 sd->taken = 1;
374
375 return 0;
376 }
377
378 return -ESRCH;
379}
380
381static int64_t
382hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
383{
384 struct sort_entry *se;
385 int64_t cmp = 0;
386
387 list_for_each_entry(se, &hist_entry__sort_list, list) {
388 cmp = se->cmp(left, right);
389 if (cmp)
390 break;
391 }
392
393 return cmp;
394}
395
396static int64_t
397hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
398{
399 struct sort_entry *se;
400 int64_t cmp = 0;
401
402 list_for_each_entry(se, &hist_entry__sort_list, list) {
403 int64_t (*f)(struct hist_entry *, struct hist_entry *);
404
405 f = se->collapse ?: se->cmp;
406
407 cmp = f(left, right);
408 if (cmp)
409 break;
410 }
411
412 return cmp;
413}
414
415static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask) 62static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask)
416{ 63{
417 int i; 64 int i;
@@ -610,7 +257,6 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
610 return ret; 257 return ret;
611} 258}
612 259
613
614static size_t 260static size_t
615hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) 261hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
616{ 262{
@@ -695,22 +341,17 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm)
695 341
696 342
697static struct symbol * 343static struct symbol *
698resolve_symbol(struct thread *thread, struct map **mapp, 344resolve_symbol(struct thread *thread, struct map **mapp, u64 *ipp)
699 struct dso **dsop, u64 *ipp)
700{ 345{
701 struct dso *dso = dsop ? *dsop : NULL;
702 struct map *map = mapp ? *mapp : NULL; 346 struct map *map = mapp ? *mapp : NULL;
703 u64 ip = *ipp; 347 u64 ip = *ipp;
704 348
705 if (!thread)
706 return NULL;
707
708 if (dso)
709 goto got_dso;
710
711 if (map) 349 if (map)
712 goto got_map; 350 goto got_map;
713 351
352 if (!thread)
353 return NULL;
354
714 map = thread__find_map(thread, ip); 355 map = thread__find_map(thread, ip);
715 if (map != NULL) { 356 if (map != NULL) {
716 /* 357 /*
@@ -725,29 +366,26 @@ resolve_symbol(struct thread *thread, struct map **mapp,
725 *mapp = map; 366 *mapp = map;
726got_map: 367got_map:
727 ip = map->map_ip(map, ip); 368 ip = map->map_ip(map, ip);
728
729 dso = map->dso;
730 } else { 369 } else {
731 /* 370 /*
732 * If this is outside of all known maps, 371 * If this is outside of all known maps,
733 * and is a negative address, try to look it 372 * and is a negative address, try to look it
734 * up in the kernel dso, as it might be a 373 * up in the kernel dso, as it might be a
735 * vsyscall (which executes in user-mode): 374 * vsyscall or vdso (which executes in user-mode).
375 *
376 * XXX This is nasty, we should have a symbol list in
377 * the "[vdso]" dso, but for now lets use the old
378 * trick of looking in the whole kernel symbol list.
736 */ 379 */
737 if ((long long)ip < 0) 380 if ((long long)ip < 0)
738 dso = kernel_dso; 381 return kernel_maps__find_symbol(ip, mapp);
739 } 382 }
740 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 383 dump_printf(" ...... dso: %s\n",
384 map ? map->dso->long_name : "<not found>");
741 dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip); 385 dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip);
742 *ipp = ip; 386 *ipp = ip;
743 387
744 if (dsop) 388 return map ? map->dso->find_symbol(map->dso, ip) : NULL;
745 *dsop = dso;
746
747 if (!dso)
748 return NULL;
749got_dso:
750 return dso->find_symbol(dso, ip);
751} 389}
752 390
753static int call__match(struct symbol *sym) 391static int call__match(struct symbol *sym)
@@ -758,9 +396,9 @@ static int call__match(struct symbol *sym)
758 return 0; 396 return 0;
759} 397}
760 398
761static struct symbol ** 399static struct symbol **resolve_callchain(struct thread *thread, struct map *map,
762resolve_callchain(struct thread *thread, struct map *map __used, 400 struct ip_callchain *chain,
763 struct ip_callchain *chain, struct hist_entry *entry) 401 struct symbol **parent)
764{ 402{
765 u64 context = PERF_CONTEXT_MAX; 403 u64 context = PERF_CONTEXT_MAX;
766 struct symbol **syms = NULL; 404 struct symbol **syms = NULL;
@@ -776,8 +414,7 @@ resolve_callchain(struct thread *thread, struct map *map __used,
776 414
777 for (i = 0; i < chain->nr; i++) { 415 for (i = 0; i < chain->nr; i++) {
778 u64 ip = chain->ips[i]; 416 u64 ip = chain->ips[i];
779 struct dso *dso = NULL; 417 struct symbol *sym = NULL;
780 struct symbol *sym;
781 418
782 if (ip >= PERF_CONTEXT_MAX) { 419 if (ip >= PERF_CONTEXT_MAX) {
783 context = ip; 420 context = ip;
@@ -786,21 +423,18 @@ resolve_callchain(struct thread *thread, struct map *map __used,
786 423
787 switch (context) { 424 switch (context) {
788 case PERF_CONTEXT_HV: 425 case PERF_CONTEXT_HV:
789 dso = hypervisor_dso;
790 break; 426 break;
791 case PERF_CONTEXT_KERNEL: 427 case PERF_CONTEXT_KERNEL:
792 dso = kernel_dso; 428 sym = kernel_maps__find_symbol(ip, &map);
793 break; 429 break;
794 default: 430 default:
431 sym = resolve_symbol(thread, &map, &ip);
795 break; 432 break;
796 } 433 }
797 434
798 sym = resolve_symbol(thread, NULL, &dso, &ip);
799
800 if (sym) { 435 if (sym) {
801 if (sort__has_parent && call__match(sym) && 436 if (sort__has_parent && !*parent && call__match(sym))
802 !entry->parent) 437 *parent = sym;
803 entry->parent = sym;
804 if (!callchain) 438 if (!callchain)
805 break; 439 break;
806 syms[i] = sym; 440 syms[i] = sym;
@@ -815,177 +449,35 @@ resolve_callchain(struct thread *thread, struct map *map __used,
815 */ 449 */
816 450
817static int 451static int
818hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 452hist_entry__add(struct thread *thread, struct map *map,
819 struct symbol *sym, u64 ip, struct ip_callchain *chain, 453 struct symbol *sym, u64 ip, struct ip_callchain *chain,
820 char level, u64 count) 454 char level, u64 count)
821{ 455{
822 struct rb_node **p = &hist.rb_node; 456 struct symbol **syms = NULL, *parent = NULL;
823 struct rb_node *parent = NULL; 457 bool hit;
824 struct hist_entry *he; 458 struct hist_entry *he;
825 struct symbol **syms = NULL;
826 struct hist_entry entry = {
827 .thread = thread,
828 .map = map,
829 .dso = dso,
830 .sym = sym,
831 .ip = ip,
832 .level = level,
833 .count = count,
834 .parent = NULL,
835 .sorted_chain = RB_ROOT
836 };
837 int cmp;
838 459
839 if ((sort__has_parent || callchain) && chain) 460 if ((sort__has_parent || callchain) && chain)
840 syms = resolve_callchain(thread, map, chain, &entry); 461 syms = resolve_callchain(thread, map, chain, &parent);
841 462
842 while (*p != NULL) { 463 he = __hist_entry__add(thread, map, sym, parent,
843 parent = *p; 464 ip, count, level, &hit);
844 he = rb_entry(parent, struct hist_entry, rb_node); 465 if (he == NULL)
845 466 return -ENOMEM;
846 cmp = hist_entry__cmp(&entry, he);
847
848 if (!cmp) {
849 he->count += count;
850 if (callchain) {
851 append_chain(&he->callchain, chain, syms);
852 free(syms);
853 }
854 return 0;
855 }
856 467
857 if (cmp < 0) 468 if (hit)
858 p = &(*p)->rb_left; 469 he->count += count;
859 else
860 p = &(*p)->rb_right;
861 }
862 470
863 he = malloc(sizeof(*he));
864 if (!he)
865 return -ENOMEM;
866 *he = entry;
867 if (callchain) { 471 if (callchain) {
868 callchain_init(&he->callchain); 472 if (!hit)
473 callchain_init(&he->callchain);
869 append_chain(&he->callchain, chain, syms); 474 append_chain(&he->callchain, chain, syms);
870 free(syms); 475 free(syms);
871 } 476 }
872 rb_link_node(&he->rb_node, parent, p);
873 rb_insert_color(&he->rb_node, &hist);
874 477
875 return 0; 478 return 0;
876} 479}
877 480
878static void hist_entry__free(struct hist_entry *he)
879{
880 free(he);
881}
882
883/*
884 * collapse the histogram
885 */
886
887static struct rb_root collapse_hists;
888
889static void collapse__insert_entry(struct hist_entry *he)
890{
891 struct rb_node **p = &collapse_hists.rb_node;
892 struct rb_node *parent = NULL;
893 struct hist_entry *iter;
894 int64_t cmp;
895
896 while (*p != NULL) {
897 parent = *p;
898 iter = rb_entry(parent, struct hist_entry, rb_node);
899
900 cmp = hist_entry__collapse(iter, he);
901
902 if (!cmp) {
903 iter->count += he->count;
904 hist_entry__free(he);
905 return;
906 }
907
908 if (cmp < 0)
909 p = &(*p)->rb_left;
910 else
911 p = &(*p)->rb_right;
912 }
913
914 rb_link_node(&he->rb_node, parent, p);
915 rb_insert_color(&he->rb_node, &collapse_hists);
916}
917
918static void collapse__resort(void)
919{
920 struct rb_node *next;
921 struct hist_entry *n;
922
923 if (!sort__need_collapse)
924 return;
925
926 next = rb_first(&hist);
927 while (next) {
928 n = rb_entry(next, struct hist_entry, rb_node);
929 next = rb_next(&n->rb_node);
930
931 rb_erase(&n->rb_node, &hist);
932 collapse__insert_entry(n);
933 }
934}
935
936/*
937 * reverse the map, sort on count.
938 */
939
940static struct rb_root output_hists;
941
942static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
943{
944 struct rb_node **p = &output_hists.rb_node;
945 struct rb_node *parent = NULL;
946 struct hist_entry *iter;
947
948 if (callchain)
949 callchain_param.sort(&he->sorted_chain, &he->callchain,
950 min_callchain_hits, &callchain_param);
951
952 while (*p != NULL) {
953 parent = *p;
954 iter = rb_entry(parent, struct hist_entry, rb_node);
955
956 if (he->count > iter->count)
957 p = &(*p)->rb_left;
958 else
959 p = &(*p)->rb_right;
960 }
961
962 rb_link_node(&he->rb_node, parent, p);
963 rb_insert_color(&he->rb_node, &output_hists);
964}
965
966static void output__resort(u64 total_samples)
967{
968 struct rb_node *next;
969 struct hist_entry *n;
970 struct rb_root *tree = &hist;
971 u64 min_callchain_hits;
972
973 min_callchain_hits = total_samples * (callchain_param.min_percent / 100);
974
975 if (sort__need_collapse)
976 tree = &collapse_hists;
977
978 next = rb_first(tree);
979
980 while (next) {
981 n = rb_entry(next, struct hist_entry, rb_node);
982 next = rb_next(&n->rb_node);
983
984 rb_erase(&n->rb_node, tree);
985 output__insert_entry(n, min_callchain_hits);
986 }
987}
988
989static size_t output__fprintf(FILE *fp, u64 total_samples) 481static size_t output__fprintf(FILE *fp, u64 total_samples)
990{ 482{
991 struct hist_entry *pos; 483 struct hist_entry *pos;
@@ -1080,13 +572,6 @@ print_entries:
1080 return ret; 572 return ret;
1081} 573}
1082 574
1083static unsigned long total = 0,
1084 total_mmap = 0,
1085 total_comm = 0,
1086 total_fork = 0,
1087 total_unknown = 0,
1088 total_lost = 0;
1089
1090static int validate_chain(struct ip_callchain *chain, event_t *event) 575static int validate_chain(struct ip_callchain *chain, event_t *event)
1091{ 576{
1092 unsigned int chain_size; 577 unsigned int chain_size;
@@ -1104,17 +589,14 @@ static int
1104process_sample_event(event_t *event, unsigned long offset, unsigned long head) 589process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1105{ 590{
1106 char level; 591 char level;
1107 int show = 0; 592 struct symbol *sym = NULL;
1108 struct dso *dso = NULL;
1109 struct thread *thread;
1110 u64 ip = event->ip.ip; 593 u64 ip = event->ip.ip;
1111 u64 period = 1; 594 u64 period = 1;
1112 struct map *map = NULL; 595 struct map *map = NULL;
1113 void *more_data = event->ip.__more_data; 596 void *more_data = event->ip.__more_data;
1114 struct ip_callchain *chain = NULL; 597 struct ip_callchain *chain = NULL;
1115 int cpumode; 598 int cpumode;
1116 599 struct thread *thread = threads__findnew(event->ip.pid);
1117 thread = threads__findnew(event->ip.pid, &threads, &last_match);
1118 600
1119 if (sample_type & PERF_SAMPLE_PERIOD) { 601 if (sample_type & PERF_SAMPLE_PERIOD) {
1120 period = *(u64 *)more_data; 602 period = *(u64 *)more_data;
@@ -1161,42 +643,35 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1161 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 643 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1162 644
1163 if (cpumode == PERF_RECORD_MISC_KERNEL) { 645 if (cpumode == PERF_RECORD_MISC_KERNEL) {
1164 show = SHOW_KERNEL;
1165 level = 'k'; 646 level = 'k';
1166 647 sym = kernel_maps__find_symbol(ip, &map);
1167 dso = kernel_dso; 648 dump_printf(" ...... dso: %s\n",
1168 649 map ? map->dso->long_name : "<not found>");
1169 dump_printf(" ...... dso: %s\n", dso->name);
1170
1171 } else if (cpumode == PERF_RECORD_MISC_USER) { 650 } else if (cpumode == PERF_RECORD_MISC_USER) {
1172
1173 show = SHOW_USER;
1174 level = '.'; 651 level = '.';
652 sym = resolve_symbol(thread, &map, &ip);
1175 653
1176 } else { 654 } else {
1177 show = SHOW_HV;
1178 level = 'H'; 655 level = 'H';
1179
1180 dso = hypervisor_dso;
1181
1182 dump_printf(" ...... dso: [hypervisor]\n"); 656 dump_printf(" ...... dso: [hypervisor]\n");
1183 } 657 }
1184 658
1185 if (show & show_mask) { 659 if (dso_list &&
1186 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip); 660 (!map || !map->dso ||
1187 661 !(strlist__has_entry(dso_list, map->dso->short_name) ||
1188 if (dso_list && (!dso || !dso->name || 662 (map->dso->short_name != map->dso->long_name &&
1189 !strlist__has_entry(dso_list, dso->name))) 663 strlist__has_entry(dso_list, map->dso->long_name)))))
1190 return 0; 664 return 0;
1191 665
1192 if (sym_list && (!sym || !strlist__has_entry(sym_list, sym->name))) 666 if (sym_list && sym && !strlist__has_entry(sym_list, sym->name))
1193 return 0; 667 return 0;
1194 668
1195 if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) { 669 if (hist_entry__add(thread, map, sym, ip,
1196 eprintf("problem incrementing symbol count, skipping event\n"); 670 chain, level, period)) {
1197 return -1; 671 eprintf("problem incrementing symbol count, skipping event\n");
1198 } 672 return -1;
1199 } 673 }
674
1200 total += period; 675 total += period;
1201 676
1202 return 0; 677 return 0;
@@ -1205,10 +680,8 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1205static int 680static int
1206process_mmap_event(event_t *event, unsigned long offset, unsigned long head) 681process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
1207{ 682{
1208 struct thread *thread;
1209 struct map *map = map__new(&event->mmap, cwd, cwdlen); 683 struct map *map = map__new(&event->mmap, cwd, cwdlen);
1210 684 struct thread *thread = threads__findnew(event->mmap.pid);
1211 thread = threads__findnew(event->mmap.pid, &threads, &last_match);
1212 685
1213 dump_printf("%p [%p]: PERF_RECORD_MMAP %d/%d: [%p(%p) @ %p]: %s\n", 686 dump_printf("%p [%p]: PERF_RECORD_MMAP %d/%d: [%p(%p) @ %p]: %s\n",
1214 (void *)(offset + head), 687 (void *)(offset + head),
@@ -1234,9 +707,7 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
1234static int 707static int
1235process_comm_event(event_t *event, unsigned long offset, unsigned long head) 708process_comm_event(event_t *event, unsigned long offset, unsigned long head)
1236{ 709{
1237 struct thread *thread; 710 struct thread *thread = threads__findnew(event->comm.pid);
1238
1239 thread = threads__findnew(event->comm.pid, &threads, &last_match);
1240 711
1241 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n", 712 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
1242 (void *)(offset + head), 713 (void *)(offset + head),
@@ -1256,11 +727,8 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
1256static int 727static int
1257process_task_event(event_t *event, unsigned long offset, unsigned long head) 728process_task_event(event_t *event, unsigned long offset, unsigned long head)
1258{ 729{
1259 struct thread *thread; 730 struct thread *thread = threads__findnew(event->fork.pid);
1260 struct thread *parent; 731 struct thread *parent = threads__findnew(event->fork.ppid);
1261
1262 thread = threads__findnew(event->fork.pid, &threads, &last_match);
1263 parent = threads__findnew(event->fork.ppid, &threads, &last_match);
1264 732
1265 dump_printf("%p [%p]: PERF_RECORD_%s: (%d:%d):(%d:%d)\n", 733 dump_printf("%p [%p]: PERF_RECORD_%s: (%d:%d):(%d:%d)\n",
1266 (void *)(offset + head), 734 (void *)(offset + head),
@@ -1331,216 +799,79 @@ process_read_event(event_t *event, unsigned long offset, unsigned long head)
1331 return 0; 799 return 0;
1332} 800}
1333 801
1334static int 802static int sample_type_check(u64 type)
1335process_event(event_t *event, unsigned long offset, unsigned long head)
1336{ 803{
1337 trace_event(event); 804 sample_type = type;
1338
1339 switch (event->header.type) {
1340 case PERF_RECORD_SAMPLE:
1341 return process_sample_event(event, offset, head);
1342
1343 case PERF_RECORD_MMAP:
1344 return process_mmap_event(event, offset, head);
1345
1346 case PERF_RECORD_COMM:
1347 return process_comm_event(event, offset, head);
1348
1349 case PERF_RECORD_FORK:
1350 case PERF_RECORD_EXIT:
1351 return process_task_event(event, offset, head);
1352
1353 case PERF_RECORD_LOST:
1354 return process_lost_event(event, offset, head);
1355
1356 case PERF_RECORD_READ:
1357 return process_read_event(event, offset, head);
1358
1359 /*
1360 * We dont process them right now but they are fine:
1361 */
1362
1363 case PERF_RECORD_THROTTLE:
1364 case PERF_RECORD_UNTHROTTLE:
1365 return 0;
1366
1367 default:
1368 return -1;
1369 }
1370
1371 return 0;
1372}
1373
1374static int __cmd_report(void)
1375{
1376 int ret, rc = EXIT_FAILURE;
1377 unsigned long offset = 0;
1378 unsigned long head, shift;
1379 struct stat input_stat;
1380 struct thread *idle;
1381 event_t *event;
1382 uint32_t size;
1383 char *buf;
1384
1385 idle = register_idle_thread(&threads, &last_match);
1386 thread__comm_adjust(idle);
1387
1388 if (show_threads)
1389 perf_read_values_init(&show_threads_values);
1390
1391 input = open(input_name, O_RDONLY);
1392 if (input < 0) {
1393 fprintf(stderr, " failed to open file: %s", input_name);
1394 if (!strcmp(input_name, "perf.data"))
1395 fprintf(stderr, " (try 'perf record' first)");
1396 fprintf(stderr, "\n");
1397 exit(-1);
1398 }
1399
1400 ret = fstat(input, &input_stat);
1401 if (ret < 0) {
1402 perror("failed to stat file");
1403 exit(-1);
1404 }
1405
1406 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
1407 fprintf(stderr, "file: %s not owned by current user or root\n", input_name);
1408 exit(-1);
1409 }
1410
1411 if (!input_stat.st_size) {
1412 fprintf(stderr, "zero-sized file, nothing to do!\n");
1413 exit(0);
1414 }
1415
1416 header = perf_header__read(input);
1417 head = header->data_offset;
1418
1419 sample_type = perf_header__sample_type(header);
1420 805
1421 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) { 806 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
1422 if (sort__has_parent) { 807 if (sort__has_parent) {
1423 fprintf(stderr, "selected --sort parent, but no" 808 fprintf(stderr, "selected --sort parent, but no"
1424 " callchain data. Did you call" 809 " callchain data. Did you call"
1425 " perf record without -g?\n"); 810 " perf record without -g?\n");
1426 exit(-1); 811 return -1;
1427 } 812 }
1428 if (callchain) { 813 if (callchain) {
1429 fprintf(stderr, "selected -g but no callchain data." 814 fprintf(stderr, "selected -g but no callchain data."
1430 " Did you call perf record without" 815 " Did you call perf record without"
1431 " -g?\n"); 816 " -g?\n");
1432 exit(-1); 817 return -1;
1433 } 818 }
1434 } else if (callchain_param.mode != CHAIN_NONE && !callchain) { 819 } else if (callchain_param.mode != CHAIN_NONE && !callchain) {
1435 callchain = 1; 820 callchain = 1;
1436 if (register_callchain_param(&callchain_param) < 0) { 821 if (register_callchain_param(&callchain_param) < 0) {
1437 fprintf(stderr, "Can't register callchain" 822 fprintf(stderr, "Can't register callchain"
1438 " params\n"); 823 " params\n");
1439 exit(-1); 824 return -1;
1440 } 825 }
1441 } 826 }
1442 827
1443 if (load_kernel() < 0) { 828 return 0;
1444 perror("failed to load kernel symbols"); 829}
1445 return EXIT_FAILURE;
1446 }
1447
1448 if (!full_paths) {
1449 if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
1450 perror("failed to get the current directory");
1451 return EXIT_FAILURE;
1452 }
1453 cwdlen = strlen(cwd);
1454 } else {
1455 cwd = NULL;
1456 cwdlen = 0;
1457 }
1458
1459 shift = page_size * (head / page_size);
1460 offset += shift;
1461 head -= shift;
1462
1463remap:
1464 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
1465 MAP_SHARED, input, offset);
1466 if (buf == MAP_FAILED) {
1467 perror("failed to mmap file");
1468 exit(-1);
1469 }
1470
1471more:
1472 event = (event_t *)(buf + head);
1473
1474 size = event->header.size;
1475 if (!size)
1476 size = 8;
1477
1478 if (head + event->header.size >= page_size * mmap_window) {
1479 int munmap_ret;
1480
1481 shift = page_size * (head / page_size);
1482
1483 munmap_ret = munmap(buf, page_size * mmap_window);
1484 assert(munmap_ret == 0);
1485
1486 offset += shift;
1487 head -= shift;
1488 goto remap;
1489 }
1490
1491 size = event->header.size;
1492
1493 dump_printf("\n%p [%p]: event: %d\n",
1494 (void *)(offset + head),
1495 (void *)(long)event->header.size,
1496 event->header.type);
1497
1498 if (!size || process_event(event, offset, head) < 0) {
1499
1500 dump_printf("%p [%p]: skipping unknown header type: %d\n",
1501 (void *)(offset + head),
1502 (void *)(long)(event->header.size),
1503 event->header.type);
1504
1505 total_unknown++;
1506 830
1507 /* 831static struct perf_file_handler file_handler = {
1508 * assume we lost track of the stream, check alignment, and 832 .process_sample_event = process_sample_event,
1509 * increment a single u64 in the hope to catch on again 'soon'. 833 .process_mmap_event = process_mmap_event,
1510 */ 834 .process_comm_event = process_comm_event,
835 .process_exit_event = process_task_event,
836 .process_fork_event = process_task_event,
837 .process_lost_event = process_lost_event,
838 .process_read_event = process_read_event,
839 .sample_type_check = sample_type_check,
840};
1511 841
1512 if (unlikely(head & 7))
1513 head &= ~7ULL;
1514 842
1515 size = 8; 843static int __cmd_report(void)
1516 } 844{
845 struct thread *idle;
846 int ret;
1517 847
1518 head += size; 848 idle = register_idle_thread();
849 thread__comm_adjust(idle);
1519 850
1520 if (offset + head >= header->data_offset + header->data_size) 851 if (show_threads)
1521 goto done; 852 perf_read_values_init(&show_threads_values);
1522 853
1523 if (offset + head < (unsigned long)input_stat.st_size) 854 register_perf_file_handler(&file_handler);
1524 goto more;
1525 855
1526done: 856 ret = mmap_dispatch_perf_file(&header, input_name, force, full_paths,
1527 rc = EXIT_SUCCESS; 857 &cwdlen, &cwd);
1528 close(input); 858 if (ret)
859 return ret;
1529 860
1530 dump_printf(" IP events: %10ld\n", total); 861 dump_printf(" IP events: %10ld\n", total);
1531 dump_printf(" mmap events: %10ld\n", total_mmap); 862 dump_printf(" mmap events: %10ld\n", total_mmap);
1532 dump_printf(" comm events: %10ld\n", total_comm); 863 dump_printf(" comm events: %10ld\n", total_comm);
1533 dump_printf(" fork events: %10ld\n", total_fork); 864 dump_printf(" fork events: %10ld\n", total_fork);
1534 dump_printf(" lost events: %10ld\n", total_lost); 865 dump_printf(" lost events: %10ld\n", total_lost);
1535 dump_printf(" unknown events: %10ld\n", total_unknown); 866 dump_printf(" unknown events: %10ld\n", file_handler.total_unknown);
1536 867
1537 if (dump_trace) 868 if (dump_trace)
1538 return 0; 869 return 0;
1539 870
1540 if (verbose >= 3) 871 if (verbose > 3)
1541 threads__fprintf(stdout, &threads); 872 threads__fprintf(stdout);
1542 873
1543 if (verbose >= 2) 874 if (verbose > 2)
1544 dsos__fprintf(stdout); 875 dsos__fprintf(stdout);
1545 876
1546 collapse__resort(); 877 collapse__resort();
@@ -1550,7 +881,7 @@ done:
1550 if (show_threads) 881 if (show_threads)
1551 perf_read_values_destroy(&show_threads_values); 882 perf_read_values_destroy(&show_threads_values);
1552 883
1553 return rc; 884 return ret;
1554} 885}
1555 886
1556static int 887static int
@@ -1606,7 +937,8 @@ setup:
1606 return 0; 937 return 0;
1607} 938}
1608 939
1609static const char * const report_usage[] = { 940//static const char * const report_usage[] = {
941const char * const report_usage[] = {
1610 "perf report [<options>] <command>", 942 "perf report [<options>] <command>",
1611 NULL 943 NULL
1612}; 944};
@@ -1692,8 +1024,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
1692{ 1024{
1693 symbol__init(); 1025 symbol__init();
1694 1026
1695 page_size = getpagesize();
1696
1697 argc = parse_options(argc, argv, options, report_usage, 0); 1027 argc = parse_options(argc, argv, options, report_usage, 0);
1698 1028
1699 setup_sorting(); 1029 setup_sorting();
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index ea9c15c0cdfe..c9c68563e964 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -11,6 +11,7 @@
11#include "util/trace-event.h" 11#include "util/trace-event.h"
12 12
13#include "util/debug.h" 13#include "util/debug.h"
14#include "util/data_map.h"
14 15
15#include <sys/types.h> 16#include <sys/types.h>
16#include <sys/prctl.h> 17#include <sys/prctl.h>
@@ -20,21 +21,20 @@
20#include <math.h> 21#include <math.h>
21 22
22static char const *input_name = "perf.data"; 23static char const *input_name = "perf.data";
23static int input;
24static unsigned long page_size;
25static unsigned long mmap_window = 32;
26 24
27static unsigned long total_comm = 0; 25static unsigned long total_comm = 0;
28 26
29static struct rb_root threads;
30static struct thread *last_match;
31
32static struct perf_header *header; 27static struct perf_header *header;
33static u64 sample_type; 28static u64 sample_type;
34 29
35static char default_sort_order[] = "avg, max, switch, runtime"; 30static char default_sort_order[] = "avg, max, switch, runtime";
36static char *sort_order = default_sort_order; 31static char *sort_order = default_sort_order;
37 32
33static int profile_cpu = -1;
34
35static char *cwd;
36static int cwdlen;
37
38#define PR_SET_NAME 15 /* Set process name */ 38#define PR_SET_NAME 15 /* Set process name */
39#define MAX_CPUS 4096 39#define MAX_CPUS 4096
40 40
@@ -74,6 +74,7 @@ enum sched_event_type {
74 SCHED_EVENT_RUN, 74 SCHED_EVENT_RUN,
75 SCHED_EVENT_SLEEP, 75 SCHED_EVENT_SLEEP,
76 SCHED_EVENT_WAKEUP, 76 SCHED_EVENT_WAKEUP,
77 SCHED_EVENT_MIGRATION,
77}; 78};
78 79
79struct sched_atom { 80struct sched_atom {
@@ -398,6 +399,8 @@ process_sched_event(struct task_desc *this_task __used, struct sched_atom *atom)
398 ret = sem_post(atom->wait_sem); 399 ret = sem_post(atom->wait_sem);
399 BUG_ON(ret); 400 BUG_ON(ret);
400 break; 401 break;
402 case SCHED_EVENT_MIGRATION:
403 break;
401 default: 404 default:
402 BUG_ON(1); 405 BUG_ON(1);
403 } 406 }
@@ -635,9 +638,7 @@ static void test_calibrations(void)
635static int 638static int
636process_comm_event(event_t *event, unsigned long offset, unsigned long head) 639process_comm_event(event_t *event, unsigned long offset, unsigned long head)
637{ 640{
638 struct thread *thread; 641 struct thread *thread = threads__findnew(event->comm.tid);
639
640 thread = threads__findnew(event->comm.pid, &threads, &last_match);
641 642
642 dump_printf("%p [%p]: perf_event_comm: %s:%d\n", 643 dump_printf("%p [%p]: perf_event_comm: %s:%d\n",
643 (void *)(offset + head), 644 (void *)(offset + head),
@@ -745,6 +746,22 @@ struct trace_fork_event {
745 u32 child_pid; 746 u32 child_pid;
746}; 747};
747 748
749struct trace_migrate_task_event {
750 u32 size;
751
752 u16 common_type;
753 u8 common_flags;
754 u8 common_preempt_count;
755 u32 common_pid;
756 u32 common_tgid;
757
758 char comm[16];
759 u32 pid;
760
761 u32 prio;
762 u32 cpu;
763};
764
748struct trace_sched_handler { 765struct trace_sched_handler {
749 void (*switch_event)(struct trace_switch_event *, 766 void (*switch_event)(struct trace_switch_event *,
750 struct event *, 767 struct event *,
@@ -769,6 +786,12 @@ struct trace_sched_handler {
769 int cpu, 786 int cpu,
770 u64 timestamp, 787 u64 timestamp,
771 struct thread *thread); 788 struct thread *thread);
789
790 void (*migrate_task_event)(struct trace_migrate_task_event *,
791 struct event *,
792 int cpu,
793 u64 timestamp,
794 struct thread *thread);
772}; 795};
773 796
774 797
@@ -1058,8 +1081,8 @@ latency_switch_event(struct trace_switch_event *switch_event,
1058 die("hm, delta: %Ld < 0 ?\n", delta); 1081 die("hm, delta: %Ld < 0 ?\n", delta);
1059 1082
1060 1083
1061 sched_out = threads__findnew(switch_event->prev_pid, &threads, &last_match); 1084 sched_out = threads__findnew(switch_event->prev_pid);
1062 sched_in = threads__findnew(switch_event->next_pid, &threads, &last_match); 1085 sched_in = threads__findnew(switch_event->next_pid);
1063 1086
1064 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid); 1087 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid);
1065 if (!out_events) { 1088 if (!out_events) {
@@ -1092,13 +1115,10 @@ latency_runtime_event(struct trace_runtime_event *runtime_event,
1092 u64 timestamp, 1115 u64 timestamp,
1093 struct thread *this_thread __used) 1116 struct thread *this_thread __used)
1094{ 1117{
1095 struct work_atoms *atoms; 1118 struct thread *thread = threads__findnew(runtime_event->pid);
1096 struct thread *thread; 1119 struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
1097 1120
1098 BUG_ON(cpu >= MAX_CPUS || cpu < 0); 1121 BUG_ON(cpu >= MAX_CPUS || cpu < 0);
1099
1100 thread = threads__findnew(runtime_event->pid, &threads, &last_match);
1101 atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
1102 if (!atoms) { 1122 if (!atoms) {
1103 thread_atoms_insert(thread); 1123 thread_atoms_insert(thread);
1104 atoms = thread_atoms_search(&atom_root, thread, &cmp_pid); 1124 atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
@@ -1125,7 +1145,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1125 if (!wakeup_event->success) 1145 if (!wakeup_event->success)
1126 return; 1146 return;
1127 1147
1128 wakee = threads__findnew(wakeup_event->pid, &threads, &last_match); 1148 wakee = threads__findnew(wakeup_event->pid);
1129 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); 1149 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid);
1130 if (!atoms) { 1150 if (!atoms) {
1131 thread_atoms_insert(wakee); 1151 thread_atoms_insert(wakee);
@@ -1139,7 +1159,12 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1139 1159
1140 atom = list_entry(atoms->work_list.prev, struct work_atom, list); 1160 atom = list_entry(atoms->work_list.prev, struct work_atom, list);
1141 1161
1142 if (atom->state != THREAD_SLEEPING) 1162 /*
1163 * You WILL be missing events if you've recorded only
1164 * one CPU, or are only looking at only one, so don't
1165 * make useless noise.
1166 */
1167 if (profile_cpu == -1 && atom->state != THREAD_SLEEPING)
1143 nr_state_machine_bugs++; 1168 nr_state_machine_bugs++;
1144 1169
1145 nr_timestamps++; 1170 nr_timestamps++;
@@ -1152,11 +1177,51 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1152 atom->wake_up_time = timestamp; 1177 atom->wake_up_time = timestamp;
1153} 1178}
1154 1179
1180static void
1181latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
1182 struct event *__event __used,
1183 int cpu __used,
1184 u64 timestamp,
1185 struct thread *thread __used)
1186{
1187 struct work_atoms *atoms;
1188 struct work_atom *atom;
1189 struct thread *migrant;
1190
1191 /*
1192 * Only need to worry about migration when profiling one CPU.
1193 */
1194 if (profile_cpu == -1)
1195 return;
1196
1197 migrant = threads__findnew(migrate_task_event->pid);
1198 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid);
1199 if (!atoms) {
1200 thread_atoms_insert(migrant);
1201 register_pid(migrant->pid, migrant->comm);
1202 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid);
1203 if (!atoms)
1204 die("migration-event: Internal tree error");
1205 add_sched_out_event(atoms, 'R', timestamp);
1206 }
1207
1208 BUG_ON(list_empty(&atoms->work_list));
1209
1210 atom = list_entry(atoms->work_list.prev, struct work_atom, list);
1211 atom->sched_in_time = atom->sched_out_time = atom->wake_up_time = timestamp;
1212
1213 nr_timestamps++;
1214
1215 if (atom->sched_out_time > timestamp)
1216 nr_unordered_timestamps++;
1217}
1218
1155static struct trace_sched_handler lat_ops = { 1219static struct trace_sched_handler lat_ops = {
1156 .wakeup_event = latency_wakeup_event, 1220 .wakeup_event = latency_wakeup_event,
1157 .switch_event = latency_switch_event, 1221 .switch_event = latency_switch_event,
1158 .runtime_event = latency_runtime_event, 1222 .runtime_event = latency_runtime_event,
1159 .fork_event = latency_fork_event, 1223 .fork_event = latency_fork_event,
1224 .migrate_task_event = latency_migrate_task_event,
1160}; 1225};
1161 1226
1162static void output_lat_thread(struct work_atoms *work_list) 1227static void output_lat_thread(struct work_atoms *work_list)
@@ -1287,7 +1352,7 @@ static struct sort_dimension *available_sorts[] = {
1287 1352
1288static LIST_HEAD(sort_list); 1353static LIST_HEAD(sort_list);
1289 1354
1290static int sort_dimension__add(char *tok, struct list_head *list) 1355static int sort_dimension__add(const char *tok, struct list_head *list)
1291{ 1356{
1292 int i; 1357 int i;
1293 1358
@@ -1385,8 +1450,8 @@ map_switch_event(struct trace_switch_event *switch_event,
1385 die("hm, delta: %Ld < 0 ?\n", delta); 1450 die("hm, delta: %Ld < 0 ?\n", delta);
1386 1451
1387 1452
1388 sched_out = threads__findnew(switch_event->prev_pid, &threads, &last_match); 1453 sched_out = threads__findnew(switch_event->prev_pid);
1389 sched_in = threads__findnew(switch_event->next_pid, &threads, &last_match); 1454 sched_in = threads__findnew(switch_event->next_pid);
1390 1455
1391 curr_thread[this_cpu] = sched_in; 1456 curr_thread[this_cpu] = sched_in;
1392 1457
@@ -1517,6 +1582,26 @@ process_sched_exit_event(struct event *event,
1517} 1582}
1518 1583
1519static void 1584static void
1585process_sched_migrate_task_event(struct raw_event_sample *raw,
1586 struct event *event,
1587 int cpu __used,
1588 u64 timestamp __used,
1589 struct thread *thread __used)
1590{
1591 struct trace_migrate_task_event migrate_task_event;
1592
1593 FILL_COMMON_FIELDS(migrate_task_event, event, raw->data);
1594
1595 FILL_ARRAY(migrate_task_event, comm, event, raw->data);
1596 FILL_FIELD(migrate_task_event, pid, event, raw->data);
1597 FILL_FIELD(migrate_task_event, prio, event, raw->data);
1598 FILL_FIELD(migrate_task_event, cpu, event, raw->data);
1599
1600 if (trace_handler->migrate_task_event)
1601 trace_handler->migrate_task_event(&migrate_task_event, event, cpu, timestamp, thread);
1602}
1603
1604static void
1520process_raw_event(event_t *raw_event __used, void *more_data, 1605process_raw_event(event_t *raw_event __used, void *more_data,
1521 int cpu, u64 timestamp, struct thread *thread) 1606 int cpu, u64 timestamp, struct thread *thread)
1522{ 1607{
@@ -1539,23 +1624,24 @@ process_raw_event(event_t *raw_event __used, void *more_data,
1539 process_sched_fork_event(raw, event, cpu, timestamp, thread); 1624 process_sched_fork_event(raw, event, cpu, timestamp, thread);
1540 if (!strcmp(event->name, "sched_process_exit")) 1625 if (!strcmp(event->name, "sched_process_exit"))
1541 process_sched_exit_event(event, cpu, timestamp, thread); 1626 process_sched_exit_event(event, cpu, timestamp, thread);
1627 if (!strcmp(event->name, "sched_migrate_task"))
1628 process_sched_migrate_task_event(raw, event, cpu, timestamp, thread);
1542} 1629}
1543 1630
1544static int 1631static int
1545process_sample_event(event_t *event, unsigned long offset, unsigned long head) 1632process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1546{ 1633{
1547 char level;
1548 int show = 0;
1549 struct dso *dso = NULL;
1550 struct thread *thread; 1634 struct thread *thread;
1551 u64 ip = event->ip.ip; 1635 u64 ip = event->ip.ip;
1552 u64 timestamp = -1; 1636 u64 timestamp = -1;
1553 u32 cpu = -1; 1637 u32 cpu = -1;
1554 u64 period = 1; 1638 u64 period = 1;
1555 void *more_data = event->ip.__more_data; 1639 void *more_data = event->ip.__more_data;
1556 int cpumode;
1557 1640
1558 thread = threads__findnew(event->ip.pid, &threads, &last_match); 1641 if (!(sample_type & PERF_SAMPLE_RAW))
1642 return 0;
1643
1644 thread = threads__findnew(event->ip.pid);
1559 1645
1560 if (sample_type & PERF_SAMPLE_TIME) { 1646 if (sample_type & PERF_SAMPLE_TIME) {
1561 timestamp = *(u64 *)more_data; 1647 timestamp = *(u64 *)more_data;
@@ -1589,161 +1675,52 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1589 return -1; 1675 return -1;
1590 } 1676 }
1591 1677
1592 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 1678 if (profile_cpu != -1 && profile_cpu != (int) cpu)
1593 1679 return 0;
1594 if (cpumode == PERF_RECORD_MISC_KERNEL) {
1595 show = SHOW_KERNEL;
1596 level = 'k';
1597
1598 dso = kernel_dso;
1599
1600 dump_printf(" ...... dso: %s\n", dso->name);
1601
1602 } else if (cpumode == PERF_RECORD_MISC_USER) {
1603
1604 show = SHOW_USER;
1605 level = '.';
1606
1607 } else {
1608 show = SHOW_HV;
1609 level = 'H';
1610
1611 dso = hypervisor_dso;
1612
1613 dump_printf(" ...... dso: [hypervisor]\n");
1614 }
1615 1680
1616 if (sample_type & PERF_SAMPLE_RAW) 1681 process_raw_event(event, more_data, cpu, timestamp, thread);
1617 process_raw_event(event, more_data, cpu, timestamp, thread);
1618 1682
1619 return 0; 1683 return 0;
1620} 1684}
1621 1685
1622static int 1686static int
1623process_event(event_t *event, unsigned long offset, unsigned long head) 1687process_lost_event(event_t *event __used,
1688 unsigned long offset __used,
1689 unsigned long head __used)
1624{ 1690{
1625 trace_event(event); 1691 nr_lost_chunks++;
1692 nr_lost_events += event->lost.lost;
1626 1693
1627 nr_events++; 1694 return 0;
1628 switch (event->header.type) { 1695}
1629 case PERF_RECORD_MMAP:
1630 return 0;
1631 case PERF_RECORD_LOST:
1632 nr_lost_chunks++;
1633 nr_lost_events += event->lost.lost;
1634 return 0;
1635
1636 case PERF_RECORD_COMM:
1637 return process_comm_event(event, offset, head);
1638
1639 case PERF_RECORD_EXIT ... PERF_RECORD_READ:
1640 return 0;
1641 1696
1642 case PERF_RECORD_SAMPLE: 1697static int sample_type_check(u64 type)
1643 return process_sample_event(event, offset, head); 1698{
1699 sample_type = type;
1644 1700
1645 case PERF_RECORD_MAX: 1701 if (!(sample_type & PERF_SAMPLE_RAW)) {
1646 default: 1702 fprintf(stderr,
1703 "No trace sample to read. Did you call perf record "
1704 "without -R?");
1647 return -1; 1705 return -1;
1648 } 1706 }
1649 1707
1650 return 0; 1708 return 0;
1651} 1709}
1652 1710
1711static struct perf_file_handler file_handler = {
1712 .process_sample_event = process_sample_event,
1713 .process_comm_event = process_comm_event,
1714 .process_lost_event = process_lost_event,
1715 .sample_type_check = sample_type_check,
1716};
1717
1653static int read_events(void) 1718static int read_events(void)
1654{ 1719{
1655 int ret, rc = EXIT_FAILURE; 1720 register_idle_thread();
1656 unsigned long offset = 0; 1721 register_perf_file_handler(&file_handler);
1657 unsigned long head = 0;
1658 struct stat perf_stat;
1659 event_t *event;
1660 uint32_t size;
1661 char *buf;
1662
1663 trace_report();
1664 register_idle_thread(&threads, &last_match);
1665
1666 input = open(input_name, O_RDONLY);
1667 if (input < 0) {
1668 perror("failed to open file");
1669 exit(-1);
1670 }
1671
1672 ret = fstat(input, &perf_stat);
1673 if (ret < 0) {
1674 perror("failed to stat file");
1675 exit(-1);
1676 }
1677
1678 if (!perf_stat.st_size) {
1679 fprintf(stderr, "zero-sized file, nothing to do!\n");
1680 exit(0);
1681 }
1682 header = perf_header__read(input);
1683 head = header->data_offset;
1684 sample_type = perf_header__sample_type(header);
1685
1686 if (!(sample_type & PERF_SAMPLE_RAW))
1687 die("No trace sample to read. Did you call perf record "
1688 "without -R?");
1689
1690 if (load_kernel() < 0) {
1691 perror("failed to load kernel symbols");
1692 return EXIT_FAILURE;
1693 }
1694
1695remap:
1696 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
1697 MAP_SHARED, input, offset);
1698 if (buf == MAP_FAILED) {
1699 perror("failed to mmap file");
1700 exit(-1);
1701 }
1702
1703more:
1704 event = (event_t *)(buf + head);
1705
1706 size = event->header.size;
1707 if (!size)
1708 size = 8;
1709
1710 if (head + event->header.size >= page_size * mmap_window) {
1711 unsigned long shift = page_size * (head / page_size);
1712 int res;
1713
1714 res = munmap(buf, page_size * mmap_window);
1715 assert(res == 0);
1716
1717 offset += shift;
1718 head -= shift;
1719 goto remap;
1720 }
1721
1722 size = event->header.size;
1723
1724
1725 if (!size || process_event(event, offset, head) < 0) {
1726
1727 /*
1728 * assume we lost track of the stream, check alignment, and
1729 * increment a single u64 in the hope to catch on again 'soon'.
1730 */
1731
1732 if (unlikely(head & 7))
1733 head &= ~7ULL;
1734
1735 size = 8;
1736 }
1737
1738 head += size;
1739
1740 if (offset + head < (unsigned long)perf_stat.st_size)
1741 goto more;
1742
1743 rc = EXIT_SUCCESS;
1744 close(input);
1745 1722
1746 return rc; 1723 return mmap_dispatch_perf_file(&header, input_name, 0, 0, &cwdlen, &cwd);
1747} 1724}
1748 1725
1749static void print_bad_events(void) 1726static void print_bad_events(void)
@@ -1883,6 +1860,8 @@ static const struct option latency_options[] = {
1883 "sort by key(s): runtime, switch, avg, max"), 1860 "sort by key(s): runtime, switch, avg, max"),
1884 OPT_BOOLEAN('v', "verbose", &verbose, 1861 OPT_BOOLEAN('v', "verbose", &verbose,
1885 "be more verbose (show symbol address, etc)"), 1862 "be more verbose (show symbol address, etc)"),
1863 OPT_INTEGER('C', "CPU", &profile_cpu,
1864 "CPU to profile on"),
1886 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1865 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1887 "dump raw trace in ASCII"), 1866 "dump raw trace in ASCII"),
1888 OPT_END() 1867 OPT_END()
@@ -1917,7 +1896,7 @@ static void setup_sorting(void)
1917 1896
1918 free(str); 1897 free(str);
1919 1898
1920 sort_dimension__add((char *)"pid", &cmp_pid); 1899 sort_dimension__add("pid", &cmp_pid);
1921} 1900}
1922 1901
1923static const char *record_args[] = { 1902static const char *record_args[] = {
@@ -1961,7 +1940,6 @@ static int __cmd_record(int argc, const char **argv)
1961int cmd_sched(int argc, const char **argv, const char *prefix __used) 1940int cmd_sched(int argc, const char **argv, const char *prefix __used)
1962{ 1941{
1963 symbol__init(); 1942 symbol__init();
1964 page_size = getpagesize();
1965 1943
1966 argc = parse_options(argc, argv, sched_options, sched_usage, 1944 argc = parse_options(argc, argv, sched_options, sched_usage,
1967 PARSE_OPT_STOP_AT_NON_OPTION); 1945 PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e5f6ece65a13..3db31e7bf173 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -69,7 +69,8 @@ static int run_idx = 0;
69static int run_count = 1; 69static int run_count = 1;
70static int inherit = 1; 70static int inherit = 1;
71static int scale = 1; 71static int scale = 1;
72static int target_pid = -1; 72static pid_t target_pid = -1;
73static pid_t child_pid = -1;
73static int null_run = 0; 74static int null_run = 0;
74 75
75static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 76static int fd[MAX_NR_CPUS][MAX_COUNTERS];
@@ -285,6 +286,8 @@ static int run_perf_stat(int argc __used, const char **argv)
285 exit(-1); 286 exit(-1);
286 } 287 }
287 288
289 child_pid = pid;
290
288 /* 291 /*
289 * Wait for the child to be ready to exec. 292 * Wait for the child to be ready to exec.
290 */ 293 */
@@ -433,6 +436,9 @@ static void skip_signal(int signo)
433 436
434static void sig_atexit(void) 437static void sig_atexit(void)
435{ 438{
439 if (child_pid != -1)
440 kill(child_pid, SIGTERM);
441
436 if (signr == -1) 442 if (signr == -1)
437 return; 443 return;
438 444
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 4405681b3134..702d8fe58fbc 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -46,6 +46,8 @@ static u64 turbo_frequency;
46 46
47static u64 first_time, last_time; 47static u64 first_time, last_time;
48 48
49static int power_only;
50
49 51
50static struct perf_header *header; 52static struct perf_header *header;
51 53
@@ -547,7 +549,7 @@ static void end_sample_processing(void)
547 u64 cpu; 549 u64 cpu;
548 struct power_event *pwr; 550 struct power_event *pwr;
549 551
550 for (cpu = 0; cpu < numcpus; cpu++) { 552 for (cpu = 0; cpu <= numcpus; cpu++) {
551 pwr = malloc(sizeof(struct power_event)); 553 pwr = malloc(sizeof(struct power_event));
552 if (!pwr) 554 if (!pwr)
553 return; 555 return;
@@ -871,7 +873,7 @@ static int determine_display_tasks(u64 threshold)
871 /* no exit marker, task kept running to the end */ 873 /* no exit marker, task kept running to the end */
872 if (p->end_time == 0) 874 if (p->end_time == 0)
873 p->end_time = last_time; 875 p->end_time = last_time;
874 if (p->total_time >= threshold) 876 if (p->total_time >= threshold && !power_only)
875 p->display = 1; 877 p->display = 1;
876 878
877 c = p->all; 879 c = p->all;
@@ -882,7 +884,7 @@ static int determine_display_tasks(u64 threshold)
882 if (c->start_time == 1) 884 if (c->start_time == 1)
883 c->start_time = first_time; 885 c->start_time = first_time;
884 886
885 if (c->total_time >= threshold) { 887 if (c->total_time >= threshold && !power_only) {
886 c->display = 1; 888 c->display = 1;
887 count++; 889 count++;
888 } 890 }
@@ -1134,6 +1136,8 @@ static const struct option options[] = {
1134 "output file name"), 1136 "output file name"),
1135 OPT_INTEGER('w', "width", &svg_page_width, 1137 OPT_INTEGER('w', "width", &svg_page_width,
1136 "page width"), 1138 "page width"),
1139 OPT_BOOLEAN('p', "power-only", &power_only,
1140 "output power data only"),
1137 OPT_END() 1141 OPT_END()
1138}; 1142};
1139 1143
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 1ca88896eee4..2d8806bac258 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -22,6 +22,7 @@
22 22
23#include "util/symbol.h" 23#include "util/symbol.h"
24#include "util/color.h" 24#include "util/color.h"
25#include "util/thread.h"
25#include "util/util.h" 26#include "util/util.h"
26#include <linux/rbtree.h> 27#include <linux/rbtree.h>
27#include "util/parse-options.h" 28#include "util/parse-options.h"
@@ -54,26 +55,26 @@
54 55
55static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 56static int fd[MAX_NR_CPUS][MAX_COUNTERS];
56 57
57static int system_wide = 0; 58static int system_wide = 0;
58 59
59static int default_interval = 100000; 60static int default_interval = 0;
60 61
61static int count_filter = 5; 62static int count_filter = 5;
62static int print_entries = 15; 63static int print_entries = 15;
63 64
64static int target_pid = -1; 65static int target_pid = -1;
65static int inherit = 0; 66static int inherit = 0;
66static int profile_cpu = -1; 67static int profile_cpu = -1;
67static int nr_cpus = 0; 68static int nr_cpus = 0;
68static unsigned int realtime_prio = 0; 69static unsigned int realtime_prio = 0;
69static int group = 0; 70static int group = 0;
70static unsigned int page_size; 71static unsigned int page_size;
71static unsigned int mmap_pages = 16; 72static unsigned int mmap_pages = 16;
72static int freq = 0; 73static int freq = 1000; /* 1 KHz */
73 74
74static int delay_secs = 2; 75static int delay_secs = 2;
75static int zero; 76static int zero = 0;
76static int dump_symtab; 77static int dump_symtab = 0;
77 78
78/* 79/*
79 * Source 80 * Source
@@ -86,19 +87,16 @@ struct source_line {
86 struct source_line *next; 87 struct source_line *next;
87}; 88};
88 89
89static char *sym_filter = NULL; 90static char *sym_filter = NULL;
90struct sym_entry *sym_filter_entry = NULL; 91struct sym_entry *sym_filter_entry = NULL;
91static int sym_pcnt_filter = 5; 92static int sym_pcnt_filter = 5;
92static int sym_counter = 0; 93static int sym_counter = 0;
93static int display_weighted = -1; 94static int display_weighted = -1;
94 95
95/* 96/*
96 * Symbols 97 * Symbols
97 */ 98 */
98 99
99static u64 min_ip;
100static u64 max_ip = -1ll;
101
102struct sym_entry { 100struct sym_entry {
103 struct rb_node rb_node; 101 struct rb_node rb_node;
104 struct list_head node; 102 struct list_head node;
@@ -106,6 +104,7 @@ struct sym_entry {
106 unsigned long snap_count; 104 unsigned long snap_count;
107 double weight; 105 double weight;
108 int skip; 106 int skip;
107 struct map *map;
109 struct source_line *source; 108 struct source_line *source;
110 struct source_line *lines; 109 struct source_line *lines;
111 struct source_line **lines_tail; 110 struct source_line **lines_tail;
@@ -119,12 +118,11 @@ struct sym_entry {
119static void parse_source(struct sym_entry *syme) 118static void parse_source(struct sym_entry *syme)
120{ 119{
121 struct symbol *sym; 120 struct symbol *sym;
122 struct module *module; 121 struct map *map;
123 struct section *section = NULL;
124 FILE *file; 122 FILE *file;
125 char command[PATH_MAX*2]; 123 char command[PATH_MAX*2];
126 const char *path = vmlinux_name; 124 const char *path;
127 u64 start, end, len; 125 u64 len;
128 126
129 if (!syme) 127 if (!syme)
130 return; 128 return;
@@ -135,27 +133,15 @@ static void parse_source(struct sym_entry *syme)
135 } 133 }
136 134
137 sym = (struct symbol *)(syme + 1); 135 sym = (struct symbol *)(syme + 1);
138 module = sym->module; 136 map = syme->map;
139 137 path = map->dso->long_name;
140 if (module)
141 path = module->path;
142 if (!path)
143 return;
144
145 start = sym->obj_start;
146 if (!start)
147 start = sym->start;
148 138
149 if (module) {
150 section = module->sections->find_section(module->sections, ".text");
151 if (section)
152 start -= section->vma;
153 }
154
155 end = start + sym->end - sym->start + 1;
156 len = sym->end - sym->start; 139 len = sym->end - sym->start;
157 140
158 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", start, end, path); 141 sprintf(command,
142 "objdump --start-address=0x%016Lx "
143 "--stop-address=0x%016Lx -dS %s",
144 sym->start, sym->end, path);
159 145
160 file = popen(command, "r"); 146 file = popen(command, "r");
161 if (!file) 147 if (!file)
@@ -187,13 +173,11 @@ static void parse_source(struct sym_entry *syme)
187 173
188 if (strlen(src->line)>8 && src->line[8] == ':') { 174 if (strlen(src->line)>8 && src->line[8] == ':') {
189 src->eip = strtoull(src->line, NULL, 16); 175 src->eip = strtoull(src->line, NULL, 16);
190 if (section) 176 src->eip += map->start;
191 src->eip += section->vma;
192 } 177 }
193 if (strlen(src->line)>8 && src->line[16] == ':') { 178 if (strlen(src->line)>8 && src->line[16] == ':') {
194 src->eip = strtoull(src->line, NULL, 16); 179 src->eip = strtoull(src->line, NULL, 16);
195 if (section) 180 src->eip += map->start;
196 src->eip += section->vma;
197 } 181 }
198 } 182 }
199 pclose(file); 183 pclose(file);
@@ -245,16 +229,9 @@ static void lookup_sym_source(struct sym_entry *syme)
245 struct symbol *symbol = (struct symbol *)(syme + 1); 229 struct symbol *symbol = (struct symbol *)(syme + 1);
246 struct source_line *line; 230 struct source_line *line;
247 char pattern[PATH_MAX]; 231 char pattern[PATH_MAX];
248 char *idx;
249 232
250 sprintf(pattern, "<%s>:", symbol->name); 233 sprintf(pattern, "<%s>:", symbol->name);
251 234
252 if (symbol->module) {
253 idx = strstr(pattern, "\t");
254 if (idx)
255 *idx = 0;
256 }
257
258 pthread_mutex_lock(&syme->source_lock); 235 pthread_mutex_lock(&syme->source_lock);
259 for (line = syme->lines; line; line = line->next) { 236 for (line = syme->lines; line; line = line->next) {
260 if (strstr(line->line, pattern)) { 237 if (strstr(line->line, pattern)) {
@@ -516,8 +493,8 @@ static void print_sym_table(void)
516 if (verbose) 493 if (verbose)
517 printf(" - %016llx", sym->start); 494 printf(" - %016llx", sym->start);
518 printf(" : %s", sym->name); 495 printf(" : %s", sym->name);
519 if (sym->module) 496 if (syme->map->dso->name[0] == '[')
520 printf("\t[%s]", sym->module->name); 497 printf(" \t%s", syme->map->dso->name);
521 printf("\n"); 498 printf("\n");
522 } 499 }
523} 500}
@@ -782,12 +759,13 @@ static const char *skip_symbols[] = {
782 "exit_idle", 759 "exit_idle",
783 "mwait_idle", 760 "mwait_idle",
784 "mwait_idle_with_hints", 761 "mwait_idle_with_hints",
762 "poll_idle",
785 "ppc64_runlatch_off", 763 "ppc64_runlatch_off",
786 "pseries_dedicated_idle_sleep", 764 "pseries_dedicated_idle_sleep",
787 NULL 765 NULL
788}; 766};
789 767
790static int symbol_filter(struct dso *self, struct symbol *sym) 768static int symbol_filter(struct map *map, struct symbol *sym)
791{ 769{
792 struct sym_entry *syme; 770 struct sym_entry *syme;
793 const char *name = sym->name; 771 const char *name = sym->name;
@@ -809,7 +787,8 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
809 strstr(name, "_text_end")) 787 strstr(name, "_text_end"))
810 return 1; 788 return 1;
811 789
812 syme = dso__sym_priv(self, sym); 790 syme = dso__sym_priv(map->dso, sym);
791 syme->map = map;
813 pthread_mutex_init(&syme->source_lock, NULL); 792 pthread_mutex_init(&syme->source_lock, NULL);
814 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) 793 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter))
815 sym_filter_entry = syme; 794 sym_filter_entry = syme;
@@ -826,34 +805,14 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
826 805
827static int parse_symbols(void) 806static int parse_symbols(void)
828{ 807{
829 struct rb_node *node; 808 if (dsos__load_kernel(vmlinux_name, sizeof(struct sym_entry),
830 struct symbol *sym; 809 symbol_filter, verbose, 1) <= 0)
831 int use_modules = vmlinux_name ? 1 : 0;
832
833 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry));
834 if (kernel_dso == NULL)
835 return -1; 810 return -1;
836 811
837 if (dso__load_kernel(kernel_dso, vmlinux_name, symbol_filter, verbose, use_modules) <= 0)
838 goto out_delete_dso;
839
840 node = rb_first(&kernel_dso->syms);
841 sym = rb_entry(node, struct symbol, rb_node);
842 min_ip = sym->start;
843
844 node = rb_last(&kernel_dso->syms);
845 sym = rb_entry(node, struct symbol, rb_node);
846 max_ip = sym->end;
847
848 if (dump_symtab) 812 if (dump_symtab)
849 dso__fprintf(kernel_dso, stderr); 813 dsos__fprintf(stderr);
850 814
851 return 0; 815 return 0;
852
853out_delete_dso:
854 dso__delete(kernel_dso);
855 kernel_dso = NULL;
856 return -1;
857} 816}
858 817
859/* 818/*
@@ -861,10 +820,11 @@ out_delete_dso:
861 */ 820 */
862static void record_ip(u64 ip, int counter) 821static void record_ip(u64 ip, int counter)
863{ 822{
864 struct symbol *sym = dso__find_symbol(kernel_dso, ip); 823 struct map *map;
824 struct symbol *sym = kernel_maps__find_symbol(ip, &map);
865 825
866 if (sym != NULL) { 826 if (sym != NULL) {
867 struct sym_entry *syme = dso__sym_priv(kernel_dso, sym); 827 struct sym_entry *syme = dso__sym_priv(map->dso, sym);
868 828
869 if (!syme->skip) { 829 if (!syme->skip) {
870 syme->count[counter]++; 830 syme->count[counter]++;
@@ -910,8 +870,6 @@ static unsigned int mmap_read_head(struct mmap_data *md)
910 return head; 870 return head;
911} 871}
912 872
913struct timeval last_read, this_read;
914
915static void mmap_read_counter(struct mmap_data *md) 873static void mmap_read_counter(struct mmap_data *md)
916{ 874{
917 unsigned int head = mmap_read_head(md); 875 unsigned int head = mmap_read_head(md);
@@ -919,8 +877,6 @@ static void mmap_read_counter(struct mmap_data *md)
919 unsigned char *data = md->base + page_size; 877 unsigned char *data = md->base + page_size;
920 int diff; 878 int diff;
921 879
922 gettimeofday(&this_read, NULL);
923
924 /* 880 /*
925 * If we're further behind than half the buffer, there's a chance 881 * If we're further behind than half the buffer, there's a chance
926 * the writer will bite our tail and mess up the samples under us. 882 * the writer will bite our tail and mess up the samples under us.
@@ -931,14 +887,7 @@ static void mmap_read_counter(struct mmap_data *md)
931 */ 887 */
932 diff = head - old; 888 diff = head - old;
933 if (diff > md->mask / 2 || diff < 0) { 889 if (diff > md->mask / 2 || diff < 0) {
934 struct timeval iv; 890 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
935 unsigned long msecs;
936
937 timersub(&this_read, &last_read, &iv);
938 msecs = iv.tv_sec*1000 + iv.tv_usec/1000;
939
940 fprintf(stderr, "WARNING: failed to keep up with mmap data."
941 " Last read %lu msecs ago.\n", msecs);
942 891
943 /* 892 /*
944 * head points to a known good entry, start there. 893 * head points to a known good entry, start there.
@@ -946,8 +895,6 @@ static void mmap_read_counter(struct mmap_data *md)
946 old = head; 895 old = head;
947 } 896 }
948 897
949 last_read = this_read;
950
951 for (; old != head;) { 898 for (; old != head;) {
952 event_t *event = (event_t *)&data[old & md->mask]; 899 event_t *event = (event_t *)&data[old & md->mask];
953 900
@@ -1015,7 +962,13 @@ static void start_counter(int i, int counter)
1015 attr = attrs + counter; 962 attr = attrs + counter;
1016 963
1017 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 964 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1018 attr->freq = freq; 965
966 if (freq) {
967 attr->sample_type |= PERF_SAMPLE_PERIOD;
968 attr->freq = 1;
969 attr->sample_freq = freq;
970 }
971
1019 attr->inherit = (cpu < 0) && inherit; 972 attr->inherit = (cpu < 0) && inherit;
1020 973
1021try_again: 974try_again:
@@ -1170,11 +1123,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1170 if (argc) 1123 if (argc)
1171 usage_with_options(top_usage, options); 1124 usage_with_options(top_usage, options);
1172 1125
1173 if (freq) {
1174 default_interval = freq;
1175 freq = 1;
1176 }
1177
1178 /* CPU and PID are mutually exclusive */ 1126 /* CPU and PID are mutually exclusive */
1179 if (target_pid != -1 && profile_cpu != -1) { 1127 if (target_pid != -1 && profile_cpu != -1) {
1180 printf("WARNING: PID switch overriding CPU\n"); 1128 printf("WARNING: PID switch overriding CPU\n");
@@ -1191,6 +1139,19 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1191 parse_symbols(); 1139 parse_symbols();
1192 parse_source(sym_filter_entry); 1140 parse_source(sym_filter_entry);
1193 1141
1142
1143 /*
1144 * User specified count overrides default frequency.
1145 */
1146 if (default_interval)
1147 freq = 0;
1148 else if (freq) {
1149 default_interval = freq;
1150 } else {
1151 fprintf(stderr, "frequency and count are zero, aborting\n");
1152 exit(EXIT_FAILURE);
1153 }
1154
1194 /* 1155 /*
1195 * Fill in the ones not specifically initialized via -c: 1156 * Fill in the ones not specifically initialized via -c:
1196 */ 1157 */
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index e9d256e2f47d..ce8459ac2845 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -12,28 +12,24 @@
12#include "util/debug.h" 12#include "util/debug.h"
13 13
14#include "util/trace-event.h" 14#include "util/trace-event.h"
15#include "util/data_map.h"
15 16
16static char const *input_name = "perf.data"; 17static char const *input_name = "perf.data";
17static int input;
18static unsigned long page_size;
19static unsigned long mmap_window = 32;
20 18
21static unsigned long total = 0; 19static unsigned long total = 0;
22static unsigned long total_comm = 0; 20static unsigned long total_comm = 0;
23 21
24static struct rb_root threads;
25static struct thread *last_match;
26
27static struct perf_header *header; 22static struct perf_header *header;
28static u64 sample_type; 23static u64 sample_type;
29 24
25static char *cwd;
26static int cwdlen;
27
30 28
31static int 29static int
32process_comm_event(event_t *event, unsigned long offset, unsigned long head) 30process_comm_event(event_t *event, unsigned long offset, unsigned long head)
33{ 31{
34 struct thread *thread; 32 struct thread *thread = threads__findnew(event->comm.pid);
35
36 thread = threads__findnew(event->comm.pid, &threads, &last_match);
37 33
38 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n", 34 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
39 (void *)(offset + head), 35 (void *)(offset + head),
@@ -53,18 +49,12 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
53static int 49static int
54process_sample_event(event_t *event, unsigned long offset, unsigned long head) 50process_sample_event(event_t *event, unsigned long offset, unsigned long head)
55{ 51{
56 char level;
57 int show = 0;
58 struct dso *dso = NULL;
59 struct thread *thread;
60 u64 ip = event->ip.ip; 52 u64 ip = event->ip.ip;
61 u64 timestamp = -1; 53 u64 timestamp = -1;
62 u32 cpu = -1; 54 u32 cpu = -1;
63 u64 period = 1; 55 u64 period = 1;
64 void *more_data = event->ip.__more_data; 56 void *more_data = event->ip.__more_data;
65 int cpumode; 57 struct thread *thread = threads__findnew(event->ip.pid);
66
67 thread = threads__findnew(event->ip.pid, &threads, &last_match);
68 58
69 if (sample_type & PERF_SAMPLE_TIME) { 59 if (sample_type & PERF_SAMPLE_TIME) {
70 timestamp = *(u64 *)more_data; 60 timestamp = *(u64 *)more_data;
@@ -98,30 +88,6 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
98 return -1; 88 return -1;
99 } 89 }
100 90
101 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
102
103 if (cpumode == PERF_RECORD_MISC_KERNEL) {
104 show = SHOW_KERNEL;
105 level = 'k';
106
107 dso = kernel_dso;
108
109 dump_printf(" ...... dso: %s\n", dso->name);
110
111 } else if (cpumode == PERF_RECORD_MISC_USER) {
112
113 show = SHOW_USER;
114 level = '.';
115
116 } else {
117 show = SHOW_HV;
118 level = 'H';
119
120 dso = hypervisor_dso;
121
122 dump_printf(" ...... dso: [hypervisor]\n");
123 }
124
125 if (sample_type & PERF_SAMPLE_RAW) { 91 if (sample_type & PERF_SAMPLE_RAW) {
126 struct { 92 struct {
127 u32 size; 93 u32 size;
@@ -140,126 +106,32 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
140 return 0; 106 return 0;
141} 107}
142 108
143static int 109static int sample_type_check(u64 type)
144process_event(event_t *event, unsigned long offset, unsigned long head)
145{ 110{
146 trace_event(event); 111 sample_type = type;
147
148 switch (event->header.type) {
149 case PERF_RECORD_MMAP ... PERF_RECORD_LOST:
150 return 0;
151
152 case PERF_RECORD_COMM:
153 return process_comm_event(event, offset, head);
154
155 case PERF_RECORD_EXIT ... PERF_RECORD_READ:
156 return 0;
157
158 case PERF_RECORD_SAMPLE:
159 return process_sample_event(event, offset, head);
160 112
161 case PERF_RECORD_MAX: 113 if (!(sample_type & PERF_SAMPLE_RAW)) {
162 default: 114 fprintf(stderr,
115 "No trace sample to read. Did you call perf record "
116 "without -R?");
163 return -1; 117 return -1;
164 } 118 }
165 119
166 return 0; 120 return 0;
167} 121}
168 122
123static struct perf_file_handler file_handler = {
124 .process_sample_event = process_sample_event,
125 .process_comm_event = process_comm_event,
126 .sample_type_check = sample_type_check,
127};
128
169static int __cmd_trace(void) 129static int __cmd_trace(void)
170{ 130{
171 int ret, rc = EXIT_FAILURE; 131 register_idle_thread();
172 unsigned long offset = 0; 132 register_perf_file_handler(&file_handler);
173 unsigned long head = 0;
174 struct stat perf_stat;
175 event_t *event;
176 uint32_t size;
177 char *buf;
178
179 trace_report();
180 register_idle_thread(&threads, &last_match);
181
182 input = open(input_name, O_RDONLY);
183 if (input < 0) {
184 perror("failed to open file");
185 exit(-1);
186 }
187
188 ret = fstat(input, &perf_stat);
189 if (ret < 0) {
190 perror("failed to stat file");
191 exit(-1);
192 }
193
194 if (!perf_stat.st_size) {
195 fprintf(stderr, "zero-sized file, nothing to do!\n");
196 exit(0);
197 }
198 header = perf_header__read(input);
199 head = header->data_offset;
200 sample_type = perf_header__sample_type(header);
201
202 if (!(sample_type & PERF_SAMPLE_RAW))
203 die("No trace sample to read. Did you call perf record "
204 "without -R?");
205
206 if (load_kernel() < 0) {
207 perror("failed to load kernel symbols");
208 return EXIT_FAILURE;
209 }
210
211remap:
212 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
213 MAP_SHARED, input, offset);
214 if (buf == MAP_FAILED) {
215 perror("failed to mmap file");
216 exit(-1);
217 }
218
219more:
220 event = (event_t *)(buf + head);
221
222 size = event->header.size;
223 if (!size)
224 size = 8;
225
226 if (head + event->header.size >= page_size * mmap_window) {
227 unsigned long shift = page_size * (head / page_size);
228 int res;
229
230 res = munmap(buf, page_size * mmap_window);
231 assert(res == 0);
232
233 offset += shift;
234 head -= shift;
235 goto remap;
236 }
237
238 size = event->header.size;
239 133
240 134 return mmap_dispatch_perf_file(&header, input_name, 0, 0, &cwdlen, &cwd);
241 if (!size || process_event(event, offset, head) < 0) {
242
243 /*
244 * assume we lost track of the stream, check alignment, and
245 * increment a single u64 in the hope to catch on again 'soon'.
246 */
247
248 if (unlikely(head & 7))
249 head &= ~7ULL;
250
251 size = 8;
252 }
253
254 head += size;
255
256 if (offset + head < (unsigned long)perf_stat.st_size)
257 goto more;
258
259 rc = EXIT_SUCCESS;
260 close(input);
261
262 return rc;
263} 135}
264 136
265static const char * const annotate_usage[] = { 137static const char * const annotate_usage[] = {
@@ -272,13 +144,14 @@ static const struct option options[] = {
272 "dump raw trace in ASCII"), 144 "dump raw trace in ASCII"),
273 OPT_BOOLEAN('v', "verbose", &verbose, 145 OPT_BOOLEAN('v', "verbose", &verbose,
274 "be more verbose (show symbol address, etc)"), 146 "be more verbose (show symbol address, etc)"),
147 OPT_BOOLEAN('l', "latency", &latency_format,
148 "show latency attributes (irqs/preemption disabled, etc)"),
275 OPT_END() 149 OPT_END()
276}; 150};
277 151
278int cmd_trace(int argc, const char **argv, const char *prefix __used) 152int cmd_trace(int argc, const char **argv, const char *prefix __used)
279{ 153{
280 symbol__init(); 154 symbol__init();
281 page_size = getpagesize();
282 155
283 argc = parse_options(argc, argv, options, annotate_usage, 0); 156 argc = parse_options(argc, argv, options, annotate_usage, 0);
284 if (argc) { 157 if (argc) {
@@ -290,7 +163,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
290 usage_with_options(annotate_usage, options); 163 usage_with_options(annotate_usage, options);
291 } 164 }
292 165
293
294 setup_pager(); 166 setup_pager();
295 167
296 return __cmd_trace(); 168 return __cmd_trace();
diff --git a/tools/perf/design.txt b/tools/perf/design.txt
index f1946d107b10..fdd42a824c98 100644
--- a/tools/perf/design.txt
+++ b/tools/perf/design.txt
@@ -455,3 +455,6 @@ will need at least this:
455 455
456If your architecture does have hardware capabilities, you can override the 456If your architecture does have hardware capabilities, you can override the
457weak stub hw_perf_event_init() to register hardware counters. 457weak stub hw_perf_event_init() to register hardware counters.
458
459Architectures that have d-cache aliassing issues, such as Sparc and ARM,
460should select PERF_USE_VMALLOC in order to avoid these for perf mmap().
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 19fc7feb9d59..624e62d9d1e0 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -89,8 +89,8 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
89 /* 89 /*
90 * Check remaining flags. 90 * Check remaining flags.
91 */ 91 */
92 if (!prefixcmp(cmd, "--exec-path")) { 92 if (!prefixcmp(cmd, CMD_EXEC_PATH)) {
93 cmd += 11; 93 cmd += strlen(CMD_EXEC_PATH);
94 if (*cmd == '=') 94 if (*cmd == '=')
95 perf_set_argv_exec_path(cmd + 1); 95 perf_set_argv_exec_path(cmd + 1);
96 else { 96 else {
@@ -117,8 +117,8 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
117 (*argv)++; 117 (*argv)++;
118 (*argc)--; 118 (*argc)--;
119 handled++; 119 handled++;
120 } else if (!prefixcmp(cmd, "--perf-dir=")) { 120 } else if (!prefixcmp(cmd, CMD_PERF_DIR)) {
121 setenv(PERF_DIR_ENVIRONMENT, cmd + 10, 1); 121 setenv(PERF_DIR_ENVIRONMENT, cmd + strlen(CMD_PERF_DIR), 1);
122 if (envchanged) 122 if (envchanged)
123 *envchanged = 1; 123 *envchanged = 1;
124 } else if (!strcmp(cmd, "--work-tree")) { 124 } else if (!strcmp(cmd, "--work-tree")) {
@@ -131,8 +131,8 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
131 *envchanged = 1; 131 *envchanged = 1;
132 (*argv)++; 132 (*argv)++;
133 (*argc)--; 133 (*argc)--;
134 } else if (!prefixcmp(cmd, "--work-tree=")) { 134 } else if (!prefixcmp(cmd, CMD_WORK_TREE)) {
135 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1); 135 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + strlen(CMD_WORK_TREE), 1);
136 if (envchanged) 136 if (envchanged)
137 *envchanged = 1; 137 *envchanged = 1;
138 } else if (!strcmp(cmd, "--debugfs-dir")) { 138 } else if (!strcmp(cmd, "--debugfs-dir")) {
@@ -146,8 +146,8 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
146 *envchanged = 1; 146 *envchanged = 1;
147 (*argv)++; 147 (*argv)++;
148 (*argc)--; 148 (*argc)--;
149 } else if (!prefixcmp(cmd, "--debugfs-dir=")) { 149 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
150 strncpy(debugfs_mntpt, cmd + 14, MAXPATHLEN); 150 strncpy(debugfs_mntpt, cmd + strlen(CMD_DEBUGFS_DIR), MAXPATHLEN);
151 debugfs_mntpt[MAXPATHLEN - 1] = '\0'; 151 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
152 if (envchanged) 152 if (envchanged)
153 *envchanged = 1; 153 *envchanged = 1;
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 6f8ea9d210b6..918eb376abe3 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -1,10 +1,15 @@
1#ifndef CACHE_H 1#ifndef __PERF_CACHE_H
2#define CACHE_H 2#define __PERF_CACHE_H
3 3
4#include "util.h" 4#include "util.h"
5#include "strbuf.h" 5#include "strbuf.h"
6#include "../perf.h" 6#include "../perf.h"
7 7
8#define CMD_EXEC_PATH "--exec-path"
9#define CMD_PERF_DIR "--perf-dir="
10#define CMD_WORK_TREE "--work-tree="
11#define CMD_DEBUGFS_DIR "--debugfs-dir="
12
8#define PERF_DIR_ENVIRONMENT "PERF_DIR" 13#define PERF_DIR_ENVIRONMENT "PERF_DIR"
9#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE" 14#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE"
10#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf" 15#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
@@ -117,4 +122,4 @@ extern char *perf_pathdup(const char *fmt, ...)
117 122
118extern size_t strlcpy(char *dest, const char *src, size_t size); 123extern size_t strlcpy(char *dest, const char *src, size_t size);
119 124
120#endif /* CACHE_H */ 125#endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 43cf3ea9e088..ad4626de4c2b 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -58,4 +58,4 @@ static inline u64 cumul_hits(struct callchain_node *node)
58int register_callchain_param(struct callchain_param *param); 58int register_callchain_param(struct callchain_param *param);
59void append_chain(struct callchain_node *root, struct ip_callchain *chain, 59void append_chain(struct callchain_node *root, struct ip_callchain *chain,
60 struct symbol **syms); 60 struct symbol **syms);
61#endif 61#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 58d597564b99..24e8809210bb 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -1,5 +1,5 @@
1#ifndef COLOR_H 1#ifndef __PERF_COLOR_H
2#define COLOR_H 2#define __PERF_COLOR_H
3 3
4/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */ 4/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
5#define COLOR_MAXLEN 24 5#define COLOR_MAXLEN 24
@@ -39,4 +39,4 @@ int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *bu
39int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 39int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
40const char *get_percent_color(double percent); 40const char *get_percent_color(double percent);
41 41
42#endif /* COLOR_H */ 42#endif /* __PERF_COLOR_H */
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
new file mode 100644
index 000000000000..242b0555ab91
--- /dev/null
+++ b/tools/perf/util/data_map.c
@@ -0,0 +1,222 @@
1#include "data_map.h"
2#include "symbol.h"
3#include "util.h"
4#include "debug.h"
5
6
7static struct perf_file_handler *curr_handler;
8static unsigned long mmap_window = 32;
9static char __cwd[PATH_MAX];
10
11static int
12process_event_stub(event_t *event __used,
13 unsigned long offset __used,
14 unsigned long head __used)
15{
16 return 0;
17}
18
19void register_perf_file_handler(struct perf_file_handler *handler)
20{
21 if (!handler->process_sample_event)
22 handler->process_sample_event = process_event_stub;
23 if (!handler->process_mmap_event)
24 handler->process_mmap_event = process_event_stub;
25 if (!handler->process_comm_event)
26 handler->process_comm_event = process_event_stub;
27 if (!handler->process_fork_event)
28 handler->process_fork_event = process_event_stub;
29 if (!handler->process_exit_event)
30 handler->process_exit_event = process_event_stub;
31 if (!handler->process_lost_event)
32 handler->process_lost_event = process_event_stub;
33 if (!handler->process_read_event)
34 handler->process_read_event = process_event_stub;
35 if (!handler->process_throttle_event)
36 handler->process_throttle_event = process_event_stub;
37 if (!handler->process_unthrottle_event)
38 handler->process_unthrottle_event = process_event_stub;
39
40 curr_handler = handler;
41}
42
43static int
44process_event(event_t *event, unsigned long offset, unsigned long head)
45{
46 trace_event(event);
47
48 switch (event->header.type) {
49 case PERF_RECORD_SAMPLE:
50 return curr_handler->process_sample_event(event, offset, head);
51 case PERF_RECORD_MMAP:
52 return curr_handler->process_mmap_event(event, offset, head);
53 case PERF_RECORD_COMM:
54 return curr_handler->process_comm_event(event, offset, head);
55 case PERF_RECORD_FORK:
56 return curr_handler->process_fork_event(event, offset, head);
57 case PERF_RECORD_EXIT:
58 return curr_handler->process_exit_event(event, offset, head);
59 case PERF_RECORD_LOST:
60 return curr_handler->process_lost_event(event, offset, head);
61 case PERF_RECORD_READ:
62 return curr_handler->process_read_event(event, offset, head);
63 case PERF_RECORD_THROTTLE:
64 return curr_handler->process_throttle_event(event, offset, head);
65 case PERF_RECORD_UNTHROTTLE:
66 return curr_handler->process_unthrottle_event(event, offset, head);
67 default:
68 curr_handler->total_unknown++;
69 return -1;
70 }
71}
72
73int mmap_dispatch_perf_file(struct perf_header **pheader,
74 const char *input_name,
75 int force,
76 int full_paths,
77 int *cwdlen,
78 char **cwd)
79{
80 int ret, rc = EXIT_FAILURE;
81 struct perf_header *header;
82 unsigned long head, shift;
83 unsigned long offset = 0;
84 struct stat input_stat;
85 size_t page_size;
86 u64 sample_type;
87 event_t *event;
88 uint32_t size;
89 int input;
90 char *buf;
91
92 if (!curr_handler)
93 die("Forgot to register perf file handler");
94
95 page_size = getpagesize();
96
97 input = open(input_name, O_RDONLY);
98 if (input < 0) {
99 fprintf(stderr, " failed to open file: %s", input_name);
100 if (!strcmp(input_name, "perf.data"))
101 fprintf(stderr, " (try 'perf record' first)");
102 fprintf(stderr, "\n");
103 exit(-1);
104 }
105
106 ret = fstat(input, &input_stat);
107 if (ret < 0) {
108 perror("failed to stat file");
109 exit(-1);
110 }
111
112 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
113 fprintf(stderr, "file: %s not owned by current user or root\n",
114 input_name);
115 exit(-1);
116 }
117
118 if (!input_stat.st_size) {
119 fprintf(stderr, "zero-sized file, nothing to do!\n");
120 exit(0);
121 }
122
123 *pheader = perf_header__read(input);
124 header = *pheader;
125 head = header->data_offset;
126
127 sample_type = perf_header__sample_type(header);
128
129 if (curr_handler->sample_type_check)
130 if (curr_handler->sample_type_check(sample_type) < 0)
131 exit(-1);
132
133 if (load_kernel() < 0) {
134 perror("failed to load kernel symbols");
135 return EXIT_FAILURE;
136 }
137
138 if (!full_paths) {
139 if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
140 perror("failed to get the current directory");
141 return EXIT_FAILURE;
142 }
143 *cwd = __cwd;
144 *cwdlen = strlen(*cwd);
145 } else {
146 *cwd = NULL;
147 *cwdlen = 0;
148 }
149
150 shift = page_size * (head / page_size);
151 offset += shift;
152 head -= shift;
153
154remap:
155 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
156 MAP_SHARED, input, offset);
157 if (buf == MAP_FAILED) {
158 perror("failed to mmap file");
159 exit(-1);
160 }
161
162more:
163 event = (event_t *)(buf + head);
164
165 size = event->header.size;
166 if (!size)
167 size = 8;
168
169 if (head + event->header.size >= page_size * mmap_window) {
170 int munmap_ret;
171
172 shift = page_size * (head / page_size);
173
174 munmap_ret = munmap(buf, page_size * mmap_window);
175 assert(munmap_ret == 0);
176
177 offset += shift;
178 head -= shift;
179 goto remap;
180 }
181
182 size = event->header.size;
183
184 dump_printf("\n%p [%p]: event: %d\n",
185 (void *)(offset + head),
186 (void *)(long)event->header.size,
187 event->header.type);
188
189 if (!size || process_event(event, offset, head) < 0) {
190
191 dump_printf("%p [%p]: skipping unknown header type: %d\n",
192 (void *)(offset + head),
193 (void *)(long)(event->header.size),
194 event->header.type);
195
196 /*
197 * assume we lost track of the stream, check alignment, and
198 * increment a single u64 in the hope to catch on again 'soon'.
199 */
200
201 if (unlikely(head & 7))
202 head &= ~7ULL;
203
204 size = 8;
205 }
206
207 head += size;
208
209 if (offset + head >= header->data_offset + header->data_size)
210 goto done;
211
212 if (offset + head < (unsigned long)input_stat.st_size)
213 goto more;
214
215done:
216 rc = EXIT_SUCCESS;
217 close(input);
218
219 return rc;
220}
221
222
diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h
new file mode 100644
index 000000000000..716d1053b074
--- /dev/null
+++ b/tools/perf/util/data_map.h
@@ -0,0 +1,31 @@
1#ifndef __PERF_DATAMAP_H
2#define __PERF_DATAMAP_H
3
4#include "event.h"
5#include "header.h"
6
7typedef int (*event_type_handler_t)(event_t *, unsigned long, unsigned long);
8
9struct perf_file_handler {
10 event_type_handler_t process_sample_event;
11 event_type_handler_t process_mmap_event;
12 event_type_handler_t process_comm_event;
13 event_type_handler_t process_fork_event;
14 event_type_handler_t process_exit_event;
15 event_type_handler_t process_lost_event;
16 event_type_handler_t process_read_event;
17 event_type_handler_t process_throttle_event;
18 event_type_handler_t process_unthrottle_event;
19 int (*sample_type_check)(u64 sample_type);
20 unsigned long total_unknown;
21};
22
23void register_perf_file_handler(struct perf_file_handler *handler);
24int mmap_dispatch_perf_file(struct perf_header **pheader,
25 const char *input_name,
26 int force,
27 int full_paths,
28 int *cwdlen,
29 char **cwd);
30
31#endif
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 437eea58ce40..02d1fa1c2465 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -1,4 +1,6 @@
1/* For debugging general purposes */ 1/* For debugging general purposes */
2#ifndef __PERF_DEBUG_H
3#define __PERF_DEBUG_H
2 4
3extern int verbose; 5extern int verbose;
4extern int dump_trace; 6extern int dump_trace;
@@ -6,3 +8,5 @@ extern int dump_trace;
6int eprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 8int eprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
7int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 9int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
8void trace_event(event_t *event); 10void trace_event(event_t *event);
11
12#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 2c9c26d6ded0..c2e62be62798 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -1,14 +1,10 @@
1#ifndef __PERF_RECORD_H 1#ifndef __PERF_RECORD_H
2#define __PERF_RECORD_H 2#define __PERF_RECORD_H
3
3#include "../perf.h" 4#include "../perf.h"
4#include "util.h" 5#include "util.h"
5#include <linux/list.h> 6#include <linux/list.h>
6 7#include <linux/rbtree.h>
7enum {
8 SHOW_KERNEL = 1,
9 SHOW_USER = 2,
10 SHOW_HV = 4,
11};
12 8
13/* 9/*
14 * PERF_SAMPLE_IP | PERF_SAMPLE_TID | * 10 * PERF_SAMPLE_IP | PERF_SAMPLE_TID | *
@@ -78,7 +74,10 @@ typedef union event_union {
78} event_t; 74} event_t;
79 75
80struct map { 76struct map {
81 struct list_head node; 77 union {
78 struct rb_node rb_node;
79 struct list_head node;
80 };
82 u64 start; 81 u64 start;
83 u64 end; 82 u64 end;
84 u64 pgoff; 83 u64 pgoff;
@@ -101,4 +100,4 @@ struct map *map__clone(struct map *self);
101int map__overlap(struct map *l, struct map *r); 100int map__overlap(struct map *l, struct map *r);
102size_t map__fprintf(struct map *self, FILE *fp); 101size_t map__fprintf(struct map *self, FILE *fp);
103 102
104#endif 103#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/exec_cmd.h b/tools/perf/util/exec_cmd.h
index effe25eb1545..31647ac92ed1 100644
--- a/tools/perf/util/exec_cmd.h
+++ b/tools/perf/util/exec_cmd.h
@@ -1,5 +1,5 @@
1#ifndef PERF_EXEC_CMD_H 1#ifndef __PERF_EXEC_CMD_H
2#define PERF_EXEC_CMD_H 2#define __PERF_EXEC_CMD_H
3 3
4extern void perf_set_argv_exec_path(const char *exec_path); 4extern void perf_set_argv_exec_path(const char *exec_path);
5extern const char *perf_extract_argv0_path(const char *path); 5extern const char *perf_extract_argv0_path(const char *path);
@@ -10,4 +10,4 @@ extern int execv_perf_cmd(const char **argv); /* NULL terminated */
10extern int execl_perf_cmd(const char *cmd, ...); 10extern int execl_perf_cmd(const char *cmd, ...);
11extern const char *system_path(const char *path); 11extern const char *system_path(const char *path);
12 12
13#endif /* PERF_EXEC_CMD_H */ 13#endif /* __PERF_EXEC_CMD_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index e306857b2c2b..9aae360c0f28 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -5,6 +5,8 @@
5 5
6#include "util.h" 6#include "util.h"
7#include "header.h" 7#include "header.h"
8#include "../perf.h"
9#include "trace-event.h"
8 10
9/* 11/*
10 * Create new perf.data header attribute: 12 * Create new perf.data header attribute:
@@ -62,6 +64,8 @@ struct perf_header *perf_header__new(void)
62 64
63 self->data_offset = 0; 65 self->data_offset = 0;
64 self->data_size = 0; 66 self->data_size = 0;
67 self->trace_info_offset = 0;
68 self->trace_info_size = 0;
65 69
66 return self; 70 return self;
67} 71}
@@ -145,8 +149,16 @@ struct perf_file_header {
145 struct perf_file_section attrs; 149 struct perf_file_section attrs;
146 struct perf_file_section data; 150 struct perf_file_section data;
147 struct perf_file_section event_types; 151 struct perf_file_section event_types;
152 struct perf_file_section trace_info;
148}; 153};
149 154
155static int trace_info;
156
157void perf_header__set_trace_info(void)
158{
159 trace_info = 1;
160}
161
150static void do_write(int fd, void *buf, size_t size) 162static void do_write(int fd, void *buf, size_t size)
151{ 163{
152 while (size) { 164 while (size) {
@@ -198,6 +210,23 @@ void perf_header__write(struct perf_header *self, int fd)
198 if (events) 210 if (events)
199 do_write(fd, events, self->event_size); 211 do_write(fd, events, self->event_size);
200 212
213 if (trace_info) {
214 static int trace_info_written;
215
216 /*
217 * Write it only once
218 */
219 if (!trace_info_written) {
220 self->trace_info_offset = lseek(fd, 0, SEEK_CUR);
221 read_tracing_data(fd, attrs, nr_counters);
222 self->trace_info_size = lseek(fd, 0, SEEK_CUR) -
223 self->trace_info_offset;
224 trace_info_written = 1;
225 } else {
226 lseek(fd, self->trace_info_offset +
227 self->trace_info_size, SEEK_SET);
228 }
229 }
201 230
202 self->data_offset = lseek(fd, 0, SEEK_CUR); 231 self->data_offset = lseek(fd, 0, SEEK_CUR);
203 232
@@ -217,6 +246,10 @@ void perf_header__write(struct perf_header *self, int fd)
217 .offset = self->event_offset, 246 .offset = self->event_offset,
218 .size = self->event_size, 247 .size = self->event_size,
219 }, 248 },
249 .trace_info = {
250 .offset = self->trace_info_offset,
251 .size = self->trace_info_size,
252 },
220 }; 253 };
221 254
222 lseek(fd, 0, SEEK_SET); 255 lseek(fd, 0, SEEK_SET);
@@ -254,10 +287,16 @@ struct perf_header *perf_header__read(int fd)
254 do_read(fd, &f_header, sizeof(f_header)); 287 do_read(fd, &f_header, sizeof(f_header));
255 288
256 if (f_header.magic != PERF_MAGIC || 289 if (f_header.magic != PERF_MAGIC ||
257 f_header.size != sizeof(f_header) ||
258 f_header.attr_size != sizeof(f_attr)) 290 f_header.attr_size != sizeof(f_attr))
259 die("incompatible file format"); 291 die("incompatible file format");
260 292
293 if (f_header.size != sizeof(f_header)) {
294 /* Support the previous format */
295 if (f_header.size == offsetof(typeof(f_header), trace_info))
296 f_header.trace_info.size = 0;
297 else
298 die("incompatible file format");
299 }
261 nr_attrs = f_header.attrs.size / sizeof(f_attr); 300 nr_attrs = f_header.attrs.size / sizeof(f_attr);
262 lseek(fd, f_header.attrs.offset, SEEK_SET); 301 lseek(fd, f_header.attrs.offset, SEEK_SET);
263 302
@@ -290,6 +329,15 @@ struct perf_header *perf_header__read(int fd)
290 do_read(fd, events, f_header.event_types.size); 329 do_read(fd, events, f_header.event_types.size);
291 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 330 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
292 } 331 }
332
333 self->trace_info_offset = f_header.trace_info.offset;
334 self->trace_info_size = f_header.trace_info.size;
335
336 if (self->trace_info_size) {
337 lseek(fd, self->trace_info_offset, SEEK_SET);
338 trace_report(fd);
339 }
340
293 self->event_offset = f_header.event_types.offset; 341 self->event_offset = f_header.event_types.offset;
294 self->event_size = f_header.event_types.size; 342 self->event_size = f_header.event_types.size;
295 343
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index a0761bc7863c..30aee5160dc0 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -1,5 +1,5 @@
1#ifndef _PERF_HEADER_H 1#ifndef __PERF_HEADER_H
2#define _PERF_HEADER_H 2#define __PERF_HEADER_H
3 3
4#include "../../../include/linux/perf_event.h" 4#include "../../../include/linux/perf_event.h"
5#include <sys/types.h> 5#include <sys/types.h>
@@ -21,6 +21,8 @@ struct perf_header {
21 u64 data_size; 21 u64 data_size;
22 u64 event_offset; 22 u64 event_offset;
23 u64 event_size; 23 u64 event_size;
24 u64 trace_info_offset;
25 u64 trace_info_size;
24}; 26};
25 27
26struct perf_header *perf_header__read(int fd); 28struct perf_header *perf_header__read(int fd);
@@ -40,8 +42,8 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
40u64 perf_header__sample_type(struct perf_header *header); 42u64 perf_header__sample_type(struct perf_header *header);
41struct perf_event_attr * 43struct perf_event_attr *
42perf_header__find_attr(u64 id, struct perf_header *header); 44perf_header__find_attr(u64 id, struct perf_header *header);
43 45void perf_header__set_trace_info(void);
44 46
45struct perf_header *perf_header__new(void); 47struct perf_header *perf_header__new(void);
46 48
47#endif /* _PERF_HEADER_H */ 49#endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/help.h b/tools/perf/util/help.h
index 7128783637b4..7f5c6dedd714 100644
--- a/tools/perf/util/help.h
+++ b/tools/perf/util/help.h
@@ -1,5 +1,5 @@
1#ifndef HELP_H 1#ifndef __PERF_HELP_H
2#define HELP_H 2#define __PERF_HELP_H
3 3
4struct cmdnames { 4struct cmdnames {
5 size_t alloc; 5 size_t alloc;
@@ -26,4 +26,4 @@ int is_in_cmdlist(struct cmdnames *c, const char *s);
26void list_commands(const char *title, struct cmdnames *main_cmds, 26void list_commands(const char *title, struct cmdnames *main_cmds,
27 struct cmdnames *other_cmds); 27 struct cmdnames *other_cmds);
28 28
29#endif /* HELP_H */ 29#endif /* __PERF_HELP_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
new file mode 100644
index 000000000000..7393a02fd8d4
--- /dev/null
+++ b/tools/perf/util/hist.c
@@ -0,0 +1,210 @@
1#include "hist.h"
2
3struct rb_root hist;
4struct rb_root collapse_hists;
5struct rb_root output_hists;
6int callchain;
7
8struct callchain_param callchain_param = {
9 .mode = CHAIN_GRAPH_REL,
10 .min_percent = 0.5
11};
12
13unsigned long total;
14unsigned long total_mmap;
15unsigned long total_comm;
16unsigned long total_fork;
17unsigned long total_unknown;
18unsigned long total_lost;
19
20/*
21 * histogram, sorted on item, collects counts
22 */
23
24struct hist_entry *__hist_entry__add(struct thread *thread, struct map *map,
25 struct symbol *sym,
26 struct symbol *sym_parent,
27 u64 ip, u64 count, char level, bool *hit)
28{
29 struct rb_node **p = &hist.rb_node;
30 struct rb_node *parent = NULL;
31 struct hist_entry *he;
32 struct hist_entry entry = {
33 .thread = thread,
34 .map = map,
35 .sym = sym,
36 .ip = ip,
37 .level = level,
38 .count = count,
39 .parent = sym_parent,
40 };
41 int cmp;
42
43 while (*p != NULL) {
44 parent = *p;
45 he = rb_entry(parent, struct hist_entry, rb_node);
46
47 cmp = hist_entry__cmp(&entry, he);
48
49 if (!cmp) {
50 *hit = true;
51 return he;
52 }
53
54 if (cmp < 0)
55 p = &(*p)->rb_left;
56 else
57 p = &(*p)->rb_right;
58 }
59
60 he = malloc(sizeof(*he));
61 if (!he)
62 return NULL;
63 *he = entry;
64 rb_link_node(&he->rb_node, parent, p);
65 rb_insert_color(&he->rb_node, &hist);
66 *hit = false;
67 return he;
68}
69
70int64_t
71hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
72{
73 struct sort_entry *se;
74 int64_t cmp = 0;
75
76 list_for_each_entry(se, &hist_entry__sort_list, list) {
77 cmp = se->cmp(left, right);
78 if (cmp)
79 break;
80 }
81
82 return cmp;
83}
84
85int64_t
86hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
87{
88 struct sort_entry *se;
89 int64_t cmp = 0;
90
91 list_for_each_entry(se, &hist_entry__sort_list, list) {
92 int64_t (*f)(struct hist_entry *, struct hist_entry *);
93
94 f = se->collapse ?: se->cmp;
95
96 cmp = f(left, right);
97 if (cmp)
98 break;
99 }
100
101 return cmp;
102}
103
104void hist_entry__free(struct hist_entry *he)
105{
106 free(he);
107}
108
109/*
110 * collapse the histogram
111 */
112
113void collapse__insert_entry(struct hist_entry *he)
114{
115 struct rb_node **p = &collapse_hists.rb_node;
116 struct rb_node *parent = NULL;
117 struct hist_entry *iter;
118 int64_t cmp;
119
120 while (*p != NULL) {
121 parent = *p;
122 iter = rb_entry(parent, struct hist_entry, rb_node);
123
124 cmp = hist_entry__collapse(iter, he);
125
126 if (!cmp) {
127 iter->count += he->count;
128 hist_entry__free(he);
129 return;
130 }
131
132 if (cmp < 0)
133 p = &(*p)->rb_left;
134 else
135 p = &(*p)->rb_right;
136 }
137
138 rb_link_node(&he->rb_node, parent, p);
139 rb_insert_color(&he->rb_node, &collapse_hists);
140}
141
142void collapse__resort(void)
143{
144 struct rb_node *next;
145 struct hist_entry *n;
146
147 if (!sort__need_collapse)
148 return;
149
150 next = rb_first(&hist);
151 while (next) {
152 n = rb_entry(next, struct hist_entry, rb_node);
153 next = rb_next(&n->rb_node);
154
155 rb_erase(&n->rb_node, &hist);
156 collapse__insert_entry(n);
157 }
158}
159
160/*
161 * reverse the map, sort on count.
162 */
163
164void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
165{
166 struct rb_node **p = &output_hists.rb_node;
167 struct rb_node *parent = NULL;
168 struct hist_entry *iter;
169
170 if (callchain)
171 callchain_param.sort(&he->sorted_chain, &he->callchain,
172 min_callchain_hits, &callchain_param);
173
174 while (*p != NULL) {
175 parent = *p;
176 iter = rb_entry(parent, struct hist_entry, rb_node);
177
178 if (he->count > iter->count)
179 p = &(*p)->rb_left;
180 else
181 p = &(*p)->rb_right;
182 }
183
184 rb_link_node(&he->rb_node, parent, p);
185 rb_insert_color(&he->rb_node, &output_hists);
186}
187
188void output__resort(u64 total_samples)
189{
190 struct rb_node *next;
191 struct hist_entry *n;
192 struct rb_root *tree = &hist;
193 u64 min_callchain_hits;
194
195 min_callchain_hits =
196 total_samples * (callchain_param.min_percent / 100);
197
198 if (sort__need_collapse)
199 tree = &collapse_hists;
200
201 next = rb_first(tree);
202
203 while (next) {
204 n = rb_entry(next, struct hist_entry, rb_node);
205 next = rb_next(&n->rb_node);
206
207 rb_erase(&n->rb_node, tree);
208 output__insert_entry(n, min_callchain_hits);
209 }
210}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
new file mode 100644
index 000000000000..ac2149c559b0
--- /dev/null
+++ b/tools/perf/util/hist.h
@@ -0,0 +1,50 @@
1#ifndef __PERF_HIST_H
2#define __PERF_HIST_H
3#include "../builtin.h"
4
5#include "util.h"
6
7#include "color.h"
8#include <linux/list.h>
9#include "cache.h"
10#include <linux/rbtree.h>
11#include "symbol.h"
12#include "string.h"
13#include "callchain.h"
14#include "strlist.h"
15#include "values.h"
16
17#include "../perf.h"
18#include "debug.h"
19#include "header.h"
20
21#include "parse-options.h"
22#include "parse-events.h"
23
24#include "thread.h"
25#include "sort.h"
26
27extern struct rb_root hist;
28extern struct rb_root collapse_hists;
29extern struct rb_root output_hists;
30extern int callchain;
31extern struct callchain_param callchain_param;
32extern unsigned long total;
33extern unsigned long total_mmap;
34extern unsigned long total_comm;
35extern unsigned long total_fork;
36extern unsigned long total_unknown;
37extern unsigned long total_lost;
38
39struct hist_entry *__hist_entry__add(struct thread *thread, struct map *map,
40 struct symbol *sym, struct symbol *parent,
41 u64 ip, u64 count, char level, bool *hit);
42extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
43extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
44extern void hist_entry__free(struct hist_entry *);
45extern void collapse__insert_entry(struct hist_entry *);
46extern void collapse__resort(void);
47extern void output__insert_entry(struct hist_entry *, u64);
48extern void output__resort(u64);
49
50#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/levenshtein.h b/tools/perf/util/levenshtein.h
index 0173abeef52c..b0fcb6d8a881 100644
--- a/tools/perf/util/levenshtein.h
+++ b/tools/perf/util/levenshtein.h
@@ -1,8 +1,8 @@
1#ifndef LEVENSHTEIN_H 1#ifndef __PERF_LEVENSHTEIN_H
2#define LEVENSHTEIN_H 2#define __PERF_LEVENSHTEIN_H
3 3
4int levenshtein(const char *string1, const char *string2, 4int levenshtein(const char *string1, const char *string2,
5 int swap_penalty, int substition_penalty, 5 int swap_penalty, int substition_penalty,
6 int insertion_penalty, int deletion_penalty); 6 int insertion_penalty, int deletion_penalty);
7 7
8#endif 8#endif /* __PERF_LEVENSHTEIN_H */
diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c
deleted file mode 100644
index 0d8c85defcd2..000000000000
--- a/tools/perf/util/module.c
+++ /dev/null
@@ -1,545 +0,0 @@
1#include "util.h"
2#include "../perf.h"
3#include "string.h"
4#include "module.h"
5
6#include <libelf.h>
7#include <libgen.h>
8#include <gelf.h>
9#include <elf.h>
10#include <dirent.h>
11#include <sys/utsname.h>
12
13static unsigned int crc32(const char *p, unsigned int len)
14{
15 int i;
16 unsigned int crc = 0;
17
18 while (len--) {
19 crc ^= *p++;
20 for (i = 0; i < 8; i++)
21 crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
22 }
23 return crc;
24}
25
26/* module section methods */
27
28struct sec_dso *sec_dso__new_dso(const char *name)
29{
30 struct sec_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
31
32 if (self != NULL) {
33 strcpy(self->name, name);
34 self->secs = RB_ROOT;
35 self->find_section = sec_dso__find_section;
36 }
37
38 return self;
39}
40
41static void sec_dso__delete_section(struct section *self)
42{
43 free(((void *)self));
44}
45
46void sec_dso__delete_sections(struct sec_dso *self)
47{
48 struct section *pos;
49 struct rb_node *next = rb_first(&self->secs);
50
51 while (next) {
52 pos = rb_entry(next, struct section, rb_node);
53 next = rb_next(&pos->rb_node);
54 rb_erase(&pos->rb_node, &self->secs);
55 sec_dso__delete_section(pos);
56 }
57}
58
59void sec_dso__delete_self(struct sec_dso *self)
60{
61 sec_dso__delete_sections(self);
62 free(self);
63}
64
65static void sec_dso__insert_section(struct sec_dso *self, struct section *sec)
66{
67 struct rb_node **p = &self->secs.rb_node;
68 struct rb_node *parent = NULL;
69 const u64 hash = sec->hash;
70 struct section *s;
71
72 while (*p != NULL) {
73 parent = *p;
74 s = rb_entry(parent, struct section, rb_node);
75 if (hash < s->hash)
76 p = &(*p)->rb_left;
77 else
78 p = &(*p)->rb_right;
79 }
80 rb_link_node(&sec->rb_node, parent, p);
81 rb_insert_color(&sec->rb_node, &self->secs);
82}
83
84struct section *sec_dso__find_section(struct sec_dso *self, const char *name)
85{
86 struct rb_node *n;
87 u64 hash;
88 int len;
89
90 if (self == NULL)
91 return NULL;
92
93 len = strlen(name);
94 hash = crc32(name, len);
95
96 n = self->secs.rb_node;
97
98 while (n) {
99 struct section *s = rb_entry(n, struct section, rb_node);
100
101 if (hash < s->hash)
102 n = n->rb_left;
103 else if (hash > s->hash)
104 n = n->rb_right;
105 else {
106 if (!strcmp(name, s->name))
107 return s;
108 else
109 n = rb_next(&s->rb_node);
110 }
111 }
112
113 return NULL;
114}
115
116static size_t sec_dso__fprintf_section(struct section *self, FILE *fp)
117{
118 return fprintf(fp, "name:%s vma:%llx path:%s\n",
119 self->name, self->vma, self->path);
120}
121
122size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp)
123{
124 size_t ret = fprintf(fp, "dso: %s\n", self->name);
125
126 struct rb_node *nd;
127 for (nd = rb_first(&self->secs); nd; nd = rb_next(nd)) {
128 struct section *pos = rb_entry(nd, struct section, rb_node);
129 ret += sec_dso__fprintf_section(pos, fp);
130 }
131
132 return ret;
133}
134
135static struct section *section__new(const char *name, const char *path)
136{
137 struct section *self = calloc(1, sizeof(*self));
138
139 if (!self)
140 goto out_failure;
141
142 self->name = calloc(1, strlen(name) + 1);
143 if (!self->name)
144 goto out_failure;
145
146 self->path = calloc(1, strlen(path) + 1);
147 if (!self->path)
148 goto out_failure;
149
150 strcpy(self->name, name);
151 strcpy(self->path, path);
152 self->hash = crc32(self->name, strlen(name));
153
154 return self;
155
156out_failure:
157 if (self) {
158 if (self->name)
159 free(self->name);
160 if (self->path)
161 free(self->path);
162 free(self);
163 }
164
165 return NULL;
166}
167
168/* module methods */
169
170struct mod_dso *mod_dso__new_dso(const char *name)
171{
172 struct mod_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
173
174 if (self != NULL) {
175 strcpy(self->name, name);
176 self->mods = RB_ROOT;
177 self->find_module = mod_dso__find_module;
178 }
179
180 return self;
181}
182
183static void mod_dso__delete_module(struct module *self)
184{
185 free(((void *)self));
186}
187
188void mod_dso__delete_modules(struct mod_dso *self)
189{
190 struct module *pos;
191 struct rb_node *next = rb_first(&self->mods);
192
193 while (next) {
194 pos = rb_entry(next, struct module, rb_node);
195 next = rb_next(&pos->rb_node);
196 rb_erase(&pos->rb_node, &self->mods);
197 mod_dso__delete_module(pos);
198 }
199}
200
201void mod_dso__delete_self(struct mod_dso *self)
202{
203 mod_dso__delete_modules(self);
204 free(self);
205}
206
207static void mod_dso__insert_module(struct mod_dso *self, struct module *mod)
208{
209 struct rb_node **p = &self->mods.rb_node;
210 struct rb_node *parent = NULL;
211 const u64 hash = mod->hash;
212 struct module *m;
213
214 while (*p != NULL) {
215 parent = *p;
216 m = rb_entry(parent, struct module, rb_node);
217 if (hash < m->hash)
218 p = &(*p)->rb_left;
219 else
220 p = &(*p)->rb_right;
221 }
222 rb_link_node(&mod->rb_node, parent, p);
223 rb_insert_color(&mod->rb_node, &self->mods);
224}
225
226struct module *mod_dso__find_module(struct mod_dso *self, const char *name)
227{
228 struct rb_node *n;
229 u64 hash;
230 int len;
231
232 if (self == NULL)
233 return NULL;
234
235 len = strlen(name);
236 hash = crc32(name, len);
237
238 n = self->mods.rb_node;
239
240 while (n) {
241 struct module *m = rb_entry(n, struct module, rb_node);
242
243 if (hash < m->hash)
244 n = n->rb_left;
245 else if (hash > m->hash)
246 n = n->rb_right;
247 else {
248 if (!strcmp(name, m->name))
249 return m;
250 else
251 n = rb_next(&m->rb_node);
252 }
253 }
254
255 return NULL;
256}
257
258static size_t mod_dso__fprintf_module(struct module *self, FILE *fp)
259{
260 return fprintf(fp, "name:%s path:%s\n", self->name, self->path);
261}
262
263size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp)
264{
265 struct rb_node *nd;
266 size_t ret;
267
268 ret = fprintf(fp, "dso: %s\n", self->name);
269
270 for (nd = rb_first(&self->mods); nd; nd = rb_next(nd)) {
271 struct module *pos = rb_entry(nd, struct module, rb_node);
272
273 ret += mod_dso__fprintf_module(pos, fp);
274 }
275
276 return ret;
277}
278
279static struct module *module__new(const char *name, const char *path)
280{
281 struct module *self = calloc(1, sizeof(*self));
282
283 if (!self)
284 goto out_failure;
285
286 self->name = calloc(1, strlen(name) + 1);
287 if (!self->name)
288 goto out_failure;
289
290 self->path = calloc(1, strlen(path) + 1);
291 if (!self->path)
292 goto out_failure;
293
294 strcpy(self->name, name);
295 strcpy(self->path, path);
296 self->hash = crc32(self->name, strlen(name));
297
298 return self;
299
300out_failure:
301 if (self) {
302 if (self->name)
303 free(self->name);
304 if (self->path)
305 free(self->path);
306 free(self);
307 }
308
309 return NULL;
310}
311
312static int mod_dso__load_sections(struct module *mod)
313{
314 int count = 0, path_len;
315 struct dirent *entry;
316 char *line = NULL;
317 char *dir_path;
318 DIR *dir;
319 size_t n;
320
321 path_len = strlen("/sys/module/");
322 path_len += strlen(mod->name);
323 path_len += strlen("/sections/");
324
325 dir_path = calloc(1, path_len + 1);
326 if (dir_path == NULL)
327 goto out_failure;
328
329 strcat(dir_path, "/sys/module/");
330 strcat(dir_path, mod->name);
331 strcat(dir_path, "/sections/");
332
333 dir = opendir(dir_path);
334 if (dir == NULL)
335 goto out_free;
336
337 while ((entry = readdir(dir))) {
338 struct section *section;
339 char *path, *vma;
340 int line_len;
341 FILE *file;
342
343 if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name))
344 continue;
345
346 path = calloc(1, path_len + strlen(entry->d_name) + 1);
347 if (path == NULL)
348 break;
349 strcat(path, dir_path);
350 strcat(path, entry->d_name);
351
352 file = fopen(path, "r");
353 if (file == NULL) {
354 free(path);
355 break;
356 }
357
358 line_len = getline(&line, &n, file);
359 if (line_len < 0) {
360 free(path);
361 fclose(file);
362 break;
363 }
364
365 if (!line) {
366 free(path);
367 fclose(file);
368 break;
369 }
370
371 line[--line_len] = '\0'; /* \n */
372
373 vma = strstr(line, "0x");
374 if (!vma) {
375 free(path);
376 fclose(file);
377 break;
378 }
379 vma += 2;
380
381 section = section__new(entry->d_name, path);
382 if (!section) {
383 fprintf(stderr, "load_sections: allocation error\n");
384 free(path);
385 fclose(file);
386 break;
387 }
388
389 hex2u64(vma, &section->vma);
390 sec_dso__insert_section(mod->sections, section);
391
392 free(path);
393 fclose(file);
394 count++;
395 }
396
397 closedir(dir);
398 free(line);
399 free(dir_path);
400
401 return count;
402
403out_free:
404 free(dir_path);
405
406out_failure:
407 return count;
408}
409
410static int mod_dso__load_module_paths(struct mod_dso *self)
411{
412 struct utsname uts;
413 int count = 0, len, err = -1;
414 char *line = NULL;
415 FILE *file;
416 char *dpath, *dir;
417 size_t n;
418
419 if (uname(&uts) < 0)
420 return err;
421
422 len = strlen("/lib/modules/");
423 len += strlen(uts.release);
424 len += strlen("/modules.dep");
425
426 dpath = calloc(1, len + 1);
427 if (dpath == NULL)
428 return err;
429
430 strcat(dpath, "/lib/modules/");
431 strcat(dpath, uts.release);
432 strcat(dpath, "/modules.dep");
433
434 file = fopen(dpath, "r");
435 if (file == NULL)
436 goto out_failure;
437
438 dir = dirname(dpath);
439 if (!dir)
440 goto out_failure;
441 strcat(dir, "/");
442
443 while (!feof(file)) {
444 struct module *module;
445 char *name, *path, *tmp;
446 FILE *modfile;
447 int line_len;
448
449 line_len = getline(&line, &n, file);
450 if (line_len < 0)
451 break;
452
453 if (!line)
454 break;
455
456 line[--line_len] = '\0'; /* \n */
457
458 path = strchr(line, ':');
459 if (!path)
460 break;
461 *path = '\0';
462
463 path = strdup(line);
464 if (!path)
465 break;
466
467 if (!strstr(path, dir)) {
468 if (strncmp(path, "kernel/", 7))
469 break;
470
471 free(path);
472 path = calloc(1, strlen(dir) + strlen(line) + 1);
473 if (!path)
474 break;
475 strcat(path, dir);
476 strcat(path, line);
477 }
478
479 modfile = fopen(path, "r");
480 if (modfile == NULL)
481 break;
482 fclose(modfile);
483
484 name = strdup(path);
485 if (!name)
486 break;
487
488 name = strtok(name, "/");
489 tmp = name;
490
491 while (tmp) {
492 tmp = strtok(NULL, "/");
493 if (tmp)
494 name = tmp;
495 }
496
497 name = strsep(&name, ".");
498 if (!name)
499 break;
500
501 /* Quirk: replace '-' with '_' in all modules */
502 for (len = strlen(name); len; len--) {
503 if (*(name+len) == '-')
504 *(name+len) = '_';
505 }
506
507 module = module__new(name, path);
508 if (!module)
509 break;
510 mod_dso__insert_module(self, module);
511
512 module->sections = sec_dso__new_dso("sections");
513 if (!module->sections)
514 break;
515
516 module->active = mod_dso__load_sections(module);
517
518 if (module->active > 0)
519 count++;
520 }
521
522 if (feof(file))
523 err = count;
524 else
525 fprintf(stderr, "load_module_paths: modules.dep parsing failure!\n");
526
527out_failure:
528 if (dpath)
529 free(dpath);
530 if (file)
531 fclose(file);
532 if (line)
533 free(line);
534
535 return err;
536}
537
538int mod_dso__load_modules(struct mod_dso *dso)
539{
540 int err;
541
542 err = mod_dso__load_module_paths(dso);
543
544 return err;
545}
diff --git a/tools/perf/util/module.h b/tools/perf/util/module.h
deleted file mode 100644
index 8a592ef641ca..000000000000
--- a/tools/perf/util/module.h
+++ /dev/null
@@ -1,53 +0,0 @@
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 87c424de79ee..8cfb48cbbea0 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -691,7 +691,10 @@ static void store_event_type(const char *orgname)
691 FILE *file; 691 FILE *file;
692 int id; 692 int id;
693 693
694 sprintf(filename, "/sys/kernel/debug/tracing/events/%s/id", orgname); 694 sprintf(filename, "%s/", debugfs_path);
695 strncat(filename, orgname, strlen(orgname));
696 strcat(filename, "/id");
697
695 c = strchr(filename, ':'); 698 c = strchr(filename, ':');
696 if (c) 699 if (c)
697 *c = '/'; 700 *c = '/';
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 30c608112845..8626a439033d 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -1,5 +1,5 @@
1#ifndef _PARSE_EVENTS_H 1#ifndef __PERF_PARSE_EVENTS_H
2#define _PARSE_EVENTS_H 2#define __PERF_PARSE_EVENTS_H
3/* 3/*
4 * Parse symbolic events/counts passed in as options: 4 * Parse symbolic events/counts passed in as options:
5 */ 5 */
@@ -31,4 +31,4 @@ extern char debugfs_path[];
31extern int valid_debugfs_mount(const char *debugfs); 31extern int valid_debugfs_mount(const char *debugfs);
32 32
33 33
34#endif /* _PARSE_EVENTS_H */ 34#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 2ee248ff27e5..948805af43c2 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -1,5 +1,5 @@
1#ifndef PARSE_OPTIONS_H 1#ifndef __PERF_PARSE_OPTIONS_H
2#define PARSE_OPTIONS_H 2#define __PERF_PARSE_OPTIONS_H
3 3
4enum parse_opt_type { 4enum parse_opt_type {
5 /* special types */ 5 /* special types */
@@ -174,4 +174,4 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
174 174
175extern const char *parse_options_fix_filename(const char *prefix, const char *file); 175extern const char *parse_options_fix_filename(const char *prefix, const char *file);
176 176
177#endif 177#endif /* __PERF_PARSE_OPTIONS_H */
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h
index a5454a1d1c13..b6a019733919 100644
--- a/tools/perf/util/quote.h
+++ b/tools/perf/util/quote.h
@@ -1,5 +1,5 @@
1#ifndef QUOTE_H 1#ifndef __PERF_QUOTE_H
2#define QUOTE_H 2#define __PERF_QUOTE_H
3 3
4#include <stddef.h> 4#include <stddef.h>
5#include <stdio.h> 5#include <stdio.h>
@@ -65,4 +65,4 @@ extern void perl_quote_print(FILE *stream, const char *src);
65extern void python_quote_print(FILE *stream, const char *src); 65extern void python_quote_print(FILE *stream, const char *src);
66extern void tcl_quote_print(FILE *stream, const char *src); 66extern void tcl_quote_print(FILE *stream, const char *src);
67 67
68#endif 68#endif /* __PERF_QUOTE_H */
diff --git a/tools/perf/util/run-command.h b/tools/perf/util/run-command.h
index cc1837deba88..d79028727ce2 100644
--- a/tools/perf/util/run-command.h
+++ b/tools/perf/util/run-command.h
@@ -1,5 +1,5 @@
1#ifndef RUN_COMMAND_H 1#ifndef __PERF_RUN_COMMAND_H
2#define RUN_COMMAND_H 2#define __PERF_RUN_COMMAND_H
3 3
4enum { 4enum {
5 ERR_RUN_COMMAND_FORK = 10000, 5 ERR_RUN_COMMAND_FORK = 10000,
@@ -85,4 +85,4 @@ struct async {
85int start_async(struct async *async); 85int start_async(struct async *async);
86int finish_async(struct async *async); 86int finish_async(struct async *async);
87 87
88#endif 88#endif /* __PERF_RUN_COMMAND_H */
diff --git a/tools/perf/util/sigchain.h b/tools/perf/util/sigchain.h
index 618083bce0c6..1a53c11265fd 100644
--- a/tools/perf/util/sigchain.h
+++ b/tools/perf/util/sigchain.h
@@ -1,5 +1,5 @@
1#ifndef SIGCHAIN_H 1#ifndef __PERF_SIGCHAIN_H
2#define SIGCHAIN_H 2#define __PERF_SIGCHAIN_H
3 3
4typedef void (*sigchain_fun)(int); 4typedef void (*sigchain_fun)(int);
5 5
@@ -8,4 +8,4 @@ int sigchain_pop(int sig);
8 8
9void sigchain_push_common(sigchain_fun f); 9void sigchain_push_common(sigchain_fun f);
10 10
11#endif /* SIGCHAIN_H */ 11#endif /* __PERF_SIGCHAIN_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
new file mode 100644
index 000000000000..40c9acd41cad
--- /dev/null
+++ b/tools/perf/util/sort.c
@@ -0,0 +1,276 @@
1#include "sort.h"
2
3regex_t parent_regex;
4char default_parent_pattern[] = "^sys_|^do_page_fault";
5char *parent_pattern = default_parent_pattern;
6char default_sort_order[] = "comm,dso,symbol";
7char *sort_order = default_sort_order;
8int sort__need_collapse = 0;
9int sort__has_parent = 0;
10
11unsigned int dsos__col_width;
12unsigned int comms__col_width;
13unsigned int threads__col_width;
14static unsigned int parent_symbol__col_width;
15char * field_sep;
16
17LIST_HEAD(hist_entry__sort_list);
18
19struct sort_entry sort_thread = {
20 .header = "Command: Pid",
21 .cmp = sort__thread_cmp,
22 .print = sort__thread_print,
23 .width = &threads__col_width,
24};
25
26struct sort_entry sort_comm = {
27 .header = "Command",
28 .cmp = sort__comm_cmp,
29 .collapse = sort__comm_collapse,
30 .print = sort__comm_print,
31 .width = &comms__col_width,
32};
33
34struct sort_entry sort_dso = {
35 .header = "Shared Object",
36 .cmp = sort__dso_cmp,
37 .print = sort__dso_print,
38 .width = &dsos__col_width,
39};
40
41struct sort_entry sort_sym = {
42 .header = "Symbol",
43 .cmp = sort__sym_cmp,
44 .print = sort__sym_print,
45};
46
47struct sort_entry sort_parent = {
48 .header = "Parent symbol",
49 .cmp = sort__parent_cmp,
50 .print = sort__parent_print,
51 .width = &parent_symbol__col_width,
52};
53
54struct sort_dimension {
55 const char *name;
56 struct sort_entry *entry;
57 int taken;
58};
59
60static struct sort_dimension sort_dimensions[] = {
61 { .name = "pid", .entry = &sort_thread, },
62 { .name = "comm", .entry = &sort_comm, },
63 { .name = "dso", .entry = &sort_dso, },
64 { .name = "symbol", .entry = &sort_sym, },
65 { .name = "parent", .entry = &sort_parent, },
66};
67
68int64_t cmp_null(void *l, void *r)
69{
70 if (!l && !r)
71 return 0;
72 else if (!l)
73 return -1;
74 else
75 return 1;
76}
77
78/* --sort pid */
79
80int64_t
81sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
82{
83 return right->thread->pid - left->thread->pid;
84}
85
86int repsep_fprintf(FILE *fp, const char *fmt, ...)
87{
88 int n;
89 va_list ap;
90
91 va_start(ap, fmt);
92 if (!field_sep)
93 n = vfprintf(fp, fmt, ap);
94 else {
95 char *bf = NULL;
96 n = vasprintf(&bf, fmt, ap);
97 if (n > 0) {
98 char *sep = bf;
99
100 while (1) {
101 sep = strchr(sep, *field_sep);
102 if (sep == NULL)
103 break;
104 *sep = '.';
105 }
106 }
107 fputs(bf, fp);
108 free(bf);
109 }
110 va_end(ap);
111 return n;
112}
113
114size_t
115sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
116{
117 return repsep_fprintf(fp, "%*s:%5d", width - 6,
118 self->thread->comm ?: "", self->thread->pid);
119}
120
121size_t
122sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
123{
124 return repsep_fprintf(fp, "%*s", width, self->thread->comm);
125}
126
127/* --sort dso */
128
129int64_t
130sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
131{
132 struct dso *dso_l = left->map ? left->map->dso : NULL;
133 struct dso *dso_r = right->map ? right->map->dso : NULL;
134 const char *dso_name_l, *dso_name_r;
135
136 if (!dso_l || !dso_r)
137 return cmp_null(dso_l, dso_r);
138
139 if (verbose) {
140 dso_name_l = dso_l->long_name;
141 dso_name_r = dso_r->long_name;
142 } else {
143 dso_name_l = dso_l->short_name;
144 dso_name_r = dso_r->short_name;
145 }
146
147 return strcmp(dso_name_l, dso_name_r);
148}
149
150size_t
151sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
152{
153 if (self->map && self->map->dso) {
154 const char *dso_name = !verbose ? self->map->dso->short_name :
155 self->map->dso->long_name;
156 return repsep_fprintf(fp, "%-*s", width, dso_name);
157 }
158
159 return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
160}
161
162/* --sort symbol */
163
164int64_t
165sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
166{
167 u64 ip_l, ip_r;
168
169 if (left->sym == right->sym)
170 return 0;
171
172 ip_l = left->sym ? left->sym->start : left->ip;
173 ip_r = right->sym ? right->sym->start : right->ip;
174
175 return (int64_t)(ip_r - ip_l);
176}
177
178
179size_t
180sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
181{
182 size_t ret = 0;
183
184 if (verbose) {
185 char o = self->map ? dso__symtab_origin(self->map->dso) : '!';
186 ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip, o);
187 }
188
189 ret += repsep_fprintf(fp, "[%c] ", self->level);
190 if (self->sym)
191 ret += repsep_fprintf(fp, "%s", self->sym->name);
192 else
193 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
194
195 return ret;
196}
197
198/* --sort comm */
199
200int64_t
201sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
202{
203 return right->thread->pid - left->thread->pid;
204}
205
206int64_t
207sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
208{
209 char *comm_l = left->thread->comm;
210 char *comm_r = right->thread->comm;
211
212 if (!comm_l || !comm_r)
213 return cmp_null(comm_l, comm_r);
214
215 return strcmp(comm_l, comm_r);
216}
217
218/* --sort parent */
219
220int64_t
221sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
222{
223 struct symbol *sym_l = left->parent;
224 struct symbol *sym_r = right->parent;
225
226 if (!sym_l || !sym_r)
227 return cmp_null(sym_l, sym_r);
228
229 return strcmp(sym_l->name, sym_r->name);
230}
231
232size_t
233sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
234{
235 return repsep_fprintf(fp, "%-*s", width,
236 self->parent ? self->parent->name : "[other]");
237}
238
239int sort_dimension__add(const char *tok)
240{
241 unsigned int i;
242
243 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
244 struct sort_dimension *sd = &sort_dimensions[i];
245
246 if (sd->taken)
247 continue;
248
249 if (strncasecmp(tok, sd->name, strlen(tok)))
250 continue;
251
252 if (sd->entry->collapse)
253 sort__need_collapse = 1;
254
255 if (sd->entry == &sort_parent) {
256 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
257 if (ret) {
258 char err[BUFSIZ];
259
260 regerror(ret, &parent_regex, err, sizeof(err));
261 fprintf(stderr, "Invalid regex: %s\n%s",
262 parent_pattern, err);
263 exit(-1);
264 }
265 sort__has_parent = 1;
266 }
267
268 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
269 sd->taken = 1;
270
271 return 0;
272 }
273
274 return -ESRCH;
275}
276
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
new file mode 100644
index 000000000000..13806d782af6
--- /dev/null
+++ b/tools/perf/util/sort.h
@@ -0,0 +1,90 @@
1#ifndef __PERF_SORT_H
2#define __PERF_SORT_H
3#include "../builtin.h"
4
5#include "util.h"
6
7#include "color.h"
8#include <linux/list.h>
9#include "cache.h"
10#include <linux/rbtree.h>
11#include "symbol.h"
12#include "string.h"
13#include "callchain.h"
14#include "strlist.h"
15#include "values.h"
16
17#include "../perf.h"
18#include "debug.h"
19#include "header.h"
20
21#include "parse-options.h"
22#include "parse-events.h"
23
24#include "thread.h"
25#include "sort.h"
26
27extern regex_t parent_regex;
28extern char *sort_order;
29extern char default_parent_pattern[];
30extern char *parent_pattern;
31extern char default_sort_order[];
32extern int sort__need_collapse;
33extern int sort__has_parent;
34extern char *field_sep;
35extern struct sort_entry sort_comm;
36extern struct sort_entry sort_dso;
37extern struct sort_entry sort_sym;
38extern struct sort_entry sort_parent;
39extern unsigned int dsos__col_width;
40extern unsigned int comms__col_width;
41extern unsigned int threads__col_width;
42
43struct hist_entry {
44 struct rb_node rb_node;
45 u64 count;
46 struct thread *thread;
47 struct map *map;
48 struct symbol *sym;
49 u64 ip;
50 char level;
51 struct symbol *parent;
52 struct callchain_node callchain;
53 struct rb_root sorted_chain;
54};
55
56/*
57 * configurable sorting bits
58 */
59
60struct sort_entry {
61 struct list_head list;
62
63 const char *header;
64
65 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
66 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
67 size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width);
68 unsigned int *width;
69 bool elide;
70};
71
72extern struct sort_entry sort_thread;
73extern struct list_head hist_entry__sort_list;
74
75extern int repsep_fprintf(FILE *fp, const char *fmt, ...);
76extern size_t sort__thread_print(FILE *, struct hist_entry *, unsigned int);
77extern size_t sort__comm_print(FILE *, struct hist_entry *, unsigned int);
78extern size_t sort__dso_print(FILE *, struct hist_entry *, unsigned int);
79extern size_t sort__sym_print(FILE *, struct hist_entry *, unsigned int __used);
80extern int64_t cmp_null(void *, void *);
81extern int64_t sort__thread_cmp(struct hist_entry *, struct hist_entry *);
82extern int64_t sort__comm_cmp(struct hist_entry *, struct hist_entry *);
83extern int64_t sort__comm_collapse(struct hist_entry *, struct hist_entry *);
84extern int64_t sort__dso_cmp(struct hist_entry *, struct hist_entry *);
85extern int64_t sort__sym_cmp(struct hist_entry *, struct hist_entry *);
86extern int64_t sort__parent_cmp(struct hist_entry *, struct hist_entry *);
87extern size_t sort__parent_print(FILE *, struct hist_entry *, unsigned int);
88extern int sort_dimension__add(const char *);
89
90#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index d2aa86c014c1..a3d121d6c83e 100644
--- a/tools/perf/util/strbuf.h
+++ b/tools/perf/util/strbuf.h
@@ -1,5 +1,5 @@
1#ifndef STRBUF_H 1#ifndef __PERF_STRBUF_H
2#define STRBUF_H 2#define __PERF_STRBUF_H
3 3
4/* 4/*
5 * Strbuf's can be use in many ways: as a byte array, or to store arbitrary 5 * Strbuf's can be use in many ways: as a byte array, or to store arbitrary
@@ -134,4 +134,4 @@ extern int launch_editor(const char *path, struct strbuf *buffer, const char *co
134extern int strbuf_branchname(struct strbuf *sb, const char *name); 134extern int strbuf_branchname(struct strbuf *sb, const char *name);
135extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name); 135extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name);
136 136
137#endif /* STRBUF_H */ 137#endif /* __PERF_STRBUF_H */
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index c93eca9a7be3..04743d3e9039 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -1,3 +1,4 @@
1#include <string.h>
1#include "string.h" 2#include "string.h"
2 3
3static int hex(char ch) 4static int hex(char ch)
@@ -32,3 +33,13 @@ int hex2u64(const char *ptr, u64 *long_val)
32 33
33 return p - ptr; 34 return p - ptr;
34} 35}
36
37char *strxfrchar(char *s, char from, char to)
38{
39 char *p = s;
40
41 while ((p = strchr(p, from)) != NULL)
42 *p++ = to;
43
44 return s;
45}
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h
index bf39dfadfd24..2c84bf65ba0f 100644
--- a/tools/perf/util/string.h
+++ b/tools/perf/util/string.h
@@ -1,11 +1,12 @@
1#ifndef _PERF_STRING_H_ 1#ifndef __PERF_STRING_H_
2#define _PERF_STRING_H_ 2#define __PERF_STRING_H_
3 3
4#include "types.h" 4#include "types.h"
5 5
6int hex2u64(const char *ptr, u64 *val); 6int hex2u64(const char *ptr, u64 *val);
7char *strxfrchar(char *s, char from, char to);
7 8
8#define _STR(x) #x 9#define _STR(x) #x
9#define STR(x) _STR(x) 10#define STR(x) _STR(x)
10 11
11#endif 12#endif /* __PERF_STRING_H */
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h
index 921818e44a54..cb4659306d7b 100644
--- a/tools/perf/util/strlist.h
+++ b/tools/perf/util/strlist.h
@@ -1,5 +1,5 @@
1#ifndef STRLIST_H_ 1#ifndef __PERF_STRLIST_H
2#define STRLIST_H_ 2#define __PERF_STRLIST_H
3 3
4#include <linux/rbtree.h> 4#include <linux/rbtree.h>
5#include <stdbool.h> 5#include <stdbool.h>
@@ -36,4 +36,4 @@ static inline unsigned int strlist__nr_entries(const struct strlist *self)
36} 36}
37 37
38int strlist__parse_list(struct strlist *self, const char *s); 38int strlist__parse_list(struct strlist *self, const char *s);
39#endif /* STRLIST_H_ */ 39#endif /* __PERF_STRLIST_H */
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index a778fd0f4ae4..856655d8b0b8 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -28,7 +28,7 @@ static u64 turbo_frequency, max_freq;
28 28
29int svg_page_width = 1000; 29int svg_page_width = 1000;
30 30
31#define MIN_TEXT_SIZE 0.001 31#define MIN_TEXT_SIZE 0.01
32 32
33static u64 total_height; 33static u64 total_height;
34static FILE *svgfile; 34static FILE *svgfile;
@@ -217,6 +217,18 @@ static char *cpu_model(void)
217 } 217 }
218 fclose(file); 218 fclose(file);
219 } 219 }
220
221 /* CPU type */
222 file = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies", "r");
223 if (file) {
224 while (fgets(buf, 255, file)) {
225 unsigned int freq;
226 freq = strtoull(buf, NULL, 10);
227 if (freq > max_freq)
228 max_freq = freq;
229 }
230 fclose(file);
231 }
220 return cpu_m; 232 return cpu_m;
221} 233}
222 234
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index cd93195aedb3..e0781989cc31 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -1,5 +1,5 @@
1#ifndef _INCLUDE_GUARD_SVG_HELPER_ 1#ifndef __PERF_SVGHELPER_H
2#define _INCLUDE_GUARD_SVG_HELPER_ 2#define __PERF_SVGHELPER_H
3 3
4#include "types.h" 4#include "types.h"
5 5
@@ -25,4 +25,4 @@ extern void svg_close(void);
25 25
26extern int svg_page_width; 26extern int svg_page_width;
27 27
28#endif 28#endif /* __PERF_SVGHELPER_H */
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 559fb06210f5..faa84f5d4f54 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2,12 +2,14 @@
2#include "../perf.h" 2#include "../perf.h"
3#include "string.h" 3#include "string.h"
4#include "symbol.h" 4#include "symbol.h"
5#include "thread.h"
5 6
6#include "debug.h" 7#include "debug.h"
7 8
8#include <libelf.h> 9#include <libelf.h>
9#include <gelf.h> 10#include <gelf.h>
10#include <elf.h> 11#include <elf.h>
12#include <sys/utsname.h>
11 13
12const char *sym_hist_filter; 14const char *sym_hist_filter;
13 15
@@ -18,12 +20,65 @@ enum dso_origin {
18 DSO__ORIG_UBUNTU, 20 DSO__ORIG_UBUNTU,
19 DSO__ORIG_BUILDID, 21 DSO__ORIG_BUILDID,
20 DSO__ORIG_DSO, 22 DSO__ORIG_DSO,
23 DSO__ORIG_KMODULE,
21 DSO__ORIG_NOT_FOUND, 24 DSO__ORIG_NOT_FOUND,
22}; 25};
23 26
24static struct symbol *symbol__new(u64 start, u64 len, 27static void dsos__add(struct dso *dso);
25 const char *name, unsigned int priv_size, 28static struct dso *dsos__find(const char *name);
26 u64 obj_start, int v) 29static struct map *map__new2(u64 start, struct dso *dso);
30static void kernel_maps__insert(struct map *map);
31
32static struct rb_root kernel_maps;
33
34static void dso__fixup_sym_end(struct dso *self)
35{
36 struct rb_node *nd, *prevnd = rb_first(&self->syms);
37 struct symbol *curr, *prev;
38
39 if (prevnd == NULL)
40 return;
41
42 curr = rb_entry(prevnd, struct symbol, rb_node);
43
44 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
45 prev = curr;
46 curr = rb_entry(nd, struct symbol, rb_node);
47
48 if (prev->end == prev->start)
49 prev->end = curr->start - 1;
50 }
51
52 /* Last entry */
53 if (curr->end == curr->start)
54 curr->end = roundup(curr->start, 4096);
55}
56
57static void kernel_maps__fixup_end(void)
58{
59 struct map *prev, *curr;
60 struct rb_node *nd, *prevnd = rb_first(&kernel_maps);
61
62 if (prevnd == NULL)
63 return;
64
65 curr = rb_entry(prevnd, struct map, rb_node);
66
67 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
68 prev = curr;
69 curr = rb_entry(nd, struct map, rb_node);
70 prev->end = curr->start - 1;
71 }
72
73 nd = rb_last(&curr->dso->syms);
74 if (nd) {
75 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
76 curr->end = sym->end;
77 }
78}
79
80static struct symbol *symbol__new(u64 start, u64 len, const char *name,
81 unsigned int priv_size, int v)
27{ 82{
28 size_t namelen = strlen(name) + 1; 83 size_t namelen = strlen(name) + 1;
29 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); 84 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen);
@@ -31,11 +86,10 @@ static struct symbol *symbol__new(u64 start, u64 len,
31 if (!self) 86 if (!self)
32 return NULL; 87 return NULL;
33 88
34 if (v >= 2) 89 if (v > 2)
35 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n", 90 printf("new symbol: %016Lx [%08lx]: %s, hist: %p\n",
36 (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start); 91 start, (unsigned long)len, name, self->hist);
37 92
38 self->obj_start= obj_start;
39 self->hist = NULL; 93 self->hist = NULL;
40 self->hist_sum = 0; 94 self->hist_sum = 0;
41 95
@@ -60,12 +114,8 @@ static void symbol__delete(struct symbol *self, unsigned int priv_size)
60 114
61static size_t symbol__fprintf(struct symbol *self, FILE *fp) 115static size_t symbol__fprintf(struct symbol *self, FILE *fp)
62{ 116{
63 if (!self->module) 117 return fprintf(fp, " %llx-%llx %s\n",
64 return fprintf(fp, " %llx-%llx %s\n",
65 self->start, self->end, self->name); 118 self->start, self->end, self->name);
66 else
67 return fprintf(fp, " %llx-%llx %s \t[%s]\n",
68 self->start, self->end, self->name, self->module->name);
69} 119}
70 120
71struct dso *dso__new(const char *name, unsigned int sym_priv_size) 121struct dso *dso__new(const char *name, unsigned int sym_priv_size)
@@ -74,6 +124,8 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
74 124
75 if (self != NULL) { 125 if (self != NULL) {
76 strcpy(self->name, name); 126 strcpy(self->name, name);
127 self->long_name = self->name;
128 self->short_name = self->name;
77 self->syms = RB_ROOT; 129 self->syms = RB_ROOT;
78 self->sym_priv_size = sym_priv_size; 130 self->sym_priv_size = sym_priv_size;
79 self->find_symbol = dso__find_symbol; 131 self->find_symbol = dso__find_symbol;
@@ -100,6 +152,8 @@ static void dso__delete_symbols(struct dso *self)
100void dso__delete(struct dso *self) 152void dso__delete(struct dso *self)
101{ 153{
102 dso__delete_symbols(self); 154 dso__delete_symbols(self);
155 if (self->long_name != self->name)
156 free(self->long_name);
103 free(self); 157 free(self);
104} 158}
105 159
@@ -147,7 +201,7 @@ struct symbol *dso__find_symbol(struct dso *self, u64 ip)
147 201
148size_t dso__fprintf(struct dso *self, FILE *fp) 202size_t dso__fprintf(struct dso *self, FILE *fp)
149{ 203{
150 size_t ret = fprintf(fp, "dso: %s\n", self->name); 204 size_t ret = fprintf(fp, "dso: %s\n", self->short_name);
151 205
152 struct rb_node *nd; 206 struct rb_node *nd;
153 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) { 207 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
@@ -158,13 +212,16 @@ size_t dso__fprintf(struct dso *self, FILE *fp)
158 return ret; 212 return ret;
159} 213}
160 214
161static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v) 215/*
216 * Loads the function entries in /proc/kallsyms into kernel_map->dso,
217 * so that we can in the next step set the symbol ->end address and then
218 * call kernel_maps__split_kallsyms.
219 */
220static int kernel_maps__load_all_kallsyms(int v)
162{ 221{
163 struct rb_node *nd, *prevnd;
164 char *line = NULL; 222 char *line = NULL;
165 size_t n; 223 size_t n;
166 FILE *file = fopen("/proc/kallsyms", "r"); 224 FILE *file = fopen("/proc/kallsyms", "r");
167 int count = 0;
168 225
169 if (file == NULL) 226 if (file == NULL)
170 goto out_failure; 227 goto out_failure;
@@ -174,6 +231,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v)
174 struct symbol *sym; 231 struct symbol *sym;
175 int line_len, len; 232 int line_len, len;
176 char symbol_type; 233 char symbol_type;
234 char *symbol_name;
177 235
178 line_len = getline(&line, &n, file); 236 line_len = getline(&line, &n, file);
179 if (line_len < 0) 237 if (line_len < 0)
@@ -196,44 +254,24 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v)
196 */ 254 */
197 if (symbol_type != 'T' && symbol_type != 'W') 255 if (symbol_type != 'T' && symbol_type != 'W')
198 continue; 256 continue;
257
258 symbol_name = line + len + 2;
199 /* 259 /*
200 * Well fix up the end later, when we have all sorted. 260 * Will fix up the end later, when we have all symbols sorted.
201 */ 261 */
202 sym = symbol__new(start, 0xdead, line + len + 2, 262 sym = symbol__new(start, 0, symbol_name,
203 self->sym_priv_size, 0, v); 263 kernel_map->dso->sym_priv_size, v);
204 264
205 if (sym == NULL) 265 if (sym == NULL)
206 goto out_delete_line; 266 goto out_delete_line;
207 267
208 if (filter && filter(self, sym)) 268 dso__insert_symbol(kernel_map->dso, sym);
209 symbol__delete(sym, self->sym_priv_size);
210 else {
211 dso__insert_symbol(self, sym);
212 count++;
213 }
214 }
215
216 /*
217 * Now that we have all sorted out, just set the ->end of all
218 * symbols
219 */
220 prevnd = rb_first(&self->syms);
221
222 if (prevnd == NULL)
223 goto out_delete_line;
224
225 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
226 struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node),
227 *curr = rb_entry(nd, struct symbol, rb_node);
228
229 prev->end = curr->start - 1;
230 prevnd = nd;
231 } 269 }
232 270
233 free(line); 271 free(line);
234 fclose(file); 272 fclose(file);
235 273
236 return count; 274 return 0;
237 275
238out_delete_line: 276out_delete_line:
239 free(line); 277 free(line);
@@ -241,14 +279,125 @@ out_failure:
241 return -1; 279 return -1;
242} 280}
243 281
244static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v) 282/*
283 * Split the symbols into maps, making sure there are no overlaps, i.e. the
284 * kernel range is broken in several maps, named [kernel].N, as we don't have
285 * the original ELF section names vmlinux have.
286 */
287static int kernel_maps__split_kallsyms(symbol_filter_t filter, int use_modules)
288{
289 struct map *map = kernel_map;
290 struct symbol *pos;
291 int count = 0;
292 struct rb_node *next = rb_first(&kernel_map->dso->syms);
293 int kernel_range = 0;
294
295 while (next) {
296 char *module;
297
298 pos = rb_entry(next, struct symbol, rb_node);
299 next = rb_next(&pos->rb_node);
300
301 module = strchr(pos->name, '\t');
302 if (module) {
303 if (!use_modules)
304 goto delete_symbol;
305
306 *module++ = '\0';
307
308 if (strcmp(map->dso->name, module)) {
309 map = kernel_maps__find_by_dso_name(module);
310 if (!map) {
311 fputs("/proc/{kallsyms,modules} "
312 "inconsistency!\n", stderr);
313 return -1;
314 }
315 }
316 /*
317 * So that we look just like we get from .ko files,
318 * i.e. not prelinked, relative to map->start.
319 */
320 pos->start = map->map_ip(map, pos->start);
321 pos->end = map->map_ip(map, pos->end);
322 } else if (map != kernel_map) {
323 char dso_name[PATH_MAX];
324 struct dso *dso;
325
326 snprintf(dso_name, sizeof(dso_name), "[kernel].%d",
327 kernel_range++);
328
329 dso = dso__new(dso_name,
330 kernel_map->dso->sym_priv_size);
331 if (dso == NULL)
332 return -1;
333
334 map = map__new2(pos->start, dso);
335 if (map == NULL) {
336 dso__delete(dso);
337 return -1;
338 }
339
340 map->map_ip = vdso__map_ip;
341 kernel_maps__insert(map);
342 ++kernel_range;
343 }
344
345 if (filter && filter(map, pos)) {
346delete_symbol:
347 rb_erase(&pos->rb_node, &kernel_map->dso->syms);
348 symbol__delete(pos, kernel_map->dso->sym_priv_size);
349 } else {
350 if (map != kernel_map) {
351 rb_erase(&pos->rb_node, &kernel_map->dso->syms);
352 dso__insert_symbol(map->dso, pos);
353 }
354 count++;
355 }
356 }
357
358 return count;
359}
360
361
362static int kernel_maps__load_kallsyms(symbol_filter_t filter,
363 int use_modules, int v)
364{
365 if (kernel_maps__load_all_kallsyms(v))
366 return -1;
367
368 dso__fixup_sym_end(kernel_map->dso);
369
370 return kernel_maps__split_kallsyms(filter, use_modules);
371}
372
373static size_t kernel_maps__fprintf(FILE *fp, int v)
374{
375 size_t printed = fprintf(stderr, "Kernel maps:\n");
376 struct rb_node *nd;
377
378 for (nd = rb_first(&kernel_maps); nd; nd = rb_next(nd)) {
379 struct map *pos = rb_entry(nd, struct map, rb_node);
380
381 printed += fprintf(fp, "Map:");
382 printed += map__fprintf(pos, fp);
383 if (v > 1) {
384 printed += dso__fprintf(pos->dso, fp);
385 printed += fprintf(fp, "--\n");
386 }
387 }
388
389 return printed + fprintf(stderr, "END kernel maps\n");
390}
391
392static int dso__load_perf_map(struct dso *self, struct map *map,
393 symbol_filter_t filter, int v)
245{ 394{
246 char *line = NULL; 395 char *line = NULL;
247 size_t n; 396 size_t n;
248 FILE *file; 397 FILE *file;
249 int nr_syms = 0; 398 int nr_syms = 0;
250 399
251 file = fopen(self->name, "r"); 400 file = fopen(self->long_name, "r");
252 if (file == NULL) 401 if (file == NULL)
253 goto out_failure; 402 goto out_failure;
254 403
@@ -279,12 +428,12 @@ static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v)
279 continue; 428 continue;
280 429
281 sym = symbol__new(start, size, line + len, 430 sym = symbol__new(start, size, line + len,
282 self->sym_priv_size, start, v); 431 self->sym_priv_size, v);
283 432
284 if (sym == NULL) 433 if (sym == NULL)
285 goto out_delete_line; 434 goto out_delete_line;
286 435
287 if (filter && filter(self, sym)) 436 if (filter && filter(map, sym))
288 symbol__delete(sym, self->sym_priv_size); 437 symbol__delete(sym, self->sym_priv_size);
289 else { 438 else {
290 dso__insert_symbol(self, sym); 439 dso__insert_symbol(self, sym);
@@ -324,8 +473,7 @@ static inline int elf_sym__is_function(const GElf_Sym *sym)
324{ 473{
325 return elf_sym__type(sym) == STT_FUNC && 474 return elf_sym__type(sym) == STT_FUNC &&
326 sym->st_name != 0 && 475 sym->st_name != 0 &&
327 sym->st_shndx != SHN_UNDEF && 476 sym->st_shndx != SHN_UNDEF;
328 sym->st_size != 0;
329} 477}
330 478
331static inline int elf_sym__is_label(const GElf_Sym *sym) 479static inline int elf_sym__is_label(const GElf_Sym *sym)
@@ -410,7 +558,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
410 Elf *elf; 558 Elf *elf;
411 int nr = 0, symidx, fd, err = 0; 559 int nr = 0, symidx, fd, err = 0;
412 560
413 fd = open(self->name, O_RDONLY); 561 fd = open(self->long_name, O_RDONLY);
414 if (fd < 0) 562 if (fd < 0)
415 goto out; 563 goto out;
416 564
@@ -478,7 +626,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
478 "%s@plt", elf_sym__name(&sym, symstrs)); 626 "%s@plt", elf_sym__name(&sym, symstrs));
479 627
480 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 628 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
481 sympltname, self->sym_priv_size, 0, v); 629 sympltname, self->sym_priv_size, v);
482 if (!f) 630 if (!f)
483 goto out_elf_end; 631 goto out_elf_end;
484 632
@@ -496,7 +644,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
496 "%s@plt", elf_sym__name(&sym, symstrs)); 644 "%s@plt", elf_sym__name(&sym, symstrs));
497 645
498 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 646 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
499 sympltname, self->sym_priv_size, 0, v); 647 sympltname, self->sym_priv_size, v);
500 if (!f) 648 if (!f)
501 goto out_elf_end; 649 goto out_elf_end;
502 650
@@ -515,13 +663,17 @@ out_close:
515 return nr; 663 return nr;
516out: 664out:
517 fprintf(stderr, "%s: problems reading %s PLT info.\n", 665 fprintf(stderr, "%s: problems reading %s PLT info.\n",
518 __func__, self->name); 666 __func__, self->long_name);
519 return 0; 667 return 0;
520} 668}
521 669
522static int dso__load_sym(struct dso *self, int fd, const char *name, 670static int dso__load_sym(struct dso *self, struct map *map, const char *name,
523 symbol_filter_t filter, int v, struct module *mod) 671 int fd, symbol_filter_t filter, int kernel,
672 int kmodule, int v)
524{ 673{
674 struct map *curr_map = map;
675 struct dso *curr_dso = self;
676 size_t dso_name_len = strlen(self->short_name);
525 Elf_Data *symstrs, *secstrs; 677 Elf_Data *symstrs, *secstrs;
526 uint32_t nr_syms; 678 uint32_t nr_syms;
527 int err = -1; 679 int err = -1;
@@ -532,7 +684,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
532 GElf_Sym sym; 684 GElf_Sym sym;
533 Elf_Scn *sec, *sec_strndx; 685 Elf_Scn *sec, *sec_strndx;
534 Elf *elf; 686 Elf *elf;
535 int nr = 0, kernel = !strcmp("[kernel]", self->name); 687 int nr = 0;
536 688
537 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 689 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
538 if (elf == NULL) { 690 if (elf == NULL) {
@@ -588,9 +740,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
588 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { 740 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
589 struct symbol *f; 741 struct symbol *f;
590 const char *elf_name; 742 const char *elf_name;
591 char *demangled; 743 char *demangled = NULL;
592 u64 obj_start;
593 struct section *section = NULL;
594 int is_label = elf_sym__is_label(&sym); 744 int is_label = elf_sym__is_label(&sym);
595 const char *section_name; 745 const char *section_name;
596 746
@@ -606,52 +756,85 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
606 if (is_label && !elf_sec__is_text(&shdr, secstrs)) 756 if (is_label && !elf_sec__is_text(&shdr, secstrs))
607 continue; 757 continue;
608 758
759 elf_name = elf_sym__name(&sym, symstrs);
609 section_name = elf_sec__name(&shdr, secstrs); 760 section_name = elf_sec__name(&shdr, secstrs);
610 obj_start = sym.st_value;
611 761
612 if (self->adjust_symbols) { 762 if (kernel || kmodule) {
613 if (v >= 2) 763 char dso_name[PATH_MAX];
764
765 if (strcmp(section_name,
766 curr_dso->short_name + dso_name_len) == 0)
767 goto new_symbol;
768
769 if (strcmp(section_name, ".text") == 0) {
770 curr_map = map;
771 curr_dso = self;
772 goto new_symbol;
773 }
774
775 snprintf(dso_name, sizeof(dso_name),
776 "%s%s", self->short_name, section_name);
777
778 curr_map = kernel_maps__find_by_dso_name(dso_name);
779 if (curr_map == NULL) {
780 u64 start = sym.st_value;
781
782 if (kmodule)
783 start += map->start + shdr.sh_offset;
784
785 curr_dso = dso__new(dso_name, self->sym_priv_size);
786 if (curr_dso == NULL)
787 goto out_elf_end;
788 curr_map = map__new2(start, curr_dso);
789 if (curr_map == NULL) {
790 dso__delete(curr_dso);
791 goto out_elf_end;
792 }
793 curr_map->map_ip = vdso__map_ip;
794 curr_dso->origin = DSO__ORIG_KERNEL;
795 kernel_maps__insert(curr_map);
796 dsos__add(curr_dso);
797 } else
798 curr_dso = curr_map->dso;
799
800 goto new_symbol;
801 }
802
803 if (curr_dso->adjust_symbols) {
804 if (v > 2)
614 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", 805 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
615 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 806 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
616 807
617 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 808 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
618 } 809 }
619
620 if (mod) {
621 section = mod->sections->find_section(mod->sections, section_name);
622 if (section)
623 sym.st_value += section->vma;
624 else {
625 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
626 mod->name, section_name);
627 goto out_elf_end;
628 }
629 }
630 /* 810 /*
631 * We need to figure out if the object was created from C++ sources 811 * We need to figure out if the object was created from C++ sources
632 * DWARF DW_compile_unit has this, but we don't always have access 812 * DWARF DW_compile_unit has this, but we don't always have access
633 * to it... 813 * to it...
634 */ 814 */
635 elf_name = elf_sym__name(&sym, symstrs);
636 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI); 815 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
637 if (demangled != NULL) 816 if (demangled != NULL)
638 elf_name = demangled; 817 elf_name = demangled;
639 818new_symbol:
640 f = symbol__new(sym.st_value, sym.st_size, elf_name, 819 f = symbol__new(sym.st_value, sym.st_size, elf_name,
641 self->sym_priv_size, obj_start, v); 820 curr_dso->sym_priv_size, v);
642 free(demangled); 821 free(demangled);
643 if (!f) 822 if (!f)
644 goto out_elf_end; 823 goto out_elf_end;
645 824
646 if (filter && filter(self, f)) 825 if (filter && filter(curr_map, f))
647 symbol__delete(f, self->sym_priv_size); 826 symbol__delete(f, curr_dso->sym_priv_size);
648 else { 827 else {
649 f->module = mod; 828 dso__insert_symbol(curr_dso, f);
650 dso__insert_symbol(self, f);
651 nr++; 829 nr++;
652 } 830 }
653 } 831 }
654 832
833 /*
834 * For misannotated, zeroed, ASM function sizes.
835 */
836 if (nr > 0)
837 dso__fixup_sym_end(self);
655 err = nr; 838 err = nr;
656out_elf_end: 839out_elf_end:
657 elf_end(elf); 840 elf_end(elf);
@@ -671,7 +854,7 @@ static char *dso__read_build_id(struct dso *self, int v)
671 char *build_id = NULL, *bid; 854 char *build_id = NULL, *bid;
672 unsigned char *raw; 855 unsigned char *raw;
673 Elf *elf; 856 Elf *elf;
674 int fd = open(self->name, O_RDONLY); 857 int fd = open(self->long_name, O_RDONLY);
675 858
676 if (fd < 0) 859 if (fd < 0)
677 goto out; 860 goto out;
@@ -680,7 +863,7 @@ static char *dso__read_build_id(struct dso *self, int v)
680 if (elf == NULL) { 863 if (elf == NULL) {
681 if (v) 864 if (v)
682 fprintf(stderr, "%s: cannot read %s ELF file.\n", 865 fprintf(stderr, "%s: cannot read %s ELF file.\n",
683 __func__, self->name); 866 __func__, self->long_name);
684 goto out_close; 867 goto out_close;
685 } 868 }
686 869
@@ -709,7 +892,7 @@ static char *dso__read_build_id(struct dso *self, int v)
709 bid += 2; 892 bid += 2;
710 } 893 }
711 if (v >= 2) 894 if (v >= 2)
712 printf("%s(%s): %s\n", __func__, self->name, build_id); 895 printf("%s(%s): %s\n", __func__, self->long_name, build_id);
713out_elf_end: 896out_elf_end:
714 elf_end(elf); 897 elf_end(elf);
715out_close: 898out_close:
@@ -727,6 +910,7 @@ char dso__symtab_origin(const struct dso *self)
727 [DSO__ORIG_UBUNTU] = 'u', 910 [DSO__ORIG_UBUNTU] = 'u',
728 [DSO__ORIG_BUILDID] = 'b', 911 [DSO__ORIG_BUILDID] = 'b',
729 [DSO__ORIG_DSO] = 'd', 912 [DSO__ORIG_DSO] = 'd',
913 [DSO__ORIG_KMODULE] = 'K',
730 }; 914 };
731 915
732 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) 916 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
@@ -734,7 +918,7 @@ char dso__symtab_origin(const struct dso *self)
734 return origin[self->origin]; 918 return origin[self->origin];
735} 919}
736 920
737int dso__load(struct dso *self, symbol_filter_t filter, int v) 921int dso__load(struct dso *self, struct map *map, symbol_filter_t filter, int v)
738{ 922{
739 int size = PATH_MAX; 923 int size = PATH_MAX;
740 char *name = malloc(size), *build_id = NULL; 924 char *name = malloc(size), *build_id = NULL;
@@ -747,7 +931,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int v)
747 self->adjust_symbols = 0; 931 self->adjust_symbols = 0;
748 932
749 if (strncmp(self->name, "/tmp/perf-", 10) == 0) { 933 if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
750 ret = dso__load_perf_map(self, filter, v); 934 ret = dso__load_perf_map(self, map, filter, v);
751 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : 935 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
752 DSO__ORIG_NOT_FOUND; 936 DSO__ORIG_NOT_FOUND;
753 return ret; 937 return ret;
@@ -760,10 +944,12 @@ more:
760 self->origin++; 944 self->origin++;
761 switch (self->origin) { 945 switch (self->origin) {
762 case DSO__ORIG_FEDORA: 946 case DSO__ORIG_FEDORA:
763 snprintf(name, size, "/usr/lib/debug%s.debug", self->name); 947 snprintf(name, size, "/usr/lib/debug%s.debug",
948 self->long_name);
764 break; 949 break;
765 case DSO__ORIG_UBUNTU: 950 case DSO__ORIG_UBUNTU:
766 snprintf(name, size, "/usr/lib/debug%s", self->name); 951 snprintf(name, size, "/usr/lib/debug%s",
952 self->long_name);
767 break; 953 break;
768 case DSO__ORIG_BUILDID: 954 case DSO__ORIG_BUILDID:
769 build_id = dso__read_build_id(self, v); 955 build_id = dso__read_build_id(self, v);
@@ -777,7 +963,7 @@ more:
777 self->origin++; 963 self->origin++;
778 /* Fall thru */ 964 /* Fall thru */
779 case DSO__ORIG_DSO: 965 case DSO__ORIG_DSO:
780 snprintf(name, size, "%s", self->name); 966 snprintf(name, size, "%s", self->long_name);
781 break; 967 break;
782 968
783 default: 969 default:
@@ -787,7 +973,7 @@ more:
787 fd = open(name, O_RDONLY); 973 fd = open(name, O_RDONLY);
788 } while (fd < 0); 974 } while (fd < 0);
789 975
790 ret = dso__load_sym(self, fd, name, filter, v, NULL); 976 ret = dso__load_sym(self, map, name, fd, filter, 0, 0, v);
791 close(fd); 977 close(fd);
792 978
793 /* 979 /*
@@ -808,89 +994,243 @@ out:
808 return ret; 994 return ret;
809} 995}
810 996
811static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, 997struct map *kernel_map;
812 symbol_filter_t filter, int v) 998
999static void kernel_maps__insert(struct map *map)
1000{
1001 maps__insert(&kernel_maps, map);
1002}
1003
1004struct symbol *kernel_maps__find_symbol(u64 ip, struct map **mapp)
813{ 1005{
814 struct module *mod = mod_dso__find_module(mods, name); 1006 struct map *map = maps__find(&kernel_maps, ip);
815 int err = 0, fd;
816 1007
817 if (mod == NULL || !mod->active) 1008 if (mapp)
818 return err; 1009 *mapp = map;
819 1010
820 fd = open(mod->path, O_RDONLY); 1011 if (map) {
1012 ip = map->map_ip(map, ip);
1013 return map->dso->find_symbol(map->dso, ip);
1014 }
821 1015
822 if (fd < 0) 1016 return NULL;
1017}
1018
1019struct map *kernel_maps__find_by_dso_name(const char *name)
1020{
1021 struct rb_node *nd;
1022
1023 for (nd = rb_first(&kernel_maps); nd; nd = rb_next(nd)) {
1024 struct map *map = rb_entry(nd, struct map, rb_node);
1025
1026 if (map->dso && strcmp(map->dso->name, name) == 0)
1027 return map;
1028 }
1029
1030 return NULL;
1031}
1032
1033static int dso__load_module_sym(struct dso *self, struct map *map,
1034 symbol_filter_t filter, int v)
1035{
1036 int err = 0, fd = open(self->long_name, O_RDONLY);
1037
1038 if (fd < 0) {
1039 if (v)
1040 fprintf(stderr, "%s: cannot open %s\n",
1041 __func__, self->long_name);
823 return err; 1042 return err;
1043 }
824 1044
825 err = dso__load_sym(self, fd, name, filter, v, mod); 1045 err = dso__load_sym(self, map, self->long_name, fd, filter, 0, 1, v);
826 close(fd); 1046 close(fd);
827 1047
828 return err; 1048 return err;
829} 1049}
830 1050
831int dso__load_modules(struct dso *self, symbol_filter_t filter, int v) 1051static int dsos__load_modules_sym_dir(char *dirname,
1052 symbol_filter_t filter, int v)
832{ 1053{
833 struct mod_dso *mods = mod_dso__new_dso("modules"); 1054 struct dirent *dent;
834 struct module *pos; 1055 int nr_symbols = 0, err;
835 struct rb_node *next; 1056 DIR *dir = opendir(dirname);
836 int err, count = 0;
837 1057
838 err = mod_dso__load_modules(mods); 1058 if (!dir) {
1059 if (v)
1060 fprintf(stderr, "%s: cannot open %s dir\n", __func__,
1061 dirname);
1062 return -1;
1063 }
839 1064
840 if (err <= 0) 1065 while ((dent = readdir(dir)) != NULL) {
841 return err; 1066 char path[PATH_MAX];
1067
1068 if (dent->d_type == DT_DIR) {
1069 if (!strcmp(dent->d_name, ".") ||
1070 !strcmp(dent->d_name, ".."))
1071 continue;
1072
1073 snprintf(path, sizeof(path), "%s/%s",
1074 dirname, dent->d_name);
1075 err = dsos__load_modules_sym_dir(path, filter, v);
1076 if (err < 0)
1077 goto failure;
1078 } else {
1079 char *dot = strrchr(dent->d_name, '.'),
1080 dso_name[PATH_MAX];
1081 struct map *map;
1082 struct rb_node *last;
1083
1084 if (dot == NULL || strcmp(dot, ".ko"))
1085 continue;
1086 snprintf(dso_name, sizeof(dso_name), "[%.*s]",
1087 (int)(dot - dent->d_name), dent->d_name);
1088
1089 strxfrchar(dso_name, '-', '_');
1090 map = kernel_maps__find_by_dso_name(dso_name);
1091 if (map == NULL)
1092 continue;
1093
1094 snprintf(path, sizeof(path), "%s/%s",
1095 dirname, dent->d_name);
1096
1097 map->dso->long_name = strdup(path);
1098 if (map->dso->long_name == NULL)
1099 goto failure;
1100
1101 err = dso__load_module_sym(map->dso, map, filter, v);
1102 if (err < 0)
1103 goto failure;
1104 last = rb_last(&map->dso->syms);
1105 if (last) {
1106 struct symbol *sym;
1107 /*
1108 * We do this here as well, even having the
1109 * symbol size found in the symtab because
1110 * misannotated ASM symbols may have the size
1111 * set to zero.
1112 */
1113 dso__fixup_sym_end(map->dso);
1114
1115 sym = rb_entry(last, struct symbol, rb_node);
1116 map->end = map->start + sym->end;
1117 }
1118 }
1119 nr_symbols += err;
1120 }
842 1121
843 /* 1122 return nr_symbols;
844 * Iterate over modules, and load active symbols. 1123failure:
845 */ 1124 closedir(dir);
846 next = rb_first(&mods->mods); 1125 return -1;
847 while (next) { 1126}
848 pos = rb_entry(next, struct module, rb_node);
849 err = dso__load_module(self, mods, pos->name, filter, v);
850 1127
851 if (err < 0) 1128static int dsos__load_modules_sym(symbol_filter_t filter, int v)
852 break; 1129{
1130 struct utsname uts;
1131 char modules_path[PATH_MAX];
853 1132
854 next = rb_next(&pos->rb_node); 1133 if (uname(&uts) < 0)
855 count += err; 1134 return -1;
856 }
857 1135
858 if (err < 0) { 1136 snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel",
859 mod_dso__delete_modules(mods); 1137 uts.release);
860 mod_dso__delete_self(mods);
861 return err;
862 }
863 1138
864 return count; 1139 return dsos__load_modules_sym_dir(modules_path, filter, v);
865} 1140}
866 1141
867static inline void dso__fill_symbol_holes(struct dso *self) 1142/*
1143 * Constructor variant for modules (where we know from /proc/modules where
1144 * they are loaded) and for vmlinux, where only after we load all the
1145 * symbols we'll know where it starts and ends.
1146 */
1147static struct map *map__new2(u64 start, struct dso *dso)
868{ 1148{
869 struct symbol *prev = NULL; 1149 struct map *self = malloc(sizeof(*self));
870 struct rb_node *nd;
871 1150
872 for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) { 1151 if (self != NULL) {
873 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 1152 self->start = start;
1153 /*
1154 * Will be filled after we load all the symbols
1155 */
1156 self->end = 0;
874 1157
875 if (prev) { 1158 self->pgoff = 0;
876 u64 hole = 0; 1159 self->dso = dso;
877 int alias = pos->start == prev->start; 1160 self->map_ip = map__map_ip;
1161 RB_CLEAR_NODE(&self->rb_node);
1162 }
1163 return self;
1164}
878 1165
879 if (!alias) 1166static int dsos__load_modules(unsigned int sym_priv_size)
880 hole = prev->start - pos->end - 1; 1167{
1168 char *line = NULL;
1169 size_t n;
1170 FILE *file = fopen("/proc/modules", "r");
1171 struct map *map;
881 1172
882 if (hole || alias) { 1173 if (file == NULL)
883 if (alias) 1174 return -1;
884 pos->end = prev->end; 1175
885 else if (hole) 1176 while (!feof(file)) {
886 pos->end = prev->start - 1; 1177 char name[PATH_MAX];
887 } 1178 u64 start;
1179 struct dso *dso;
1180 char *sep;
1181 int line_len;
1182
1183 line_len = getline(&line, &n, file);
1184 if (line_len < 0)
1185 break;
1186
1187 if (!line)
1188 goto out_failure;
1189
1190 line[--line_len] = '\0'; /* \n */
1191
1192 sep = strrchr(line, 'x');
1193 if (sep == NULL)
1194 continue;
1195
1196 hex2u64(sep + 1, &start);
1197
1198 sep = strchr(line, ' ');
1199 if (sep == NULL)
1200 continue;
1201
1202 *sep = '\0';
1203
1204 snprintf(name, sizeof(name), "[%s]", line);
1205 dso = dso__new(name, sym_priv_size);
1206
1207 if (dso == NULL)
1208 goto out_delete_line;
1209
1210 map = map__new2(start, dso);
1211 if (map == NULL) {
1212 dso__delete(dso);
1213 goto out_delete_line;
888 } 1214 }
889 prev = pos; 1215
1216 dso->origin = DSO__ORIG_KMODULE;
1217 kernel_maps__insert(map);
1218 dsos__add(dso);
890 } 1219 }
1220
1221 free(line);
1222 fclose(file);
1223
1224 return 0;
1225
1226out_delete_line:
1227 free(line);
1228out_failure:
1229 return -1;
891} 1230}
892 1231
893static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 1232static int dso__load_vmlinux(struct dso *self, struct map *map,
1233 const char *vmlinux,
894 symbol_filter_t filter, int v) 1234 symbol_filter_t filter, int v)
895{ 1235{
896 int err, fd = open(vmlinux, O_RDONLY); 1236 int err, fd = open(vmlinux, O_RDONLY);
@@ -898,47 +1238,82 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
898 if (fd < 0) 1238 if (fd < 0)
899 return -1; 1239 return -1;
900 1240
901 err = dso__load_sym(self, fd, vmlinux, filter, v, NULL); 1241 err = dso__load_sym(self, map, self->long_name, fd, filter, 1, 0, v);
902
903 if (err > 0)
904 dso__fill_symbol_holes(self);
905 1242
906 close(fd); 1243 close(fd);
907 1244
908 return err; 1245 return err;
909} 1246}
910 1247
911int dso__load_kernel(struct dso *self, const char *vmlinux, 1248int dsos__load_kernel(const char *vmlinux, unsigned int sym_priv_size,
912 symbol_filter_t filter, int v, int use_modules) 1249 symbol_filter_t filter, int v, int use_modules)
913{ 1250{
914 int err = -1; 1251 int err = -1;
1252 struct dso *dso = dso__new(vmlinux, sym_priv_size);
1253
1254 if (dso == NULL)
1255 return -1;
1256
1257 dso->short_name = "[kernel]";
1258 kernel_map = map__new2(0, dso);
1259 if (kernel_map == NULL)
1260 goto out_delete_dso;
1261
1262 kernel_map->map_ip = vdso__map_ip;
1263
1264 if (use_modules && dsos__load_modules(sym_priv_size) < 0) {
1265 fprintf(stderr, "Failed to load list of modules in use! "
1266 "Continuing...\n");
1267 use_modules = 0;
1268 }
915 1269
916 if (vmlinux) { 1270 if (vmlinux) {
917 err = dso__load_vmlinux(self, vmlinux, filter, v); 1271 err = dso__load_vmlinux(dso, kernel_map, vmlinux, filter, v);
918 if (err > 0 && use_modules) { 1272 if (err > 0 && use_modules) {
919 int syms = dso__load_modules(self, filter, v); 1273 int syms = dsos__load_modules_sym(filter, v);
920 1274
921 if (syms < 0) { 1275 if (syms < 0)
922 fprintf(stderr, "dso__load_modules failed!\n"); 1276 fprintf(stderr, "Failed to read module symbols!"
923 return syms; 1277 " Continuing...\n");
924 } 1278 else
925 err += syms; 1279 err += syms;
926 } 1280 }
927 } 1281 }
928 1282
929 if (err <= 0) 1283 if (err <= 0)
930 err = dso__load_kallsyms(self, filter, v); 1284 err = kernel_maps__load_kallsyms(filter, use_modules, v);
931 1285
932 if (err > 0) 1286 if (err > 0) {
933 self->origin = DSO__ORIG_KERNEL; 1287 struct rb_node *node = rb_first(&dso->syms);
1288 struct symbol *sym = rb_entry(node, struct symbol, rb_node);
1289
1290 kernel_map->start = sym->start;
1291 node = rb_last(&dso->syms);
1292 sym = rb_entry(node, struct symbol, rb_node);
1293 kernel_map->end = sym->end;
1294
1295 dso->origin = DSO__ORIG_KERNEL;
1296 kernel_maps__insert(kernel_map);
1297 /*
1298 * Now that we have all sorted out, just set the ->end of all
1299 * maps:
1300 */
1301 kernel_maps__fixup_end();
1302 dsos__add(dso);
1303
1304 if (v > 0)
1305 kernel_maps__fprintf(stderr, v);
1306 }
934 1307
935 return err; 1308 return err;
1309
1310out_delete_dso:
1311 dso__delete(dso);
1312 return -1;
936} 1313}
937 1314
938LIST_HEAD(dsos); 1315LIST_HEAD(dsos);
939struct dso *kernel_dso;
940struct dso *vdso; 1316struct dso *vdso;
941struct dso *hypervisor_dso;
942 1317
943const char *vmlinux_name = "vmlinux"; 1318const char *vmlinux_name = "vmlinux";
944int modules; 1319int modules;
@@ -970,7 +1345,7 @@ struct dso *dsos__findnew(const char *name)
970 if (!dso) 1345 if (!dso)
971 goto out_delete_dso; 1346 goto out_delete_dso;
972 1347
973 nr = dso__load(dso, NULL, verbose); 1348 nr = dso__load(dso, NULL, NULL, verbose);
974 if (nr < 0) { 1349 if (nr < 0) {
975 eprintf("Failed to open: %s\n", name); 1350 eprintf("Failed to open: %s\n", name);
976 goto out_delete_dso; 1351 goto out_delete_dso;
@@ -995,43 +1370,20 @@ void dsos__fprintf(FILE *fp)
995 dso__fprintf(pos, fp); 1370 dso__fprintf(pos, fp);
996} 1371}
997 1372
998static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
999{
1000 return dso__find_symbol(dso, ip);
1001}
1002
1003int load_kernel(void) 1373int load_kernel(void)
1004{ 1374{
1005 int err; 1375 if (dsos__load_kernel(vmlinux_name, 0, NULL, verbose, modules) <= 0)
1006
1007 kernel_dso = dso__new("[kernel]", 0);
1008 if (!kernel_dso)
1009 return -1; 1376 return -1;
1010 1377
1011 err = dso__load_kernel(kernel_dso, vmlinux_name, NULL, verbose, modules);
1012 if (err <= 0) {
1013 dso__delete(kernel_dso);
1014 kernel_dso = NULL;
1015 } else
1016 dsos__add(kernel_dso);
1017
1018 vdso = dso__new("[vdso]", 0); 1378 vdso = dso__new("[vdso]", 0);
1019 if (!vdso) 1379 if (!vdso)
1020 return -1; 1380 return -1;
1021 1381
1022 vdso->find_symbol = vdso__find_symbol;
1023
1024 dsos__add(vdso); 1382 dsos__add(vdso);
1025 1383
1026 hypervisor_dso = dso__new("[hypervisor]", 0); 1384 return 0;
1027 if (!hypervisor_dso)
1028 return -1;
1029 dsos__add(hypervisor_dso);
1030
1031 return err;
1032} 1385}
1033 1386
1034
1035void symbol__init(void) 1387void symbol__init(void)
1036{ 1388{
1037 elf_version(EV_CURRENT); 1389 elf_version(EV_CURRENT);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 6e8490716408..2e4522edeb07 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -1,11 +1,10 @@
1#ifndef _PERF_SYMBOL_ 1#ifndef __PERF_SYMBOL
2#define _PERF_SYMBOL_ 1 2#define __PERF_SYMBOL 1
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include "types.h" 5#include "types.h"
6#include <linux/list.h> 6#include <linux/list.h>
7#include <linux/rbtree.h> 7#include <linux/rbtree.h>
8#include "module.h"
9#include "event.h" 8#include "event.h"
10 9
11#ifdef HAVE_CPLUS_DEMANGLE 10#ifdef HAVE_CPLUS_DEMANGLE
@@ -36,10 +35,8 @@ struct symbol {
36 struct rb_node rb_node; 35 struct rb_node rb_node;
37 u64 start; 36 u64 start;
38 u64 end; 37 u64 end;
39 u64 obj_start;
40 u64 hist_sum; 38 u64 hist_sum;
41 u64 *hist; 39 u64 *hist;
42 struct module *module;
43 void *priv; 40 void *priv;
44 char name[0]; 41 char name[0];
45}; 42};
@@ -52,12 +49,14 @@ struct dso {
52 unsigned char adjust_symbols; 49 unsigned char adjust_symbols;
53 unsigned char slen_calculated; 50 unsigned char slen_calculated;
54 unsigned char origin; 51 unsigned char origin;
52 const char *short_name;
53 char *long_name;
55 char name[0]; 54 char name[0];
56}; 55};
57 56
58extern const char *sym_hist_filter; 57extern const char *sym_hist_filter;
59 58
60typedef int (*symbol_filter_t)(struct dso *self, struct symbol *sym); 59typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
61 60
62struct dso *dso__new(const char *name, unsigned int sym_priv_size); 61struct dso *dso__new(const char *name, unsigned int sym_priv_size);
63void dso__delete(struct dso *self); 62void dso__delete(struct dso *self);
@@ -69,10 +68,10 @@ static inline void *dso__sym_priv(struct dso *self, struct symbol *sym)
69 68
70struct symbol *dso__find_symbol(struct dso *self, u64 ip); 69struct symbol *dso__find_symbol(struct dso *self, u64 ip);
71 70
72int dso__load_kernel(struct dso *self, const char *vmlinux, 71int dsos__load_kernel(const char *vmlinux, unsigned int sym_priv_size,
73 symbol_filter_t filter, int verbose, int modules); 72 symbol_filter_t filter, int verbose, int modules);
74int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose); 73int dso__load(struct dso *self, struct map *map, symbol_filter_t filter,
75int dso__load(struct dso *self, symbol_filter_t filter, int verbose); 74 int verbose);
76struct dso *dsos__findnew(const char *name); 75struct dso *dsos__findnew(const char *name);
77void dsos__fprintf(FILE *fp); 76void dsos__fprintf(FILE *fp);
78 77
@@ -84,9 +83,8 @@ int load_kernel(void);
84void symbol__init(void); 83void symbol__init(void);
85 84
86extern struct list_head dsos; 85extern struct list_head dsos;
87extern struct dso *kernel_dso; 86extern struct map *kernel_map;
88extern struct dso *vdso; 87extern struct dso *vdso;
89extern struct dso *hypervisor_dso;
90extern const char *vmlinux_name; 88extern const char *vmlinux_name;
91extern int modules; 89extern int modules;
92#endif /* _PERF_SYMBOL_ */ 90#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 45efb5db0d19..f53fad7c0a8d 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -6,6 +6,9 @@
6#include "util.h" 6#include "util.h"
7#include "debug.h" 7#include "debug.h"
8 8
9static struct rb_root threads;
10static struct thread *last_match;
11
9static struct thread *thread__new(pid_t pid) 12static struct thread *thread__new(pid_t pid)
10{ 13{
11 struct thread *self = calloc(1, sizeof(*self)); 14 struct thread *self = calloc(1, sizeof(*self));
@@ -15,7 +18,8 @@ static struct thread *thread__new(pid_t pid)
15 self->comm = malloc(32); 18 self->comm = malloc(32);
16 if (self->comm) 19 if (self->comm)
17 snprintf(self->comm, 32, ":%d", self->pid); 20 snprintf(self->comm, 32, ":%d", self->pid);
18 INIT_LIST_HEAD(&self->maps); 21 self->maps = RB_ROOT;
22 INIT_LIST_HEAD(&self->removed_maps);
19 } 23 }
20 24
21 return self; 25 return self;
@@ -31,19 +35,27 @@ int thread__set_comm(struct thread *self, const char *comm)
31 35
32static size_t thread__fprintf(struct thread *self, FILE *fp) 36static size_t thread__fprintf(struct thread *self, FILE *fp)
33{ 37{
38 struct rb_node *nd;
34 struct map *pos; 39 struct map *pos;
35 size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); 40 size_t ret = fprintf(fp, "Thread %d %s\nCurrent maps:\n",
41 self->pid, self->comm);
42
43 for (nd = rb_first(&self->maps); nd; nd = rb_next(nd)) {
44 pos = rb_entry(nd, struct map, rb_node);
45 ret += map__fprintf(pos, fp);
46 }
47
48 ret = fprintf(fp, "Removed maps:\n");
36 49
37 list_for_each_entry(pos, &self->maps, node) 50 list_for_each_entry(pos, &self->removed_maps, node)
38 ret += map__fprintf(pos, fp); 51 ret += map__fprintf(pos, fp);
39 52
40 return ret; 53 return ret;
41} 54}
42 55
43struct thread * 56struct thread *threads__findnew(pid_t pid)
44threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
45{ 57{
46 struct rb_node **p = &threads->rb_node; 58 struct rb_node **p = &threads.rb_node;
47 struct rb_node *parent = NULL; 59 struct rb_node *parent = NULL;
48 struct thread *th; 60 struct thread *th;
49 61
@@ -52,15 +64,15 @@ threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
52 * so most of the time we dont have to look up 64 * so most of the time we dont have to look up
53 * the full rbtree: 65 * the full rbtree:
54 */ 66 */
55 if (*last_match && (*last_match)->pid == pid) 67 if (last_match && last_match->pid == pid)
56 return *last_match; 68 return last_match;
57 69
58 while (*p != NULL) { 70 while (*p != NULL) {
59 parent = *p; 71 parent = *p;
60 th = rb_entry(parent, struct thread, rb_node); 72 th = rb_entry(parent, struct thread, rb_node);
61 73
62 if (th->pid == pid) { 74 if (th->pid == pid) {
63 *last_match = th; 75 last_match = th;
64 return th; 76 return th;
65 } 77 }
66 78
@@ -73,17 +85,16 @@ threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
73 th = thread__new(pid); 85 th = thread__new(pid);
74 if (th != NULL) { 86 if (th != NULL) {
75 rb_link_node(&th->rb_node, parent, p); 87 rb_link_node(&th->rb_node, parent, p);
76 rb_insert_color(&th->rb_node, threads); 88 rb_insert_color(&th->rb_node, &threads);
77 *last_match = th; 89 last_match = th;
78 } 90 }
79 91
80 return th; 92 return th;
81} 93}
82 94
83struct thread * 95struct thread *register_idle_thread(void)
84register_idle_thread(struct rb_root *threads, struct thread **last_match)
85{ 96{
86 struct thread *thread = threads__findnew(0, threads, last_match); 97 struct thread *thread = threads__findnew(0);
87 98
88 if (!thread || thread__set_comm(thread, "swapper")) { 99 if (!thread || thread__set_comm(thread, "swapper")) {
89 fprintf(stderr, "problem inserting idle task.\n"); 100 fprintf(stderr, "problem inserting idle task.\n");
@@ -93,42 +104,82 @@ register_idle_thread(struct rb_root *threads, struct thread **last_match)
93 return thread; 104 return thread;
94} 105}
95 106
96void thread__insert_map(struct thread *self, struct map *map) 107static void thread__remove_overlappings(struct thread *self, struct map *map)
97{ 108{
98 struct map *pos, *tmp; 109 struct rb_node *next = rb_first(&self->maps);
99 110
100 list_for_each_entry_safe(pos, tmp, &self->maps, node) { 111 while (next) {
101 if (map__overlap(pos, map)) { 112 struct map *pos = rb_entry(next, struct map, rb_node);
102 if (verbose >= 2) { 113 next = rb_next(&pos->rb_node);
103 printf("overlapping maps:\n"); 114
104 map__fprintf(map, stdout); 115 if (!map__overlap(pos, map))
105 map__fprintf(pos, stdout); 116 continue;
106 } 117
107 118 if (verbose >= 2) {
108 if (map->start <= pos->start && map->end > pos->start) 119 printf("overlapping maps:\n");
109 pos->start = map->end; 120 map__fprintf(map, stdout);
110 121 map__fprintf(pos, stdout);
111 if (map->end >= pos->end && map->start < pos->end)
112 pos->end = map->start;
113
114 if (verbose >= 2) {
115 printf("after collision:\n");
116 map__fprintf(pos, stdout);
117 }
118
119 if (pos->start >= pos->end) {
120 list_del_init(&pos->node);
121 free(pos);
122 }
123 } 122 }
123
124 rb_erase(&pos->rb_node, &self->maps);
125 /*
126 * We may have references to this map, for instance in some
127 * hist_entry instances, so just move them to a separate
128 * list.
129 */
130 list_add_tail(&pos->node, &self->removed_maps);
131 }
132}
133
134void maps__insert(struct rb_root *maps, struct map *map)
135{
136 struct rb_node **p = &maps->rb_node;
137 struct rb_node *parent = NULL;
138 const u64 ip = map->start;
139 struct map *m;
140
141 while (*p != NULL) {
142 parent = *p;
143 m = rb_entry(parent, struct map, rb_node);
144 if (ip < m->start)
145 p = &(*p)->rb_left;
146 else
147 p = &(*p)->rb_right;
148 }
149
150 rb_link_node(&map->rb_node, parent, p);
151 rb_insert_color(&map->rb_node, maps);
152}
153
154struct map *maps__find(struct rb_root *maps, u64 ip)
155{
156 struct rb_node **p = &maps->rb_node;
157 struct rb_node *parent = NULL;
158 struct map *m;
159
160 while (*p != NULL) {
161 parent = *p;
162 m = rb_entry(parent, struct map, rb_node);
163 if (ip < m->start)
164 p = &(*p)->rb_left;
165 else if (ip > m->end)
166 p = &(*p)->rb_right;
167 else
168 return m;
124 } 169 }
125 170
126 list_add_tail(&map->node, &self->maps); 171 return NULL;
172}
173
174void thread__insert_map(struct thread *self, struct map *map)
175{
176 thread__remove_overlappings(self, map);
177 maps__insert(&self->maps, map);
127} 178}
128 179
129int thread__fork(struct thread *self, struct thread *parent) 180int thread__fork(struct thread *self, struct thread *parent)
130{ 181{
131 struct map *map; 182 struct rb_node *nd;
132 183
133 if (self->comm) 184 if (self->comm)
134 free(self->comm); 185 free(self->comm);
@@ -136,7 +187,8 @@ int thread__fork(struct thread *self, struct thread *parent)
136 if (!self->comm) 187 if (!self->comm)
137 return -ENOMEM; 188 return -ENOMEM;
138 189
139 list_for_each_entry(map, &parent->maps, node) { 190 for (nd = rb_first(&parent->maps); nd; nd = rb_next(nd)) {
191 struct map *map = rb_entry(nd, struct map, rb_node);
140 struct map *new = map__clone(map); 192 struct map *new = map__clone(map);
141 if (!new) 193 if (!new)
142 return -ENOMEM; 194 return -ENOMEM;
@@ -146,26 +198,12 @@ int thread__fork(struct thread *self, struct thread *parent)
146 return 0; 198 return 0;
147} 199}
148 200
149struct map *thread__find_map(struct thread *self, u64 ip) 201size_t threads__fprintf(FILE *fp)
150{
151 struct map *pos;
152
153 if (self == NULL)
154 return NULL;
155
156 list_for_each_entry(pos, &self->maps, node)
157 if (ip >= pos->start && ip <= pos->end)
158 return pos;
159
160 return NULL;
161}
162
163size_t threads__fprintf(FILE *fp, struct rb_root *threads)
164{ 202{
165 size_t ret = 0; 203 size_t ret = 0;
166 struct rb_node *nd; 204 struct rb_node *nd;
167 205
168 for (nd = rb_first(threads); nd; nd = rb_next(nd)) { 206 for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
169 struct thread *pos = rb_entry(nd, struct thread, rb_node); 207 struct thread *pos = rb_entry(nd, struct thread, rb_node);
170 208
171 ret += thread__fprintf(pos, fp); 209 ret += thread__fprintf(pos, fp);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 32aea3c1c2ad..1abef3b7455d 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -1,22 +1,35 @@
1#ifndef __PERF_THREAD_H
2#define __PERF_THREAD_H
3
1#include <linux/rbtree.h> 4#include <linux/rbtree.h>
2#include <linux/list.h>
3#include <unistd.h> 5#include <unistd.h>
4#include "symbol.h" 6#include "symbol.h"
5 7
6struct thread { 8struct thread {
7 struct rb_node rb_node; 9 struct rb_node rb_node;
8 struct list_head maps; 10 struct rb_root maps;
11 struct list_head removed_maps;
9 pid_t pid; 12 pid_t pid;
10 char shortname[3]; 13 char shortname[3];
11 char *comm; 14 char *comm;
12}; 15};
13 16
14int thread__set_comm(struct thread *self, const char *comm); 17int thread__set_comm(struct thread *self, const char *comm);
15struct thread * 18struct thread *threads__findnew(pid_t pid);
16threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match); 19struct thread *register_idle_thread(void);
17struct thread *
18register_idle_thread(struct rb_root *threads, struct thread **last_match);
19void thread__insert_map(struct thread *self, struct map *map); 20void thread__insert_map(struct thread *self, struct map *map);
20int thread__fork(struct thread *self, struct thread *parent); 21int thread__fork(struct thread *self, struct thread *parent);
21struct map *thread__find_map(struct thread *self, u64 ip); 22size_t threads__fprintf(FILE *fp);
22size_t threads__fprintf(FILE *fp, struct rb_root *threads); 23
24void maps__insert(struct rb_root *maps, struct map *map);
25struct map *maps__find(struct rb_root *maps, u64 ip);
26
27struct symbol *kernel_maps__find_symbol(const u64 ip, struct map **mapp);
28struct map *kernel_maps__find_by_dso_name(const char *name);
29
30static inline struct map *thread__find_map(struct thread *self, u64 ip)
31{
32 return self ? maps__find(&self->maps, ip) : NULL;
33}
34
35#endif /* __PERF_THREAD_H */
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index af4b0573b37f..831052d4b4fb 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -496,14 +496,12 @@ get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events)
496 496
497 return path.next; 497 return path.next;
498} 498}
499void read_tracing_data(struct perf_event_attr *pattrs, int nb_events) 499void read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events)
500{ 500{
501 char buf[BUFSIZ]; 501 char buf[BUFSIZ];
502 struct tracepoint_path *tps; 502 struct tracepoint_path *tps;
503 503
504 output_fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644); 504 output_fd = fd;
505 if (output_fd < 0)
506 die("creating file '%s'", output_file);
507 505
508 buf[0] = 23; 506 buf[0] = 23;
509 buf[1] = 8; 507 buf[1] = 8;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index f6a8437141c8..4b61b497040e 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -40,6 +40,8 @@ int header_page_size_size;
40int header_page_data_offset; 40int header_page_data_offset;
41int header_page_data_size; 41int header_page_data_size;
42 42
43int latency_format;
44
43static char *input_buf; 45static char *input_buf;
44static unsigned long long input_buf_ptr; 46static unsigned long long input_buf_ptr;
45static unsigned long long input_buf_siz; 47static unsigned long long input_buf_siz;
@@ -284,18 +286,16 @@ void parse_ftrace_printk(char *file, unsigned int size __unused)
284 char *line; 286 char *line;
285 char *next = NULL; 287 char *next = NULL;
286 char *addr_str; 288 char *addr_str;
287 int ret; 289 char *fmt;
288 int i; 290 int i;
289 291
290 line = strtok_r(file, "\n", &next); 292 line = strtok_r(file, "\n", &next);
291 while (line) { 293 while (line) {
292 item = malloc_or_die(sizeof(*item)); 294 item = malloc_or_die(sizeof(*item));
293 ret = sscanf(line, "%as : %as", 295 addr_str = strtok_r(line, ":", &fmt);
294 (float *)(void *)&addr_str, /* workaround gcc warning */
295 (float *)(void *)&item->printk);
296 item->addr = strtoull(addr_str, NULL, 16); 296 item->addr = strtoull(addr_str, NULL, 16);
297 free(addr_str); 297 /* fmt still has a space, skip it */
298 298 item->printk = strdup(fmt+1);
299 item->next = list; 299 item->next = list;
300 list = item; 300 list = item;
301 line = strtok_r(NULL, "\n", &next); 301 line = strtok_r(NULL, "\n", &next);
@@ -522,7 +522,10 @@ static enum event_type __read_token(char **tok)
522 last_ch = ch; 522 last_ch = ch;
523 ch = __read_char(); 523 ch = __read_char();
524 buf[i++] = ch; 524 buf[i++] = ch;
525 } while (ch != quote_ch && last_ch != '\\'); 525 /* the '\' '\' will cancel itself */
526 if (ch == '\\' && last_ch == '\\')
527 last_ch = 0;
528 } while (ch != quote_ch || last_ch == '\\');
526 /* remove the last quote */ 529 /* remove the last quote */
527 i--; 530 i--;
528 goto out; 531 goto out;
@@ -610,7 +613,7 @@ static enum event_type read_token_item(char **tok)
610static int test_type(enum event_type type, enum event_type expect) 613static int test_type(enum event_type type, enum event_type expect)
611{ 614{
612 if (type != expect) { 615 if (type != expect) {
613 die("Error: expected type %d but read %d", 616 warning("Error: expected type %d but read %d",
614 expect, type); 617 expect, type);
615 return -1; 618 return -1;
616 } 619 }
@@ -618,16 +621,16 @@ static int test_type(enum event_type type, enum event_type expect)
618} 621}
619 622
620static int test_type_token(enum event_type type, char *token, 623static int test_type_token(enum event_type type, char *token,
621 enum event_type expect, char *expect_tok) 624 enum event_type expect, const char *expect_tok)
622{ 625{
623 if (type != expect) { 626 if (type != expect) {
624 die("Error: expected type %d but read %d", 627 warning("Error: expected type %d but read %d",
625 expect, type); 628 expect, type);
626 return -1; 629 return -1;
627 } 630 }
628 631
629 if (strcmp(token, expect_tok) != 0) { 632 if (strcmp(token, expect_tok) != 0) {
630 die("Error: expected '%s' but read '%s'", 633 warning("Error: expected '%s' but read '%s'",
631 expect_tok, token); 634 expect_tok, token);
632 return -1; 635 return -1;
633 } 636 }
@@ -650,7 +653,7 @@ static int read_expect_type(enum event_type expect, char **tok)
650 return __read_expect_type(expect, tok, 1); 653 return __read_expect_type(expect, tok, 1);
651} 654}
652 655
653static int __read_expected(enum event_type expect, char *str, int newline_ok) 656static int __read_expected(enum event_type expect, const char *str, int newline_ok)
654{ 657{
655 enum event_type type; 658 enum event_type type;
656 char *token; 659 char *token;
@@ -665,15 +668,15 @@ static int __read_expected(enum event_type expect, char *str, int newline_ok)
665 668
666 free_token(token); 669 free_token(token);
667 670
668 return 0; 671 return ret;
669} 672}
670 673
671static int read_expected(enum event_type expect, char *str) 674static int read_expected(enum event_type expect, const char *str)
672{ 675{
673 return __read_expected(expect, str, 1); 676 return __read_expected(expect, str, 1);
674} 677}
675 678
676static int read_expected_item(enum event_type expect, char *str) 679static int read_expected_item(enum event_type expect, const char *str)
677{ 680{
678 return __read_expected(expect, str, 0); 681 return __read_expected(expect, str, 0);
679} 682}
@@ -682,10 +685,10 @@ static char *event_read_name(void)
682{ 685{
683 char *token; 686 char *token;
684 687
685 if (read_expected(EVENT_ITEM, (char *)"name") < 0) 688 if (read_expected(EVENT_ITEM, "name") < 0)
686 return NULL; 689 return NULL;
687 690
688 if (read_expected(EVENT_OP, (char *)":") < 0) 691 if (read_expected(EVENT_OP, ":") < 0)
689 return NULL; 692 return NULL;
690 693
691 if (read_expect_type(EVENT_ITEM, &token) < 0) 694 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -703,10 +706,10 @@ static int event_read_id(void)
703 char *token; 706 char *token;
704 int id; 707 int id;
705 708
706 if (read_expected_item(EVENT_ITEM, (char *)"ID") < 0) 709 if (read_expected_item(EVENT_ITEM, "ID") < 0)
707 return -1; 710 return -1;
708 711
709 if (read_expected(EVENT_OP, (char *)":") < 0) 712 if (read_expected(EVENT_OP, ":") < 0)
710 return -1; 713 return -1;
711 714
712 if (read_expect_type(EVENT_ITEM, &token) < 0) 715 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -721,6 +724,24 @@ static int event_read_id(void)
721 return -1; 724 return -1;
722} 725}
723 726
727static int field_is_string(struct format_field *field)
728{
729 if ((field->flags & FIELD_IS_ARRAY) &&
730 (!strstr(field->type, "char") || !strstr(field->type, "u8") ||
731 !strstr(field->type, "s8")))
732 return 1;
733
734 return 0;
735}
736
737static int field_is_dynamic(struct format_field *field)
738{
739 if (!strcmp(field->type, "__data_loc"))
740 return 1;
741
742 return 0;
743}
744
724static int event_read_fields(struct event *event, struct format_field **fields) 745static int event_read_fields(struct event *event, struct format_field **fields)
725{ 746{
726 struct format_field *field = NULL; 747 struct format_field *field = NULL;
@@ -738,7 +759,7 @@ static int event_read_fields(struct event *event, struct format_field **fields)
738 759
739 count++; 760 count++;
740 761
741 if (test_type_token(type, token, EVENT_ITEM, (char *)"field")) 762 if (test_type_token(type, token, EVENT_ITEM, "field"))
742 goto fail; 763 goto fail;
743 free_token(token); 764 free_token(token);
744 765
@@ -753,7 +774,7 @@ static int event_read_fields(struct event *event, struct format_field **fields)
753 type = read_token(&token); 774 type = read_token(&token);
754 } 775 }
755 776
756 if (test_type_token(type, token, EVENT_OP, (char *)":") < 0) 777 if (test_type_token(type, token, EVENT_OP, ":") < 0)
757 return -1; 778 return -1;
758 779
759 if (read_expect_type(EVENT_ITEM, &token) < 0) 780 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -865,14 +886,20 @@ static int event_read_fields(struct event *event, struct format_field **fields)
865 free(brackets); 886 free(brackets);
866 } 887 }
867 888
868 if (test_type_token(type, token, EVENT_OP, (char *)";")) 889 if (field_is_string(field)) {
890 field->flags |= FIELD_IS_STRING;
891 if (field_is_dynamic(field))
892 field->flags |= FIELD_IS_DYNAMIC;
893 }
894
895 if (test_type_token(type, token, EVENT_OP, ";"))
869 goto fail; 896 goto fail;
870 free_token(token); 897 free_token(token);
871 898
872 if (read_expected(EVENT_ITEM, (char *)"offset") < 0) 899 if (read_expected(EVENT_ITEM, "offset") < 0)
873 goto fail_expect; 900 goto fail_expect;
874 901
875 if (read_expected(EVENT_OP, (char *)":") < 0) 902 if (read_expected(EVENT_OP, ":") < 0)
876 goto fail_expect; 903 goto fail_expect;
877 904
878 if (read_expect_type(EVENT_ITEM, &token)) 905 if (read_expect_type(EVENT_ITEM, &token))
@@ -880,13 +907,13 @@ static int event_read_fields(struct event *event, struct format_field **fields)
880 field->offset = strtoul(token, NULL, 0); 907 field->offset = strtoul(token, NULL, 0);
881 free_token(token); 908 free_token(token);
882 909
883 if (read_expected(EVENT_OP, (char *)";") < 0) 910 if (read_expected(EVENT_OP, ";") < 0)
884 goto fail_expect; 911 goto fail_expect;
885 912
886 if (read_expected(EVENT_ITEM, (char *)"size") < 0) 913 if (read_expected(EVENT_ITEM, "size") < 0)
887 goto fail_expect; 914 goto fail_expect;
888 915
889 if (read_expected(EVENT_OP, (char *)":") < 0) 916 if (read_expected(EVENT_OP, ":") < 0)
890 goto fail_expect; 917 goto fail_expect;
891 918
892 if (read_expect_type(EVENT_ITEM, &token)) 919 if (read_expect_type(EVENT_ITEM, &token))
@@ -894,11 +921,33 @@ static int event_read_fields(struct event *event, struct format_field **fields)
894 field->size = strtoul(token, NULL, 0); 921 field->size = strtoul(token, NULL, 0);
895 free_token(token); 922 free_token(token);
896 923
897 if (read_expected(EVENT_OP, (char *)";") < 0) 924 if (read_expected(EVENT_OP, ";") < 0)
898 goto fail_expect; 925 goto fail_expect;
899 926
900 if (read_expect_type(EVENT_NEWLINE, &token) < 0) 927 type = read_token(&token);
901 goto fail; 928 if (type != EVENT_NEWLINE) {
929 /* newer versions of the kernel have a "signed" type */
930 if (test_type_token(type, token, EVENT_ITEM, "signed"))
931 goto fail;
932
933 free_token(token);
934
935 if (read_expected(EVENT_OP, ":") < 0)
936 goto fail_expect;
937
938 if (read_expect_type(EVENT_ITEM, &token))
939 goto fail;
940
941 /* add signed type */
942
943 free_token(token);
944 if (read_expected(EVENT_OP, ";") < 0)
945 goto fail_expect;
946
947 if (read_expect_type(EVENT_NEWLINE, &token))
948 goto fail;
949 }
950
902 free_token(token); 951 free_token(token);
903 952
904 *fields = field; 953 *fields = field;
@@ -921,10 +970,10 @@ static int event_read_format(struct event *event)
921 char *token; 970 char *token;
922 int ret; 971 int ret;
923 972
924 if (read_expected_item(EVENT_ITEM, (char *)"format") < 0) 973 if (read_expected_item(EVENT_ITEM, "format") < 0)
925 return -1; 974 return -1;
926 975
927 if (read_expected(EVENT_OP, (char *)":") < 0) 976 if (read_expected(EVENT_OP, ":") < 0)
928 return -1; 977 return -1;
929 978
930 if (read_expect_type(EVENT_NEWLINE, &token)) 979 if (read_expect_type(EVENT_NEWLINE, &token))
@@ -984,7 +1033,7 @@ process_cond(struct event *event, struct print_arg *top, char **tok)
984 1033
985 *tok = NULL; 1034 *tok = NULL;
986 type = process_arg(event, left, &token); 1035 type = process_arg(event, left, &token);
987 if (test_type_token(type, token, EVENT_OP, (char *)":")) 1036 if (test_type_token(type, token, EVENT_OP, ":"))
988 goto out_free; 1037 goto out_free;
989 1038
990 arg->op.op = token; 1039 arg->op.op = token;
@@ -1004,6 +1053,35 @@ out_free:
1004 return EVENT_ERROR; 1053 return EVENT_ERROR;
1005} 1054}
1006 1055
1056static enum event_type
1057process_array(struct event *event, struct print_arg *top, char **tok)
1058{
1059 struct print_arg *arg;
1060 enum event_type type;
1061 char *token = NULL;
1062
1063 arg = malloc_or_die(sizeof(*arg));
1064 memset(arg, 0, sizeof(*arg));
1065
1066 *tok = NULL;
1067 type = process_arg(event, arg, &token);
1068 if (test_type_token(type, token, EVENT_OP, "]"))
1069 goto out_free;
1070
1071 top->op.right = arg;
1072
1073 free_token(token);
1074 type = read_token_item(&token);
1075 *tok = token;
1076
1077 return type;
1078
1079out_free:
1080 free_token(*tok);
1081 free_arg(arg);
1082 return EVENT_ERROR;
1083}
1084
1007static int get_op_prio(char *op) 1085static int get_op_prio(char *op)
1008{ 1086{
1009 if (!op[1]) { 1087 if (!op[1]) {
@@ -1128,6 +1206,8 @@ process_op(struct event *event, struct print_arg *arg, char **tok)
1128 strcmp(token, "*") == 0 || 1206 strcmp(token, "*") == 0 ||
1129 strcmp(token, "^") == 0 || 1207 strcmp(token, "^") == 0 ||
1130 strcmp(token, "/") == 0 || 1208 strcmp(token, "/") == 0 ||
1209 strcmp(token, "<") == 0 ||
1210 strcmp(token, ">") == 0 ||
1131 strcmp(token, "==") == 0 || 1211 strcmp(token, "==") == 0 ||
1132 strcmp(token, "!=") == 0) { 1212 strcmp(token, "!=") == 0) {
1133 1213
@@ -1144,17 +1224,46 @@ process_op(struct event *event, struct print_arg *arg, char **tok)
1144 1224
1145 right = malloc_or_die(sizeof(*right)); 1225 right = malloc_or_die(sizeof(*right));
1146 1226
1147 type = process_arg(event, right, tok); 1227 type = read_token_item(&token);
1228 *tok = token;
1229
1230 /* could just be a type pointer */
1231 if ((strcmp(arg->op.op, "*") == 0) &&
1232 type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
1233 if (left->type != PRINT_ATOM)
1234 die("bad pointer type");
1235 left->atom.atom = realloc(left->atom.atom,
1236 sizeof(left->atom.atom) + 3);
1237 strcat(left->atom.atom, " *");
1238 *arg = *left;
1239 free(arg);
1240
1241 return type;
1242 }
1243
1244 type = process_arg_token(event, right, tok, type);
1148 1245
1149 arg->op.right = right; 1246 arg->op.right = right;
1150 1247
1248 } else if (strcmp(token, "[") == 0) {
1249
1250 left = malloc_or_die(sizeof(*left));
1251 *left = *arg;
1252
1253 arg->type = PRINT_OP;
1254 arg->op.op = token;
1255 arg->op.left = left;
1256
1257 arg->op.prio = 0;
1258 type = process_array(event, arg, tok);
1259
1151 } else { 1260 } else {
1152 die("unknown op '%s'", token); 1261 warning("unknown op '%s'", token);
1262 event->flags |= EVENT_FL_FAILED;
1153 /* the arg is now the left side */ 1263 /* the arg is now the left side */
1154 return EVENT_NONE; 1264 return EVENT_NONE;
1155 } 1265 }
1156 1266
1157
1158 if (type == EVENT_OP) { 1267 if (type == EVENT_OP) {
1159 int prio; 1268 int prio;
1160 1269
@@ -1178,7 +1287,7 @@ process_entry(struct event *event __unused, struct print_arg *arg,
1178 char *field; 1287 char *field;
1179 char *token; 1288 char *token;
1180 1289
1181 if (read_expected(EVENT_OP, (char *)"->") < 0) 1290 if (read_expected(EVENT_OP, "->") < 0)
1182 return EVENT_ERROR; 1291 return EVENT_ERROR;
1183 1292
1184 if (read_expect_type(EVENT_ITEM, &token) < 0) 1293 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -1338,14 +1447,14 @@ process_fields(struct event *event, struct print_flag_sym **list, char **tok)
1338 do { 1447 do {
1339 free_token(token); 1448 free_token(token);
1340 type = read_token_item(&token); 1449 type = read_token_item(&token);
1341 if (test_type_token(type, token, EVENT_OP, (char *)"{")) 1450 if (test_type_token(type, token, EVENT_OP, "{"))
1342 break; 1451 break;
1343 1452
1344 arg = malloc_or_die(sizeof(*arg)); 1453 arg = malloc_or_die(sizeof(*arg));
1345 1454
1346 free_token(token); 1455 free_token(token);
1347 type = process_arg(event, arg, &token); 1456 type = process_arg(event, arg, &token);
1348 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1457 if (test_type_token(type, token, EVENT_DELIM, ","))
1349 goto out_free; 1458 goto out_free;
1350 1459
1351 field = malloc_or_die(sizeof(*field)); 1460 field = malloc_or_die(sizeof(*field));
@@ -1356,7 +1465,7 @@ process_fields(struct event *event, struct print_flag_sym **list, char **tok)
1356 1465
1357 free_token(token); 1466 free_token(token);
1358 type = process_arg(event, arg, &token); 1467 type = process_arg(event, arg, &token);
1359 if (test_type_token(type, token, EVENT_OP, (char *)"}")) 1468 if (test_type_token(type, token, EVENT_OP, "}"))
1360 goto out_free; 1469 goto out_free;
1361 1470
1362 value = arg_eval(arg); 1471 value = arg_eval(arg);
@@ -1391,13 +1500,13 @@ process_flags(struct event *event, struct print_arg *arg, char **tok)
1391 memset(arg, 0, sizeof(*arg)); 1500 memset(arg, 0, sizeof(*arg));
1392 arg->type = PRINT_FLAGS; 1501 arg->type = PRINT_FLAGS;
1393 1502
1394 if (read_expected_item(EVENT_DELIM, (char *)"(") < 0) 1503 if (read_expected_item(EVENT_DELIM, "(") < 0)
1395 return EVENT_ERROR; 1504 return EVENT_ERROR;
1396 1505
1397 field = malloc_or_die(sizeof(*field)); 1506 field = malloc_or_die(sizeof(*field));
1398 1507
1399 type = process_arg(event, field, &token); 1508 type = process_arg(event, field, &token);
1400 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1509 if (test_type_token(type, token, EVENT_DELIM, ","))
1401 goto out_free; 1510 goto out_free;
1402 1511
1403 arg->flags.field = field; 1512 arg->flags.field = field;
@@ -1408,11 +1517,11 @@ process_flags(struct event *event, struct print_arg *arg, char **tok)
1408 type = read_token_item(&token); 1517 type = read_token_item(&token);
1409 } 1518 }
1410 1519
1411 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1520 if (test_type_token(type, token, EVENT_DELIM, ","))
1412 goto out_free; 1521 goto out_free;
1413 1522
1414 type = process_fields(event, &arg->flags.flags, &token); 1523 type = process_fields(event, &arg->flags.flags, &token);
1415 if (test_type_token(type, token, EVENT_DELIM, (char *)")")) 1524 if (test_type_token(type, token, EVENT_DELIM, ")"))
1416 goto out_free; 1525 goto out_free;
1417 1526
1418 free_token(token); 1527 free_token(token);
@@ -1434,19 +1543,19 @@ process_symbols(struct event *event, struct print_arg *arg, char **tok)
1434 memset(arg, 0, sizeof(*arg)); 1543 memset(arg, 0, sizeof(*arg));
1435 arg->type = PRINT_SYMBOL; 1544 arg->type = PRINT_SYMBOL;
1436 1545
1437 if (read_expected_item(EVENT_DELIM, (char *)"(") < 0) 1546 if (read_expected_item(EVENT_DELIM, "(") < 0)
1438 return EVENT_ERROR; 1547 return EVENT_ERROR;
1439 1548
1440 field = malloc_or_die(sizeof(*field)); 1549 field = malloc_or_die(sizeof(*field));
1441 1550
1442 type = process_arg(event, field, &token); 1551 type = process_arg(event, field, &token);
1443 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1552 if (test_type_token(type, token, EVENT_DELIM, ","))
1444 goto out_free; 1553 goto out_free;
1445 1554
1446 arg->symbol.field = field; 1555 arg->symbol.field = field;
1447 1556
1448 type = process_fields(event, &arg->symbol.symbols, &token); 1557 type = process_fields(event, &arg->symbol.symbols, &token);
1449 if (test_type_token(type, token, EVENT_DELIM, (char *)")")) 1558 if (test_type_token(type, token, EVENT_DELIM, ")"))
1450 goto out_free; 1559 goto out_free;
1451 1560
1452 free_token(token); 1561 free_token(token);
@@ -1463,7 +1572,6 @@ process_paren(struct event *event, struct print_arg *arg, char **tok)
1463{ 1572{
1464 struct print_arg *item_arg; 1573 struct print_arg *item_arg;
1465 enum event_type type; 1574 enum event_type type;
1466 int ptr_cast = 0;
1467 char *token; 1575 char *token;
1468 1576
1469 type = process_arg(event, arg, &token); 1577 type = process_arg(event, arg, &token);
@@ -1471,28 +1579,13 @@ process_paren(struct event *event, struct print_arg *arg, char **tok)
1471 if (type == EVENT_ERROR) 1579 if (type == EVENT_ERROR)
1472 return EVENT_ERROR; 1580 return EVENT_ERROR;
1473 1581
1474 if (type == EVENT_OP) { 1582 if (type == EVENT_OP)
1475 /* handle the ptr casts */ 1583 type = process_op(event, arg, &token);
1476 if (!strcmp(token, "*")) {
1477 /*
1478 * FIXME: should we zapp whitespaces before ')' ?
1479 * (may require a peek_token_item())
1480 */
1481 if (__peek_char() == ')') {
1482 ptr_cast = 1;
1483 free_token(token);
1484 type = read_token_item(&token);
1485 }
1486 }
1487 if (!ptr_cast) {
1488 type = process_op(event, arg, &token);
1489 1584
1490 if (type == EVENT_ERROR) 1585 if (type == EVENT_ERROR)
1491 return EVENT_ERROR; 1586 return EVENT_ERROR;
1492 }
1493 }
1494 1587
1495 if (test_type_token(type, token, EVENT_DELIM, (char *)")")) { 1588 if (test_type_token(type, token, EVENT_DELIM, ")")) {
1496 free_token(token); 1589 free_token(token);
1497 return EVENT_ERROR; 1590 return EVENT_ERROR;
1498 } 1591 }
@@ -1516,13 +1609,6 @@ process_paren(struct event *event, struct print_arg *arg, char **tok)
1516 item_arg = malloc_or_die(sizeof(*item_arg)); 1609 item_arg = malloc_or_die(sizeof(*item_arg));
1517 1610
1518 arg->type = PRINT_TYPE; 1611 arg->type = PRINT_TYPE;
1519 if (ptr_cast) {
1520 char *old = arg->atom.atom;
1521
1522 arg->atom.atom = malloc_or_die(strlen(old + 3));
1523 sprintf(arg->atom.atom, "%s *", old);
1524 free(old);
1525 }
1526 arg->typecast.type = arg->atom.atom; 1612 arg->typecast.type = arg->atom.atom;
1527 arg->typecast.item = item_arg; 1613 arg->typecast.item = item_arg;
1528 type = process_arg_token(event, item_arg, &token, type); 1614 type = process_arg_token(event, item_arg, &token, type);
@@ -1540,7 +1626,7 @@ process_str(struct event *event __unused, struct print_arg *arg, char **tok)
1540 enum event_type type; 1626 enum event_type type;
1541 char *token; 1627 char *token;
1542 1628
1543 if (read_expected(EVENT_DELIM, (char *)"(") < 0) 1629 if (read_expected(EVENT_DELIM, "(") < 0)
1544 return EVENT_ERROR; 1630 return EVENT_ERROR;
1545 1631
1546 if (read_expect_type(EVENT_ITEM, &token) < 0) 1632 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -1550,7 +1636,7 @@ process_str(struct event *event __unused, struct print_arg *arg, char **tok)
1550 arg->string.string = token; 1636 arg->string.string = token;
1551 arg->string.offset = -1; 1637 arg->string.offset = -1;
1552 1638
1553 if (read_expected(EVENT_DELIM, (char *)")") < 0) 1639 if (read_expected(EVENT_DELIM, ")") < 0)
1554 return EVENT_ERROR; 1640 return EVENT_ERROR;
1555 1641
1556 type = read_token(&token); 1642 type = read_token(&token);
@@ -1637,12 +1723,18 @@ process_arg_token(struct event *event, struct print_arg *arg,
1637 1723
1638static int event_read_print_args(struct event *event, struct print_arg **list) 1724static int event_read_print_args(struct event *event, struct print_arg **list)
1639{ 1725{
1640 enum event_type type; 1726 enum event_type type = EVENT_ERROR;
1641 struct print_arg *arg; 1727 struct print_arg *arg;
1642 char *token; 1728 char *token;
1643 int args = 0; 1729 int args = 0;
1644 1730
1645 do { 1731 do {
1732 if (type == EVENT_NEWLINE) {
1733 free_token(token);
1734 type = read_token_item(&token);
1735 continue;
1736 }
1737
1646 arg = malloc_or_die(sizeof(*arg)); 1738 arg = malloc_or_die(sizeof(*arg));
1647 memset(arg, 0, sizeof(*arg)); 1739 memset(arg, 0, sizeof(*arg));
1648 1740
@@ -1683,18 +1775,19 @@ static int event_read_print(struct event *event)
1683 char *token; 1775 char *token;
1684 int ret; 1776 int ret;
1685 1777
1686 if (read_expected_item(EVENT_ITEM, (char *)"print") < 0) 1778 if (read_expected_item(EVENT_ITEM, "print") < 0)
1687 return -1; 1779 return -1;
1688 1780
1689 if (read_expected(EVENT_ITEM, (char *)"fmt") < 0) 1781 if (read_expected(EVENT_ITEM, "fmt") < 0)
1690 return -1; 1782 return -1;
1691 1783
1692 if (read_expected(EVENT_OP, (char *)":") < 0) 1784 if (read_expected(EVENT_OP, ":") < 0)
1693 return -1; 1785 return -1;
1694 1786
1695 if (read_expect_type(EVENT_DQUOTE, &token) < 0) 1787 if (read_expect_type(EVENT_DQUOTE, &token) < 0)
1696 goto fail; 1788 goto fail;
1697 1789
1790 concat:
1698 event->print_fmt.format = token; 1791 event->print_fmt.format = token;
1699 event->print_fmt.args = NULL; 1792 event->print_fmt.args = NULL;
1700 1793
@@ -1704,7 +1797,22 @@ static int event_read_print(struct event *event)
1704 if (type == EVENT_NONE) 1797 if (type == EVENT_NONE)
1705 return 0; 1798 return 0;
1706 1799
1707 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1800 /* Handle concatination of print lines */
1801 if (type == EVENT_DQUOTE) {
1802 char *cat;
1803
1804 cat = malloc_or_die(strlen(event->print_fmt.format) +
1805 strlen(token) + 1);
1806 strcpy(cat, event->print_fmt.format);
1807 strcat(cat, token);
1808 free_token(token);
1809 free_token(event->print_fmt.format);
1810 event->print_fmt.format = NULL;
1811 token = cat;
1812 goto concat;
1813 }
1814
1815 if (test_type_token(type, token, EVENT_DELIM, ","))
1708 goto fail; 1816 goto fail;
1709 1817
1710 free_token(token); 1818 free_token(token);
@@ -1713,7 +1821,7 @@ static int event_read_print(struct event *event)
1713 if (ret < 0) 1821 if (ret < 0)
1714 return -1; 1822 return -1;
1715 1823
1716 return 0; 1824 return ret;
1717 1825
1718 fail: 1826 fail:
1719 free_token(token); 1827 free_token(token);
@@ -1822,37 +1930,67 @@ static int get_common_info(const char *type, int *offset, int *size)
1822 return 0; 1930 return 0;
1823} 1931}
1824 1932
1825int trace_parse_common_type(void *data) 1933static int __parse_common(void *data, int *size, int *offset,
1934 const char *name)
1826{ 1935{
1827 static int type_offset;
1828 static int type_size;
1829 int ret; 1936 int ret;
1830 1937
1831 if (!type_size) { 1938 if (!*size) {
1832 ret = get_common_info("common_type", 1939 ret = get_common_info(name, offset, size);
1833 &type_offset,
1834 &type_size);
1835 if (ret < 0) 1940 if (ret < 0)
1836 return ret; 1941 return ret;
1837 } 1942 }
1838 return read_size(data + type_offset, type_size); 1943 return read_size(data + *offset, *size);
1944}
1945
1946int trace_parse_common_type(void *data)
1947{
1948 static int type_offset;
1949 static int type_size;
1950
1951 return __parse_common(data, &type_size, &type_offset,
1952 "common_type");
1839} 1953}
1840 1954
1841static int parse_common_pid(void *data) 1955static int parse_common_pid(void *data)
1842{ 1956{
1843 static int pid_offset; 1957 static int pid_offset;
1844 static int pid_size; 1958 static int pid_size;
1959
1960 return __parse_common(data, &pid_size, &pid_offset,
1961 "common_pid");
1962}
1963
1964static int parse_common_pc(void *data)
1965{
1966 static int pc_offset;
1967 static int pc_size;
1968
1969 return __parse_common(data, &pc_size, &pc_offset,
1970 "common_preempt_count");
1971}
1972
1973static int parse_common_flags(void *data)
1974{
1975 static int flags_offset;
1976 static int flags_size;
1977
1978 return __parse_common(data, &flags_size, &flags_offset,
1979 "common_flags");
1980}
1981
1982static int parse_common_lock_depth(void *data)
1983{
1984 static int ld_offset;
1985 static int ld_size;
1845 int ret; 1986 int ret;
1846 1987
1847 if (!pid_size) { 1988 ret = __parse_common(data, &ld_size, &ld_offset,
1848 ret = get_common_info("common_pid", 1989 "common_lock_depth");
1849 &pid_offset, 1990 if (ret < 0)
1850 &pid_size); 1991 return -1;
1851 if (ret < 0)
1852 return ret;
1853 }
1854 1992
1855 return read_size(data + pid_offset, pid_size); 1993 return ret;
1856} 1994}
1857 1995
1858struct event *trace_find_event(int id) 1996struct event *trace_find_event(int id)
@@ -1871,6 +2009,7 @@ static unsigned long long eval_num_arg(void *data, int size,
1871{ 2009{
1872 unsigned long long val = 0; 2010 unsigned long long val = 0;
1873 unsigned long long left, right; 2011 unsigned long long left, right;
2012 struct print_arg *larg;
1874 2013
1875 switch (arg->type) { 2014 switch (arg->type) {
1876 case PRINT_NULL: 2015 case PRINT_NULL:
@@ -1897,6 +2036,26 @@ static unsigned long long eval_num_arg(void *data, int size,
1897 return 0; 2036 return 0;
1898 break; 2037 break;
1899 case PRINT_OP: 2038 case PRINT_OP:
2039 if (strcmp(arg->op.op, "[") == 0) {
2040 /*
2041 * Arrays are special, since we don't want
2042 * to read the arg as is.
2043 */
2044 if (arg->op.left->type != PRINT_FIELD)
2045 goto default_op; /* oops, all bets off */
2046 larg = arg->op.left;
2047 if (!larg->field.field) {
2048 larg->field.field =
2049 find_any_field(event, larg->field.name);
2050 if (!larg->field.field)
2051 die("field %s not found", larg->field.name);
2052 }
2053 right = eval_num_arg(data, size, event, arg->op.right);
2054 val = read_size(data + larg->field.field->offset +
2055 right * long_size, long_size);
2056 break;
2057 }
2058 default_op:
1900 left = eval_num_arg(data, size, event, arg->op.left); 2059 left = eval_num_arg(data, size, event, arg->op.left);
1901 right = eval_num_arg(data, size, event, arg->op.right); 2060 right = eval_num_arg(data, size, event, arg->op.right);
1902 switch (arg->op.op[0]) { 2061 switch (arg->op.op[0]) {
@@ -1947,6 +2106,12 @@ static unsigned long long eval_num_arg(void *data, int size,
1947 die("unknown op '%s'", arg->op.op); 2106 die("unknown op '%s'", arg->op.op);
1948 val = left == right; 2107 val = left == right;
1949 break; 2108 break;
2109 case '-':
2110 val = left - right;
2111 break;
2112 case '+':
2113 val = left + right;
2114 break;
1950 default: 2115 default:
1951 die("unknown op '%s'", arg->op.op); 2116 die("unknown op '%s'", arg->op.op);
1952 } 2117 }
@@ -1968,10 +2133,11 @@ static const struct flag flags[] = {
1968 { "NET_TX_SOFTIRQ", 2 }, 2133 { "NET_TX_SOFTIRQ", 2 },
1969 { "NET_RX_SOFTIRQ", 3 }, 2134 { "NET_RX_SOFTIRQ", 3 },
1970 { "BLOCK_SOFTIRQ", 4 }, 2135 { "BLOCK_SOFTIRQ", 4 },
1971 { "TASKLET_SOFTIRQ", 5 }, 2136 { "BLOCK_IOPOLL_SOFTIRQ", 5 },
1972 { "SCHED_SOFTIRQ", 6 }, 2137 { "TASKLET_SOFTIRQ", 6 },
1973 { "HRTIMER_SOFTIRQ", 7 }, 2138 { "SCHED_SOFTIRQ", 7 },
1974 { "RCU_SOFTIRQ", 8 }, 2139 { "HRTIMER_SOFTIRQ", 8 },
2140 { "RCU_SOFTIRQ", 9 },
1975 2141
1976 { "HRTIMER_NORESTART", 0 }, 2142 { "HRTIMER_NORESTART", 0 },
1977 { "HRTIMER_RESTART", 1 }, 2143 { "HRTIMER_RESTART", 1 },
@@ -2144,8 +2310,9 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
2144 case 'u': 2310 case 'u':
2145 case 'x': 2311 case 'x':
2146 case 'i': 2312 case 'i':
2147 bptr = (void *)(((unsigned long)bptr + (long_size - 1)) & 2313 /* the pointers are always 4 bytes aligned */
2148 ~(long_size - 1)); 2314 bptr = (void *)(((unsigned long)bptr + 3) &
2315 ~3);
2149 switch (ls) { 2316 switch (ls) {
2150 case 0: 2317 case 0:
2151 case 1: 2318 case 1:
@@ -2269,7 +2436,27 @@ static void pretty_print(void *data, int size, struct event *event)
2269 2436
2270 for (; *ptr; ptr++) { 2437 for (; *ptr; ptr++) {
2271 ls = 0; 2438 ls = 0;
2272 if (*ptr == '%') { 2439 if (*ptr == '\\') {
2440 ptr++;
2441 switch (*ptr) {
2442 case 'n':
2443 printf("\n");
2444 break;
2445 case 't':
2446 printf("\t");
2447 break;
2448 case 'r':
2449 printf("\r");
2450 break;
2451 case '\\':
2452 printf("\\");
2453 break;
2454 default:
2455 printf("%c", *ptr);
2456 break;
2457 }
2458
2459 } else if (*ptr == '%') {
2273 saveptr = ptr; 2460 saveptr = ptr;
2274 show_func = 0; 2461 show_func = 0;
2275 cont_process: 2462 cont_process:
@@ -2376,6 +2563,41 @@ static inline int log10_cpu(int nb)
2376 return 1; 2563 return 1;
2377} 2564}
2378 2565
2566static void print_lat_fmt(void *data, int size __unused)
2567{
2568 unsigned int lat_flags;
2569 unsigned int pc;
2570 int lock_depth;
2571 int hardirq;
2572 int softirq;
2573
2574 lat_flags = parse_common_flags(data);
2575 pc = parse_common_pc(data);
2576 lock_depth = parse_common_lock_depth(data);
2577
2578 hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
2579 softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
2580
2581 printf("%c%c%c",
2582 (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
2583 (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
2584 'X' : '.',
2585 (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
2586 'N' : '.',
2587 (hardirq && softirq) ? 'H' :
2588 hardirq ? 'h' : softirq ? 's' : '.');
2589
2590 if (pc)
2591 printf("%x", pc);
2592 else
2593 printf(".");
2594
2595 if (lock_depth < 0)
2596 printf(".");
2597 else
2598 printf("%d", lock_depth);
2599}
2600
2379/* taken from Linux, written by Frederic Weisbecker */ 2601/* taken from Linux, written by Frederic Weisbecker */
2380static void print_graph_cpu(int cpu) 2602static void print_graph_cpu(int cpu)
2381{ 2603{
@@ -2619,6 +2841,11 @@ pretty_print_func_ent(void *data, int size, struct event *event,
2619 2841
2620 printf(" | "); 2842 printf(" | ");
2621 2843
2844 if (latency_format) {
2845 print_lat_fmt(data, size);
2846 printf(" | ");
2847 }
2848
2622 field = find_field(event, "func"); 2849 field = find_field(event, "func");
2623 if (!field) 2850 if (!field)
2624 die("function entry does not have func field"); 2851 die("function entry does not have func field");
@@ -2662,6 +2889,11 @@ pretty_print_func_ret(void *data, int size __unused, struct event *event,
2662 2889
2663 printf(" | "); 2890 printf(" | ");
2664 2891
2892 if (latency_format) {
2893 print_lat_fmt(data, size);
2894 printf(" | ");
2895 }
2896
2665 field = find_field(event, "rettime"); 2897 field = find_field(event, "rettime");
2666 if (!field) 2898 if (!field)
2667 die("can't find rettime in return graph"); 2899 die("can't find rettime in return graph");
@@ -2723,7 +2955,7 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
2723 2955
2724 event = trace_find_event(type); 2956 event = trace_find_event(type);
2725 if (!event) { 2957 if (!event) {
2726 printf("ug! no event found for type %d\n", type); 2958 warning("ug! no event found for type %d", type);
2727 return; 2959 return;
2728 } 2960 }
2729 2961
@@ -2733,9 +2965,20 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
2733 return pretty_print_func_graph(data, size, event, cpu, 2965 return pretty_print_func_graph(data, size, event, cpu,
2734 pid, comm, secs, usecs); 2966 pid, comm, secs, usecs);
2735 2967
2736 printf("%16s-%-5d [%03d] %5lu.%09Lu: %s: ", 2968 if (latency_format) {
2737 comm, pid, cpu, 2969 printf("%8.8s-%-5d %3d",
2738 secs, nsecs, event->name); 2970 comm, pid, cpu);
2971 print_lat_fmt(data, size);
2972 } else
2973 printf("%16s-%-5d [%03d]", comm, pid, cpu);
2974
2975 printf(" %5lu.%06lu: %s: ", secs, usecs, event->name);
2976
2977 if (event->flags & EVENT_FL_FAILED) {
2978 printf("EVENT '%s' FAILED TO PARSE\n",
2979 event->name);
2980 return;
2981 }
2739 2982
2740 pretty_print(data, size, event); 2983 pretty_print(data, size, event);
2741 printf("\n"); 2984 printf("\n");
@@ -2806,46 +3049,71 @@ static void print_args(struct print_arg *args)
2806 } 3049 }
2807} 3050}
2808 3051
2809static void parse_header_field(char *type, 3052static void parse_header_field(const char *field,
2810 int *offset, int *size) 3053 int *offset, int *size)
2811{ 3054{
2812 char *token; 3055 char *token;
3056 int type;
2813 3057
2814 if (read_expected(EVENT_ITEM, (char *)"field") < 0) 3058 if (read_expected(EVENT_ITEM, "field") < 0)
2815 return; 3059 return;
2816 if (read_expected(EVENT_OP, (char *)":") < 0) 3060 if (read_expected(EVENT_OP, ":") < 0)
2817 return; 3061 return;
3062
2818 /* type */ 3063 /* type */
2819 if (read_expect_type(EVENT_ITEM, &token) < 0) 3064 if (read_expect_type(EVENT_ITEM, &token) < 0)
2820 return; 3065 goto fail;
2821 free_token(token); 3066 free_token(token);
2822 3067
2823 if (read_expected(EVENT_ITEM, type) < 0) 3068 if (read_expected(EVENT_ITEM, field) < 0)
2824 return; 3069 return;
2825 if (read_expected(EVENT_OP, (char *)";") < 0) 3070 if (read_expected(EVENT_OP, ";") < 0)
2826 return; 3071 return;
2827 if (read_expected(EVENT_ITEM, (char *)"offset") < 0) 3072 if (read_expected(EVENT_ITEM, "offset") < 0)
2828 return; 3073 return;
2829 if (read_expected(EVENT_OP, (char *)":") < 0) 3074 if (read_expected(EVENT_OP, ":") < 0)
2830 return; 3075 return;
2831 if (read_expect_type(EVENT_ITEM, &token) < 0) 3076 if (read_expect_type(EVENT_ITEM, &token) < 0)
2832 return; 3077 goto fail;
2833 *offset = atoi(token); 3078 *offset = atoi(token);
2834 free_token(token); 3079 free_token(token);
2835 if (read_expected(EVENT_OP, (char *)";") < 0) 3080 if (read_expected(EVENT_OP, ";") < 0)
2836 return; 3081 return;
2837 if (read_expected(EVENT_ITEM, (char *)"size") < 0) 3082 if (read_expected(EVENT_ITEM, "size") < 0)
2838 return; 3083 return;
2839 if (read_expected(EVENT_OP, (char *)":") < 0) 3084 if (read_expected(EVENT_OP, ":") < 0)
2840 return; 3085 return;
2841 if (read_expect_type(EVENT_ITEM, &token) < 0) 3086 if (read_expect_type(EVENT_ITEM, &token) < 0)
2842 return; 3087 goto fail;
2843 *size = atoi(token); 3088 *size = atoi(token);
2844 free_token(token); 3089 free_token(token);
2845 if (read_expected(EVENT_OP, (char *)";") < 0) 3090 if (read_expected(EVENT_OP, ";") < 0)
2846 return;
2847 if (read_expect_type(EVENT_NEWLINE, &token) < 0)
2848 return; 3091 return;
3092 type = read_token(&token);
3093 if (type != EVENT_NEWLINE) {
3094 /* newer versions of the kernel have a "signed" type */
3095 if (type != EVENT_ITEM)
3096 goto fail;
3097
3098 if (strcmp(token, "signed") != 0)
3099 goto fail;
3100
3101 free_token(token);
3102
3103 if (read_expected(EVENT_OP, ":") < 0)
3104 return;
3105
3106 if (read_expect_type(EVENT_ITEM, &token))
3107 goto fail;
3108
3109 free_token(token);
3110 if (read_expected(EVENT_OP, ";") < 0)
3111 return;
3112
3113 if (read_expect_type(EVENT_NEWLINE, &token))
3114 goto fail;
3115 }
3116 fail:
2849 free_token(token); 3117 free_token(token);
2850} 3118}
2851 3119
@@ -2853,11 +3121,11 @@ int parse_header_page(char *buf, unsigned long size)
2853{ 3121{
2854 init_input_buf(buf, size); 3122 init_input_buf(buf, size);
2855 3123
2856 parse_header_field((char *)"timestamp", &header_page_ts_offset, 3124 parse_header_field("timestamp", &header_page_ts_offset,
2857 &header_page_ts_size); 3125 &header_page_ts_size);
2858 parse_header_field((char *)"commit", &header_page_size_offset, 3126 parse_header_field("commit", &header_page_size_offset,
2859 &header_page_size_size); 3127 &header_page_size_size);
2860 parse_header_field((char *)"data", &header_page_data_offset, 3128 parse_header_field("data", &header_page_data_offset,
2861 &header_page_data_size); 3129 &header_page_data_size);
2862 3130
2863 return 0; 3131 return 0;
@@ -2908,6 +3176,9 @@ int parse_ftrace_file(char *buf, unsigned long size)
2908 if (ret < 0) 3176 if (ret < 0)
2909 die("failed to read ftrace event print fmt"); 3177 die("failed to read ftrace event print fmt");
2910 3178
3179 /* New ftrace handles args */
3180 if (ret > 0)
3181 return 0;
2911 /* 3182 /*
2912 * The arguments for ftrace files are parsed by the fields. 3183 * The arguments for ftrace files are parsed by the fields.
2913 * Set up the fields as their arguments. 3184 * Set up the fields as their arguments.
@@ -2925,7 +3196,7 @@ int parse_ftrace_file(char *buf, unsigned long size)
2925 return 0; 3196 return 0;
2926} 3197}
2927 3198
2928int parse_event_file(char *buf, unsigned long size, char *system__unused __unused) 3199int parse_event_file(char *buf, unsigned long size, char *sys)
2929{ 3200{
2930 struct event *event; 3201 struct event *event;
2931 int ret; 3202 int ret;
@@ -2945,12 +3216,18 @@ int parse_event_file(char *buf, unsigned long size, char *system__unused __unuse
2945 die("failed to read event id"); 3216 die("failed to read event id");
2946 3217
2947 ret = event_read_format(event); 3218 ret = event_read_format(event);
2948 if (ret < 0) 3219 if (ret < 0) {
2949 die("failed to read event format"); 3220 warning("failed to read event format for %s", event->name);
3221 goto event_failed;
3222 }
2950 3223
2951 ret = event_read_print(event); 3224 ret = event_read_print(event);
2952 if (ret < 0) 3225 if (ret < 0) {
2953 die("failed to read event print fmt"); 3226 warning("failed to read event print fmt for %s", event->name);
3227 goto event_failed;
3228 }
3229
3230 event->system = strdup(sys);
2954 3231
2955#define PRINT_ARGS 0 3232#define PRINT_ARGS 0
2956 if (PRINT_ARGS && event->print_fmt.args) 3233 if (PRINT_ARGS && event->print_fmt.args)
@@ -2958,6 +3235,12 @@ int parse_event_file(char *buf, unsigned long size, char *system__unused __unuse
2958 3235
2959 add_event(event); 3236 add_event(event);
2960 return 0; 3237 return 0;
3238
3239 event_failed:
3240 event->flags |= EVENT_FL_FAILED;
3241 /* still add it even if it failed */
3242 add_event(event);
3243 return -1;
2961} 3244}
2962 3245
2963void parse_set_info(int nr_cpus, int long_sz) 3246void parse_set_info(int nr_cpus, int long_sz)
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 1b5c847d2c22..44292e06cca4 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -458,9 +458,8 @@ struct record *trace_read_data(int cpu)
458 return data; 458 return data;
459} 459}
460 460
461void trace_report(void) 461void trace_report(int fd)
462{ 462{
463 const char *input_file = "trace.info";
464 char buf[BUFSIZ]; 463 char buf[BUFSIZ];
465 char test[] = { 23, 8, 68 }; 464 char test[] = { 23, 8, 68 };
466 char *version; 465 char *version;
@@ -468,9 +467,7 @@ void trace_report(void)
468 int show_funcs = 0; 467 int show_funcs = 0;
469 int show_printk = 0; 468 int show_printk = 0;
470 469
471 input_fd = open(input_file, O_RDONLY); 470 input_fd = fd;
472 if (input_fd < 0)
473 die("opening '%s'\n", input_file);
474 471
475 read_or_die(buf, 3); 472 read_or_die(buf, 3);
476 if (memcmp(buf, test, 3) != 0) 473 if (memcmp(buf, test, 3) != 0)
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 693f815c9429..f6637c2fa1fe 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -1,5 +1,5 @@
1#ifndef _TRACE_EVENTS_H 1#ifndef __PERF_TRACE_EVENTS_H
2#define _TRACE_EVENTS_H 2#define __PERF_TRACE_EVENTS_H
3 3
4#include "parse-events.h" 4#include "parse-events.h"
5 5
@@ -26,6 +26,9 @@ enum {
26enum format_flags { 26enum format_flags {
27 FIELD_IS_ARRAY = 1, 27 FIELD_IS_ARRAY = 1,
28 FIELD_IS_POINTER = 2, 28 FIELD_IS_POINTER = 2,
29 FIELD_IS_SIGNED = 4,
30 FIELD_IS_STRING = 8,
31 FIELD_IS_DYNAMIC = 16,
29}; 32};
30 33
31struct format_field { 34struct format_field {
@@ -132,15 +135,18 @@ struct event {
132 int flags; 135 int flags;
133 struct format format; 136 struct format format;
134 struct print_fmt print_fmt; 137 struct print_fmt print_fmt;
138 char *system;
135}; 139};
136 140
137enum { 141enum {
138 EVENT_FL_ISFTRACE = 1, 142 EVENT_FL_ISFTRACE = 0x01,
139 EVENT_FL_ISPRINT = 2, 143 EVENT_FL_ISPRINT = 0x02,
140 EVENT_FL_ISBPRINT = 4, 144 EVENT_FL_ISBPRINT = 0x04,
141 EVENT_FL_ISFUNC = 8, 145 EVENT_FL_ISFUNC = 0x08,
142 EVENT_FL_ISFUNCENT = 16, 146 EVENT_FL_ISFUNCENT = 0x10,
143 EVENT_FL_ISFUNCRET = 32, 147 EVENT_FL_ISFUNCRET = 0x20,
148
149 EVENT_FL_FAILED = 0x80000000
144}; 150};
145 151
146struct record { 152struct record {
@@ -154,7 +160,7 @@ struct record *trace_read_data(int cpu);
154 160
155void parse_set_info(int nr_cpus, int long_sz); 161void parse_set_info(int nr_cpus, int long_sz);
156 162
157void trace_report(void); 163void trace_report(int fd);
158 164
159void *malloc_or_die(unsigned int size); 165void *malloc_or_die(unsigned int size);
160 166
@@ -166,7 +172,7 @@ void print_funcs(void);
166void print_printk(void); 172void print_printk(void);
167 173
168int parse_ftrace_file(char *buf, unsigned long size); 174int parse_ftrace_file(char *buf, unsigned long size);
169int parse_event_file(char *buf, unsigned long size, char *system); 175int parse_event_file(char *buf, unsigned long size, char *sys);
170void print_event(int cpu, void *data, int size, unsigned long long nsecs, 176void print_event(int cpu, void *data, int size, unsigned long long nsecs,
171 char *comm); 177 char *comm);
172 178
@@ -233,6 +239,8 @@ extern int header_page_size_size;
233extern int header_page_data_offset; 239extern int header_page_data_offset;
234extern int header_page_data_size; 240extern int header_page_data_size;
235 241
242extern int latency_format;
243
236int parse_header_page(char *buf, unsigned long size); 244int parse_header_page(char *buf, unsigned long size);
237int trace_parse_common_type(void *data); 245int trace_parse_common_type(void *data);
238struct event *trace_find_event(int id); 246struct event *trace_find_event(int id);
@@ -240,6 +248,15 @@ unsigned long long
240raw_field_value(struct event *event, const char *name, void *data); 248raw_field_value(struct event *event, const char *name, void *data);
241void *raw_field_ptr(struct event *event, const char *name, void *data); 249void *raw_field_ptr(struct event *event, const char *name, void *data);
242 250
243void read_tracing_data(struct perf_event_attr *pattrs, int nb_events); 251void read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events);
252
253/* taken from kernel/trace/trace.h */
254enum trace_flag_type {
255 TRACE_FLAG_IRQS_OFF = 0x01,
256 TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
257 TRACE_FLAG_NEED_RESCHED = 0x04,
258 TRACE_FLAG_HARDIRQ = 0x08,
259 TRACE_FLAG_SOFTIRQ = 0x10,
260};
244 261
245#endif /* _TRACE_EVENTS_H */ 262#endif /* __PERF_TRACE_EVENTS_H */
diff --git a/tools/perf/util/types.h b/tools/perf/util/types.h
index 5e75f9005940..7d6b8331f898 100644
--- a/tools/perf/util/types.h
+++ b/tools/perf/util/types.h
@@ -1,5 +1,5 @@
1#ifndef _PERF_TYPES_H 1#ifndef __PERF_TYPES_H
2#define _PERF_TYPES_H 2#define __PERF_TYPES_H
3 3
4/* 4/*
5 * We define u64 as unsigned long long for every architecture 5 * We define u64 as unsigned long long for every architecture
@@ -14,4 +14,4 @@ typedef signed short s16;
14typedef unsigned char u8; 14typedef unsigned char u8;
15typedef signed char s8; 15typedef signed char s8;
16 16
17#endif /* _PERF_TYPES_H */ 17#endif /* __PERF_TYPES_H */
diff --git a/tools/perf/util/values.h b/tools/perf/util/values.h
index cadf8cf2a590..2fa967e1a88a 100644
--- a/tools/perf/util/values.h
+++ b/tools/perf/util/values.h
@@ -1,5 +1,5 @@
1#ifndef _PERF_VALUES_H 1#ifndef __PERF_VALUES_H
2#define _PERF_VALUES_H 2#define __PERF_VALUES_H
3 3
4#include "types.h" 4#include "types.h"
5 5
@@ -24,4 +24,4 @@ void perf_read_values_add_value(struct perf_read_values *values,
24void perf_read_values_display(FILE *fp, struct perf_read_values *values, 24void perf_read_values_display(FILE *fp, struct perf_read_values *values,
25 int raw); 25 int raw);
26 26
27#endif /* _PERF_VALUES_H */ 27#endif /* __PERF_VALUES_H */