aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-report.txt3
-rw-r--r--tools/perf/Makefile12
-rw-r--r--tools/perf/builtin-annotate.c459
-rw-r--r--tools/perf/builtin-help.c1
-rw-r--r--tools/perf/builtin-record.c21
-rw-r--r--tools/perf/builtin-report.c697
-rw-r--r--tools/perf/builtin-stat.c3
-rw-r--r--tools/perf/builtin-top.c49
-rw-r--r--tools/perf/builtin.h1
-rw-r--r--tools/perf/util/abspath.c3
-rw-r--r--tools/perf/util/cache.h1
-rw-r--r--tools/perf/util/callchain.c2
-rw-r--r--tools/perf/util/callchain.h1
-rw-r--r--tools/perf/util/color.c16
-rw-r--r--tools/perf/util/color.h3
-rw-r--r--tools/perf/util/config.c22
-rw-r--r--tools/perf/util/debug.c95
-rw-r--r--tools/perf/util/debug.h8
-rw-r--r--tools/perf/util/event.h96
-rw-r--r--tools/perf/util/exec_cmd.c1
-rw-r--r--tools/perf/util/header.c35
-rw-r--r--tools/perf/util/header.h4
-rw-r--r--tools/perf/util/map.c97
-rw-r--r--tools/perf/util/module.c4
-rw-r--r--tools/perf/util/parse-events.c26
-rw-r--r--tools/perf/util/parse-events.h4
-rw-r--r--tools/perf/util/parse-options.c22
-rw-r--r--tools/perf/util/path.c25
-rw-r--r--tools/perf/util/run-command.c6
-rw-r--r--tools/perf/util/symbol.c199
-rw-r--r--tools/perf/util/symbol.h14
-rw-r--r--tools/perf/util/thread.c162
-rw-r--r--tools/perf/util/thread.h19
-rw-r--r--tools/perf/util/util.h5
-rw-r--r--tools/perf/util/values.c230
-rw-r--r--tools/perf/util/values.h27
36 files changed, 1240 insertions, 1133 deletions
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index e72e93110782..370344afb5b2 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -27,6 +27,9 @@ OPTIONS
27-n 27-n
28--show-nr-samples 28--show-nr-samples
29 Show the number of samples for each symbol 29 Show the number of samples for each symbol
30-T
31--threads
32 Show per-thread event counters
30-C:: 33-C::
31--comms=:: 34--comms=::
32 Only consider symbols in these comms. CSV that understands 35 Only consider symbols in these comms. CSV that understands
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index c045b4271e57..5d54ddb83ab1 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -166,7 +166,12 @@ endif
166 166
167# CFLAGS and LDFLAGS are for the users to override from the command line. 167# CFLAGS and LDFLAGS are for the users to override from the command line.
168 168
169CFLAGS = $(M64) -ggdb3 -Wall -Wextra -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6 169#
170# Include saner warnings here, which can catch bugs:
171#
172EXTRA_WARNINGS = -Wcast-align -Wformat -Wformat-security -Wformat-y2k -Wshadow -Winit-self -Wpacked -Wredundant-decls -Wstack-protector -Wstrict-aliasing=3 -Wswitch-default -Wswitch-enum -Wno-system-headers -Wundef -Wvolatile-register-var -Wwrite-strings -Wbad-function-cast -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wstrict-prototypes -Wdeclaration-after-statement
173
174CFLAGS = $(M64) -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -fstack-protector-all -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS)
170LDFLAGS = -lpthread -lrt -lelf -lm 175LDFLAGS = -lpthread -lrt -lelf -lm
171ALL_CFLAGS = $(CFLAGS) 176ALL_CFLAGS = $(CFLAGS)
172ALL_LDFLAGS = $(LDFLAGS) 177ALL_LDFLAGS = $(LDFLAGS)
@@ -310,6 +315,7 @@ LIB_H += util/sigchain.h
310LIB_H += util/symbol.h 315LIB_H += util/symbol.h
311LIB_H += util/module.h 316LIB_H += util/module.h
312LIB_H += util/color.h 317LIB_H += util/color.h
318LIB_H += util/values.h
313 319
314LIB_OBJS += util/abspath.o 320LIB_OBJS += util/abspath.o
315LIB_OBJS += util/alias.o 321LIB_OBJS += util/alias.o
@@ -337,6 +343,10 @@ LIB_OBJS += util/color.o
337LIB_OBJS += util/pager.o 343LIB_OBJS += util/pager.o
338LIB_OBJS += util/header.o 344LIB_OBJS += util/header.o
339LIB_OBJS += util/callchain.o 345LIB_OBJS += util/callchain.o
346LIB_OBJS += util/values.o
347LIB_OBJS += util/debug.o
348LIB_OBJS += util/map.o
349LIB_OBJS += util/thread.o
340 350
341BUILTIN_OBJS += builtin-annotate.o 351BUILTIN_OBJS += builtin-annotate.o
342BUILTIN_OBJS += builtin-help.o 352BUILTIN_OBJS += builtin-help.o
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 5e17de984dc8..4ac618b34254 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -17,16 +17,13 @@
17#include "util/string.h" 17#include "util/string.h"
18 18
19#include "perf.h" 19#include "perf.h"
20#include "util/debug.h"
20 21
21#include "util/parse-options.h" 22#include "util/parse-options.h"
22#include "util/parse-events.h" 23#include "util/parse-events.h"
23 24#include "util/thread.h"
24#define SHOW_KERNEL 1
25#define SHOW_USER 2
26#define SHOW_HV 4
27 25
28static char const *input_name = "perf.data"; 26static char const *input_name = "perf.data";
29static char *vmlinux = "vmlinux";
30 27
31static char default_sort_order[] = "comm,symbol"; 28static char default_sort_order[] = "comm,symbol";
32static char *sort_order = default_sort_order; 29static char *sort_order = default_sort_order;
@@ -35,13 +32,6 @@ static int force;
35static int input; 32static int input;
36static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; 33static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
37 34
38static int dump_trace = 0;
39#define dprintf(x...) do { if (dump_trace) printf(x); } while (0)
40
41static int verbose;
42
43static int modules;
44
45static int full_paths; 35static int full_paths;
46 36
47static int print_line; 37static int print_line;
@@ -49,39 +39,8 @@ static int print_line;
49static unsigned long page_size; 39static unsigned long page_size;
50static unsigned long mmap_window = 32; 40static unsigned long mmap_window = 32;
51 41
52struct ip_event { 42static struct rb_root threads;
53 struct perf_event_header header; 43static struct thread *last_match;
54 u64 ip;
55 u32 pid, tid;
56};
57
58struct mmap_event {
59 struct perf_event_header header;
60 u32 pid, tid;
61 u64 start;
62 u64 len;
63 u64 pgoff;
64 char filename[PATH_MAX];
65};
66
67struct comm_event {
68 struct perf_event_header header;
69 u32 pid, tid;
70 char comm[16];
71};
72
73struct fork_event {
74 struct perf_event_header header;
75 u32 pid, ppid;
76};
77
78typedef union event_union {
79 struct perf_event_header header;
80 struct ip_event ip;
81 struct mmap_event mmap;
82 struct comm_event comm;
83 struct fork_event fork;
84} event_t;
85 44
86 45
87struct sym_ext { 46struct sym_ext {
@@ -90,323 +49,6 @@ struct sym_ext {
90 char *path; 49 char *path;
91}; 50};
92 51
93static LIST_HEAD(dsos);
94static struct dso *kernel_dso;
95static struct dso *vdso;
96
97
98static void dsos__add(struct dso *dso)
99{
100 list_add_tail(&dso->node, &dsos);
101}
102
103static struct dso *dsos__find(const char *name)
104{
105 struct dso *pos;
106
107 list_for_each_entry(pos, &dsos, node)
108 if (strcmp(pos->name, name) == 0)
109 return pos;
110 return NULL;
111}
112
113static struct dso *dsos__findnew(const char *name)
114{
115 struct dso *dso = dsos__find(name);
116 int nr;
117
118 if (dso)
119 return dso;
120
121 dso = dso__new(name, 0);
122 if (!dso)
123 goto out_delete_dso;
124
125 nr = dso__load(dso, NULL, verbose);
126 if (nr < 0) {
127 if (verbose)
128 fprintf(stderr, "Failed to open: %s\n", name);
129 goto out_delete_dso;
130 }
131 if (!nr && verbose) {
132 fprintf(stderr,
133 "No symbols found in: %s, maybe install a debug package?\n",
134 name);
135 }
136
137 dsos__add(dso);
138
139 return dso;
140
141out_delete_dso:
142 dso__delete(dso);
143 return NULL;
144}
145
146static void dsos__fprintf(FILE *fp)
147{
148 struct dso *pos;
149
150 list_for_each_entry(pos, &dsos, node)
151 dso__fprintf(pos, fp);
152}
153
154static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
155{
156 return dso__find_symbol(dso, ip);
157}
158
159static int load_kernel(void)
160{
161 int err;
162
163 kernel_dso = dso__new("[kernel]", 0);
164 if (!kernel_dso)
165 return -1;
166
167 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules);
168 if (err <= 0) {
169 dso__delete(kernel_dso);
170 kernel_dso = NULL;
171 } else
172 dsos__add(kernel_dso);
173
174 vdso = dso__new("[vdso]", 0);
175 if (!vdso)
176 return -1;
177
178 vdso->find_symbol = vdso__find_symbol;
179
180 dsos__add(vdso);
181
182 return err;
183}
184
185struct map {
186 struct list_head node;
187 u64 start;
188 u64 end;
189 u64 pgoff;
190 u64 (*map_ip)(struct map *, u64);
191 struct dso *dso;
192};
193
194static u64 map__map_ip(struct map *map, u64 ip)
195{
196 return ip - map->start + map->pgoff;
197}
198
199static u64 vdso__map_ip(struct map *map __used, u64 ip)
200{
201 return ip;
202}
203
204static struct map *map__new(struct mmap_event *event)
205{
206 struct map *self = malloc(sizeof(*self));
207
208 if (self != NULL) {
209 const char *filename = event->filename;
210
211 self->start = event->start;
212 self->end = event->start + event->len;
213 self->pgoff = event->pgoff;
214
215 self->dso = dsos__findnew(filename);
216 if (self->dso == NULL)
217 goto out_delete;
218
219 if (self->dso == vdso)
220 self->map_ip = vdso__map_ip;
221 else
222 self->map_ip = map__map_ip;
223 }
224 return self;
225out_delete:
226 free(self);
227 return NULL;
228}
229
230static struct map *map__clone(struct map *self)
231{
232 struct map *map = malloc(sizeof(*self));
233
234 if (!map)
235 return NULL;
236
237 memcpy(map, self, sizeof(*self));
238
239 return map;
240}
241
242static int map__overlap(struct map *l, struct map *r)
243{
244 if (l->start > r->start) {
245 struct map *t = l;
246 l = r;
247 r = t;
248 }
249
250 if (l->end > r->start)
251 return 1;
252
253 return 0;
254}
255
256static size_t map__fprintf(struct map *self, FILE *fp)
257{
258 return fprintf(fp, " %Lx-%Lx %Lx %s\n",
259 self->start, self->end, self->pgoff, self->dso->name);
260}
261
262
263struct thread {
264 struct rb_node rb_node;
265 struct list_head maps;
266 pid_t pid;
267 char *comm;
268};
269
270static struct thread *thread__new(pid_t pid)
271{
272 struct thread *self = malloc(sizeof(*self));
273
274 if (self != NULL) {
275 self->pid = pid;
276 self->comm = malloc(32);
277 if (self->comm)
278 snprintf(self->comm, 32, ":%d", self->pid);
279 INIT_LIST_HEAD(&self->maps);
280 }
281
282 return self;
283}
284
285static int thread__set_comm(struct thread *self, const char *comm)
286{
287 if (self->comm)
288 free(self->comm);
289 self->comm = strdup(comm);
290 return self->comm ? 0 : -ENOMEM;
291}
292
293static size_t thread__fprintf(struct thread *self, FILE *fp)
294{
295 struct map *pos;
296 size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm);
297
298 list_for_each_entry(pos, &self->maps, node)
299 ret += map__fprintf(pos, fp);
300
301 return ret;
302}
303
304
305static struct rb_root threads;
306static struct thread *last_match;
307
308static struct thread *threads__findnew(pid_t pid)
309{
310 struct rb_node **p = &threads.rb_node;
311 struct rb_node *parent = NULL;
312 struct thread *th;
313
314 /*
315 * Font-end cache - PID lookups come in blocks,
316 * so most of the time we dont have to look up
317 * the full rbtree:
318 */
319 if (last_match && last_match->pid == pid)
320 return last_match;
321
322 while (*p != NULL) {
323 parent = *p;
324 th = rb_entry(parent, struct thread, rb_node);
325
326 if (th->pid == pid) {
327 last_match = th;
328 return th;
329 }
330
331 if (pid < th->pid)
332 p = &(*p)->rb_left;
333 else
334 p = &(*p)->rb_right;
335 }
336
337 th = thread__new(pid);
338 if (th != NULL) {
339 rb_link_node(&th->rb_node, parent, p);
340 rb_insert_color(&th->rb_node, &threads);
341 last_match = th;
342 }
343
344 return th;
345}
346
347static void thread__insert_map(struct thread *self, struct map *map)
348{
349 struct map *pos, *tmp;
350
351 list_for_each_entry_safe(pos, tmp, &self->maps, node) {
352 if (map__overlap(pos, map)) {
353 list_del_init(&pos->node);
354 /* XXX leaks dsos */
355 free(pos);
356 }
357 }
358
359 list_add_tail(&map->node, &self->maps);
360}
361
362static int thread__fork(struct thread *self, struct thread *parent)
363{
364 struct map *map;
365
366 if (self->comm)
367 free(self->comm);
368 self->comm = strdup(parent->comm);
369 if (!self->comm)
370 return -ENOMEM;
371
372 list_for_each_entry(map, &parent->maps, node) {
373 struct map *new = map__clone(map);
374 if (!new)
375 return -ENOMEM;
376 thread__insert_map(self, new);
377 }
378
379 return 0;
380}
381
382static struct map *thread__find_map(struct thread *self, u64 ip)
383{
384 struct map *pos;
385
386 if (self == NULL)
387 return NULL;
388
389 list_for_each_entry(pos, &self->maps, node)
390 if (ip >= pos->start && ip <= pos->end)
391 return pos;
392
393 return NULL;
394}
395
396static size_t threads__fprintf(FILE *fp)
397{
398 size_t ret = 0;
399 struct rb_node *nd;
400
401 for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
402 struct thread *pos = rb_entry(nd, struct thread, rb_node);
403
404 ret += thread__fprintf(pos, fp);
405 }
406
407 return ret;
408}
409
410/* 52/*
411 * histogram, sorted on item, collects counts 53 * histogram, sorted on item, collects counts
412 */ 54 */
@@ -433,7 +75,7 @@ struct hist_entry {
433struct sort_entry { 75struct sort_entry {
434 struct list_head list; 76 struct list_head list;
435 77
436 char *header; 78 const char *header;
437 79
438 int64_t (*cmp)(struct hist_entry *, struct hist_entry *); 80 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
439 int64_t (*collapse)(struct hist_entry *, struct hist_entry *); 81 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
@@ -577,7 +219,7 @@ static struct sort_entry sort_sym = {
577static int sort__need_collapse = 0; 219static int sort__need_collapse = 0;
578 220
579struct sort_dimension { 221struct sort_dimension {
580 char *name; 222 const char *name;
581 struct sort_entry *entry; 223 struct sort_entry *entry;
582 int taken; 224 int taken;
583}; 225};
@@ -832,7 +474,7 @@ static void output__resort(void)
832 474
833static void register_idle_thread(void) 475static void register_idle_thread(void)
834{ 476{
835 struct thread *thread = threads__findnew(0); 477 struct thread *thread = threads__findnew(0, &threads, &last_match);
836 478
837 if (thread == NULL || 479 if (thread == NULL ||
838 thread__set_comm(thread, "[idle]")) { 480 thread__set_comm(thread, "[idle]")) {
@@ -853,18 +495,20 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
853 char level; 495 char level;
854 int show = 0; 496 int show = 0;
855 struct dso *dso = NULL; 497 struct dso *dso = NULL;
856 struct thread *thread = threads__findnew(event->ip.pid); 498 struct thread *thread;
857 u64 ip = event->ip.ip; 499 u64 ip = event->ip.ip;
858 struct map *map = NULL; 500 struct map *map = NULL;
859 501
860 dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", 502 thread = threads__findnew(event->ip.pid, &threads, &last_match);
503
504 dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
861 (void *)(offset + head), 505 (void *)(offset + head),
862 (void *)(long)(event->header.size), 506 (void *)(long)(event->header.size),
863 event->header.misc, 507 event->header.misc,
864 event->ip.pid, 508 event->ip.pid,
865 (void *)(long)ip); 509 (void *)(long)ip);
866 510
867 dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid); 511 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
868 512
869 if (thread == NULL) { 513 if (thread == NULL) {
870 fprintf(stderr, "problem processing %d event, skipping it.\n", 514 fprintf(stderr, "problem processing %d event, skipping it.\n",
@@ -878,7 +522,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
878 522
879 dso = kernel_dso; 523 dso = kernel_dso;
880 524
881 dprintf(" ...... dso: %s\n", dso->name); 525 dump_printf(" ...... dso: %s\n", dso->name);
882 526
883 } else if (event->header.misc & PERF_EVENT_MISC_USER) { 527 } else if (event->header.misc & PERF_EVENT_MISC_USER) {
884 528
@@ -899,12 +543,12 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
899 if ((long long)ip < 0) 543 if ((long long)ip < 0)
900 dso = kernel_dso; 544 dso = kernel_dso;
901 } 545 }
902 dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 546 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
903 547
904 } else { 548 } else {
905 show = SHOW_HV; 549 show = SHOW_HV;
906 level = 'H'; 550 level = 'H';
907 dprintf(" ...... dso: [hypervisor]\n"); 551 dump_printf(" ...... dso: [hypervisor]\n");
908 } 552 }
909 553
910 if (show & show_mask) { 554 if (show & show_mask) {
@@ -927,10 +571,12 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
927static int 571static int
928process_mmap_event(event_t *event, unsigned long offset, unsigned long head) 572process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
929{ 573{
930 struct thread *thread = threads__findnew(event->mmap.pid); 574 struct thread *thread;
931 struct map *map = map__new(&event->mmap); 575 struct map *map = map__new(&event->mmap, NULL, 0);
576
577 thread = threads__findnew(event->mmap.pid, &threads, &last_match);
932 578
933 dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", 579 dump_printf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n",
934 (void *)(offset + head), 580 (void *)(offset + head),
935 (void *)(long)(event->header.size), 581 (void *)(long)(event->header.size),
936 event->mmap.pid, 582 event->mmap.pid,
@@ -940,7 +586,7 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
940 event->mmap.filename); 586 event->mmap.filename);
941 587
942 if (thread == NULL || map == NULL) { 588 if (thread == NULL || map == NULL) {
943 dprintf("problem processing PERF_EVENT_MMAP, skipping event.\n"); 589 dump_printf("problem processing PERF_EVENT_MMAP, skipping event.\n");
944 return 0; 590 return 0;
945 } 591 }
946 592
@@ -953,16 +599,17 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
953static int 599static int
954process_comm_event(event_t *event, unsigned long offset, unsigned long head) 600process_comm_event(event_t *event, unsigned long offset, unsigned long head)
955{ 601{
956 struct thread *thread = threads__findnew(event->comm.pid); 602 struct thread *thread;
957 603
958 dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n", 604 thread = threads__findnew(event->comm.pid, &threads, &last_match);
605 dump_printf("%p [%p]: PERF_EVENT_COMM: %s:%d\n",
959 (void *)(offset + head), 606 (void *)(offset + head),
960 (void *)(long)(event->header.size), 607 (void *)(long)(event->header.size),
961 event->comm.comm, event->comm.pid); 608 event->comm.comm, event->comm.pid);
962 609
963 if (thread == NULL || 610 if (thread == NULL ||
964 thread__set_comm(thread, event->comm.comm)) { 611 thread__set_comm(thread, event->comm.comm)) {
965 dprintf("problem processing PERF_EVENT_COMM, skipping event.\n"); 612 dump_printf("problem processing PERF_EVENT_COMM, skipping event.\n");
966 return -1; 613 return -1;
967 } 614 }
968 total_comm++; 615 total_comm++;
@@ -973,10 +620,12 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
973static int 620static int
974process_fork_event(event_t *event, unsigned long offset, unsigned long head) 621process_fork_event(event_t *event, unsigned long offset, unsigned long head)
975{ 622{
976 struct thread *thread = threads__findnew(event->fork.pid); 623 struct thread *thread;
977 struct thread *parent = threads__findnew(event->fork.ppid); 624 struct thread *parent;
978 625
979 dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n", 626 thread = threads__findnew(event->fork.pid, &threads, &last_match);
627 parent = threads__findnew(event->fork.ppid, &threads, &last_match);
628 dump_printf("%p [%p]: PERF_EVENT_FORK: %d:%d\n",
980 (void *)(offset + head), 629 (void *)(offset + head),
981 (void *)(long)(event->header.size), 630 (void *)(long)(event->header.size),
982 event->fork.pid, event->fork.ppid); 631 event->fork.pid, event->fork.ppid);
@@ -989,7 +638,7 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
989 return 0; 638 return 0;
990 639
991 if (!thread || !parent || thread__fork(thread, parent)) { 640 if (!thread || !parent || thread__fork(thread, parent)) {
992 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); 641 dump_printf("problem processing PERF_EVENT_FORK, skipping event.\n");
993 return -1; 642 return -1;
994 } 643 }
995 total_fork++; 644 total_fork++;
@@ -1075,7 +724,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1075 const char *path = NULL; 724 const char *path = NULL;
1076 unsigned int hits = 0; 725 unsigned int hits = 0;
1077 double percent = 0.0; 726 double percent = 0.0;
1078 char *color; 727 const char *color;
1079 struct sym_ext *sym_ext = sym->priv; 728 struct sym_ext *sym_ext = sym->priv;
1080 729
1081 offset = line_ip - start; 730 offset = line_ip - start;
@@ -1157,7 +806,7 @@ static void free_source_line(struct symbol *sym, int len)
1157 806
1158/* Get the filename:line for the colored entries */ 807/* Get the filename:line for the colored entries */
1159static void 808static void
1160get_source_line(struct symbol *sym, u64 start, int len, char *filename) 809get_source_line(struct symbol *sym, u64 start, int len, const char *filename)
1161{ 810{
1162 int i; 811 int i;
1163 char cmd[PATH_MAX * 2]; 812 char cmd[PATH_MAX * 2];
@@ -1203,7 +852,7 @@ get_source_line(struct symbol *sym, u64 start, int len, char *filename)
1203 } 852 }
1204} 853}
1205 854
1206static void print_summary(char *filename) 855static void print_summary(const char *filename)
1207{ 856{
1208 struct sym_ext *sym_ext; 857 struct sym_ext *sym_ext;
1209 struct rb_node *node; 858 struct rb_node *node;
@@ -1219,7 +868,7 @@ static void print_summary(char *filename)
1219 node = rb_first(&root_sym_ext); 868 node = rb_first(&root_sym_ext);
1220 while (node) { 869 while (node) {
1221 double percent; 870 double percent;
1222 char *color; 871 const char *color;
1223 char *path; 872 char *path;
1224 873
1225 sym_ext = rb_entry(node, struct sym_ext, node); 874 sym_ext = rb_entry(node, struct sym_ext, node);
@@ -1234,7 +883,7 @@ static void print_summary(char *filename)
1234 883
1235static void annotate_sym(struct dso *dso, struct symbol *sym) 884static void annotate_sym(struct dso *dso, struct symbol *sym)
1236{ 885{
1237 char *filename = dso->name, *d_filename; 886 const char *filename = dso->name, *d_filename;
1238 u64 start, end, len; 887 u64 start, end, len;
1239 char command[PATH_MAX*2]; 888 char command[PATH_MAX*2];
1240 FILE *file; 889 FILE *file;
@@ -1244,7 +893,7 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
1244 if (sym->module) 893 if (sym->module)
1245 filename = sym->module->path; 894 filename = sym->module->path;
1246 else if (dso == kernel_dso) 895 else if (dso == kernel_dso)
1247 filename = vmlinux; 896 filename = vmlinux_name;
1248 897
1249 start = sym->obj_start; 898 start = sym->obj_start;
1250 if (!start) 899 if (!start)
@@ -1316,7 +965,7 @@ static int __cmd_annotate(void)
1316 int ret, rc = EXIT_FAILURE; 965 int ret, rc = EXIT_FAILURE;
1317 unsigned long offset = 0; 966 unsigned long offset = 0;
1318 unsigned long head = 0; 967 unsigned long head = 0;
1319 struct stat stat; 968 struct stat input_stat;
1320 event_t *event; 969 event_t *event;
1321 uint32_t size; 970 uint32_t size;
1322 char *buf; 971 char *buf;
@@ -1329,18 +978,18 @@ static int __cmd_annotate(void)
1329 exit(-1); 978 exit(-1);
1330 } 979 }
1331 980
1332 ret = fstat(input, &stat); 981 ret = fstat(input, &input_stat);
1333 if (ret < 0) { 982 if (ret < 0) {
1334 perror("failed to stat file"); 983 perror("failed to stat file");
1335 exit(-1); 984 exit(-1);
1336 } 985 }
1337 986
1338 if (!force && (stat.st_uid != geteuid())) { 987 if (!force && (input_stat.st_uid != geteuid())) {
1339 fprintf(stderr, "file: %s not owned by current user\n", input_name); 988 fprintf(stderr, "file: %s not owned by current user\n", input_name);
1340 exit(-1); 989 exit(-1);
1341 } 990 }
1342 991
1343 if (!stat.st_size) { 992 if (!input_stat.st_size) {
1344 fprintf(stderr, "zero-sized file, nothing to do!\n"); 993 fprintf(stderr, "zero-sized file, nothing to do!\n");
1345 exit(0); 994 exit(0);
1346 } 995 }
@@ -1367,10 +1016,10 @@ more:
1367 1016
1368 if (head + event->header.size >= page_size * mmap_window) { 1017 if (head + event->header.size >= page_size * mmap_window) {
1369 unsigned long shift = page_size * (head / page_size); 1018 unsigned long shift = page_size * (head / page_size);
1370 int ret; 1019 int munmap_ret;
1371 1020
1372 ret = munmap(buf, page_size * mmap_window); 1021 munmap_ret = munmap(buf, page_size * mmap_window);
1373 assert(ret == 0); 1022 assert(munmap_ret == 0);
1374 1023
1375 offset += shift; 1024 offset += shift;
1376 head -= shift; 1025 head -= shift;
@@ -1379,14 +1028,14 @@ more:
1379 1028
1380 size = event->header.size; 1029 size = event->header.size;
1381 1030
1382 dprintf("%p [%p]: event: %d\n", 1031 dump_printf("%p [%p]: event: %d\n",
1383 (void *)(offset + head), 1032 (void *)(offset + head),
1384 (void *)(long)event->header.size, 1033 (void *)(long)event->header.size,
1385 event->header.type); 1034 event->header.type);
1386 1035
1387 if (!size || process_event(event, offset, head) < 0) { 1036 if (!size || process_event(event, offset, head) < 0) {
1388 1037
1389 dprintf("%p [%p]: skipping unknown header type: %d\n", 1038 dump_printf("%p [%p]: skipping unknown header type: %d\n",
1390 (void *)(offset + head), 1039 (void *)(offset + head),
1391 (void *)(long)(event->header.size), 1040 (void *)(long)(event->header.size),
1392 event->header.type); 1041 event->header.type);
@@ -1406,23 +1055,23 @@ more:
1406 1055
1407 head += size; 1056 head += size;
1408 1057
1409 if (offset + head < (unsigned long)stat.st_size) 1058 if (offset + head < (unsigned long)input_stat.st_size)
1410 goto more; 1059 goto more;
1411 1060
1412 rc = EXIT_SUCCESS; 1061 rc = EXIT_SUCCESS;
1413 close(input); 1062 close(input);
1414 1063
1415 dprintf(" IP events: %10ld\n", total); 1064 dump_printf(" IP events: %10ld\n", total);
1416 dprintf(" mmap events: %10ld\n", total_mmap); 1065 dump_printf(" mmap events: %10ld\n", total_mmap);
1417 dprintf(" comm events: %10ld\n", total_comm); 1066 dump_printf(" comm events: %10ld\n", total_comm);
1418 dprintf(" fork events: %10ld\n", total_fork); 1067 dump_printf(" fork events: %10ld\n", total_fork);
1419 dprintf(" unknown events: %10ld\n", total_unknown); 1068 dump_printf(" unknown events: %10ld\n", total_unknown);
1420 1069
1421 if (dump_trace) 1070 if (dump_trace)
1422 return 0; 1071 return 0;
1423 1072
1424 if (verbose >= 3) 1073 if (verbose >= 3)
1425 threads__fprintf(stdout); 1074 threads__fprintf(stdout, &threads);
1426 1075
1427 if (verbose >= 2) 1076 if (verbose >= 2)
1428 dsos__fprintf(stdout); 1077 dsos__fprintf(stdout);
@@ -1450,7 +1099,7 @@ static const struct option options[] = {
1450 "be more verbose (show symbol address, etc)"), 1099 "be more verbose (show symbol address, etc)"),
1451 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1100 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1452 "dump raw trace in ASCII"), 1101 "dump raw trace in ASCII"),
1453 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1102 OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"),
1454 OPT_BOOLEAN('m', "modules", &modules, 1103 OPT_BOOLEAN('m', "modules", &modules,
1455 "load module symbols - WARNING: use only with -k and LIVE kernel"), 1104 "load module symbols - WARNING: use only with -k and LIVE kernel"),
1456 OPT_BOOLEAN('l', "print-line", &print_line, 1105 OPT_BOOLEAN('l', "print-line", &print_line,
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 2599d86a733b..4fb8734a796e 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -456,6 +456,7 @@ int cmd_help(int argc, const char **argv, const char *prefix __used)
456 break; 456 break;
457 case HELP_FORMAT_WEB: 457 case HELP_FORMAT_WEB:
458 show_html_page(argv[0]); 458 show_html_page(argv[0]);
459 default:
459 break; 460 break;
460 } 461 }
461 462
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 89a5ddcd1ded..6a5db675ee4f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -15,6 +15,8 @@
15#include "util/string.h" 15#include "util/string.h"
16 16
17#include "util/header.h" 17#include "util/header.h"
18#include "util/event.h"
19#include "util/debug.h"
18 20
19#include <unistd.h> 21#include <unistd.h>
20#include <sched.h> 22#include <sched.h>
@@ -42,7 +44,6 @@ static int inherit = 1;
42static int force = 0; 44static int force = 0;
43static int append_file = 0; 45static int append_file = 0;
44static int call_graph = 0; 46static int call_graph = 0;
45static int verbose = 0;
46static int inherit_stat = 0; 47static int inherit_stat = 0;
47static int no_samples = 0; 48static int no_samples = 0;
48static int sample_address = 0; 49static int sample_address = 0;
@@ -62,24 +63,6 @@ static int file_new = 1;
62 63
63struct perf_header *header; 64struct perf_header *header;
64 65
65struct mmap_event {
66 struct perf_event_header header;
67 u32 pid;
68 u32 tid;
69 u64 start;
70 u64 len;
71 u64 pgoff;
72 char filename[PATH_MAX];
73};
74
75struct comm_event {
76 struct perf_event_header header;
77 u32 pid;
78 u32 tid;
79 char comm[16];
80};
81
82
83struct mmap_data { 66struct mmap_data {
84 int counter; 67 int counter;
85 void *base; 68 void *base;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 8b2ec882e6e0..d2e28820ee60 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -17,19 +17,18 @@
17#include "util/string.h" 17#include "util/string.h"
18#include "util/callchain.h" 18#include "util/callchain.h"
19#include "util/strlist.h" 19#include "util/strlist.h"
20#include "util/values.h"
20 21
21#include "perf.h" 22#include "perf.h"
23#include "util/debug.h"
22#include "util/header.h" 24#include "util/header.h"
23 25
24#include "util/parse-options.h" 26#include "util/parse-options.h"
25#include "util/parse-events.h" 27#include "util/parse-events.h"
26 28
27#define SHOW_KERNEL 1 29#include "util/thread.h"
28#define SHOW_USER 2
29#define SHOW_HV 4
30 30
31static char const *input_name = "perf.data"; 31static char const *input_name = "perf.data";
32static char *vmlinux = NULL;
33 32
34static char default_sort_order[] = "comm,dso,symbol"; 33static char default_sort_order[] = "comm,dso,symbol";
35static char *sort_order = default_sort_order; 34static char *sort_order = default_sort_order;
@@ -42,18 +41,15 @@ static int force;
42static int input; 41static int input;
43static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; 42static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
44 43
45static int dump_trace = 0;
46#define dprintf(x...) do { if (dump_trace) printf(x); } while (0)
47#define cdprintf(x...) do { if (dump_trace) color_fprintf(stdout, color, x); } while (0)
48
49static int verbose;
50#define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0)
51
52static int modules;
53
54static int full_paths; 44static int full_paths;
55static int show_nr_samples; 45static int show_nr_samples;
56 46
47static int show_threads;
48static struct perf_read_values show_threads_values;
49
50static char default_pretty_printing_style[] = "normal";
51static char *pretty_printing_style = default_pretty_printing_style;
52
57static unsigned long page_size; 53static unsigned long page_size;
58static unsigned long mmap_window = 32; 54static unsigned long mmap_window = 32;
59 55
@@ -67,6 +63,15 @@ static char callchain_default_opt[] = "fractal,0.5";
67 63
68static int callchain; 64static int callchain;
69 65
66static char __cwd[PATH_MAX];
67static char *cwd = __cwd;
68static int cwdlen;
69
70static struct rb_root threads;
71static struct thread *last_match;
72
73static struct perf_header *header;
74
70static 75static
71struct callchain_param callchain_param = { 76struct callchain_param callchain_param = {
72 .mode = CHAIN_GRAPH_REL, 77 .mode = CHAIN_GRAPH_REL,
@@ -75,59 +80,6 @@ struct callchain_param callchain_param = {
75 80
76static u64 sample_type; 81static u64 sample_type;
77 82
78struct ip_event {
79 struct perf_event_header header;
80 u64 ip;
81 u32 pid, tid;
82 unsigned char __more_data[];
83};
84
85struct mmap_event {
86 struct perf_event_header header;
87 u32 pid, tid;
88 u64 start;
89 u64 len;
90 u64 pgoff;
91 char filename[PATH_MAX];
92};
93
94struct comm_event {
95 struct perf_event_header header;
96 u32 pid, tid;
97 char comm[16];
98};
99
100struct fork_event {
101 struct perf_event_header header;
102 u32 pid, ppid;
103 u32 tid, ptid;
104};
105
106struct lost_event {
107 struct perf_event_header header;
108 u64 id;
109 u64 lost;
110};
111
112struct read_event {
113 struct perf_event_header header;
114 u32 pid,tid;
115 u64 value;
116 u64 time_enabled;
117 u64 time_running;
118 u64 id;
119};
120
121typedef union event_union {
122 struct perf_event_header header;
123 struct ip_event ip;
124 struct mmap_event mmap;
125 struct comm_event comm;
126 struct fork_event fork;
127 struct lost_event lost;
128 struct read_event read;
129} event_t;
130
131static int repsep_fprintf(FILE *fp, const char *fmt, ...) 83static int repsep_fprintf(FILE *fp, const char *fmt, ...)
132{ 84{
133 int n; 85 int n;
@@ -141,6 +93,7 @@ static int repsep_fprintf(FILE *fp, const char *fmt, ...)
141 n = vasprintf(&bf, fmt, ap); 93 n = vasprintf(&bf, fmt, ap);
142 if (n > 0) { 94 if (n > 0) {
143 char *sep = bf; 95 char *sep = bf;
96
144 while (1) { 97 while (1) {
145 sep = strchr(sep, *field_sep); 98 sep = strchr(sep, *field_sep);
146 if (sep == NULL) 99 if (sep == NULL)
@@ -155,396 +108,10 @@ static int repsep_fprintf(FILE *fp, const char *fmt, ...)
155 return n; 108 return n;
156} 109}
157 110
158static LIST_HEAD(dsos);
159static struct dso *kernel_dso;
160static struct dso *vdso;
161static struct dso *hypervisor_dso;
162
163static void dsos__add(struct dso *dso)
164{
165 list_add_tail(&dso->node, &dsos);
166}
167
168static struct dso *dsos__find(const char *name)
169{
170 struct dso *pos;
171
172 list_for_each_entry(pos, &dsos, node)
173 if (strcmp(pos->name, name) == 0)
174 return pos;
175 return NULL;
176}
177
178static struct dso *dsos__findnew(const char *name)
179{
180 struct dso *dso = dsos__find(name);
181 int nr;
182
183 if (dso)
184 return dso;
185
186 dso = dso__new(name, 0);
187 if (!dso)
188 goto out_delete_dso;
189
190 nr = dso__load(dso, NULL, verbose);
191 if (nr < 0) {
192 eprintf("Failed to open: %s\n", name);
193 goto out_delete_dso;
194 }
195 if (!nr)
196 eprintf("No symbols found in: %s, maybe install a debug package?\n", name);
197
198 dsos__add(dso);
199
200 return dso;
201
202out_delete_dso:
203 dso__delete(dso);
204 return NULL;
205}
206
207static void dsos__fprintf(FILE *fp)
208{
209 struct dso *pos;
210
211 list_for_each_entry(pos, &dsos, node)
212 dso__fprintf(pos, fp);
213}
214
215static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
216{
217 return dso__find_symbol(dso, ip);
218}
219
220static int load_kernel(void)
221{
222 int err;
223
224 kernel_dso = dso__new("[kernel]", 0);
225 if (!kernel_dso)
226 return -1;
227
228 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules);
229 if (err <= 0) {
230 dso__delete(kernel_dso);
231 kernel_dso = NULL;
232 } else
233 dsos__add(kernel_dso);
234
235 vdso = dso__new("[vdso]", 0);
236 if (!vdso)
237 return -1;
238
239 vdso->find_symbol = vdso__find_symbol;
240
241 dsos__add(vdso);
242
243 hypervisor_dso = dso__new("[hypervisor]", 0);
244 if (!hypervisor_dso)
245 return -1;
246 dsos__add(hypervisor_dso);
247
248 return err;
249}
250
251static char __cwd[PATH_MAX];
252static char *cwd = __cwd;
253static int cwdlen;
254
255static int strcommon(const char *pathname)
256{
257 int n = 0;
258
259 while (n < cwdlen && pathname[n] == cwd[n])
260 ++n;
261
262 return n;
263}
264
265struct map {
266 struct list_head node;
267 u64 start;
268 u64 end;
269 u64 pgoff;
270 u64 (*map_ip)(struct map *, u64);
271 struct dso *dso;
272};
273
274static u64 map__map_ip(struct map *map, u64 ip)
275{
276 return ip - map->start + map->pgoff;
277}
278
279static u64 vdso__map_ip(struct map *map __used, u64 ip)
280{
281 return ip;
282}
283
284static inline int is_anon_memory(const char *filename)
285{
286 return strcmp(filename, "//anon") == 0;
287}
288
289static struct map *map__new(struct mmap_event *event)
290{
291 struct map *self = malloc(sizeof(*self));
292
293 if (self != NULL) {
294 const char *filename = event->filename;
295 char newfilename[PATH_MAX];
296 int anon;
297
298 if (cwd) {
299 int n = strcommon(filename);
300
301 if (n == cwdlen) {
302 snprintf(newfilename, sizeof(newfilename),
303 ".%s", filename + n);
304 filename = newfilename;
305 }
306 }
307
308 anon = is_anon_memory(filename);
309
310 if (anon) {
311 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid);
312 filename = newfilename;
313 }
314
315 self->start = event->start;
316 self->end = event->start + event->len;
317 self->pgoff = event->pgoff;
318
319 self->dso = dsos__findnew(filename);
320 if (self->dso == NULL)
321 goto out_delete;
322
323 if (self->dso == vdso || anon)
324 self->map_ip = vdso__map_ip;
325 else
326 self->map_ip = map__map_ip;
327 }
328 return self;
329out_delete:
330 free(self);
331 return NULL;
332}
333
334static struct map *map__clone(struct map *self)
335{
336 struct map *map = malloc(sizeof(*self));
337
338 if (!map)
339 return NULL;
340
341 memcpy(map, self, sizeof(*self));
342
343 return map;
344}
345
346static int map__overlap(struct map *l, struct map *r)
347{
348 if (l->start > r->start) {
349 struct map *t = l;
350 l = r;
351 r = t;
352 }
353
354 if (l->end > r->start)
355 return 1;
356
357 return 0;
358}
359
360static size_t map__fprintf(struct map *self, FILE *fp)
361{
362 return fprintf(fp, " %Lx-%Lx %Lx %s\n",
363 self->start, self->end, self->pgoff, self->dso->name);
364}
365
366
367struct thread {
368 struct rb_node rb_node;
369 struct list_head maps;
370 pid_t pid;
371 char *comm;
372};
373
374static struct thread *thread__new(pid_t pid)
375{
376 struct thread *self = malloc(sizeof(*self));
377
378 if (self != NULL) {
379 self->pid = pid;
380 self->comm = malloc(32);
381 if (self->comm)
382 snprintf(self->comm, 32, ":%d", self->pid);
383 INIT_LIST_HEAD(&self->maps);
384 }
385
386 return self;
387}
388
389static unsigned int dsos__col_width, 111static unsigned int dsos__col_width,
390 comms__col_width, 112 comms__col_width,
391 threads__col_width; 113 threads__col_width;
392 114
393static int thread__set_comm(struct thread *self, const char *comm)
394{
395 if (self->comm)
396 free(self->comm);
397 self->comm = strdup(comm);
398 if (!self->comm)
399 return -ENOMEM;
400
401 if (!col_width_list_str && !field_sep &&
402 (!comm_list || strlist__has_entry(comm_list, comm))) {
403 unsigned int slen = strlen(comm);
404 if (slen > comms__col_width) {
405 comms__col_width = slen;
406 threads__col_width = slen + 6;
407 }
408 }
409
410 return 0;
411}
412
413static size_t thread__fprintf(struct thread *self, FILE *fp)
414{
415 struct map *pos;
416 size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm);
417
418 list_for_each_entry(pos, &self->maps, node)
419 ret += map__fprintf(pos, fp);
420
421 return ret;
422}
423
424
425static struct rb_root threads;
426static struct thread *last_match;
427
428static struct thread *threads__findnew(pid_t pid)
429{
430 struct rb_node **p = &threads.rb_node;
431 struct rb_node *parent = NULL;
432 struct thread *th;
433
434 /*
435 * Font-end cache - PID lookups come in blocks,
436 * so most of the time we dont have to look up
437 * the full rbtree:
438 */
439 if (last_match && last_match->pid == pid)
440 return last_match;
441
442 while (*p != NULL) {
443 parent = *p;
444 th = rb_entry(parent, struct thread, rb_node);
445
446 if (th->pid == pid) {
447 last_match = th;
448 return th;
449 }
450
451 if (pid < th->pid)
452 p = &(*p)->rb_left;
453 else
454 p = &(*p)->rb_right;
455 }
456
457 th = thread__new(pid);
458 if (th != NULL) {
459 rb_link_node(&th->rb_node, parent, p);
460 rb_insert_color(&th->rb_node, &threads);
461 last_match = th;
462 }
463
464 return th;
465}
466
467static void thread__insert_map(struct thread *self, struct map *map)
468{
469 struct map *pos, *tmp;
470
471 list_for_each_entry_safe(pos, tmp, &self->maps, node) {
472 if (map__overlap(pos, map)) {
473 if (verbose >= 2) {
474 printf("overlapping maps:\n");
475 map__fprintf(map, stdout);
476 map__fprintf(pos, stdout);
477 }
478
479 if (map->start <= pos->start && map->end > pos->start)
480 pos->start = map->end;
481
482 if (map->end >= pos->end && map->start < pos->end)
483 pos->end = map->start;
484
485 if (verbose >= 2) {
486 printf("after collision:\n");
487 map__fprintf(pos, stdout);
488 }
489
490 if (pos->start >= pos->end) {
491 list_del_init(&pos->node);
492 free(pos);
493 }
494 }
495 }
496
497 list_add_tail(&map->node, &self->maps);
498}
499
500static int thread__fork(struct thread *self, struct thread *parent)
501{
502 struct map *map;
503
504 if (self->comm)
505 free(self->comm);
506 self->comm = strdup(parent->comm);
507 if (!self->comm)
508 return -ENOMEM;
509
510 list_for_each_entry(map, &parent->maps, node) {
511 struct map *new = map__clone(map);
512 if (!new)
513 return -ENOMEM;
514 thread__insert_map(self, new);
515 }
516
517 return 0;
518}
519
520static struct map *thread__find_map(struct thread *self, u64 ip)
521{
522 struct map *pos;
523
524 if (self == NULL)
525 return NULL;
526
527 list_for_each_entry(pos, &self->maps, node)
528 if (ip >= pos->start && ip <= pos->end)
529 return pos;
530
531 return NULL;
532}
533
534static size_t threads__fprintf(FILE *fp)
535{
536 size_t ret = 0;
537 struct rb_node *nd;
538
539 for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
540 struct thread *pos = rb_entry(nd, struct thread, rb_node);
541
542 ret += thread__fprintf(pos, fp);
543 }
544
545 return ret;
546}
547
548/* 115/*
549 * histogram, sorted on item, collects counts 116 * histogram, sorted on item, collects counts
550 */ 117 */
@@ -574,7 +141,7 @@ struct hist_entry {
574struct sort_entry { 141struct sort_entry {
575 struct list_head list; 142 struct list_head list;
576 143
577 char *header; 144 const char *header;
578 145
579 int64_t (*cmp)(struct hist_entry *, struct hist_entry *); 146 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
580 int64_t (*collapse)(struct hist_entry *, struct hist_entry *); 147 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
@@ -758,7 +325,7 @@ static int sort__need_collapse = 0;
758static int sort__has_parent = 0; 325static int sort__has_parent = 0;
759 326
760struct sort_dimension { 327struct sort_dimension {
761 char *name; 328 const char *name;
762 struct sort_entry *entry; 329 struct sort_entry *entry;
763 int taken; 330 int taken;
764}; 331};
@@ -773,7 +340,7 @@ static struct sort_dimension sort_dimensions[] = {
773 340
774static LIST_HEAD(hist_entry__sort_list); 341static LIST_HEAD(hist_entry__sort_list);
775 342
776static int sort_dimension__add(char *tok) 343static int sort_dimension__add(const char *tok)
777{ 344{
778 unsigned int i; 345 unsigned int i;
779 346
@@ -1032,6 +599,7 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
1032 case CHAIN_GRAPH_REL: 599 case CHAIN_GRAPH_REL:
1033 ret += callchain__fprintf_graph(fp, chain, 600 ret += callchain__fprintf_graph(fp, chain,
1034 total_samples, 1, 1); 601 total_samples, 1, 1);
602 case CHAIN_NONE:
1035 default: 603 default:
1036 break; 604 break;
1037 } 605 }
@@ -1098,6 +666,27 @@ static void dso__calc_col_width(struct dso *self)
1098 self->slen_calculated = 1; 666 self->slen_calculated = 1;
1099} 667}
1100 668
669static int thread__set_comm_adjust(struct thread *self, const char *comm)
670{
671 int ret = thread__set_comm(self, comm);
672
673 if (ret)
674 return ret;
675
676 if (!col_width_list_str && !field_sep &&
677 (!comm_list || strlist__has_entry(comm_list, comm))) {
678 unsigned int slen = strlen(comm);
679
680 if (slen > comms__col_width) {
681 comms__col_width = slen;
682 threads__col_width = slen + 6;
683 }
684 }
685
686 return 0;
687}
688
689
1101static struct symbol * 690static struct symbol *
1102resolve_symbol(struct thread *thread, struct map **mapp, 691resolve_symbol(struct thread *thread, struct map **mapp,
1103 struct dso **dsop, u64 *ipp) 692 struct dso **dsop, u64 *ipp)
@@ -1141,8 +730,8 @@ got_map:
1141 if ((long long)ip < 0) 730 if ((long long)ip < 0)
1142 dso = kernel_dso; 731 dso = kernel_dso;
1143 } 732 }
1144 dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 733 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
1145 dprintf(" ...... map: %Lx -> %Lx\n", *ipp, ip); 734 dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip);
1146 *ipp = ip; 735 *ipp = ip;
1147 736
1148 if (dsop) 737 if (dsop)
@@ -1398,6 +987,9 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
1398 size_t ret = 0; 987 size_t ret = 0;
1399 unsigned int width; 988 unsigned int width;
1400 char *col_width = col_width_list_str; 989 char *col_width = col_width_list_str;
990 int raw_printing_style;
991
992 raw_printing_style = !strcmp(pretty_printing_style, "raw");
1401 993
1402 init_rem_hits(); 994 init_rem_hits();
1403 995
@@ -1474,15 +1066,19 @@ print_entries:
1474 1066
1475 free(rem_sq_bracket); 1067 free(rem_sq_bracket);
1476 1068
1069 if (show_threads)
1070 perf_read_values_display(fp, &show_threads_values,
1071 raw_printing_style);
1072
1477 return ret; 1073 return ret;
1478} 1074}
1479 1075
1480static void register_idle_thread(void) 1076static void register_idle_thread(void)
1481{ 1077{
1482 struct thread *thread = threads__findnew(0); 1078 struct thread *thread = threads__findnew(0, &threads, &last_match);
1483 1079
1484 if (thread == NULL || 1080 if (thread == NULL ||
1485 thread__set_comm(thread, "[idle]")) { 1081 thread__set_comm_adjust(thread, "[idle]")) {
1486 fprintf(stderr, "problem inserting idle task.\n"); 1082 fprintf(stderr, "problem inserting idle task.\n");
1487 exit(-1); 1083 exit(-1);
1488 } 1084 }
@@ -1514,7 +1110,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1514 char level; 1110 char level;
1515 int show = 0; 1111 int show = 0;
1516 struct dso *dso = NULL; 1112 struct dso *dso = NULL;
1517 struct thread *thread = threads__findnew(event->ip.pid); 1113 struct thread *thread;
1518 u64 ip = event->ip.ip; 1114 u64 ip = event->ip.ip;
1519 u64 period = 1; 1115 u64 period = 1;
1520 struct map *map = NULL; 1116 struct map *map = NULL;
@@ -1522,12 +1118,14 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1522 struct ip_callchain *chain = NULL; 1118 struct ip_callchain *chain = NULL;
1523 int cpumode; 1119 int cpumode;
1524 1120
1121 thread = threads__findnew(event->ip.pid, &threads, &last_match);
1122
1525 if (sample_type & PERF_SAMPLE_PERIOD) { 1123 if (sample_type & PERF_SAMPLE_PERIOD) {
1526 period = *(u64 *)more_data; 1124 period = *(u64 *)more_data;
1527 more_data += sizeof(u64); 1125 more_data += sizeof(u64);
1528 } 1126 }
1529 1127
1530 dprintf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n", 1128 dump_printf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n",
1531 (void *)(offset + head), 1129 (void *)(offset + head),
1532 (void *)(long)(event->header.size), 1130 (void *)(long)(event->header.size),
1533 event->header.misc, 1131 event->header.misc,
@@ -1540,7 +1138,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1540 1138
1541 chain = (void *)more_data; 1139 chain = (void *)more_data;
1542 1140
1543 dprintf("... chain: nr:%Lu\n", chain->nr); 1141 dump_printf("... chain: nr:%Lu\n", chain->nr);
1544 1142
1545 if (validate_chain(chain, event) < 0) { 1143 if (validate_chain(chain, event) < 0) {
1546 eprintf("call-chain problem with event, skipping it.\n"); 1144 eprintf("call-chain problem with event, skipping it.\n");
@@ -1549,11 +1147,11 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1549 1147
1550 if (dump_trace) { 1148 if (dump_trace) {
1551 for (i = 0; i < chain->nr; i++) 1149 for (i = 0; i < chain->nr; i++)
1552 dprintf("..... %2d: %016Lx\n", i, chain->ips[i]); 1150 dump_printf("..... %2d: %016Lx\n", i, chain->ips[i]);
1553 } 1151 }
1554 } 1152 }
1555 1153
1556 dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid); 1154 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
1557 1155
1558 if (thread == NULL) { 1156 if (thread == NULL) {
1559 eprintf("problem processing %d event, skipping it.\n", 1157 eprintf("problem processing %d event, skipping it.\n",
@@ -1572,7 +1170,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1572 1170
1573 dso = kernel_dso; 1171 dso = kernel_dso;
1574 1172
1575 dprintf(" ...... dso: %s\n", dso->name); 1173 dump_printf(" ...... dso: %s\n", dso->name);
1576 1174
1577 } else if (cpumode == PERF_EVENT_MISC_USER) { 1175 } else if (cpumode == PERF_EVENT_MISC_USER) {
1578 1176
@@ -1585,7 +1183,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1585 1183
1586 dso = hypervisor_dso; 1184 dso = hypervisor_dso;
1587 1185
1588 dprintf(" ...... dso: [hypervisor]\n"); 1186 dump_printf(" ...... dso: [hypervisor]\n");
1589 } 1187 }
1590 1188
1591 if (show & show_mask) { 1189 if (show & show_mask) {
@@ -1611,10 +1209,12 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1611static int 1209static int
1612process_mmap_event(event_t *event, unsigned long offset, unsigned long head) 1210process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
1613{ 1211{
1614 struct thread *thread = threads__findnew(event->mmap.pid); 1212 struct thread *thread;
1615 struct map *map = map__new(&event->mmap); 1213 struct map *map = map__new(&event->mmap, cwd, cwdlen);
1616 1214
1617 dprintf("%p [%p]: PERF_EVENT_MMAP %d/%d: [%p(%p) @ %p]: %s\n", 1215 thread = threads__findnew(event->mmap.pid, &threads, &last_match);
1216
1217 dump_printf("%p [%p]: PERF_EVENT_MMAP %d/%d: [%p(%p) @ %p]: %s\n",
1618 (void *)(offset + head), 1218 (void *)(offset + head),
1619 (void *)(long)(event->header.size), 1219 (void *)(long)(event->header.size),
1620 event->mmap.pid, 1220 event->mmap.pid,
@@ -1625,7 +1225,7 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
1625 event->mmap.filename); 1225 event->mmap.filename);
1626 1226
1627 if (thread == NULL || map == NULL) { 1227 if (thread == NULL || map == NULL) {
1628 dprintf("problem processing PERF_EVENT_MMAP, skipping event.\n"); 1228 dump_printf("problem processing PERF_EVENT_MMAP, skipping event.\n");
1629 return 0; 1229 return 0;
1630 } 1230 }
1631 1231
@@ -1638,16 +1238,18 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
1638static int 1238static int
1639process_comm_event(event_t *event, unsigned long offset, unsigned long head) 1239process_comm_event(event_t *event, unsigned long offset, unsigned long head)
1640{ 1240{
1641 struct thread *thread = threads__findnew(event->comm.pid); 1241 struct thread *thread;
1242
1243 thread = threads__findnew(event->comm.pid, &threads, &last_match);
1642 1244
1643 dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n", 1245 dump_printf("%p [%p]: PERF_EVENT_COMM: %s:%d\n",
1644 (void *)(offset + head), 1246 (void *)(offset + head),
1645 (void *)(long)(event->header.size), 1247 (void *)(long)(event->header.size),
1646 event->comm.comm, event->comm.pid); 1248 event->comm.comm, event->comm.pid);
1647 1249
1648 if (thread == NULL || 1250 if (thread == NULL ||
1649 thread__set_comm(thread, event->comm.comm)) { 1251 thread__set_comm_adjust(thread, event->comm.comm)) {
1650 dprintf("problem processing PERF_EVENT_COMM, skipping event.\n"); 1252 dump_printf("problem processing PERF_EVENT_COMM, skipping event.\n");
1651 return -1; 1253 return -1;
1652 } 1254 }
1653 total_comm++; 1255 total_comm++;
@@ -1658,10 +1260,13 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
1658static int 1260static int
1659process_task_event(event_t *event, unsigned long offset, unsigned long head) 1261process_task_event(event_t *event, unsigned long offset, unsigned long head)
1660{ 1262{
1661 struct thread *thread = threads__findnew(event->fork.pid); 1263 struct thread *thread;
1662 struct thread *parent = threads__findnew(event->fork.ppid); 1264 struct thread *parent;
1663 1265
1664 dprintf("%p [%p]: PERF_EVENT_%s: (%d:%d):(%d:%d)\n", 1266 thread = threads__findnew(event->fork.pid, &threads, &last_match);
1267 parent = threads__findnew(event->fork.ppid, &threads, &last_match);
1268
1269 dump_printf("%p [%p]: PERF_EVENT_%s: (%d:%d):(%d:%d)\n",
1665 (void *)(offset + head), 1270 (void *)(offset + head),
1666 (void *)(long)(event->header.size), 1271 (void *)(long)(event->header.size),
1667 event->header.type == PERF_EVENT_FORK ? "FORK" : "EXIT", 1272 event->header.type == PERF_EVENT_FORK ? "FORK" : "EXIT",
@@ -1679,7 +1284,7 @@ process_task_event(event_t *event, unsigned long offset, unsigned long head)
1679 return 0; 1284 return 0;
1680 1285
1681 if (!thread || !parent || thread__fork(thread, parent)) { 1286 if (!thread || !parent || thread__fork(thread, parent)) {
1682 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); 1287 dump_printf("problem processing PERF_EVENT_FORK, skipping event.\n");
1683 return -1; 1288 return -1;
1684 } 1289 }
1685 total_fork++; 1290 total_fork++;
@@ -1690,7 +1295,7 @@ process_task_event(event_t *event, unsigned long offset, unsigned long head)
1690static int 1295static int
1691process_lost_event(event_t *event, unsigned long offset, unsigned long head) 1296process_lost_event(event_t *event, unsigned long offset, unsigned long head)
1692{ 1297{
1693 dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", 1298 dump_printf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n",
1694 (void *)(offset + head), 1299 (void *)(offset + head),
1695 (void *)(long)(event->header.size), 1300 (void *)(long)(event->header.size),
1696 event->lost.id, 1301 event->lost.id,
@@ -1701,67 +1306,24 @@ process_lost_event(event_t *event, unsigned long offset, unsigned long head)
1701 return 0; 1306 return 0;
1702} 1307}
1703 1308
1704static void trace_event(event_t *event) 1309static int
1705{ 1310process_read_event(event_t *event, unsigned long offset, unsigned long head)
1706 unsigned char *raw_event = (void *)event;
1707 char *color = PERF_COLOR_BLUE;
1708 int i, j;
1709
1710 if (!dump_trace)
1711 return;
1712
1713 dprintf(".");
1714 cdprintf("\n. ... raw event: size %d bytes\n", event->header.size);
1715
1716 for (i = 0; i < event->header.size; i++) {
1717 if ((i & 15) == 0) {
1718 dprintf(".");
1719 cdprintf(" %04x: ", i);
1720 }
1721
1722 cdprintf(" %02x", raw_event[i]);
1723
1724 if (((i & 15) == 15) || i == event->header.size-1) {
1725 cdprintf(" ");
1726 for (j = 0; j < 15-(i & 15); j++)
1727 cdprintf(" ");
1728 for (j = 0; j < (i & 15); j++) {
1729 if (isprint(raw_event[i-15+j]))
1730 cdprintf("%c", raw_event[i-15+j]);
1731 else
1732 cdprintf(".");
1733 }
1734 cdprintf("\n");
1735 }
1736 }
1737 dprintf(".\n");
1738}
1739
1740static struct perf_header *header;
1741
1742static struct perf_counter_attr *perf_header__find_attr(u64 id)
1743{ 1311{
1744 int i; 1312 struct perf_counter_attr *attr;
1745 1313
1746 for (i = 0; i < header->attrs; i++) { 1314 attr = perf_header__find_attr(event->read.id, header);
1747 struct perf_header_attr *attr = header->attr[i];
1748 int j;
1749 1315
1750 for (j = 0; j < attr->ids; j++) { 1316 if (show_threads) {
1751 if (attr->id[j] == id) 1317 const char *name = attr ? __event_name(attr->type, attr->config)
1752 return &attr->attr; 1318 : "unknown";
1753 } 1319 perf_read_values_add_value(&show_threads_values,
1320 event->read.pid, event->read.tid,
1321 event->read.id,
1322 name,
1323 event->read.value);
1754 } 1324 }
1755 1325
1756 return NULL; 1326 dump_printf("%p [%p]: PERF_EVENT_READ: %d %d %s %Lu\n",
1757}
1758
1759static int
1760process_read_event(event_t *event, unsigned long offset, unsigned long head)
1761{
1762 struct perf_counter_attr *attr = perf_header__find_attr(event->read.id);
1763
1764 dprintf("%p [%p]: PERF_EVENT_READ: %d %d %s %Lu\n",
1765 (void *)(offset + head), 1327 (void *)(offset + head),
1766 (void *)(long)(event->header.size), 1328 (void *)(long)(event->header.size),
1767 event->read.pid, 1329 event->read.pid,
@@ -1813,35 +1375,21 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1813 return 0; 1375 return 0;
1814} 1376}
1815 1377
1816static u64 perf_header__sample_type(void)
1817{
1818 u64 sample_type = 0;
1819 int i;
1820
1821 for (i = 0; i < header->attrs; i++) {
1822 struct perf_header_attr *attr = header->attr[i];
1823
1824 if (!sample_type)
1825 sample_type = attr->attr.sample_type;
1826 else if (sample_type != attr->attr.sample_type)
1827 die("non matching sample_type");
1828 }
1829
1830 return sample_type;
1831}
1832
1833static int __cmd_report(void) 1378static int __cmd_report(void)
1834{ 1379{
1835 int ret, rc = EXIT_FAILURE; 1380 int ret, rc = EXIT_FAILURE;
1836 unsigned long offset = 0; 1381 unsigned long offset = 0;
1837 unsigned long head, shift; 1382 unsigned long head, shift;
1838 struct stat stat; 1383 struct stat input_stat;
1839 event_t *event; 1384 event_t *event;
1840 uint32_t size; 1385 uint32_t size;
1841 char *buf; 1386 char *buf;
1842 1387
1843 register_idle_thread(); 1388 register_idle_thread();
1844 1389
1390 if (show_threads)
1391 perf_read_values_init(&show_threads_values);
1392
1845 input = open(input_name, O_RDONLY); 1393 input = open(input_name, O_RDONLY);
1846 if (input < 0) { 1394 if (input < 0) {
1847 fprintf(stderr, " failed to open file: %s", input_name); 1395 fprintf(stderr, " failed to open file: %s", input_name);
@@ -1851,18 +1399,18 @@ static int __cmd_report(void)
1851 exit(-1); 1399 exit(-1);
1852 } 1400 }
1853 1401
1854 ret = fstat(input, &stat); 1402 ret = fstat(input, &input_stat);
1855 if (ret < 0) { 1403 if (ret < 0) {
1856 perror("failed to stat file"); 1404 perror("failed to stat file");
1857 exit(-1); 1405 exit(-1);
1858 } 1406 }
1859 1407
1860 if (!force && (stat.st_uid != geteuid())) { 1408 if (!force && (input_stat.st_uid != geteuid())) {
1861 fprintf(stderr, "file: %s not owned by current user\n", input_name); 1409 fprintf(stderr, "file: %s not owned by current user\n", input_name);
1862 exit(-1); 1410 exit(-1);
1863 } 1411 }
1864 1412
1865 if (!stat.st_size) { 1413 if (!input_stat.st_size) {
1866 fprintf(stderr, "zero-sized file, nothing to do!\n"); 1414 fprintf(stderr, "zero-sized file, nothing to do!\n");
1867 exit(0); 1415 exit(0);
1868 } 1416 }
@@ -1870,7 +1418,7 @@ static int __cmd_report(void)
1870 header = perf_header__read(input); 1418 header = perf_header__read(input);
1871 head = header->data_offset; 1419 head = header->data_offset;
1872 1420
1873 sample_type = perf_header__sample_type(); 1421 sample_type = perf_header__sample_type(header);
1874 1422
1875 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) { 1423 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
1876 if (sort__has_parent) { 1424 if (sort__has_parent) {
@@ -1930,12 +1478,12 @@ more:
1930 size = 8; 1478 size = 8;
1931 1479
1932 if (head + event->header.size >= page_size * mmap_window) { 1480 if (head + event->header.size >= page_size * mmap_window) {
1933 int ret; 1481 int munmap_ret;
1934 1482
1935 shift = page_size * (head / page_size); 1483 shift = page_size * (head / page_size);
1936 1484
1937 ret = munmap(buf, page_size * mmap_window); 1485 munmap_ret = munmap(buf, page_size * mmap_window);
1938 assert(ret == 0); 1486 assert(munmap_ret == 0);
1939 1487
1940 offset += shift; 1488 offset += shift;
1941 head -= shift; 1489 head -= shift;
@@ -1944,14 +1492,14 @@ more:
1944 1492
1945 size = event->header.size; 1493 size = event->header.size;
1946 1494
1947 dprintf("\n%p [%p]: event: %d\n", 1495 dump_printf("\n%p [%p]: event: %d\n",
1948 (void *)(offset + head), 1496 (void *)(offset + head),
1949 (void *)(long)event->header.size, 1497 (void *)(long)event->header.size,
1950 event->header.type); 1498 event->header.type);
1951 1499
1952 if (!size || process_event(event, offset, head) < 0) { 1500 if (!size || process_event(event, offset, head) < 0) {
1953 1501
1954 dprintf("%p [%p]: skipping unknown header type: %d\n", 1502 dump_printf("%p [%p]: skipping unknown header type: %d\n",
1955 (void *)(offset + head), 1503 (void *)(offset + head),
1956 (void *)(long)(event->header.size), 1504 (void *)(long)(event->header.size),
1957 event->header.type); 1505 event->header.type);
@@ -1974,25 +1522,25 @@ more:
1974 if (offset + head >= header->data_offset + header->data_size) 1522 if (offset + head >= header->data_offset + header->data_size)
1975 goto done; 1523 goto done;
1976 1524
1977 if (offset + head < (unsigned long)stat.st_size) 1525 if (offset + head < (unsigned long)input_stat.st_size)
1978 goto more; 1526 goto more;
1979 1527
1980done: 1528done:
1981 rc = EXIT_SUCCESS; 1529 rc = EXIT_SUCCESS;
1982 close(input); 1530 close(input);
1983 1531
1984 dprintf(" IP events: %10ld\n", total); 1532 dump_printf(" IP events: %10ld\n", total);
1985 dprintf(" mmap events: %10ld\n", total_mmap); 1533 dump_printf(" mmap events: %10ld\n", total_mmap);
1986 dprintf(" comm events: %10ld\n", total_comm); 1534 dump_printf(" comm events: %10ld\n", total_comm);
1987 dprintf(" fork events: %10ld\n", total_fork); 1535 dump_printf(" fork events: %10ld\n", total_fork);
1988 dprintf(" lost events: %10ld\n", total_lost); 1536 dump_printf(" lost events: %10ld\n", total_lost);
1989 dprintf(" unknown events: %10ld\n", total_unknown); 1537 dump_printf(" unknown events: %10ld\n", total_unknown);
1990 1538
1991 if (dump_trace) 1539 if (dump_trace)
1992 return 0; 1540 return 0;
1993 1541
1994 if (verbose >= 3) 1542 if (verbose >= 3)
1995 threads__fprintf(stdout); 1543 threads__fprintf(stdout, &threads);
1996 1544
1997 if (verbose >= 2) 1545 if (verbose >= 2)
1998 dsos__fprintf(stdout); 1546 dsos__fprintf(stdout);
@@ -2001,6 +1549,9 @@ done:
2001 output__resort(total); 1549 output__resort(total);
2002 output__fprintf(stdout, total); 1550 output__fprintf(stdout, total);
2003 1551
1552 if (show_threads)
1553 perf_read_values_destroy(&show_threads_values);
1554
2004 return rc; 1555 return rc;
2005} 1556}
2006 1557
@@ -2069,12 +1620,16 @@ static const struct option options[] = {
2069 "be more verbose (show symbol address, etc)"), 1620 "be more verbose (show symbol address, etc)"),
2070 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1621 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
2071 "dump raw trace in ASCII"), 1622 "dump raw trace in ASCII"),
2072 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1623 OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"),
2073 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 1624 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
2074 OPT_BOOLEAN('m', "modules", &modules, 1625 OPT_BOOLEAN('m', "modules", &modules,
2075 "load module symbols - WARNING: use only with -k and LIVE kernel"), 1626 "load module symbols - WARNING: use only with -k and LIVE kernel"),
2076 OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples, 1627 OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,
2077 "Show a column with the number of samples"), 1628 "Show a column with the number of samples"),
1629 OPT_BOOLEAN('T', "threads", &show_threads,
1630 "Show per-thread event counters"),
1631 OPT_STRING(0, "pretty", &pretty_printing_style, "key",
1632 "pretty printing style key: normal raw"),
2078 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1633 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
2079 "sort by key(s): pid, comm, dso, symbol, parent"), 1634 "sort by key(s): pid, comm, dso, symbol, parent"),
2080 OPT_BOOLEAN('P', "full-paths", &full_paths, 1635 OPT_BOOLEAN('P', "full-paths", &full_paths,
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index b4b06c7903e1..1a2626230660 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -42,6 +42,8 @@
42#include "util/util.h" 42#include "util/util.h"
43#include "util/parse-options.h" 43#include "util/parse-options.h"
44#include "util/parse-events.h" 44#include "util/parse-events.h"
45#include "util/event.h"
46#include "util/debug.h"
45 47
46#include <sys/prctl.h> 48#include <sys/prctl.h>
47#include <math.h> 49#include <math.h>
@@ -63,7 +65,6 @@ static struct perf_counter_attr default_attrs[] = {
63#define MAX_RUN 100 65#define MAX_RUN 100
64 66
65static int system_wide = 0; 67static int system_wide = 0;
66static int verbose = 0;
67static unsigned int nr_cpus = 0; 68static unsigned int nr_cpus = 0;
68static int run_idx = 0; 69static int run_idx = 0;
69 70
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 7de28ce9ca26..62b55ecab2c6 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -27,6 +27,8 @@
27#include "util/parse-options.h" 27#include "util/parse-options.h"
28#include "util/parse-events.h" 28#include "util/parse-events.h"
29 29
30#include "util/debug.h"
31
30#include <assert.h> 32#include <assert.h>
31#include <fcntl.h> 33#include <fcntl.h>
32 34
@@ -68,8 +70,6 @@ static int group = 0;
68static unsigned int page_size; 70static unsigned int page_size;
69static unsigned int mmap_pages = 16; 71static unsigned int mmap_pages = 16;
70static int freq = 0; 72static int freq = 0;
71static int verbose = 0;
72static char *vmlinux = NULL;
73 73
74static int delay_secs = 2; 74static int delay_secs = 2;
75static int zero; 75static int zero;
@@ -122,7 +122,8 @@ static void parse_source(struct sym_entry *syme)
122 struct module *module; 122 struct module *module;
123 struct section *section = NULL; 123 struct section *section = NULL;
124 FILE *file; 124 FILE *file;
125 char command[PATH_MAX*2], *path = vmlinux; 125 char command[PATH_MAX*2];
126 const char *path = vmlinux_name;
126 u64 start, end, len; 127 u64 start, end, len;
127 128
128 if (!syme) 129 if (!syme)
@@ -338,8 +339,6 @@ static void show_details(struct sym_entry *syme)
338 printf("%d lines not displayed, maybe increase display entries [e]\n", more); 339 printf("%d lines not displayed, maybe increase display entries [e]\n", more);
339} 340}
340 341
341struct dso *kernel_dso;
342
343/* 342/*
344 * Symbols will be added here in record_ip and will get out 343 * Symbols will be added here in record_ip and will get out
345 * after decayed. 344 * after decayed.
@@ -491,10 +490,12 @@ static void print_sym_table(void)
491 ); 490 );
492 491
493 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { 492 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
494 struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node); 493 struct symbol *sym;
495 struct symbol *sym = (struct symbol *)(syme + 1);
496 double pcnt; 494 double pcnt;
497 495
496 syme = rb_entry(nd, struct sym_entry, rb_node);
497 sym = (struct symbol *)(syme + 1);
498
498 if (++printed > print_entries || (int)syme->snap_count < count_filter) 499 if (++printed > print_entries || (int)syme->snap_count < count_filter)
499 continue; 500 continue;
500 501
@@ -613,7 +614,7 @@ static void print_mapped_keys(void)
613 614
614 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); 615 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
615 616
616 if (vmlinux) { 617 if (vmlinux_name) {
617 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); 618 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter);
618 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 619 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
619 fprintf(stdout, "\t[S] stop annotation.\n"); 620 fprintf(stdout, "\t[S] stop annotation.\n");
@@ -642,7 +643,9 @@ static int key_mapped(int c)
642 case 'F': 643 case 'F':
643 case 's': 644 case 's':
644 case 'S': 645 case 'S':
645 return vmlinux ? 1 : 0; 646 return vmlinux_name ? 1 : 0;
647 default:
648 break;
646 } 649 }
647 650
648 return 0; 651 return 0;
@@ -728,6 +731,8 @@ static void handle_keypress(int c)
728 case 'z': 731 case 'z':
729 zero = ~zero; 732 zero = ~zero;
730 break; 733 break;
734 default:
735 break;
731 } 736 }
732} 737}
733 738
@@ -816,13 +821,13 @@ static int parse_symbols(void)
816{ 821{
817 struct rb_node *node; 822 struct rb_node *node;
818 struct symbol *sym; 823 struct symbol *sym;
819 int modules = vmlinux ? 1 : 0; 824 int use_modules = vmlinux_name ? 1 : 0;
820 825
821 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry)); 826 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry));
822 if (kernel_dso == NULL) 827 if (kernel_dso == NULL)
823 return -1; 828 return -1;
824 829
825 if (dso__load_kernel(kernel_dso, vmlinux, symbol_filter, verbose, modules) <= 0) 830 if (dso__load_kernel(kernel_dso, vmlinux_name, symbol_filter, verbose, use_modules) <= 0)
826 goto out_delete_dso; 831 goto out_delete_dso;
827 832
828 node = rb_first(&kernel_dso->syms); 833 node = rb_first(&kernel_dso->syms);
@@ -937,26 +942,6 @@ static void mmap_read_counter(struct mmap_data *md)
937 last_read = this_read; 942 last_read = this_read;
938 943
939 for (; old != head;) { 944 for (; old != head;) {
940 struct ip_event {
941 struct perf_event_header header;
942 u64 ip;
943 u32 pid, target_pid;
944 };
945 struct mmap_event {
946 struct perf_event_header header;
947 u32 pid, target_pid;
948 u64 start;
949 u64 len;
950 u64 pgoff;
951 char filename[PATH_MAX];
952 };
953
954 typedef union event_union {
955 struct perf_event_header header;
956 struct ip_event ip;
957 struct mmap_event mmap;
958 } event_t;
959
960 event_t *event = (event_t *)&data[old & md->mask]; 945 event_t *event = (event_t *)&data[old & md->mask];
961 946
962 event_t event_copy; 947 event_t event_copy;
@@ -1138,7 +1123,7 @@ static const struct option options[] = {
1138 "system-wide collection from all CPUs"), 1123 "system-wide collection from all CPUs"),
1139 OPT_INTEGER('C', "CPU", &profile_cpu, 1124 OPT_INTEGER('C', "CPU", &profile_cpu,
1140 "CPU to profile on"), 1125 "CPU to profile on"),
1141 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1126 OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"),
1142 OPT_INTEGER('m', "mmap-pages", &mmap_pages, 1127 OPT_INTEGER('m', "mmap-pages", &mmap_pages,
1143 "number of mmap data pages"), 1128 "number of mmap data pages"),
1144 OPT_INTEGER('r', "realtime", &realtime_prio, 1129 OPT_INTEGER('r', "realtime", &realtime_prio,
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 51d168230ee7..3a63e41fb44e 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -22,5 +22,6 @@ extern int cmd_stat(int argc, const char **argv, const char *prefix);
22extern int cmd_top(int argc, const char **argv, const char *prefix); 22extern int cmd_top(int argc, const char **argv, const char *prefix);
23extern int cmd_version(int argc, const char **argv, const char *prefix); 23extern int cmd_version(int argc, const char **argv, const char *prefix);
24extern int cmd_list(int argc, const char **argv, const char *prefix); 24extern int cmd_list(int argc, const char **argv, const char *prefix);
25extern int cmd_trace(int argc, const char **argv, const char *prefix);
25 26
26#endif 27#endif
diff --git a/tools/perf/util/abspath.c b/tools/perf/util/abspath.c
index 61d33b81fc97..a791dd467261 100644
--- a/tools/perf/util/abspath.c
+++ b/tools/perf/util/abspath.c
@@ -50,7 +50,8 @@ const char *make_absolute_path(const char *path)
50 die ("Could not get current working directory"); 50 die ("Could not get current working directory");
51 51
52 if (last_elem) { 52 if (last_elem) {
53 int len = strlen(buf); 53 len = strlen(buf);
54
54 if (len + strlen(last_elem) + 2 > PATH_MAX) 55 if (len + strlen(last_elem) + 2 > PATH_MAX)
55 die ("Too long path name: '%s/%s'", 56 die ("Too long path name: '%s/%s'",
56 buf, last_elem); 57 buf, last_elem);
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 4b50c412b9c5..6f8ea9d210b6 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -52,7 +52,6 @@ extern const char *perf_mailmap_file;
52extern void maybe_flush_or_die(FILE *, const char *); 52extern void maybe_flush_or_die(FILE *, const char *);
53extern int copy_fd(int ifd, int ofd); 53extern int copy_fd(int ifd, int ofd);
54extern int copy_file(const char *dst, const char *src, int mode); 54extern int copy_file(const char *dst, const char *src, int mode);
55extern ssize_t read_in_full(int fd, void *buf, size_t count);
56extern ssize_t write_in_full(int fd, const void *buf, size_t count); 55extern ssize_t write_in_full(int fd, const void *buf, size_t count);
57extern void write_or_die(int fd, const void *buf, size_t count); 56extern void write_or_die(int fd, const void *buf, size_t count);
58extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg); 57extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg);
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 011473411642..3b8380f1b478 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -50,6 +50,7 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
50 else 50 else
51 p = &(*p)->rb_right; 51 p = &(*p)->rb_right;
52 break; 52 break;
53 case CHAIN_NONE:
53 default: 54 default:
54 break; 55 break;
55 } 56 }
@@ -143,6 +144,7 @@ int register_callchain_param(struct callchain_param *param)
143 case CHAIN_FLAT: 144 case CHAIN_FLAT:
144 param->sort = sort_chain_flat; 145 param->sort = sort_chain_flat;
145 break; 146 break;
147 case CHAIN_NONE:
146 default: 148 default:
147 return -1; 149 return -1;
148 } 150 }
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index a926ae4f5a16..43cf3ea9e088 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -4,6 +4,7 @@
4#include "../perf.h" 4#include "../perf.h"
5#include <linux/list.h> 5#include <linux/list.h>
6#include <linux/rbtree.h> 6#include <linux/rbtree.h>
7#include "util.h"
7#include "symbol.h" 8#include "symbol.h"
8 9
9enum chain_mode { 10enum chain_mode {
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 90a044d1fe7d..e88bca55a599 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -166,7 +166,7 @@ int perf_color_default_config(const char *var, const char *value, void *cb)
166 return perf_default_config(var, value, cb); 166 return perf_default_config(var, value, cb);
167} 167}
168 168
169static int color_vfprintf(FILE *fp, const char *color, const char *fmt, 169static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
170 va_list args, const char *trail) 170 va_list args, const char *trail)
171{ 171{
172 int r = 0; 172 int r = 0;
@@ -191,6 +191,10 @@ static int color_vfprintf(FILE *fp, const char *color, const char *fmt,
191 return r; 191 return r;
192} 192}
193 193
194int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args)
195{
196 return __color_vfprintf(fp, color, fmt, args, NULL);
197}
194 198
195 199
196int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) 200int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
@@ -199,7 +203,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
199 int r; 203 int r;
200 204
201 va_start(args, fmt); 205 va_start(args, fmt);
202 r = color_vfprintf(fp, color, fmt, args, NULL); 206 r = color_vfprintf(fp, color, fmt, args);
203 va_end(args); 207 va_end(args);
204 return r; 208 return r;
205} 209}
@@ -209,7 +213,7 @@ int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...)
209 va_list args; 213 va_list args;
210 int r; 214 int r;
211 va_start(args, fmt); 215 va_start(args, fmt);
212 r = color_vfprintf(fp, color, fmt, args, "\n"); 216 r = __color_vfprintf(fp, color, fmt, args, "\n");
213 va_end(args); 217 va_end(args);
214 return r; 218 return r;
215} 219}
@@ -242,9 +246,9 @@ int color_fwrite_lines(FILE *fp, const char *color,
242 return 0; 246 return 0;
243} 247}
244 248
245char *get_percent_color(double percent) 249const char *get_percent_color(double percent)
246{ 250{
247 char *color = PERF_COLOR_NORMAL; 251 const char *color = PERF_COLOR_NORMAL;
248 252
249 /* 253 /*
250 * We color high-overhead entries in red, mid-overhead 254 * We color high-overhead entries in red, mid-overhead
@@ -263,7 +267,7 @@ char *get_percent_color(double percent)
263int percent_color_fprintf(FILE *fp, const char *fmt, double percent) 267int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
264{ 268{
265 int r; 269 int r;
266 char *color; 270 const char *color;
267 271
268 color = get_percent_color(percent); 272 color = get_percent_color(percent);
269 r = color_fprintf(fp, color, fmt, percent); 273 r = color_fprintf(fp, color, fmt, percent);
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 706cec50bd25..58d597564b99 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -32,10 +32,11 @@ int perf_color_default_config(const char *var, const char *value, void *cb);
32int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty); 32int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty);
33void color_parse(const char *value, const char *var, char *dst); 33void color_parse(const char *value, const char *var, char *dst);
34void color_parse_mem(const char *value, int len, const char *var, char *dst); 34void color_parse_mem(const char *value, int len, const char *var, char *dst);
35int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args);
35int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); 36int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
36int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); 37int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
37int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); 38int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
38int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 39int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
39char *get_percent_color(double percent); 40const char *get_percent_color(double percent);
40 41
41#endif /* COLOR_H */ 42#endif /* COLOR_H */
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 780df541006d..8784649109ce 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -160,17 +160,18 @@ static int get_extended_base_var(char *name, int baselen, int c)
160 name[baselen++] = '.'; 160 name[baselen++] = '.';
161 161
162 for (;;) { 162 for (;;) {
163 int c = get_next_char(); 163 int ch = get_next_char();
164 if (c == '\n') 164
165 if (ch == '\n')
165 return -1; 166 return -1;
166 if (c == '"') 167 if (ch == '"')
167 break; 168 break;
168 if (c == '\\') { 169 if (ch == '\\') {
169 c = get_next_char(); 170 ch = get_next_char();
170 if (c == '\n') 171 if (ch == '\n')
171 return -1; 172 return -1;
172 } 173 }
173 name[baselen++] = c; 174 name[baselen++] = ch;
174 if (baselen > MAXNAME / 2) 175 if (baselen > MAXNAME / 2)
175 return -1; 176 return -1;
176 } 177 }
@@ -530,6 +531,8 @@ static int store_aux(const char* key, const char* value, void *cb __used)
530 store.offset[store.seen] = ftell(config_file); 531 store.offset[store.seen] = ftell(config_file);
531 } 532 }
532 } 533 }
534 default:
535 break;
533 } 536 }
534 return 0; 537 return 0;
535} 538}
@@ -619,6 +622,7 @@ contline:
619 switch (contents[offset]) { 622 switch (contents[offset]) {
620 case '=': equal_offset = offset; break; 623 case '=': equal_offset = offset; break;
621 case ']': bracket_offset = offset; break; 624 case ']': bracket_offset = offset; break;
625 default: break;
622 } 626 }
623 if (offset > 0 && contents[offset-1] == '\\') { 627 if (offset > 0 && contents[offset-1] == '\\') {
624 offset_ = offset; 628 offset_ = offset;
@@ -742,9 +746,9 @@ int perf_config_set_multivar(const char* key, const char* value,
742 goto write_err_out; 746 goto write_err_out;
743 } else { 747 } else {
744 struct stat st; 748 struct stat st;
745 char* contents; 749 char *contents;
746 ssize_t contents_sz, copy_begin, copy_end; 750 ssize_t contents_sz, copy_begin, copy_end;
747 int i, new_line = 0; 751 int new_line = 0;
748 752
749 if (value_regex == NULL) 753 if (value_regex == NULL)
750 store.value_regex = NULL; 754 store.value_regex = NULL;
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
new file mode 100644
index 000000000000..e8ca98fe0bd4
--- /dev/null
+++ b/tools/perf/util/debug.c
@@ -0,0 +1,95 @@
1/* For general debugging purposes */
2
3#include "../perf.h"
4
5#include <string.h>
6#include <stdarg.h>
7#include <stdio.h>
8
9#include "color.h"
10#include "event.h"
11#include "debug.h"
12
13int verbose = 0;
14int dump_trace = 0;
15
16int eprintf(const char *fmt, ...)
17{
18 va_list args;
19 int ret = 0;
20
21 if (verbose) {
22 va_start(args, fmt);
23 ret = vfprintf(stderr, fmt, args);
24 va_end(args);
25 }
26
27 return ret;
28}
29
30int dump_printf(const char *fmt, ...)
31{
32 va_list args;
33 int ret = 0;
34
35 if (dump_trace) {
36 va_start(args, fmt);
37 ret = vprintf(fmt, args);
38 va_end(args);
39 }
40
41 return ret;
42}
43
44static int dump_printf_color(const char *fmt, const char *color, ...)
45{
46 va_list args;
47 int ret = 0;
48
49 if (dump_trace) {
50 va_start(args, color);
51 ret = color_vfprintf(stdout, color, fmt, args);
52 va_end(args);
53 }
54
55 return ret;
56}
57
58
59void trace_event(event_t *event)
60{
61 unsigned char *raw_event = (void *)event;
62 const char *color = PERF_COLOR_BLUE;
63 int i, j;
64
65 if (!dump_trace)
66 return;
67
68 dump_printf(".");
69 dump_printf_color("\n. ... raw event: size %d bytes\n", color,
70 event->header.size);
71
72 for (i = 0; i < event->header.size; i++) {
73 if ((i & 15) == 0) {
74 dump_printf(".");
75 dump_printf_color(" %04x: ", color, i);
76 }
77
78 dump_printf_color(" %02x", color, raw_event[i]);
79
80 if (((i & 15) == 15) || i == event->header.size-1) {
81 dump_printf_color(" ", color);
82 for (j = 0; j < 15-(i & 15); j++)
83 dump_printf_color(" ", color);
84 for (j = 0; j < (i & 15); j++) {
85 if (isprint(raw_event[i-15+j]))
86 dump_printf_color("%c", color,
87 raw_event[i-15+j]);
88 else
89 dump_printf_color(".", color);
90 }
91 dump_printf_color("\n", color);
92 }
93 }
94 dump_printf(".\n");
95}
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
new file mode 100644
index 000000000000..437eea58ce40
--- /dev/null
+++ b/tools/perf/util/debug.h
@@ -0,0 +1,8 @@
1/* For debugging general purposes */
2
3extern int verbose;
4extern int dump_trace;
5
6int eprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
7int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
8void trace_event(event_t *event);
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
new file mode 100644
index 000000000000..fa2d4e91d329
--- /dev/null
+++ b/tools/perf/util/event.h
@@ -0,0 +1,96 @@
1#ifndef __PERF_EVENT_H
2#define __PERF_EVENT_H
3#include "../perf.h"
4#include "util.h"
5#include <linux/list.h>
6
7enum {
8 SHOW_KERNEL = 1,
9 SHOW_USER = 2,
10 SHOW_HV = 4,
11};
12
13/*
14 * PERF_SAMPLE_IP | PERF_SAMPLE_TID | *
15 */
16struct ip_event {
17 struct perf_event_header header;
18 u64 ip;
19 u32 pid, tid;
20 unsigned char __more_data[];
21};
22
23struct mmap_event {
24 struct perf_event_header header;
25 u32 pid, tid;
26 u64 start;
27 u64 len;
28 u64 pgoff;
29 char filename[PATH_MAX];
30};
31
32struct comm_event {
33 struct perf_event_header header;
34 u32 pid, tid;
35 char comm[16];
36};
37
38struct fork_event {
39 struct perf_event_header header;
40 u32 pid, ppid;
41 u32 tid, ptid;
42};
43
44struct lost_event {
45 struct perf_event_header header;
46 u64 id;
47 u64 lost;
48};
49
50/*
51 * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID
52 */
53struct read_event {
54 struct perf_event_header header;
55 u32 pid,tid;
56 u64 value;
57 u64 time_enabled;
58 u64 time_running;
59 u64 id;
60};
61
62typedef union event_union {
63 struct perf_event_header header;
64 struct ip_event ip;
65 struct mmap_event mmap;
66 struct comm_event comm;
67 struct fork_event fork;
68 struct lost_event lost;
69 struct read_event read;
70} event_t;
71
72struct map {
73 struct list_head node;
74 u64 start;
75 u64 end;
76 u64 pgoff;
77 u64 (*map_ip)(struct map *, u64);
78 struct dso *dso;
79};
80
81static inline u64 map__map_ip(struct map *map, u64 ip)
82{
83 return ip - map->start + map->pgoff;
84}
85
86static inline u64 vdso__map_ip(struct map *map __used, u64 ip)
87{
88 return ip;
89}
90
91struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen);
92struct map *map__clone(struct map *self);
93int map__overlap(struct map *l, struct map *r);
94size_t map__fprintf(struct map *self, FILE *fp);
95
96#endif
diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
index 34a352867382..2745605dba11 100644
--- a/tools/perf/util/exec_cmd.c
+++ b/tools/perf/util/exec_cmd.c
@@ -6,7 +6,6 @@
6 6
7#define MAX_ARGS 32 7#define MAX_ARGS 32
8 8
9extern char **environ;
10static const char *argv_exec_path; 9static const char *argv_exec_path;
11static const char *argv0_path; 10static const char *argv0_path;
12 11
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index b92a457ca32e..a37a2221a0c3 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -243,3 +243,38 @@ struct perf_header *perf_header__read(int fd)
243 243
244 return self; 244 return self;
245} 245}
246
247u64 perf_header__sample_type(struct perf_header *header)
248{
249 u64 type = 0;
250 int i;
251
252 for (i = 0; i < header->attrs; i++) {
253 struct perf_header_attr *attr = header->attr[i];
254
255 if (!type)
256 type = attr->attr.sample_type;
257 else if (type != attr->attr.sample_type)
258 die("non matching sample_type");
259 }
260
261 return type;
262}
263
264struct perf_counter_attr *
265perf_header__find_attr(u64 id, struct perf_header *header)
266{
267 int i;
268
269 for (i = 0; i < header->attrs; i++) {
270 struct perf_header_attr *attr = header->attr[i];
271 int j;
272
273 for (j = 0; j < attr->ids; j++) {
274 if (attr->id[j] == id)
275 return &attr->attr;
276 }
277 }
278
279 return NULL;
280}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index bf280449fcfd..5d0a72ecc919 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -31,6 +31,10 @@ struct perf_header_attr *
31perf_header_attr__new(struct perf_counter_attr *attr); 31perf_header_attr__new(struct perf_counter_attr *attr);
32void perf_header_attr__add_id(struct perf_header_attr *self, u64 id); 32void perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
33 33
34u64 perf_header__sample_type(struct perf_header *header);
35struct perf_counter_attr *
36perf_header__find_attr(u64 id, struct perf_header *header);
37
34 38
35struct perf_header *perf_header__new(void); 39struct perf_header *perf_header__new(void);
36 40
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
new file mode 100644
index 000000000000..804e02382739
--- /dev/null
+++ b/tools/perf/util/map.c
@@ -0,0 +1,97 @@
1#include "event.h"
2#include "symbol.h"
3#include <stdlib.h>
4#include <string.h>
5#include <stdio.h>
6
7static inline int is_anon_memory(const char *filename)
8{
9 return strcmp(filename, "//anon") == 0;
10}
11
12static int strcommon(const char *pathname, char *cwd, int cwdlen)
13{
14 int n = 0;
15
16 while (n < cwdlen && pathname[n] == cwd[n])
17 ++n;
18
19 return n;
20}
21
22 struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen)
23{
24 struct map *self = malloc(sizeof(*self));
25
26 if (self != NULL) {
27 const char *filename = event->filename;
28 char newfilename[PATH_MAX];
29 int anon;
30
31 if (cwd) {
32 int n = strcommon(filename, cwd, cwdlen);
33
34 if (n == cwdlen) {
35 snprintf(newfilename, sizeof(newfilename),
36 ".%s", filename + n);
37 filename = newfilename;
38 }
39 }
40
41 anon = is_anon_memory(filename);
42
43 if (anon) {
44 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid);
45 filename = newfilename;
46 }
47
48 self->start = event->start;
49 self->end = event->start + event->len;
50 self->pgoff = event->pgoff;
51
52 self->dso = dsos__findnew(filename);
53 if (self->dso == NULL)
54 goto out_delete;
55
56 if (self->dso == vdso || anon)
57 self->map_ip = vdso__map_ip;
58 else
59 self->map_ip = map__map_ip;
60 }
61 return self;
62out_delete:
63 free(self);
64 return NULL;
65}
66
67struct map *map__clone(struct map *self)
68{
69 struct map *map = malloc(sizeof(*self));
70
71 if (!map)
72 return NULL;
73
74 memcpy(map, self, sizeof(*self));
75
76 return map;
77}
78
79int map__overlap(struct map *l, struct map *r)
80{
81 if (l->start > r->start) {
82 struct map *t = l;
83 l = r;
84 r = t;
85 }
86
87 if (l->end > r->start)
88 return 1;
89
90 return 0;
91}
92
93size_t map__fprintf(struct map *self, FILE *fp)
94{
95 return fprintf(fp, " %Lx-%Lx %Lx %s\n",
96 self->start, self->end, self->pgoff, self->dso->name);
97}
diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c
index ddabe925d65d..3d567fe59c79 100644
--- a/tools/perf/util/module.c
+++ b/tools/perf/util/module.c
@@ -436,9 +436,9 @@ static int mod_dso__load_module_paths(struct mod_dso *self)
436 goto out_failure; 436 goto out_failure;
437 437
438 while (!feof(file)) { 438 while (!feof(file)) {
439 char *path, *name, *tmp; 439 char *name, *tmp;
440 struct module *module; 440 struct module *module;
441 int line_len, len; 441 int line_len;
442 442
443 line_len = getline(&line, &n, file); 443 line_len = getline(&line, &n, file);
444 if (line_len < 0) 444 if (line_len < 0)
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 044178408783..1cda97b39118 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -14,10 +14,10 @@ int nr_counters;
14struct perf_counter_attr attrs[MAX_COUNTERS]; 14struct perf_counter_attr attrs[MAX_COUNTERS];
15 15
16struct event_symbol { 16struct event_symbol {
17 u8 type; 17 u8 type;
18 u64 config; 18 u64 config;
19 char *symbol; 19 const char *symbol;
20 char *alias; 20 const char *alias;
21}; 21};
22 22
23char debugfs_path[MAXPATHLEN]; 23char debugfs_path[MAXPATHLEN];
@@ -51,7 +51,7 @@ static struct event_symbol event_symbols[] = {
51#define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE) 51#define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE)
52#define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT) 52#define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT)
53 53
54static char *hw_event_names[] = { 54static const char *hw_event_names[] = {
55 "cycles", 55 "cycles",
56 "instructions", 56 "instructions",
57 "cache-references", 57 "cache-references",
@@ -61,7 +61,7 @@ static char *hw_event_names[] = {
61 "bus-cycles", 61 "bus-cycles",
62}; 62};
63 63
64static char *sw_event_names[] = { 64static const char *sw_event_names[] = {
65 "cpu-clock-msecs", 65 "cpu-clock-msecs",
66 "task-clock-msecs", 66 "task-clock-msecs",
67 "page-faults", 67 "page-faults",
@@ -73,7 +73,7 @@ static char *sw_event_names[] = {
73 73
74#define MAX_ALIASES 8 74#define MAX_ALIASES 8
75 75
76static char *hw_cache[][MAX_ALIASES] = { 76static const char *hw_cache[][MAX_ALIASES] = {
77 { "L1-dcache", "l1-d", "l1d", "L1-data", }, 77 { "L1-dcache", "l1-d", "l1d", "L1-data", },
78 { "L1-icache", "l1-i", "l1i", "L1-instruction", }, 78 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
79 { "LLC", "L2" }, 79 { "LLC", "L2" },
@@ -82,13 +82,13 @@ static char *hw_cache[][MAX_ALIASES] = {
82 { "branch", "branches", "bpu", "btb", "bpc", }, 82 { "branch", "branches", "bpu", "btb", "bpc", },
83}; 83};
84 84
85static char *hw_cache_op[][MAX_ALIASES] = { 85static const char *hw_cache_op[][MAX_ALIASES] = {
86 { "load", "loads", "read", }, 86 { "load", "loads", "read", },
87 { "store", "stores", "write", }, 87 { "store", "stores", "write", },
88 { "prefetch", "prefetches", "speculative-read", "speculative-load", }, 88 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
89}; 89};
90 90
91static char *hw_cache_result[][MAX_ALIASES] = { 91static const char *hw_cache_result[][MAX_ALIASES] = {
92 { "refs", "Reference", "ops", "access", }, 92 { "refs", "Reference", "ops", "access", },
93 { "misses", "miss", }, 93 { "misses", "miss", },
94}; 94};
@@ -158,7 +158,7 @@ int valid_debugfs_mount(const char *debugfs)
158 return 0; 158 return 0;
159} 159}
160 160
161static char *tracepoint_id_to_name(u64 config) 161static const char *tracepoint_id_to_name(u64 config)
162{ 162{
163 static char tracepoint_name[2 * MAX_EVENT_LENGTH]; 163 static char tracepoint_name[2 * MAX_EVENT_LENGTH];
164 DIR *sys_dir, *evt_dir; 164 DIR *sys_dir, *evt_dir;
@@ -235,7 +235,7 @@ static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
235 return name; 235 return name;
236} 236}
237 237
238char *event_name(int counter) 238const char *event_name(int counter)
239{ 239{
240 u64 config = attrs[counter].config; 240 u64 config = attrs[counter].config;
241 int type = attrs[counter].type; 241 int type = attrs[counter].type;
@@ -243,7 +243,7 @@ char *event_name(int counter)
243 return __event_name(type, config); 243 return __event_name(type, config);
244} 244}
245 245
246char *__event_name(int type, u64 config) 246const char *__event_name(int type, u64 config)
247{ 247{
248 static char buf[32]; 248 static char buf[32];
249 249
@@ -294,7 +294,7 @@ char *__event_name(int type, u64 config)
294 return "unknown"; 294 return "unknown";
295} 295}
296 296
297static int parse_aliases(const char **str, char *names[][MAX_ALIASES], int size) 297static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size)
298{ 298{
299 int i, j; 299 int i, j;
300 int n, longest = -1; 300 int n, longest = -1;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 192a962e3a0f..9b1aeea01636 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -9,8 +9,8 @@ extern int nr_counters;
9 9
10extern struct perf_counter_attr attrs[MAX_COUNTERS]; 10extern struct perf_counter_attr attrs[MAX_COUNTERS];
11 11
12extern char *event_name(int ctr); 12extern const char *event_name(int ctr);
13extern char *__event_name(int type, u64 config); 13extern const char *__event_name(int type, u64 config);
14 14
15extern int parse_events(const struct option *opt, const char *str, int unset); 15extern int parse_events(const struct option *opt, const char *str, int unset);
16 16
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 1bf67190c820..6d8af48c925e 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -53,6 +53,12 @@ static int get_value(struct parse_opt_ctx_t *p,
53 case OPTION_SET_INT: 53 case OPTION_SET_INT:
54 case OPTION_SET_PTR: 54 case OPTION_SET_PTR:
55 return opterror(opt, "takes no value", flags); 55 return opterror(opt, "takes no value", flags);
56 case OPTION_END:
57 case OPTION_ARGUMENT:
58 case OPTION_GROUP:
59 case OPTION_STRING:
60 case OPTION_INTEGER:
61 case OPTION_LONG:
56 default: 62 default:
57 break; 63 break;
58 } 64 }
@@ -130,6 +136,9 @@ static int get_value(struct parse_opt_ctx_t *p,
130 return opterror(opt, "expects a numerical value", flags); 136 return opterror(opt, "expects a numerical value", flags);
131 return 0; 137 return 0;
132 138
139 case OPTION_END:
140 case OPTION_ARGUMENT:
141 case OPTION_GROUP:
133 default: 142 default:
134 die("should not happen, someone must be hit on the forehead"); 143 die("should not happen, someone must be hit on the forehead");
135 } 144 }
@@ -296,6 +305,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
296 return parse_options_usage(usagestr, options); 305 return parse_options_usage(usagestr, options);
297 case -2: 306 case -2:
298 goto unknown; 307 goto unknown;
308 default:
309 break;
299 } 310 }
300 if (ctx->opt) 311 if (ctx->opt)
301 check_typos(arg + 1, options); 312 check_typos(arg + 1, options);
@@ -314,6 +325,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
314 ctx->argv[0] = strdup(ctx->opt - 1); 325 ctx->argv[0] = strdup(ctx->opt - 1);
315 *(char *)ctx->argv[0] = '-'; 326 *(char *)ctx->argv[0] = '-';
316 goto unknown; 327 goto unknown;
328 default:
329 break;
317 } 330 }
318 } 331 }
319 continue; 332 continue;
@@ -336,6 +349,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
336 return parse_options_usage(usagestr, options); 349 return parse_options_usage(usagestr, options);
337 case -2: 350 case -2:
338 goto unknown; 351 goto unknown;
352 default:
353 break;
339 } 354 }
340 continue; 355 continue;
341unknown: 356unknown:
@@ -456,6 +471,13 @@ int usage_with_options_internal(const char * const *usagestr,
456 } 471 }
457 break; 472 break;
458 default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */ 473 default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */
474 case OPTION_END:
475 case OPTION_GROUP:
476 case OPTION_BIT:
477 case OPTION_BOOLEAN:
478 case OPTION_SET_INT:
479 case OPTION_SET_PTR:
480 case OPTION_LONG:
459 break; 481 break;
460 } 482 }
461 483
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index a501a40dd2cb..fd1f2faaade4 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -17,7 +17,7 @@ static char bad_path[] = "/bad-path/";
17 * Two hacks: 17 * Two hacks:
18 */ 18 */
19 19
20static char *get_perf_dir(void) 20static const char *get_perf_dir(void)
21{ 21{
22 return "."; 22 return ".";
23} 23}
@@ -38,8 +38,9 @@ size_t strlcpy(char *dest, const char *src, size_t size)
38static char *get_pathname(void) 38static char *get_pathname(void)
39{ 39{
40 static char pathname_array[4][PATH_MAX]; 40 static char pathname_array[4][PATH_MAX];
41 static int index; 41 static int idx;
42 return pathname_array[3 & ++index]; 42
43 return pathname_array[3 & ++idx];
43} 44}
44 45
45static char *cleanup_path(char *path) 46static char *cleanup_path(char *path)
@@ -161,20 +162,24 @@ int perf_mkstemp(char *path, size_t len, const char *template)
161} 162}
162 163
163 164
164const char *make_relative_path(const char *abs, const char *base) 165const char *make_relative_path(const char *abs_path, const char *base)
165{ 166{
166 static char buf[PATH_MAX + 1]; 167 static char buf[PATH_MAX + 1];
167 int baselen; 168 int baselen;
169
168 if (!base) 170 if (!base)
169 return abs; 171 return abs_path;
172
170 baselen = strlen(base); 173 baselen = strlen(base);
171 if (prefixcmp(abs, base)) 174 if (prefixcmp(abs_path, base))
172 return abs; 175 return abs_path;
173 if (abs[baselen] == '/') 176 if (abs_path[baselen] == '/')
174 baselen++; 177 baselen++;
175 else if (base[baselen - 1] != '/') 178 else if (base[baselen - 1] != '/')
176 return abs; 179 return abs_path;
177 strcpy(buf, abs + baselen); 180
181 strcpy(buf, abs_path + baselen);
182
178 return buf; 183 return buf;
179} 184}
180 185
diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c
index a3935343091a..2b615acf94d7 100644
--- a/tools/perf/util/run-command.c
+++ b/tools/perf/util/run-command.c
@@ -262,7 +262,7 @@ int run_hook(const char *index_file, const char *name, ...)
262{ 262{
263 struct child_process hook; 263 struct child_process hook;
264 const char **argv = NULL, *env[2]; 264 const char **argv = NULL, *env[2];
265 char index[PATH_MAX]; 265 char idx[PATH_MAX];
266 va_list args; 266 va_list args;
267 int ret; 267 int ret;
268 size_t i = 0, alloc = 0; 268 size_t i = 0, alloc = 0;
@@ -284,8 +284,8 @@ int run_hook(const char *index_file, const char *name, ...)
284 hook.no_stdin = 1; 284 hook.no_stdin = 1;
285 hook.stdout_to_stderr = 1; 285 hook.stdout_to_stderr = 1;
286 if (index_file) { 286 if (index_file) {
287 snprintf(index, sizeof(index), "PERF_INDEX_FILE=%s", index_file); 287 snprintf(idx, sizeof(idx), "PERF_INDEX_FILE=%s", index_file);
288 env[0] = index; 288 env[0] = idx;
289 env[1] = NULL; 289 env[1] = NULL;
290 hook.env = env; 290 hook.env = env;
291 } 291 }
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 5c0f42e6b33b..fd3d9c8e90fc 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -3,6 +3,8 @@
3#include "string.h" 3#include "string.h"
4#include "symbol.h" 4#include "symbol.h"
5 5
6#include "debug.h"
7
6#include <libelf.h> 8#include <libelf.h>
7#include <gelf.h> 9#include <gelf.h>
8#include <elf.h> 10#include <elf.h>
@@ -21,7 +23,7 @@ enum dso_origin {
21 23
22static struct symbol *symbol__new(u64 start, u64 len, 24static struct symbol *symbol__new(u64 start, u64 len,
23 const char *name, unsigned int priv_size, 25 const char *name, unsigned int priv_size,
24 u64 obj_start, int verbose) 26 u64 obj_start, int v)
25{ 27{
26 size_t namelen = strlen(name) + 1; 28 size_t namelen = strlen(name) + 1;
27 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); 29 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen);
@@ -29,7 +31,7 @@ static struct symbol *symbol__new(u64 start, u64 len,
29 if (!self) 31 if (!self)
30 return NULL; 32 return NULL;
31 33
32 if (verbose >= 2) 34 if (v >= 2)
33 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n", 35 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n",
34 (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start); 36 (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start);
35 37
@@ -156,7 +158,7 @@ size_t dso__fprintf(struct dso *self, FILE *fp)
156 return ret; 158 return ret;
157} 159}
158 160
159static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verbose) 161static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v)
160{ 162{
161 struct rb_node *nd, *prevnd; 163 struct rb_node *nd, *prevnd;
162 char *line = NULL; 164 char *line = NULL;
@@ -198,7 +200,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
198 * Well fix up the end later, when we have all sorted. 200 * Well fix up the end later, when we have all sorted.
199 */ 201 */
200 sym = symbol__new(start, 0xdead, line + len + 2, 202 sym = symbol__new(start, 0xdead, line + len + 2,
201 self->sym_priv_size, 0, verbose); 203 self->sym_priv_size, 0, v);
202 204
203 if (sym == NULL) 205 if (sym == NULL)
204 goto out_delete_line; 206 goto out_delete_line;
@@ -239,7 +241,7 @@ out_failure:
239 return -1; 241 return -1;
240} 242}
241 243
242static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int verbose) 244static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v)
243{ 245{
244 char *line = NULL; 246 char *line = NULL;
245 size_t n; 247 size_t n;
@@ -277,7 +279,7 @@ static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int verb
277 continue; 279 continue;
278 280
279 sym = symbol__new(start, size, line + len, 281 sym = symbol__new(start, size, line + len,
280 self->sym_priv_size, start, verbose); 282 self->sym_priv_size, start, v);
281 283
282 if (sym == NULL) 284 if (sym == NULL)
283 goto out_delete_line; 285 goto out_delete_line;
@@ -305,13 +307,13 @@ out_failure:
305 * elf_symtab__for_each_symbol - iterate thru all the symbols 307 * elf_symtab__for_each_symbol - iterate thru all the symbols
306 * 308 *
307 * @self: struct elf_symtab instance to iterate 309 * @self: struct elf_symtab instance to iterate
308 * @index: uint32_t index 310 * @idx: uint32_t idx
309 * @sym: GElf_Sym iterator 311 * @sym: GElf_Sym iterator
310 */ 312 */
311#define elf_symtab__for_each_symbol(syms, nr_syms, index, sym) \ 313#define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \
312 for (index = 0, gelf_getsym(syms, index, &sym);\ 314 for (idx = 0, gelf_getsym(syms, idx, &sym);\
313 index < nr_syms; \ 315 idx < nr_syms; \
314 index++, gelf_getsym(syms, index, &sym)) 316 idx++, gelf_getsym(syms, idx, &sym))
315 317
316static inline uint8_t elf_sym__type(const GElf_Sym *sym) 318static inline uint8_t elf_sym__type(const GElf_Sym *sym)
317{ 319{
@@ -354,7 +356,7 @@ static inline const char *elf_sym__name(const GElf_Sym *sym,
354 356
355static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, 357static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
356 GElf_Shdr *shp, const char *name, 358 GElf_Shdr *shp, const char *name,
357 size_t *index) 359 size_t *idx)
358{ 360{
359 Elf_Scn *sec = NULL; 361 Elf_Scn *sec = NULL;
360 size_t cnt = 1; 362 size_t cnt = 1;
@@ -365,8 +367,8 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
365 gelf_getshdr(sec, shp); 367 gelf_getshdr(sec, shp);
366 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); 368 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
367 if (!strcmp(name, str)) { 369 if (!strcmp(name, str)) {
368 if (index) 370 if (idx)
369 *index = cnt; 371 *idx = cnt;
370 break; 372 break;
371 } 373 }
372 ++cnt; 374 ++cnt;
@@ -392,7 +394,7 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
392 * And always look at the original dso, not at debuginfo packages, that 394 * And always look at the original dso, not at debuginfo packages, that
393 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). 395 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
394 */ 396 */
395static int dso__synthesize_plt_symbols(struct dso *self, int verbose) 397static int dso__synthesize_plt_symbols(struct dso *self, int v)
396{ 398{
397 uint32_t nr_rel_entries, idx; 399 uint32_t nr_rel_entries, idx;
398 GElf_Sym sym; 400 GElf_Sym sym;
@@ -442,7 +444,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int verbose)
442 goto out_elf_end; 444 goto out_elf_end;
443 445
444 /* 446 /*
445 * Fetch the relocation section to find the indexes to the GOT 447 * Fetch the relocation section to find the idxes to the GOT
446 * and the symbols in the .dynsym they refer to. 448 * and the symbols in the .dynsym they refer to.
447 */ 449 */
448 reldata = elf_getdata(scn_plt_rel, NULL); 450 reldata = elf_getdata(scn_plt_rel, NULL);
@@ -476,7 +478,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int verbose)
476 "%s@plt", elf_sym__name(&sym, symstrs)); 478 "%s@plt", elf_sym__name(&sym, symstrs));
477 479
478 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 480 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
479 sympltname, self->sym_priv_size, 0, verbose); 481 sympltname, self->sym_priv_size, 0, v);
480 if (!f) 482 if (!f)
481 goto out_elf_end; 483 goto out_elf_end;
482 484
@@ -494,7 +496,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int verbose)
494 "%s@plt", elf_sym__name(&sym, symstrs)); 496 "%s@plt", elf_sym__name(&sym, symstrs));
495 497
496 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 498 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
497 sympltname, self->sym_priv_size, 0, verbose); 499 sympltname, self->sym_priv_size, 0, v);
498 if (!f) 500 if (!f)
499 goto out_elf_end; 501 goto out_elf_end;
500 502
@@ -518,12 +520,12 @@ out:
518} 520}
519 521
520static int dso__load_sym(struct dso *self, int fd, const char *name, 522static int dso__load_sym(struct dso *self, int fd, const char *name,
521 symbol_filter_t filter, int verbose, struct module *mod) 523 symbol_filter_t filter, int v, struct module *mod)
522{ 524{
523 Elf_Data *symstrs, *secstrs; 525 Elf_Data *symstrs, *secstrs;
524 uint32_t nr_syms; 526 uint32_t nr_syms;
525 int err = -1; 527 int err = -1;
526 uint32_t index; 528 uint32_t idx;
527 GElf_Ehdr ehdr; 529 GElf_Ehdr ehdr;
528 GElf_Shdr shdr; 530 GElf_Shdr shdr;
529 Elf_Data *syms; 531 Elf_Data *syms;
@@ -534,14 +536,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
534 536
535 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 537 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
536 if (elf == NULL) { 538 if (elf == NULL) {
537 if (verbose) 539 if (v)
538 fprintf(stderr, "%s: cannot read %s ELF file.\n", 540 fprintf(stderr, "%s: cannot read %s ELF file.\n",
539 __func__, name); 541 __func__, name);
540 goto out_close; 542 goto out_close;
541 } 543 }
542 544
543 if (gelf_getehdr(elf, &ehdr) == NULL) { 545 if (gelf_getehdr(elf, &ehdr) == NULL) {
544 if (verbose) 546 if (v)
545 fprintf(stderr, "%s: cannot get elf header.\n", __func__); 547 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
546 goto out_elf_end; 548 goto out_elf_end;
547 } 549 }
@@ -583,9 +585,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
583 NULL) != NULL); 585 NULL) != NULL);
584 } else self->adjust_symbols = 0; 586 } else self->adjust_symbols = 0;
585 587
586 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 588 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
587 struct symbol *f; 589 struct symbol *f;
588 const char *name; 590 const char *elf_name;
589 char *demangled; 591 char *demangled;
590 u64 obj_start; 592 u64 obj_start;
591 struct section *section = NULL; 593 struct section *section = NULL;
@@ -608,7 +610,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
608 obj_start = sym.st_value; 610 obj_start = sym.st_value;
609 611
610 if (self->adjust_symbols) { 612 if (self->adjust_symbols) {
611 if (verbose >= 2) 613 if (v >= 2)
612 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", 614 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
613 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 615 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
614 616
@@ -630,13 +632,13 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
630 * DWARF DW_compile_unit has this, but we don't always have access 632 * DWARF DW_compile_unit has this, but we don't always have access
631 * to it... 633 * to it...
632 */ 634 */
633 name = elf_sym__name(&sym, symstrs); 635 elf_name = elf_sym__name(&sym, symstrs);
634 demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI); 636 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
635 if (demangled != NULL) 637 if (demangled != NULL)
636 name = demangled; 638 elf_name = demangled;
637 639
638 f = symbol__new(sym.st_value, sym.st_size, name, 640 f = symbol__new(sym.st_value, sym.st_size, elf_name,
639 self->sym_priv_size, obj_start, verbose); 641 self->sym_priv_size, obj_start, v);
640 free(demangled); 642 free(demangled);
641 if (!f) 643 if (!f)
642 goto out_elf_end; 644 goto out_elf_end;
@@ -659,7 +661,7 @@ out_close:
659 661
660#define BUILD_ID_SIZE 128 662#define BUILD_ID_SIZE 128
661 663
662static char *dso__read_build_id(struct dso *self, int verbose) 664static char *dso__read_build_id(struct dso *self, int v)
663{ 665{
664 int i; 666 int i;
665 GElf_Ehdr ehdr; 667 GElf_Ehdr ehdr;
@@ -676,14 +678,14 @@ static char *dso__read_build_id(struct dso *self, int verbose)
676 678
677 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 679 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
678 if (elf == NULL) { 680 if (elf == NULL) {
679 if (verbose) 681 if (v)
680 fprintf(stderr, "%s: cannot read %s ELF file.\n", 682 fprintf(stderr, "%s: cannot read %s ELF file.\n",
681 __func__, self->name); 683 __func__, self->name);
682 goto out_close; 684 goto out_close;
683 } 685 }
684 686
685 if (gelf_getehdr(elf, &ehdr) == NULL) { 687 if (gelf_getehdr(elf, &ehdr) == NULL) {
686 if (verbose) 688 if (v)
687 fprintf(stderr, "%s: cannot get elf header.\n", __func__); 689 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
688 goto out_elf_end; 690 goto out_elf_end;
689 } 691 }
@@ -706,7 +708,7 @@ static char *dso__read_build_id(struct dso *self, int verbose)
706 ++raw; 708 ++raw;
707 bid += 2; 709 bid += 2;
708 } 710 }
709 if (verbose >= 2) 711 if (v >= 2)
710 printf("%s(%s): %s\n", __func__, self->name, build_id); 712 printf("%s(%s): %s\n", __func__, self->name, build_id);
711out_elf_end: 713out_elf_end:
712 elf_end(elf); 714 elf_end(elf);
@@ -732,7 +734,7 @@ char dso__symtab_origin(const struct dso *self)
732 return origin[self->origin]; 734 return origin[self->origin];
733} 735}
734 736
735int dso__load(struct dso *self, symbol_filter_t filter, int verbose) 737int dso__load(struct dso *self, symbol_filter_t filter, int v)
736{ 738{
737 int size = PATH_MAX; 739 int size = PATH_MAX;
738 char *name = malloc(size), *build_id = NULL; 740 char *name = malloc(size), *build_id = NULL;
@@ -745,7 +747,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
745 self->adjust_symbols = 0; 747 self->adjust_symbols = 0;
746 748
747 if (strncmp(self->name, "/tmp/perf-", 10) == 0) { 749 if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
748 ret = dso__load_perf_map(self, filter, verbose); 750 ret = dso__load_perf_map(self, filter, v);
749 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : 751 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
750 DSO__ORIG_NOT_FOUND; 752 DSO__ORIG_NOT_FOUND;
751 return ret; 753 return ret;
@@ -764,7 +766,7 @@ more:
764 snprintf(name, size, "/usr/lib/debug%s", self->name); 766 snprintf(name, size, "/usr/lib/debug%s", self->name);
765 break; 767 break;
766 case DSO__ORIG_BUILDID: 768 case DSO__ORIG_BUILDID:
767 build_id = dso__read_build_id(self, verbose); 769 build_id = dso__read_build_id(self, v);
768 if (build_id != NULL) { 770 if (build_id != NULL) {
769 snprintf(name, size, 771 snprintf(name, size,
770 "/usr/lib/debug/.build-id/%.2s/%s.debug", 772 "/usr/lib/debug/.build-id/%.2s/%s.debug",
@@ -785,7 +787,7 @@ more:
785 fd = open(name, O_RDONLY); 787 fd = open(name, O_RDONLY);
786 } while (fd < 0); 788 } while (fd < 0);
787 789
788 ret = dso__load_sym(self, fd, name, filter, verbose, NULL); 790 ret = dso__load_sym(self, fd, name, filter, v, NULL);
789 close(fd); 791 close(fd);
790 792
791 /* 793 /*
@@ -795,7 +797,7 @@ more:
795 goto more; 797 goto more;
796 798
797 if (ret > 0) { 799 if (ret > 0) {
798 int nr_plt = dso__synthesize_plt_symbols(self, verbose); 800 int nr_plt = dso__synthesize_plt_symbols(self, v);
799 if (nr_plt > 0) 801 if (nr_plt > 0)
800 ret += nr_plt; 802 ret += nr_plt;
801 } 803 }
@@ -807,7 +809,7 @@ out:
807} 809}
808 810
809static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, 811static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name,
810 symbol_filter_t filter, int verbose) 812 symbol_filter_t filter, int v)
811{ 813{
812 struct module *mod = mod_dso__find_module(mods, name); 814 struct module *mod = mod_dso__find_module(mods, name);
813 int err = 0, fd; 815 int err = 0, fd;
@@ -820,13 +822,13 @@ static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *
820 if (fd < 0) 822 if (fd < 0)
821 return err; 823 return err;
822 824
823 err = dso__load_sym(self, fd, name, filter, verbose, mod); 825 err = dso__load_sym(self, fd, name, filter, v, mod);
824 close(fd); 826 close(fd);
825 827
826 return err; 828 return err;
827} 829}
828 830
829int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose) 831int dso__load_modules(struct dso *self, symbol_filter_t filter, int v)
830{ 832{
831 struct mod_dso *mods = mod_dso__new_dso("modules"); 833 struct mod_dso *mods = mod_dso__new_dso("modules");
832 struct module *pos; 834 struct module *pos;
@@ -844,7 +846,7 @@ int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose)
844 next = rb_first(&mods->mods); 846 next = rb_first(&mods->mods);
845 while (next) { 847 while (next) {
846 pos = rb_entry(next, struct module, rb_node); 848 pos = rb_entry(next, struct module, rb_node);
847 err = dso__load_module(self, mods, pos->name, filter, verbose); 849 err = dso__load_module(self, mods, pos->name, filter, v);
848 850
849 if (err < 0) 851 if (err < 0)
850 break; 852 break;
@@ -887,14 +889,14 @@ static inline void dso__fill_symbol_holes(struct dso *self)
887} 889}
888 890
889static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 891static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
890 symbol_filter_t filter, int verbose) 892 symbol_filter_t filter, int v)
891{ 893{
892 int err, fd = open(vmlinux, O_RDONLY); 894 int err, fd = open(vmlinux, O_RDONLY);
893 895
894 if (fd < 0) 896 if (fd < 0)
895 return -1; 897 return -1;
896 898
897 err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL); 899 err = dso__load_sym(self, fd, vmlinux, filter, v, NULL);
898 900
899 if (err > 0) 901 if (err > 0)
900 dso__fill_symbol_holes(self); 902 dso__fill_symbol_holes(self);
@@ -905,18 +907,18 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
905} 907}
906 908
907int dso__load_kernel(struct dso *self, const char *vmlinux, 909int dso__load_kernel(struct dso *self, const char *vmlinux,
908 symbol_filter_t filter, int verbose, int modules) 910 symbol_filter_t filter, int v, int use_modules)
909{ 911{
910 int err = -1; 912 int err = -1;
911 913
912 if (vmlinux) { 914 if (vmlinux) {
913 err = dso__load_vmlinux(self, vmlinux, filter, verbose); 915 err = dso__load_vmlinux(self, vmlinux, filter, v);
914 if (err > 0 && modules) 916 if (err > 0 && use_modules)
915 err = dso__load_modules(self, filter, verbose); 917 err = dso__load_modules(self, filter, v);
916 } 918 }
917 919
918 if (err <= 0) 920 if (err <= 0)
919 err = dso__load_kallsyms(self, filter, verbose); 921 err = dso__load_kallsyms(self, filter, v);
920 922
921 if (err > 0) 923 if (err > 0)
922 self->origin = DSO__ORIG_KERNEL; 924 self->origin = DSO__ORIG_KERNEL;
@@ -924,6 +926,103 @@ int dso__load_kernel(struct dso *self, const char *vmlinux,
924 return err; 926 return err;
925} 927}
926 928
929LIST_HEAD(dsos);
930struct dso *kernel_dso;
931struct dso *vdso;
932struct dso *hypervisor_dso;
933
934const char *vmlinux_name = "vmlinux";
935int modules;
936
937static void dsos__add(struct dso *dso)
938{
939 list_add_tail(&dso->node, &dsos);
940}
941
942static struct dso *dsos__find(const char *name)
943{
944 struct dso *pos;
945
946 list_for_each_entry(pos, &dsos, node)
947 if (strcmp(pos->name, name) == 0)
948 return pos;
949 return NULL;
950}
951
952struct dso *dsos__findnew(const char *name)
953{
954 struct dso *dso = dsos__find(name);
955 int nr;
956
957 if (dso)
958 return dso;
959
960 dso = dso__new(name, 0);
961 if (!dso)
962 goto out_delete_dso;
963
964 nr = dso__load(dso, NULL, verbose);
965 if (nr < 0) {
966 eprintf("Failed to open: %s\n", name);
967 goto out_delete_dso;
968 }
969 if (!nr)
970 eprintf("No symbols found in: %s, maybe install a debug package?\n", name);
971
972 dsos__add(dso);
973
974 return dso;
975
976out_delete_dso:
977 dso__delete(dso);
978 return NULL;
979}
980
981void dsos__fprintf(FILE *fp)
982{
983 struct dso *pos;
984
985 list_for_each_entry(pos, &dsos, node)
986 dso__fprintf(pos, fp);
987}
988
989static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
990{
991 return dso__find_symbol(dso, ip);
992}
993
994int load_kernel(void)
995{
996 int err;
997
998 kernel_dso = dso__new("[kernel]", 0);
999 if (!kernel_dso)
1000 return -1;
1001
1002 err = dso__load_kernel(kernel_dso, vmlinux_name, NULL, verbose, modules);
1003 if (err <= 0) {
1004 dso__delete(kernel_dso);
1005 kernel_dso = NULL;
1006 } else
1007 dsos__add(kernel_dso);
1008
1009 vdso = dso__new("[vdso]", 0);
1010 if (!vdso)
1011 return -1;
1012
1013 vdso->find_symbol = vdso__find_symbol;
1014
1015 dsos__add(vdso);
1016
1017 hypervisor_dso = dso__new("[hypervisor]", 0);
1018 if (!hypervisor_dso)
1019 return -1;
1020 dsos__add(hypervisor_dso);
1021
1022 return err;
1023}
1024
1025
927void symbol__init(void) 1026void symbol__init(void)
928{ 1027{
929 elf_version(EV_CURRENT); 1028 elf_version(EV_CURRENT);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index b53bf0125c1b..6e8490716408 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -6,6 +6,7 @@
6#include <linux/list.h> 6#include <linux/list.h>
7#include <linux/rbtree.h> 7#include <linux/rbtree.h>
8#include "module.h" 8#include "module.h"
9#include "event.h"
9 10
10#ifdef HAVE_CPLUS_DEMANGLE 11#ifdef HAVE_CPLUS_DEMANGLE
11extern char *cplus_demangle(const char *, int); 12extern char *cplus_demangle(const char *, int);
@@ -54,7 +55,7 @@ struct dso {
54 char name[0]; 55 char name[0];
55}; 56};
56 57
57const char *sym_hist_filter; 58extern const char *sym_hist_filter;
58 59
59typedef int (*symbol_filter_t)(struct dso *self, struct symbol *sym); 60typedef int (*symbol_filter_t)(struct dso *self, struct symbol *sym);
60 61
@@ -72,9 +73,20 @@ int dso__load_kernel(struct dso *self, const char *vmlinux,
72 symbol_filter_t filter, int verbose, int modules); 73 symbol_filter_t filter, int verbose, int modules);
73int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose); 74int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose);
74int dso__load(struct dso *self, symbol_filter_t filter, int verbose); 75int dso__load(struct dso *self, symbol_filter_t filter, int verbose);
76struct dso *dsos__findnew(const char *name);
77void dsos__fprintf(FILE *fp);
75 78
76size_t dso__fprintf(struct dso *self, FILE *fp); 79size_t dso__fprintf(struct dso *self, FILE *fp);
77char dso__symtab_origin(const struct dso *self); 80char dso__symtab_origin(const struct dso *self);
78 81
82int load_kernel(void);
83
79void symbol__init(void); 84void symbol__init(void);
85
86extern struct list_head dsos;
87extern struct dso *kernel_dso;
88extern struct dso *vdso;
89extern struct dso *hypervisor_dso;
90extern const char *vmlinux_name;
91extern int modules;
80#endif /* _PERF_SYMBOL_ */ 92#endif /* _PERF_SYMBOL_ */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
new file mode 100644
index 000000000000..f98032c135c6
--- /dev/null
+++ b/tools/perf/util/thread.c
@@ -0,0 +1,162 @@
1#include "../perf.h"
2#include <stdlib.h>
3#include <stdio.h>
4#include <string.h>
5#include "thread.h"
6#include "util.h"
7#include "debug.h"
8
9static struct thread *thread__new(pid_t pid)
10{
11 struct thread *self = malloc(sizeof(*self));
12
13 if (self != NULL) {
14 self->pid = pid;
15 self->comm = malloc(32);
16 if (self->comm)
17 snprintf(self->comm, 32, ":%d", self->pid);
18 INIT_LIST_HEAD(&self->maps);
19 }
20
21 return self;
22}
23
24int thread__set_comm(struct thread *self, const char *comm)
25{
26 if (self->comm)
27 free(self->comm);
28 self->comm = strdup(comm);
29 return self->comm ? 0 : -ENOMEM;
30}
31
32static size_t thread__fprintf(struct thread *self, FILE *fp)
33{
34 struct map *pos;
35 size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm);
36
37 list_for_each_entry(pos, &self->maps, node)
38 ret += map__fprintf(pos, fp);
39
40 return ret;
41}
42
43struct thread *
44threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
45{
46 struct rb_node **p = &threads->rb_node;
47 struct rb_node *parent = NULL;
48 struct thread *th;
49
50 /*
51 * Font-end cache - PID lookups come in blocks,
52 * so most of the time we dont have to look up
53 * the full rbtree:
54 */
55 if (*last_match && (*last_match)->pid == pid)
56 return *last_match;
57
58 while (*p != NULL) {
59 parent = *p;
60 th = rb_entry(parent, struct thread, rb_node);
61
62 if (th->pid == pid) {
63 *last_match = th;
64 return th;
65 }
66
67 if (pid < th->pid)
68 p = &(*p)->rb_left;
69 else
70 p = &(*p)->rb_right;
71 }
72
73 th = thread__new(pid);
74 if (th != NULL) {
75 rb_link_node(&th->rb_node, parent, p);
76 rb_insert_color(&th->rb_node, threads);
77 *last_match = th;
78 }
79
80 return th;
81}
82
83void thread__insert_map(struct thread *self, struct map *map)
84{
85 struct map *pos, *tmp;
86
87 list_for_each_entry_safe(pos, tmp, &self->maps, node) {
88 if (map__overlap(pos, map)) {
89 if (verbose >= 2) {
90 printf("overlapping maps:\n");
91 map__fprintf(map, stdout);
92 map__fprintf(pos, stdout);
93 }
94
95 if (map->start <= pos->start && map->end > pos->start)
96 pos->start = map->end;
97
98 if (map->end >= pos->end && map->start < pos->end)
99 pos->end = map->start;
100
101 if (verbose >= 2) {
102 printf("after collision:\n");
103 map__fprintf(pos, stdout);
104 }
105
106 if (pos->start >= pos->end) {
107 list_del_init(&pos->node);
108 free(pos);
109 }
110 }
111 }
112
113 list_add_tail(&map->node, &self->maps);
114}
115
116int thread__fork(struct thread *self, struct thread *parent)
117{
118 struct map *map;
119
120 if (self->comm)
121 free(self->comm);
122 self->comm = strdup(parent->comm);
123 if (!self->comm)
124 return -ENOMEM;
125
126 list_for_each_entry(map, &parent->maps, node) {
127 struct map *new = map__clone(map);
128 if (!new)
129 return -ENOMEM;
130 thread__insert_map(self, new);
131 }
132
133 return 0;
134}
135
136struct map *thread__find_map(struct thread *self, u64 ip)
137{
138 struct map *pos;
139
140 if (self == NULL)
141 return NULL;
142
143 list_for_each_entry(pos, &self->maps, node)
144 if (ip >= pos->start && ip <= pos->end)
145 return pos;
146
147 return NULL;
148}
149
150size_t threads__fprintf(FILE *fp, struct rb_root *threads)
151{
152 size_t ret = 0;
153 struct rb_node *nd;
154
155 for (nd = rb_first(threads); nd; nd = rb_next(nd)) {
156 struct thread *pos = rb_entry(nd, struct thread, rb_node);
157
158 ret += thread__fprintf(pos, fp);
159 }
160
161 return ret;
162}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
new file mode 100644
index 000000000000..b1c66719379b
--- /dev/null
+++ b/tools/perf/util/thread.h
@@ -0,0 +1,19 @@
1#include <linux/rbtree.h>
2#include <linux/list.h>
3#include <unistd.h>
4#include "symbol.h"
5
6struct thread {
7 struct rb_node rb_node;
8 struct list_head maps;
9 pid_t pid;
10 char *comm;
11};
12
13int thread__set_comm(struct thread *self, const char *comm);
14struct thread *
15threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match);
16void thread__insert_map(struct thread *self, struct map *map);
17int thread__fork(struct thread *self, struct thread *parent);
18struct map *thread__find_map(struct thread *self, u64 ip);
19size_t threads__fprintf(FILE *fp, struct rb_root *threads);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 68fe157d72fb..15004d211663 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -39,10 +39,6 @@
39/* Approximation of the length of the decimal representation of this type. */ 39/* Approximation of the length of the decimal representation of this type. */
40#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) 40#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
41 41
42#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && !defined(_M_UNIX)
43#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
44#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
45#endif
46#define _ALL_SOURCE 1 42#define _ALL_SOURCE 1
47#define _GNU_SOURCE 1 43#define _GNU_SOURCE 1
48#define _BSD_SOURCE 1 44#define _BSD_SOURCE 1
@@ -83,6 +79,7 @@
83#include <inttypes.h> 79#include <inttypes.h>
84#include "../../../include/linux/magic.h" 80#include "../../../include/linux/magic.h"
85 81
82
86#ifndef NO_ICONV 83#ifndef NO_ICONV
87#include <iconv.h> 84#include <iconv.h>
88#endif 85#endif
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
new file mode 100644
index 000000000000..1c15e39f99e3
--- /dev/null
+++ b/tools/perf/util/values.c
@@ -0,0 +1,230 @@
1#include <stdlib.h>
2
3#include "util.h"
4#include "values.h"
5
6void perf_read_values_init(struct perf_read_values *values)
7{
8 values->threads_max = 16;
9 values->pid = malloc(values->threads_max * sizeof(*values->pid));
10 values->tid = malloc(values->threads_max * sizeof(*values->tid));
11 values->value = malloc(values->threads_max * sizeof(*values->value));
12 if (!values->pid || !values->tid || !values->value)
13 die("failed to allocate read_values threads arrays");
14 values->threads = 0;
15
16 values->counters_max = 16;
17 values->counterrawid = malloc(values->counters_max
18 * sizeof(*values->counterrawid));
19 values->countername = malloc(values->counters_max
20 * sizeof(*values->countername));
21 if (!values->counterrawid || !values->countername)
22 die("failed to allocate read_values counters arrays");
23 values->counters = 0;
24}
25
26void perf_read_values_destroy(struct perf_read_values *values)
27{
28 int i;
29
30 if (!values->threads_max || !values->counters_max)
31 return;
32
33 for (i = 0; i < values->threads; i++)
34 free(values->value[i]);
35 free(values->pid);
36 free(values->tid);
37 free(values->counterrawid);
38 for (i = 0; i < values->counters; i++)
39 free(values->countername[i]);
40 free(values->countername);
41}
42
43static void perf_read_values__enlarge_threads(struct perf_read_values *values)
44{
45 values->threads_max *= 2;
46 values->pid = realloc(values->pid,
47 values->threads_max * sizeof(*values->pid));
48 values->tid = realloc(values->tid,
49 values->threads_max * sizeof(*values->tid));
50 values->value = realloc(values->value,
51 values->threads_max * sizeof(*values->value));
52 if (!values->pid || !values->tid || !values->value)
53 die("failed to enlarge read_values threads arrays");
54}
55
56static int perf_read_values__findnew_thread(struct perf_read_values *values,
57 u32 pid, u32 tid)
58{
59 int i;
60
61 for (i = 0; i < values->threads; i++)
62 if (values->pid[i] == pid && values->tid[i] == tid)
63 return i;
64
65 if (values->threads == values->threads_max)
66 perf_read_values__enlarge_threads(values);
67
68 i = values->threads++;
69 values->pid[i] = pid;
70 values->tid[i] = tid;
71 values->value[i] = malloc(values->counters_max * sizeof(**values->value));
72 if (!values->value[i])
73 die("failed to allocate read_values counters array");
74
75 return i;
76}
77
78static void perf_read_values__enlarge_counters(struct perf_read_values *values)
79{
80 int i;
81
82 values->counters_max *= 2;
83 values->counterrawid = realloc(values->counterrawid,
84 values->counters_max * sizeof(*values->counterrawid));
85 values->countername = realloc(values->countername,
86 values->counters_max * sizeof(*values->countername));
87 if (!values->counterrawid || !values->countername)
88 die("failed to enlarge read_values counters arrays");
89
90 for (i = 0; i < values->threads; i++) {
91 values->value[i] = realloc(values->value[i],
92 values->counters_max * sizeof(**values->value));
93 if (!values->value[i])
94 die("failed to enlarge read_values counters arrays");
95 }
96}
97
98static int perf_read_values__findnew_counter(struct perf_read_values *values,
99 u64 rawid, const char *name)
100{
101 int i;
102
103 for (i = 0; i < values->counters; i++)
104 if (values->counterrawid[i] == rawid)
105 return i;
106
107 if (values->counters == values->counters_max)
108 perf_read_values__enlarge_counters(values);
109
110 i = values->counters++;
111 values->counterrawid[i] = rawid;
112 values->countername[i] = strdup(name);
113
114 return i;
115}
116
117void perf_read_values_add_value(struct perf_read_values *values,
118 u32 pid, u32 tid,
119 u64 rawid, const char *name, u64 value)
120{
121 int tindex, cindex;
122
123 tindex = perf_read_values__findnew_thread(values, pid, tid);
124 cindex = perf_read_values__findnew_counter(values, rawid, name);
125
126 values->value[tindex][cindex] = value;
127}
128
129static void perf_read_values__display_pretty(FILE *fp,
130 struct perf_read_values *values)
131{
132 int i, j;
133 int pidwidth, tidwidth;
134 int *counterwidth;
135
136 counterwidth = malloc(values->counters * sizeof(*counterwidth));
137 if (!counterwidth)
138 die("failed to allocate counterwidth array");
139 tidwidth = 3;
140 pidwidth = 3;
141 for (j = 0; j < values->counters; j++)
142 counterwidth[j] = strlen(values->countername[j]);
143 for (i = 0; i < values->threads; i++) {
144 int width;
145
146 width = snprintf(NULL, 0, "%d", values->pid[i]);
147 if (width > pidwidth)
148 pidwidth = width;
149 width = snprintf(NULL, 0, "%d", values->tid[i]);
150 if (width > tidwidth)
151 tidwidth = width;
152 for (j = 0; j < values->counters; j++) {
153 width = snprintf(NULL, 0, "%Lu", values->value[i][j]);
154 if (width > counterwidth[j])
155 counterwidth[j] = width;
156 }
157 }
158
159 fprintf(fp, "# %*s %*s", pidwidth, "PID", tidwidth, "TID");
160 for (j = 0; j < values->counters; j++)
161 fprintf(fp, " %*s", counterwidth[j], values->countername[j]);
162 fprintf(fp, "\n");
163
164 for (i = 0; i < values->threads; i++) {
165 fprintf(fp, " %*d %*d", pidwidth, values->pid[i],
166 tidwidth, values->tid[i]);
167 for (j = 0; j < values->counters; j++)
168 fprintf(fp, " %*Lu",
169 counterwidth[j], values->value[i][j]);
170 fprintf(fp, "\n");
171 }
172}
173
174static void perf_read_values__display_raw(FILE *fp,
175 struct perf_read_values *values)
176{
177 int width, pidwidth, tidwidth, namewidth, rawwidth, countwidth;
178 int i, j;
179
180 tidwidth = 3; /* TID */
181 pidwidth = 3; /* PID */
182 namewidth = 4; /* "Name" */
183 rawwidth = 3; /* "Raw" */
184 countwidth = 5; /* "Count" */
185
186 for (i = 0; i < values->threads; i++) {
187 width = snprintf(NULL, 0, "%d", values->pid[i]);
188 if (width > pidwidth)
189 pidwidth = width;
190 width = snprintf(NULL, 0, "%d", values->tid[i]);
191 if (width > tidwidth)
192 tidwidth = width;
193 }
194 for (j = 0; j < values->counters; j++) {
195 width = strlen(values->countername[j]);
196 if (width > namewidth)
197 namewidth = width;
198 width = snprintf(NULL, 0, "%llx", values->counterrawid[j]);
199 if (width > rawwidth)
200 rawwidth = width;
201 }
202 for (i = 0; i < values->threads; i++) {
203 for (j = 0; j < values->counters; j++) {
204 width = snprintf(NULL, 0, "%Lu", values->value[i][j]);
205 if (width > countwidth)
206 countwidth = width;
207 }
208 }
209
210 fprintf(fp, "# %*s %*s %*s %*s %*s\n",
211 pidwidth, "PID", tidwidth, "TID",
212 namewidth, "Name", rawwidth, "Raw",
213 countwidth, "Count");
214 for (i = 0; i < values->threads; i++)
215 for (j = 0; j < values->counters; j++)
216 fprintf(fp, " %*d %*d %*s %*llx %*Lu\n",
217 pidwidth, values->pid[i],
218 tidwidth, values->tid[i],
219 namewidth, values->countername[j],
220 rawwidth, values->counterrawid[j],
221 countwidth, values->value[i][j]);
222}
223
224void perf_read_values_display(FILE *fp, struct perf_read_values *values, int raw)
225{
226 if (raw)
227 perf_read_values__display_raw(fp, values);
228 else
229 perf_read_values__display_pretty(fp, values);
230}
diff --git a/tools/perf/util/values.h b/tools/perf/util/values.h
new file mode 100644
index 000000000000..cadf8cf2a590
--- /dev/null
+++ b/tools/perf/util/values.h
@@ -0,0 +1,27 @@
1#ifndef _PERF_VALUES_H
2#define _PERF_VALUES_H
3
4#include "types.h"
5
6struct perf_read_values {
7 int threads;
8 int threads_max;
9 u32 *pid, *tid;
10 int counters;
11 int counters_max;
12 u64 *counterrawid;
13 char **countername;
14 u64 **value;
15};
16
17void perf_read_values_init(struct perf_read_values *values);
18void perf_read_values_destroy(struct perf_read_values *values);
19
20void perf_read_values_add_value(struct perf_read_values *values,
21 u32 pid, u32 tid,
22 u64 rawid, const char *name, u64 value);
23
24void perf_read_values_display(FILE *fp, struct perf_read_values *values,
25 int raw);
26
27#endif /* _PERF_VALUES_H */