aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-annotate.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r--tools/perf/builtin-annotate.c530
1 files changed, 62 insertions, 468 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 1ec741615814..56ba71658d70 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -22,15 +22,13 @@
22#include "util/parse-options.h" 22#include "util/parse-options.h"
23#include "util/parse-events.h" 23#include "util/parse-events.h"
24#include "util/thread.h" 24#include "util/thread.h"
25#include "util/sort.h"
26#include "util/hist.h"
25 27
26static char const *input_name = "perf.data"; 28static char const *input_name = "perf.data";
27 29
28static char default_sort_order[] = "comm,symbol";
29static char *sort_order = default_sort_order;
30
31static int force; 30static int force;
32static int input; 31static int input;
33static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
34 32
35static int full_paths; 33static int full_paths;
36 34
@@ -39,258 +37,12 @@ static int print_line;
39static unsigned long page_size; 37static unsigned long page_size;
40static unsigned long mmap_window = 32; 38static unsigned long mmap_window = 32;
41 39
42static struct rb_root threads;
43static struct thread *last_match;
44
45
46struct sym_ext { 40struct sym_ext {
47 struct rb_node node; 41 struct rb_node node;
48 double percent; 42 double percent;
49 char *path; 43 char *path;
50}; 44};
51 45
52/*
53 * histogram, sorted on item, collects counts
54 */
55
56static struct rb_root hist;
57
58struct hist_entry {
59 struct rb_node rb_node;
60
61 struct thread *thread;
62 struct map *map;
63 struct dso *dso;
64 struct symbol *sym;
65 u64 ip;
66 char level;
67
68 uint32_t count;
69};
70
71/*
72 * configurable sorting bits
73 */
74
75struct sort_entry {
76 struct list_head list;
77
78 const char *header;
79
80 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
81 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
82 size_t (*print)(FILE *fp, struct hist_entry *);
83};
84
85/* --sort pid */
86
87static int64_t
88sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
89{
90 return right->thread->pid - left->thread->pid;
91}
92
93static size_t
94sort__thread_print(FILE *fp, struct hist_entry *self)
95{
96 return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid);
97}
98
99static struct sort_entry sort_thread = {
100 .header = " Command: Pid",
101 .cmp = sort__thread_cmp,
102 .print = sort__thread_print,
103};
104
105/* --sort comm */
106
107static int64_t
108sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
109{
110 return right->thread->pid - left->thread->pid;
111}
112
113static int64_t
114sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
115{
116 char *comm_l = left->thread->comm;
117 char *comm_r = right->thread->comm;
118
119 if (!comm_l || !comm_r) {
120 if (!comm_l && !comm_r)
121 return 0;
122 else if (!comm_l)
123 return -1;
124 else
125 return 1;
126 }
127
128 return strcmp(comm_l, comm_r);
129}
130
131static size_t
132sort__comm_print(FILE *fp, struct hist_entry *self)
133{
134 return fprintf(fp, "%16s", self->thread->comm);
135}
136
137static struct sort_entry sort_comm = {
138 .header = " Command",
139 .cmp = sort__comm_cmp,
140 .collapse = sort__comm_collapse,
141 .print = sort__comm_print,
142};
143
144/* --sort dso */
145
146static int64_t
147sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
148{
149 struct dso *dso_l = left->dso;
150 struct dso *dso_r = right->dso;
151
152 if (!dso_l || !dso_r) {
153 if (!dso_l && !dso_r)
154 return 0;
155 else if (!dso_l)
156 return -1;
157 else
158 return 1;
159 }
160
161 return strcmp(dso_l->name, dso_r->name);
162}
163
164static size_t
165sort__dso_print(FILE *fp, struct hist_entry *self)
166{
167 if (self->dso)
168 return fprintf(fp, "%-25s", self->dso->name);
169
170 return fprintf(fp, "%016llx ", (u64)self->ip);
171}
172
173static struct sort_entry sort_dso = {
174 .header = "Shared Object ",
175 .cmp = sort__dso_cmp,
176 .print = sort__dso_print,
177};
178
179/* --sort symbol */
180
181static int64_t
182sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
183{
184 u64 ip_l, ip_r;
185
186 if (left->sym == right->sym)
187 return 0;
188
189 ip_l = left->sym ? left->sym->start : left->ip;
190 ip_r = right->sym ? right->sym->start : right->ip;
191
192 return (int64_t)(ip_r - ip_l);
193}
194
195static size_t
196sort__sym_print(FILE *fp, struct hist_entry *self)
197{
198 size_t ret = 0;
199
200 if (verbose)
201 ret += fprintf(fp, "%#018llx ", (u64)self->ip);
202
203 if (self->sym) {
204 ret += fprintf(fp, "[%c] %s",
205 self->dso == kernel_dso ? 'k' : '.', self->sym->name);
206 } else {
207 ret += fprintf(fp, "%#016llx", (u64)self->ip);
208 }
209
210 return ret;
211}
212
213static struct sort_entry sort_sym = {
214 .header = "Symbol",
215 .cmp = sort__sym_cmp,
216 .print = sort__sym_print,
217};
218
219static int sort__need_collapse = 0;
220
221struct sort_dimension {
222 const char *name;
223 struct sort_entry *entry;
224 int taken;
225};
226
227static struct sort_dimension sort_dimensions[] = {
228 { .name = "pid", .entry = &sort_thread, },
229 { .name = "comm", .entry = &sort_comm, },
230 { .name = "dso", .entry = &sort_dso, },
231 { .name = "symbol", .entry = &sort_sym, },
232};
233
234static LIST_HEAD(hist_entry__sort_list);
235
236static int sort_dimension__add(char *tok)
237{
238 unsigned int i;
239
240 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
241 struct sort_dimension *sd = &sort_dimensions[i];
242
243 if (sd->taken)
244 continue;
245
246 if (strncasecmp(tok, sd->name, strlen(tok)))
247 continue;
248
249 if (sd->entry->collapse)
250 sort__need_collapse = 1;
251
252 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
253 sd->taken = 1;
254
255 return 0;
256 }
257
258 return -ESRCH;
259}
260
261static int64_t
262hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
263{
264 struct sort_entry *se;
265 int64_t cmp = 0;
266
267 list_for_each_entry(se, &hist_entry__sort_list, list) {
268 cmp = se->cmp(left, right);
269 if (cmp)
270 break;
271 }
272
273 return cmp;
274}
275
276static int64_t
277hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
278{
279 struct sort_entry *se;
280 int64_t cmp = 0;
281
282 list_for_each_entry(se, &hist_entry__sort_list, list) {
283 int64_t (*f)(struct hist_entry *, struct hist_entry *);
284
285 f = se->collapse ?: se->cmp;
286
287 cmp = f(left, right);
288 if (cmp)
289 break;
290 }
291
292 return cmp;
293}
294 46
295/* 47/*
296 * collect histogram counts 48 * collect histogram counts
@@ -306,6 +58,7 @@ static void hist_hit(struct hist_entry *he, u64 ip)
306 return; 58 return;
307 59
308 sym_size = sym->end - sym->start; 60 sym_size = sym->end - sym->start;
61 ip = he->map->map_ip(he->map, ip);
309 offset = ip - sym->start; 62 offset = ip - sym->start;
310 63
311 if (offset >= sym_size) 64 if (offset >= sym_size)
@@ -322,173 +75,27 @@ static void hist_hit(struct hist_entry *he, u64 ip)
322 sym->hist[offset]); 75 sym->hist[offset]);
323} 76}
324 77
325static int 78static int hist_entry__add(struct thread *thread, struct map *map,
326hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 79 struct symbol *sym, u64 ip, u64 count, char level)
327 struct symbol *sym, u64 ip, char level)
328{ 80{
329 struct rb_node **p = &hist.rb_node; 81 bool hit;
330 struct rb_node *parent = NULL; 82 struct hist_entry *he = __hist_entry__add(thread, map, sym, NULL, ip,
331 struct hist_entry *he; 83 count, level, &hit);
332 struct hist_entry entry = { 84 if (he == NULL)
333 .thread = thread,
334 .map = map,
335 .dso = dso,
336 .sym = sym,
337 .ip = ip,
338 .level = level,
339 .count = 1,
340 };
341 int cmp;
342
343 while (*p != NULL) {
344 parent = *p;
345 he = rb_entry(parent, struct hist_entry, rb_node);
346
347 cmp = hist_entry__cmp(&entry, he);
348
349 if (!cmp) {
350 hist_hit(he, ip);
351
352 return 0;
353 }
354
355 if (cmp < 0)
356 p = &(*p)->rb_left;
357 else
358 p = &(*p)->rb_right;
359 }
360
361 he = malloc(sizeof(*he));
362 if (!he)
363 return -ENOMEM; 85 return -ENOMEM;
364 *he = entry; 86 if (hit)
365 rb_link_node(&he->rb_node, parent, p); 87 hist_hit(he, ip);
366 rb_insert_color(&he->rb_node, &hist);
367
368 return 0; 88 return 0;
369} 89}
370 90
371static void hist_entry__free(struct hist_entry *he)
372{
373 free(he);
374}
375
376/*
377 * collapse the histogram
378 */
379
380static struct rb_root collapse_hists;
381
382static void collapse__insert_entry(struct hist_entry *he)
383{
384 struct rb_node **p = &collapse_hists.rb_node;
385 struct rb_node *parent = NULL;
386 struct hist_entry *iter;
387 int64_t cmp;
388
389 while (*p != NULL) {
390 parent = *p;
391 iter = rb_entry(parent, struct hist_entry, rb_node);
392
393 cmp = hist_entry__collapse(iter, he);
394
395 if (!cmp) {
396 iter->count += he->count;
397 hist_entry__free(he);
398 return;
399 }
400
401 if (cmp < 0)
402 p = &(*p)->rb_left;
403 else
404 p = &(*p)->rb_right;
405 }
406
407 rb_link_node(&he->rb_node, parent, p);
408 rb_insert_color(&he->rb_node, &collapse_hists);
409}
410
411static void collapse__resort(void)
412{
413 struct rb_node *next;
414 struct hist_entry *n;
415
416 if (!sort__need_collapse)
417 return;
418
419 next = rb_first(&hist);
420 while (next) {
421 n = rb_entry(next, struct hist_entry, rb_node);
422 next = rb_next(&n->rb_node);
423
424 rb_erase(&n->rb_node, &hist);
425 collapse__insert_entry(n);
426 }
427}
428
429/*
430 * reverse the map, sort on count.
431 */
432
433static struct rb_root output_hists;
434
435static void output__insert_entry(struct hist_entry *he)
436{
437 struct rb_node **p = &output_hists.rb_node;
438 struct rb_node *parent = NULL;
439 struct hist_entry *iter;
440
441 while (*p != NULL) {
442 parent = *p;
443 iter = rb_entry(parent, struct hist_entry, rb_node);
444
445 if (he->count > iter->count)
446 p = &(*p)->rb_left;
447 else
448 p = &(*p)->rb_right;
449 }
450
451 rb_link_node(&he->rb_node, parent, p);
452 rb_insert_color(&he->rb_node, &output_hists);
453}
454
455static void output__resort(void)
456{
457 struct rb_node *next;
458 struct hist_entry *n;
459 struct rb_root *tree = &hist;
460
461 if (sort__need_collapse)
462 tree = &collapse_hists;
463
464 next = rb_first(tree);
465
466 while (next) {
467 n = rb_entry(next, struct hist_entry, rb_node);
468 next = rb_next(&n->rb_node);
469
470 rb_erase(&n->rb_node, tree);
471 output__insert_entry(n);
472 }
473}
474
475static unsigned long total = 0,
476 total_mmap = 0,
477 total_comm = 0,
478 total_fork = 0,
479 total_unknown = 0;
480
481static int 91static int
482process_sample_event(event_t *event, unsigned long offset, unsigned long head) 92process_sample_event(event_t *event, unsigned long offset, unsigned long head)
483{ 93{
484 char level; 94 char level;
485 int show = 0;
486 struct dso *dso = NULL;
487 struct thread *thread;
488 u64 ip = event->ip.ip; 95 u64 ip = event->ip.ip;
489 struct map *map = NULL; 96 struct map *map = NULL;
490 97 struct symbol *sym = NULL;
491 thread = threads__findnew(event->ip.pid, &threads, &last_match); 98 struct thread *thread = threads__findnew(event->ip.pid);
492 99
493 dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", 100 dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
494 (void *)(offset + head), 101 (void *)(offset + head),
@@ -497,60 +104,53 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
497 event->ip.pid, 104 event->ip.pid,
498 (void *)(long)ip); 105 (void *)(long)ip);
499 106
500 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
501
502 if (thread == NULL) { 107 if (thread == NULL) {
503 fprintf(stderr, "problem processing %d event, skipping it.\n", 108 fprintf(stderr, "problem processing %d event, skipping it.\n",
504 event->header.type); 109 event->header.type);
505 return -1; 110 return -1;
506 } 111 }
507 112
113 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
114
508 if (event->header.misc & PERF_RECORD_MISC_KERNEL) { 115 if (event->header.misc & PERF_RECORD_MISC_KERNEL) {
509 show = SHOW_KERNEL;
510 level = 'k'; 116 level = 'k';
511 117 sym = kernel_maps__find_symbol(ip, &map);
512 dso = kernel_dso; 118 dump_printf(" ...... dso: %s\n",
513 119 map ? map->dso->long_name : "<not found>");
514 dump_printf(" ...... dso: %s\n", dso->name);
515
516 } else if (event->header.misc & PERF_RECORD_MISC_USER) { 120 } else if (event->header.misc & PERF_RECORD_MISC_USER) {
517
518 show = SHOW_USER;
519 level = '.'; 121 level = '.';
520
521 map = thread__find_map(thread, ip); 122 map = thread__find_map(thread, ip);
522 if (map != NULL) { 123 if (map != NULL) {
124got_map:
523 ip = map->map_ip(map, ip); 125 ip = map->map_ip(map, ip);
524 dso = map->dso; 126 sym = map->dso->find_symbol(map->dso, ip);
525 } else { 127 } else {
526 /* 128 /*
527 * If this is outside of all known maps, 129 * If this is outside of all known maps,
528 * and is a negative address, try to look it 130 * and is a negative address, try to look it
529 * up in the kernel dso, as it might be a 131 * up in the kernel dso, as it might be a
530 * vsyscall (which executes in user-mode): 132 * vsyscall or vdso (which executes in user-mode).
133 *
134 * XXX This is nasty, we should have a symbol list in
135 * the "[vdso]" dso, but for now lets use the old
136 * trick of looking in the whole kernel symbol list.
531 */ 137 */
532 if ((long long)ip < 0) 138 if ((long long)ip < 0) {
533 dso = kernel_dso; 139 map = kernel_map;
140 goto got_map;
141 }
534 } 142 }
535 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 143 dump_printf(" ...... dso: %s\n",
536 144 map ? map->dso->long_name : "<not found>");
537 } else { 145 } else {
538 show = SHOW_HV;
539 level = 'H'; 146 level = 'H';
540 dump_printf(" ...... dso: [hypervisor]\n"); 147 dump_printf(" ...... dso: [hypervisor]\n");
541 } 148 }
542 149
543 if (show & show_mask) { 150 if (hist_entry__add(thread, map, sym, ip, 1, level)) {
544 struct symbol *sym = NULL; 151 fprintf(stderr, "problem incrementing symbol count, "
545 152 "skipping event\n");
546 if (dso) 153 return -1;
547 sym = dso->find_symbol(dso, ip);
548
549 if (hist_entry__add(thread, map, dso, sym, ip, level)) {
550 fprintf(stderr,
551 "problem incrementing symbol count, skipping event\n");
552 return -1;
553 }
554 } 154 }
555 total++; 155 total++;
556 156
@@ -560,10 +160,8 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
560static int 160static int
561process_mmap_event(event_t *event, unsigned long offset, unsigned long head) 161process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
562{ 162{
563 struct thread *thread;
564 struct map *map = map__new(&event->mmap, NULL, 0); 163 struct map *map = map__new(&event->mmap, NULL, 0);
565 164 struct thread *thread = threads__findnew(event->mmap.pid);
566 thread = threads__findnew(event->mmap.pid, &threads, &last_match);
567 165
568 dump_printf("%p [%p]: PERF_RECORD_MMAP %d: [%p(%p) @ %p]: %s\n", 166 dump_printf("%p [%p]: PERF_RECORD_MMAP %d: [%p(%p) @ %p]: %s\n",
569 (void *)(offset + head), 167 (void *)(offset + head),
@@ -588,9 +186,8 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
588static int 186static int
589process_comm_event(event_t *event, unsigned long offset, unsigned long head) 187process_comm_event(event_t *event, unsigned long offset, unsigned long head)
590{ 188{
591 struct thread *thread; 189 struct thread *thread = threads__findnew(event->comm.pid);
592 190
593 thread = threads__findnew(event->comm.pid, &threads, &last_match);
594 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n", 191 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
595 (void *)(offset + head), 192 (void *)(offset + head),
596 (void *)(long)(event->header.size), 193 (void *)(long)(event->header.size),
@@ -609,11 +206,9 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
609static int 206static int
610process_fork_event(event_t *event, unsigned long offset, unsigned long head) 207process_fork_event(event_t *event, unsigned long offset, unsigned long head)
611{ 208{
612 struct thread *thread; 209 struct thread *thread = threads__findnew(event->fork.pid);
613 struct thread *parent; 210 struct thread *parent = threads__findnew(event->fork.ppid);
614 211
615 thread = threads__findnew(event->fork.pid, &threads, &last_match);
616 parent = threads__findnew(event->fork.ppid, &threads, &last_match);
617 dump_printf("%p [%p]: PERF_RECORD_FORK: %d:%d\n", 212 dump_printf("%p [%p]: PERF_RECORD_FORK: %d:%d\n",
618 (void *)(offset + head), 213 (void *)(offset + head),
619 (void *)(long)(event->header.size), 214 (void *)(long)(event->header.size),
@@ -666,7 +261,7 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
666} 261}
667 262
668static int 263static int
669parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) 264parse_line(FILE *file, struct symbol *sym, u64 len)
670{ 265{
671 char *line = NULL, *tmp, *tmp2; 266 char *line = NULL, *tmp, *tmp2;
672 static const char *prev_line; 267 static const char *prev_line;
@@ -716,7 +311,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
716 const char *color; 311 const char *color;
717 struct sym_ext *sym_ext = sym->priv; 312 struct sym_ext *sym_ext = sym->priv;
718 313
719 offset = line_ip - start; 314 offset = line_ip - sym->start;
720 if (offset < len) 315 if (offset < len)
721 hits = sym->hist[offset]; 316 hits = sym->hist[offset];
722 317
@@ -795,7 +390,7 @@ static void free_source_line(struct symbol *sym, int len)
795 390
796/* Get the filename:line for the colored entries */ 391/* Get the filename:line for the colored entries */
797static void 392static void
798get_source_line(struct symbol *sym, u64 start, int len, const char *filename) 393get_source_line(struct symbol *sym, int len, const char *filename)
799{ 394{
800 int i; 395 int i;
801 char cmd[PATH_MAX * 2]; 396 char cmd[PATH_MAX * 2];
@@ -820,7 +415,7 @@ get_source_line(struct symbol *sym, u64 start, int len, const char *filename)
820 if (sym_ext[i].percent <= 0.5) 415 if (sym_ext[i].percent <= 0.5)
821 continue; 416 continue;
822 417
823 offset = start + i; 418 offset = sym->start + i;
824 sprintf(cmd, "addr2line -e %s %016llx", filename, offset); 419 sprintf(cmd, "addr2line -e %s %016llx", filename, offset);
825 fp = popen(cmd, "r"); 420 fp = popen(cmd, "r");
826 if (!fp) 421 if (!fp)
@@ -872,31 +467,23 @@ static void print_summary(const char *filename)
872 467
873static void annotate_sym(struct dso *dso, struct symbol *sym) 468static void annotate_sym(struct dso *dso, struct symbol *sym)
874{ 469{
875 const char *filename = dso->name, *d_filename; 470 const char *filename = dso->long_name, *d_filename;
876 u64 start, end, len; 471 u64 len;
877 char command[PATH_MAX*2]; 472 char command[PATH_MAX*2];
878 FILE *file; 473 FILE *file;
879 474
880 if (!filename) 475 if (!filename)
881 return; 476 return;
882 if (sym->module) 477
883 filename = sym->module->path;
884 else if (dso == kernel_dso)
885 filename = vmlinux_name;
886
887 start = sym->obj_start;
888 if (!start)
889 start = sym->start;
890 if (full_paths) 478 if (full_paths)
891 d_filename = filename; 479 d_filename = filename;
892 else 480 else
893 d_filename = basename(filename); 481 d_filename = basename(filename);
894 482
895 end = start + sym->end - sym->start + 1;
896 len = sym->end - sym->start; 483 len = sym->end - sym->start;
897 484
898 if (print_line) { 485 if (print_line) {
899 get_source_line(sym, start, len, filename); 486 get_source_line(sym, len, filename);
900 print_summary(filename); 487 print_summary(filename);
901 } 488 }
902 489
@@ -905,10 +492,11 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
905 printf("------------------------------------------------\n"); 492 printf("------------------------------------------------\n");
906 493
907 if (verbose >= 2) 494 if (verbose >= 2)
908 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 495 printf("annotating [%p] %30s : [%p] %30s\n",
496 dso, dso->long_name, sym, sym->name);
909 497
910 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", 498 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
911 (u64)start, (u64)end, filename, filename); 499 sym->start, sym->end, filename, filename);
912 500
913 if (verbose >= 3) 501 if (verbose >= 3)
914 printf("doing: %s\n", command); 502 printf("doing: %s\n", command);
@@ -918,7 +506,7 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
918 return; 506 return;
919 507
920 while (!feof(file)) { 508 while (!feof(file)) {
921 if (parse_line(file, sym, start, len) < 0) 509 if (parse_line(file, sym, len) < 0)
922 break; 510 break;
923 } 511 }
924 512
@@ -959,7 +547,7 @@ static int __cmd_annotate(void)
959 uint32_t size; 547 uint32_t size;
960 char *buf; 548 char *buf;
961 549
962 register_idle_thread(&threads, &last_match); 550 register_idle_thread();
963 551
964 input = open(input_name, O_RDONLY); 552 input = open(input_name, O_RDONLY);
965 if (input < 0) { 553 if (input < 0) {
@@ -1059,14 +647,14 @@ more:
1059 if (dump_trace) 647 if (dump_trace)
1060 return 0; 648 return 0;
1061 649
1062 if (verbose >= 3) 650 if (verbose > 3)
1063 threads__fprintf(stdout, &threads); 651 threads__fprintf(stdout);
1064 652
1065 if (verbose >= 2) 653 if (verbose > 2)
1066 dsos__fprintf(stdout); 654 dsos__fprintf(stdout);
1067 655
1068 collapse__resort(); 656 collapse__resort();
1069 output__resort(); 657 output__resort(total);
1070 658
1071 find_annotations(); 659 find_annotations();
1072 660
@@ -1139,5 +727,11 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
1139 727
1140 setup_pager(); 728 setup_pager();
1141 729
730 if (field_sep && *field_sep == '.') {
731 fputs("'.' is the only non valid --field-separator argument\n",
732 stderr);
733 exit(129);
734 }
735
1142 return __cmd_annotate(); 736 return __cmd_annotate();
1143} 737}