Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * builtin-annotate.c
  3  *
  4  * Builtin annotate command: Analyze the perf.data input file,
  5  * look up and read DSOs and symbol information and display
  6  * a histogram of results, along various sorting keys.
  7  */
  8 #include "builtin.h"
  9 
 10 #include "util/util.h"
 11 
 12 #include "util/color.h"
 13 #include <linux/list.h>
 14 #include "util/cache.h"
 15 #include <linux/rbtree.h>
 16 #include "util/symbol.h"
 17 #include "util/string.h"
 18 
 19 #include "perf.h"
 20 
 21 #include "util/parse-options.h"
 22 #include "util/parse-events.h"
 23 
 24 #define SHOW_KERNEL     1
 25 #define SHOW_USER       2
 26 #define SHOW_HV         4
 27 
 28 static char             const *input_name = "perf.data";
 29 static char             *vmlinux = "vmlinux";
 30 
 31 static char             default_sort_order[] = "comm,symbol";
 32 static char             *sort_order = default_sort_order;
 33 
 34 static int              force;
 35 static int              input;
 36 static int              show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
 37 
 38 static int              dump_trace = 0;
 39 #define dprintf(x...)   do { if (dump_trace) printf(x); } while (0)
 40 
 41 static int              verbose;
 42 
 43 static int              modules;
 44 
 45 static int              full_paths;
 46 
 47 static int              print_line;
 48 
 49 static unsigned long    page_size;
 50 static unsigned long    mmap_window = 32;
 51 
 52 struct ip_event {
 53         struct perf_event_header header;
 54         u64 ip;
 55         u32 pid, tid;
 56 };
 57 
 58 struct 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 
 67 struct comm_event {
 68         struct perf_event_header header;
 69         u32 pid, tid;
 70         char comm[16];
 71 };
 72 
 73 struct fork_event {
 74         struct perf_event_header header;
 75         u32 pid, ppid;
 76 };
 77 
 78 typedef 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 
 86 
 87 struct sym_ext {
 88         struct rb_node  node;
 89         double          percent;
 90         char            *path;
 91 };
 92 
 93 static LIST_HEAD(dsos);
 94 static struct dso *kernel_dso;
 95 static struct dso *vdso;
 96 
 97 
 98 static void dsos__add(struct dso *dso)
 99 {
100         list_add_tail(&dso->node, &dsos);
101 }
102 
103 static 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 
113 static 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 
141 out_delete_dso:
142         dso__delete(dso);
143         return NULL;
144 }
145 
146 static 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 
154 static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
155 {
156         return dso__find_symbol(dso, ip);
157 }
158 
159 static 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 
185 struct 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 
194 static u64 map__map_ip(struct map *map, u64 ip)
195 {
196         return ip - map->start + map->pgoff;
197 }
198 
199 static u64 vdso__map_ip(struct map *map __used, u64 ip)
200 {
201         return ip;
202 }
203 
204 static 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;
225 out_delete:
226         free(self);
227         return NULL;
228 }
229 
230 static 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 
242 static 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 
256 static 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 
263 struct thread {
264         struct rb_node   rb_node;
265         struct list_head maps;
266         pid_t            pid;
267         char             *comm;
268 };
269 
270 static 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 
285 static 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 
293 static 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 
305 static struct rb_root threads;
306 static struct thread *last_match;
307 
308 static 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 
347 static 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 
362 static 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 
382 static 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 
396 static 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 /*
411  * histogram, sorted on item, collects counts
412  */
413 
414 static struct rb_root hist;
415 
416 struct hist_entry {
417         struct rb_node   rb_node;
418 
419         struct thread    *thread;
420         struct map       *map;
421         struct dso       *dso;
422         struct symbol    *sym;
423         u64      ip;
424         char             level;
425 
426         uint32_t         count;
427 };
428 
429 /*
430  * configurable sorting bits
431  */
432 
433 struct sort_entry {
434         struct list_head list;
435 
436         char *header;
437 
438         int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
439         int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
440         size_t  (*print)(FILE *fp, struct hist_entry *);
441 };
442 
443 /* --sort pid */
444 
445 static int64_t
446 sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
447 {
448         return right->thread->pid - left->thread->pid;
449 }
450 
451 static size_t
452 sort__thread_print(FILE *fp, struct hist_entry *self)
453 {
454         return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid);
455 }
456 
457 static struct sort_entry sort_thread = {
458         .header = "         Command:  Pid",
459         .cmp    = sort__thread_cmp,
460         .print  = sort__thread_print,
461 };
462 
463 /* --sort comm */
464 
465 static int64_t
466 sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
467 {
468         return right->thread->pid - left->thread->pid;
469 }
470 
471 static int64_t
472 sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
473 {
474         char *comm_l = left->thread->comm;
475         char *comm_r = right->thread->comm;
476 
477         if (!comm_l || !comm_r) {
478                 if (!comm_l && !comm_r)
479                         return 0;
480                 else if (!comm_l)
481                         return -1;
482                 else
483                         return 1;
484         }
485 
486         return strcmp(comm_l, comm_r);
487 }
488 
489 static size_t
490 sort__comm_print(FILE *fp, struct hist_entry *self)
491 {
492         return fprintf(fp, "%16s", self->thread->comm);
493 }
494 
495 static struct sort_entry sort_comm = {
496         .header         = "         Command",
497         .cmp            = sort__comm_cmp,
498         .collapse       = sort__comm_collapse,
499         .print          = sort__comm_print,
500 };
501 
502 /* --sort dso */
503 
504 static int64_t
505 sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
506 {
507         struct dso *dso_l = left->dso;
508         struct dso *dso_r = right->dso;
509 
510         if (!dso_l || !dso_r) {
511                 if (!dso_l && !dso_r)
512                         return 0;
513                 else if (!dso_l)
514                         return -1;
515                 else
516                         return 1;
517         }
518 
519         return strcmp(dso_l->name, dso_r->name);
520 }
521 
522 static size_t
523 sort__dso_print(FILE *fp, struct hist_entry *self)
524 {
525         if (self->dso)
526                 return fprintf(fp, "%-25s", self->dso->name);
527 
528         return fprintf(fp, "%016llx         ", (u64)self->ip);
529 }
530 
531 static struct sort_entry sort_dso = {
532         .header = "Shared Object            ",
533         .cmp    = sort__dso_cmp,
534         .print  = sort__dso_print,
535 };
536 
537 /* --sort symbol */
538 
539 static int64_t
540 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
541 {
542         u64 ip_l, ip_r;
543 
544         if (left->sym == right->sym)
545                 return 0;
546 
547         ip_l = left->sym ? left->sym->start : left->ip;
548         ip_r = right->sym ? right->sym->start : right->ip;
549 
550         return (int64_t)(ip_r - ip_l);
551 }
552 
553 static size_t
554 sort__sym_print(FILE *fp, struct hist_entry *self)
555 {
556         size_t ret = 0;
557 
558         if (verbose)
559                 ret += fprintf(fp, "%#018llx  ", (u64)self->ip);
560 
561         if (self->sym) {
562                 ret += fprintf(fp, "[%c] %s",
563                         self->dso == kernel_dso ? 'k' : '.', self->sym->name);
564         } else {
565                 ret += fprintf(fp, "%#016llx", (u64)self->ip);
566         }
567 
568         return ret;
569 }
570 
571 static struct sort_entry sort_sym = {
572         .header = "Symbol",
573         .cmp    = sort__sym_cmp,
574         .print  = sort__sym_print,
575 };
576 
577 static int sort__need_collapse = 0;
578 
579 struct sort_dimension {
580         char                    *name;
581         struct sort_entry       *entry;
582         int                     taken;
583 };
584 
585 static struct sort_dimension sort_dimensions[] = {
586         { .name = "pid",        .entry = &sort_thread,  },
587         { .name = "comm",       .entry = &sort_comm,    },
588         { .name = "dso",        .entry = &sort_dso,     },
589         { .name = "symbol",     .entry = &sort_sym,     },
590 };
591 
592 static LIST_HEAD(hist_entry__sort_list);
593 
594 static int sort_dimension__add(char *tok)
595 {
596         unsigned int i;
597 
598         for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
599                 struct sort_dimension *sd = &sort_dimensions[i];
600 
601                 if (sd->taken)
602                         continue;
603 
604                 if (strncasecmp(tok, sd->name, strlen(tok)))
605                         continue;
606 
607                 if (sd->entry->collapse)
608                         sort__need_collapse = 1;
609 
610                 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
611                 sd->taken = 1;
612 
613                 return 0;
614         }
615 
616         return -ESRCH;
617 }
618 
619 static int64_t
620 hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
621 {
622         struct sort_entry *se;
623         int64_t cmp = 0;
624 
625         list_for_each_entry(se, &hist_entry__sort_list, list) {
626                 cmp = se->cmp(left, right);
627                 if (cmp)
628                         break;
629         }
630 
631         return cmp;
632 }
633 
634 static int64_t
635 hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
636 {
637         struct sort_entry *se;
638         int64_t cmp = 0;
639 
640         list_for_each_entry(se, &hist_entry__sort_list, list) {
641                 int64_t (*f)(struct hist_entry *, struct hist_entry *);
642 
643                 f = se->collapse ?: se->cmp;
644 
645                 cmp = f(left, right);
646                 if (cmp)
647                         break;
648         }
649 
650         return cmp;
651 }
652 
653 /*
654  * collect histogram counts
655  */
656 static void hist_hit(struct hist_entry *he, u64 ip)
657 {
658         unsigned int sym_size, offset;
659         struct symbol *sym = he->sym;
660 
661         he->count++;
662 
663         if (!sym || !sym->hist)
664                 return;
665 
666         sym_size = sym->end - sym->start;
667         offset = ip - sym->start;
668 
669         if (offset >= sym_size)
670                 return;
671 
672         sym->hist_sum++;
673         sym->hist[offset]++;
674 
675         if (verbose >= 3)
676                 printf("%p %s: count++ [ip: %p, %08Lx] => %Ld\n",
677                         (void *)(unsigned long)he->sym->start,
678                         he->sym->name,
679                         (void *)(unsigned long)ip, ip - he->sym->start,
680                         sym->hist[offset]);
681 }
682 
683 static int
684 hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
685                 struct symbol *sym, u64 ip, char level)
686 {
687         struct rb_node **p = &hist.rb_node;
688         struct rb_node *parent = NULL;
689         struct hist_entry *he;
690         struct hist_entry entry = {
691                 .thread = thread,
692                 .map    = map,
693                 .dso    = dso,
694                 .sym    = sym,
695                 .ip     = ip,
696                 .level  = level,
697                 .count  = 1,
698         };
699         int cmp;
700 
701         while (*p != NULL) {
702                 parent = *p;
703                 he = rb_entry(parent, struct hist_entry, rb_node);
704 
705                 cmp = hist_entry__cmp(&entry, he);
706 
707                 if (!cmp) {
708                         hist_hit(he, ip);
709 
710                         return 0;
711                 }
712 
713                 if (cmp < 0)
714                         p = &(*p)->rb_left;
715                 else
716                         p = &(*p)->rb_right;
717         }
718 
719         he = malloc(sizeof(*he));
720         if (!he)
721                 return -ENOMEM;
722         *he = entry;
723         rb_link_node(&he->rb_node, parent, p);
724         rb_insert_color(&he->rb_node, &hist);
725 
726         return 0;
727 }
728 
729 static void hist_entry__free(struct hist_entry *he)
730 {
731         free(he);
732 }
733 
734 /*
735  * collapse the histogram
736  */
737 
738 static struct rb_root collapse_hists;
739 
740 static void collapse__insert_entry(struct hist_entry *he)
741 {
742         struct rb_node **p = &collapse_hists.rb_node;
743         struct rb_node *parent = NULL;
744         struct hist_entry *iter;
745         int64_t cmp;
746 
747         while (*p != NULL) {
748                 parent = *p;
749                 iter = rb_entry(parent, struct hist_entry, rb_node);
750 
751                 cmp = hist_entry__collapse(iter, he);
752 
753                 if (!cmp) {
754                         iter->count += he->count;
755                         hist_entry__free(he);
756                         return;
757                 }
758 
759                 if (cmp < 0)
760                         p = &(*p)->rb_left;
761                 else
762                         p = &(*p)->rb_right;
763         }
764 
765         rb_link_node(&he->rb_node, parent, p);
766         rb_insert_color(&he->rb_node, &collapse_hists);
767 }
768 
769 static void collapse__resort(void)
770 {
771         struct rb_node *next;
772         struct hist_entry *n;
773 
774         if (!sort__need_collapse)
775                 return;
776 
777         next = rb_first(&hist);
778         while (next) {
779                 n = rb_entry(next, struct hist_entry, rb_node);
780                 next = rb_next(&n->rb_node);
781 
782                 rb_erase(&n->rb_node, &hist);
783                 collapse__insert_entry(n);
784         }
785 }
786 
787 /*
788  * reverse the map, sort on count.
789  */
790 
791 static struct rb_root output_hists;
792 
793 static void output__insert_entry(struct hist_entry *he)
794 {
795         struct rb_node **p = &output_hists.rb_node;
796         struct rb_node *parent = NULL;
797         struct hist_entry *iter;
798 
799         while (*p != NULL) {
800                 parent = *p;
801                 iter = rb_entry(parent, struct hist_entry, rb_node);
802 
803                 if (he->count > iter->count)
804                         p = &(*p)->rb_left;
805                 else
806                         p = &(*p)->rb_right;
807         }
808 
809         rb_link_node(&he->rb_node, parent, p);
810         rb_insert_color(&he->rb_node, &output_hists);
811 }
812 
813 static void output__resort(void)
814 {
815         struct rb_node *next;
816         struct hist_entry *n;
817         struct rb_root *tree = &hist;
818 
819         if (sort__need_collapse)
820                 tree = &collapse_hists;
821 
822         next = rb_first(tree);
823 
824         while (next) {
825                 n = rb_entry(next, struct hist_entry, rb_node);
826                 next = rb_next(&n->rb_node);
827 
828                 rb_erase(&n->rb_node, tree);
829                 output__insert_entry(n);
830         }
831 }
832 
833 static void register_idle_thread(void)
834 {
835         struct thread *thread = threads__findnew(0);
836 
837         if (thread == NULL ||
838                         thread__set_comm(thread, "[idle]")) {
839                 fprintf(stderr, "problem inserting idle task.\n");
840                 exit(-1);
841         }
842 }
843 
844 static unsigned long total = 0,
845                      total_mmap = 0,
846                      total_comm = 0,
847                      total_fork = 0,
848                      total_unknown = 0;
849 
850 static int
851 process_sample_event(event_t *event, unsigned long offset, unsigned long head)
852 {
853         char level;
854         int show = 0;
855         struct dso *dso = NULL;
856         struct thread *thread = threads__findnew(event->ip.pid);
857         u64 ip = event->ip.ip;
858         struct map *map = NULL;
859 
860         dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
861                 (void *)(offset + head),
862                 (void *)(long)(event->header.size),
863                 event->header.misc,
864                 event->ip.pid,
865                 (void *)(long)ip);
866 
867         dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid);
868 
869         if (thread == NULL) {
870                 fprintf(stderr, "problem processing %d event, skipping it.\n",
871                         event->header.type);
872                 return -1;
873         }
874 
875         if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
876                 show = SHOW_KERNEL;
877                 level = 'k';
878 
879                 dso = kernel_dso;
880 
881                 dprintf(" ...... dso: %s\n", dso->name);
882 
883         } else if (event->header.misc & PERF_EVENT_MISC_USER) {
884 
885                 show = SHOW_USER;
886                 level = '.';
887 
888                 map = thread__find_map(thread, ip);
889                 if (map != NULL) {
890                         ip = map->map_ip(map, ip);
891                         dso = map->dso;
892                 } else {
893                         /*
894                          * If this is outside of all known maps,
895                          * and is a negative address, try to look it
896                          * up in the kernel dso, as it might be a
897                          * vsyscall (which executes in user-mode):
898                          */
899                         if ((long long)ip < 0)
900                                 dso = kernel_dso;
901                 }
902                 dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
903 
904         } else {
905                 show = SHOW_HV;
906                 level = 'H';
907                 dprintf(" ...... dso: [hypervisor]\n");
908         }
909 
910         if (show & show_mask) {
911                 struct symbol *sym = NULL;
912 
913                 if (dso)
914                         sym = dso->find_symbol(dso, ip);
915 
916                 if (hist_entry__add(thread, map, dso, sym, ip, level)) {
917                         fprintf(stderr,
918                 "problem incrementing symbol count, skipping event\n");
919                         return -1;
920                 }
921         }
922         total++;
923 
924         return 0;
925 }
926 
927 static int
928 process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
929 {
930         struct thread *thread = threads__findnew(event->mmap.pid);
931         struct map *map = map__new(&event->mmap);
932 
933         dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n",
934                 (void *)(offset + head),
935                 (void *)(long)(event->header.size),
936                 event->mmap.pid,
937                 (void *)(long)event->mmap.start,
938                 (void *)(long)event->mmap.len,
939                 (void *)(long)event->mmap.pgoff,
940                 event->mmap.filename);
941 
942         if (thread == NULL || map == NULL) {
943                 dprintf("problem processing PERF_EVENT_MMAP, skipping event.\n");
944                 return 0;
945         }
946 
947         thread__insert_map(thread, map);
948         total_mmap++;
949 
950         return 0;
951 }
952 
953 static int
954 process_comm_event(event_t *event, unsigned long offset, unsigned long head)
955 {
956         struct thread *thread = threads__findnew(event->comm.pid);
957 
958         dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n",
959                 (void *)(offset + head),
960                 (void *)(long)(event->header.size),
961                 event->comm.comm, event->comm.pid);
962 
963         if (thread == NULL ||
964             thread__set_comm(thread, event->comm.comm)) {
965                 dprintf("problem processing PERF_EVENT_COMM, skipping event.\n");
966                 return -1;
967         }
968         total_comm++;
969 
970         return 0;
971 }
972 
973 static int
974 process_fork_event(event_t *event, unsigned long offset, unsigned long head)
975 {
976         struct thread *thread = threads__findnew(event->fork.pid);
977         struct thread *parent = threads__findnew(event->fork.ppid);
978 
979         dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n",
980                 (void *)(offset + head),
981                 (void *)(long)(event->header.size),
982                 event->fork.pid, event->fork.ppid);
983 
984         /*
985          * A thread clone will have the same PID for both
986          * parent and child.
987          */
988         if (thread == parent)
989                 return 0;
990 
991         if (!thread || !parent || thread__fork(thread, parent)) {
992                 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
993                 return -1;
994         }
995         total_fork++;
996 
997         return 0;
998 }
999 
1000 static int
1001 process_event(event_t *event, unsigned long offset, unsigned long head)
1002 {
1003         switch (event->header.type) {
1004         case PERF_EVENT_SAMPLE:
1005                 return process_sample_event(event, offset, head);
1006 
1007         case PERF_EVENT_MMAP:
1008                 return process_mmap_event(event, offset, head);
1009 
1010         case PERF_EVENT_COMM:
1011                 return process_comm_event(event, offset, head);
1012 
1013         case PERF_EVENT_FORK:
1014                 return process_fork_event(event, offset, head);
1015         /*
1016          * We dont process them right now but they are fine:
1017          */
1018 
1019         case PERF_EVENT_THROTTLE:
1020         case PERF_EVENT_UNTHROTTLE:
1021                 return 0;
1022 
1023         default:
1024                 return -1;
1025         }
1026 
1027         return 0;
1028 }
1029 
1030 static int
1031 parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1032 {
1033         char *line = NULL, *tmp, *tmp2;
1034         static const char *prev_line;
1035         static const char *prev_color;
1036         unsigned int offset;
1037         size_t line_len;
1038         s64 line_ip;
1039         int ret;
1040         char *c;
1041 
1042         if (getline(&line, &line_len, file) < 0)
1043                 return -1;
1044         if (!line)
1045                 return -1;
1046 
1047         c = strchr(line, '\n');
1048         if (c)
1049                 *c = 0;
1050 
1051         line_ip = -1;
1052         offset = 0;
1053         ret = -2;
1054 
1055         /*
1056          * Strip leading spaces:
1057          */
1058         tmp = line;
1059         while (*tmp) {
1060                 if (*tmp != ' ')
1061                         break;
1062                 tmp++;
1063         }
1064 
1065         if (*tmp) {
1066                 /*
1067                  * Parse hexa addresses followed by ':'
1068                  */
1069                 line_ip = strtoull(tmp, &tmp2, 16);
1070                 if (*tmp2 != ':')
1071                         line_ip = -1;
1072         }
1073 
1074         if (line_ip != -1) {
1075                 const char *path = NULL;
1076                 unsigned int hits = 0;
1077                 double percent = 0.0;
1078                 char *color;
1079                 struct sym_ext *sym_ext = sym->priv;
1080 
1081                 offset = line_ip - start;
1082                 if (offset < len)
1083                         hits = sym->hist[offset];
1084 
1085                 if (offset < len && sym_ext) {
1086                         path = sym_ext[offset].path;
1087                         percent = sym_ext[offset].percent;
1088                 } else if (sym->hist_sum)
1089                         percent = 100.0 * hits / sym->hist_sum;
1090 
1091                 color = get_percent_color(percent);
1092 
1093                 /*
1094                  * Also color the filename and line if needed, with
1095                  * the same color than the percentage. Don't print it
1096                  * twice for close colored ip with the same filename:line
1097                  */
1098                 if (path) {
1099                         if (!prev_line || strcmp(prev_line, path)
1100                                        || color != prev_color) {
1101                                 color_fprintf(stdout, color, " %s", path);
1102                                 prev_line = path;
1103                                 prev_color = color;
1104                         }
1105                 }
1106 
1107                 color_fprintf(stdout, color, " %7.2f", percent);
1108                 printf(" :      ");
1109                 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", line);
1110         } else {
1111                 if (!*line)
1112                         printf("         :\n");
1113                 else
1114                         printf("         :      %s\n", line);
1115         }
1116 
1117         return 0;
1118 }
1119 
1120 static struct rb_root root_sym_ext;
1121 
1122 static void insert_source_line(struct sym_ext *sym_ext)
1123 {
1124         struct sym_ext *iter;
1125         struct rb_node **p = &root_sym_ext.rb_node;
1126         struct rb_node *parent = NULL;
1127 
1128         while (*p != NULL) {
1129                 parent = *p;
1130                 iter = rb_entry(parent, struct sym_ext, node);
1131 
1132                 if (sym_ext->percent > iter->percent)
1133                         p = &(*p)->rb_left;
1134                 else
1135                         p = &(*p)->rb_right;
1136         }
1137 
1138         rb_link_node(&sym_ext->node, parent, p);
1139         rb_insert_color(&sym_ext->node, &root_sym_ext);
1140 }
1141 
1142 static void free_source_line(struct symbol *sym, int len)
1143 {
1144         struct sym_ext *sym_ext = sym->priv;
1145         int i;
1146 
1147         if (!sym_ext)
1148                 return;
1149 
1150         for (i = 0; i < len; i++)
1151                 free(sym_ext[i].path);
1152         free(sym_ext);
1153 
1154         sym->priv = NULL;
1155         root_sym_ext = RB_ROOT;
1156 }
1157 
1158 /* Get the filename:line for the colored entries */
1159 static void
1160 get_source_line(struct symbol *sym, u64 start, int len, char *filename)
1161 {
1162         int i;
1163         char cmd[PATH_MAX * 2];
1164         struct sym_ext *sym_ext;
1165 
1166         if (!sym->hist_sum)
1167                 return;
1168 
1169         sym->priv = calloc(len, sizeof(struct sym_ext));
1170         if (!sym->priv)
1171                 return;
1172 
1173         sym_ext = sym->priv;
1174 
1175         for (i = 0; i < len; i++) {
1176                 char *path = NULL;
1177                 size_t line_len;
1178                 u64 offset;
1179                 FILE *fp;
1180 
1181                 sym_ext[i].percent = 100.0 * sym->hist[i] / sym->hist_sum;
1182                 if (sym_ext[i].percent <= 0.5)
1183                         continue;
1184 
1185                 offset = start + i;
1186                 sprintf(cmd, "addr2line -e %s %016llx", filename, offset);
1187                 fp = popen(cmd, "r");
1188                 if (!fp)
1189                         continue;
1190 
1191                 if (getline(&path, &line_len, fp) < 0 || !line_len)
1192                         goto next;
1193 
1194                 sym_ext[i].path = malloc(sizeof(char) * line_len + 1);
1195                 if (!sym_ext[i].path)
1196                         goto next;
1197 
1198                 strcpy(sym_ext[i].path, path);
1199                 insert_source_line(&sym_ext[i]);
1200 
1201         next:
1202                 pclose(fp);
1203         }
1204 }
1205 
1206 static void print_summary(char *filename)
1207 {
1208         struct sym_ext *sym_ext;
1209         struct rb_node *node;
1210 
1211         printf("\nSorted summary for file %s\n", filename);
1212         printf("----------------------------------------------\n\n");
1213 
1214         if (RB_EMPTY_ROOT(&root_sym_ext)) {
1215                 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
1216                 return;
1217         }
1218 
1219         node = rb_first(&root_sym_ext);
1220         while (node) {
1221                 double percent;
1222                 char *color;
1223                 char *path;
1224 
1225                 sym_ext = rb_entry(node, struct sym_ext, node);
1226                 percent = sym_ext->percent;
1227                 color = get_percent_color(percent);
1228                 path = sym_ext->path;
1229 
1230                 color_fprintf(stdout, color, " %7.2f %s", percent, path);
1231                 node = rb_next(node);
1232         }
1233 }
1234 
1235 static void annotate_sym(struct dso *dso, struct symbol *sym)
1236 {
1237         char *filename = dso->name, *d_filename;
1238         u64 start, end, len;
1239         char command[PATH_MAX*2];
1240         FILE *file;
1241 
1242         if (!filename)
1243                 return;
1244         if (sym->module)
1245                 filename = sym->module->path;
1246         else if (dso == kernel_dso)
1247                 filename = vmlinux;
1248 
1249         start = sym->obj_start;
1250         if (!start)
1251                 start = sym->start;
1252         if (full_paths)
1253                 d_filename = filename;
1254         else
1255                 d_filename = basename(filename);
1256 
1257         end = start + sym->end - sym->start + 1;
1258         len = sym->end - sym->start;
1259 
1260         if (print_line) {
1261                 get_source_line(sym, start, len, filename);
1262                 print_summary(filename);
1263         }
1264 
1265         printf("\n\n------------------------------------------------\n");
1266         printf(" Percent |      Source code & Disassembly of %s\n", d_filename);
1267         printf("------------------------------------------------\n");
1268 
1269         if (verbose >= 2)
1270                 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);
1271 
1272         sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
1273                         (u64)start, (u64)end, filename, filename);
1274 
1275         if (verbose >= 3)
1276                 printf("doing: %s\n", command);
1277 
1278         file = popen(command, "r");
1279         if (!file)
1280                 return;
1281 
1282         while (!feof(file)) {
1283                 if (parse_line(file, sym, start, len) < 0)
1284                         break;
1285         }
1286 
1287         pclose(file);
1288         if (print_line)
1289                 free_source_line(sym, len);
1290 }
1291 
1292 static void find_annotations(void)
1293 {
1294         struct rb_node *nd;
1295         struct dso *dso;
1296         int count = 0;
1297 
1298         list_for_each_entry(dso, &dsos, node) {
1299 
1300                 for (nd = rb_first(&dso->syms); nd; nd = rb_next(nd)) {
1301                         struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
1302 
1303                         if (sym->hist) {
1304                                 annotate_sym(dso, sym);
1305                                 count++;
1306                         }
1307                 }
1308         }
1309 
1310         if (!count)
1311                 printf(" Error: symbol '%s' not present amongst the samples.\n", sym_hist_filter);
1312 }
1313 
1314 static int __cmd_annotate(void)
1315 {
1316         int ret, rc = EXIT_FAILURE;
1317         unsigned long offset = 0;
1318         unsigned long head = 0;
1319         struct stat stat;
1320         event_t *event;
1321         uint32_t size;
1322         char *buf;
1323 
1324         register_idle_thread();
1325 
1326         input = open(input_name, O_RDONLY);
1327         if (input < 0) {
1328                 perror("failed to open file");
1329                 exit(-1);
1330         }
1331 
1332         ret = fstat(input, &stat);
1333         if (ret < 0) {
1334                 perror("failed to stat file");
1335                 exit(-1);
1336         }
1337 
1338         if (!force && stat.st_uid && (stat.st_uid != geteuid())) {
1339                 fprintf(stderr, "file: %s not owned by current user or root\n", input_name);
1340                 exit(-1);
1341         }
1342 
1343         if (!stat.st_size) {
1344                 fprintf(stderr, "zero-sized file, nothing to do!\n");
1345                 exit(0);
1346         }
1347 
1348         if (load_kernel() < 0) {
1349                 perror("failed to load kernel symbols");
1350                 return EXIT_FAILURE;
1351         }
1352 
1353 remap:
1354         buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
1355                            MAP_SHARED, input, offset);
1356         if (buf == MAP_FAILED) {
1357                 perror("failed to mmap file");
1358                 exit(-1);
1359         }
1360 
1361 more:
1362         event = (event_t *)(buf + head);
1363 
1364         size = event->header.size;
1365         if (!size)
1366                 size = 8;
1367 
1368         if (head + event->header.size >= page_size * mmap_window) {
1369                 unsigned long shift = page_size * (head / page_size);
1370                 int ret;
1371 
1372                 ret = munmap(buf, page_size * mmap_window);
1373                 assert(ret == 0);
1374 
1375                 offset += shift;
1376                 head -= shift;
1377                 goto remap;
1378         }
1379 
1380         size = event->header.size;
1381 
1382         dprintf("%p [%p]: event: %d\n",
1383                         (void *)(offset + head),
1384                         (void *)(long)event->header.size,
1385                         event->header.type);
1386 
1387         if (!size || process_event(event, offset, head) < 0) {
1388 
1389                 dprintf("%p [%p]: skipping unknown header type: %d\n",
1390                         (void *)(offset + head),
1391                         (void *)(long)(event->header.size),
1392                         event->header.type);
1393 
1394                 total_unknown++;
1395 
1396                 /*
1397                  * assume we lost track of the stream, check alignment, and
1398                  * increment a single u64 in the hope to catch on again 'soon'.
1399                  */
1400 
1401                 if (unlikely(head & 7))
1402                         head &= ~7ULL;
1403 
1404                 size = 8;
1405         }
1406 
1407         head += size;
1408 
1409         if (offset + head < (unsigned long)stat.st_size)
1410                 goto more;
1411 
1412         rc = EXIT_SUCCESS;
1413         close(input);
1414 
1415         dprintf("      IP events: %10ld\n", total);
1416         dprintf("    mmap events: %10ld\n", total_mmap);
1417         dprintf("    comm events: %10ld\n", total_comm);
1418         dprintf("    fork events: %10ld\n", total_fork);
1419         dprintf(" unknown events: %10ld\n", total_unknown);
1420 
1421         if (dump_trace)
1422                 return 0;
1423 
1424         if (verbose >= 3)
1425                 threads__fprintf(stdout);
1426 
1427         if (verbose >= 2)
1428                 dsos__fprintf(stdout);
1429 
1430         collapse__resort();
1431         output__resort();
1432 
1433         find_annotations();
1434 
1435         return rc;
1436 }
1437 
1438 static const char * const annotate_usage[] = {
1439         "perf annotate [<options>] <command>",
1440         NULL
1441 };
1442 
1443 static const struct option options[] = {
1444         OPT_STRING('i', "input", &input_name, "file",
1445                     "input file name"),
1446         OPT_STRING('s', "symbol", &sym_hist_filter, "symbol",
1447                     "symbol to annotate"),
1448         OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
1449         OPT_BOOLEAN('v', "verbose", &verbose,
1450                     "be more verbose (show symbol address, etc)"),
1451         OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1452                     "dump raw trace in ASCII"),
1453         OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1454         OPT_BOOLEAN('m', "modules", &modules,
1455                     "load module symbols - WARNING: use only with -k and LIVE kernel"),
1456         OPT_BOOLEAN('l', "print-line", &print_line,
1457                     "print matching source lines (may be slow)"),
1458         OPT_BOOLEAN('P', "full-paths", &full_paths,
1459                     "Don't shorten the displayed pathnames"),
1460         OPT_END()
1461 };
1462 
1463 static void setup_sorting(void)
1464 {
1465         char *tmp, *tok, *str = strdup(sort_order);
1466 
1467         for (tok = strtok_r(str, ", ", &tmp);
1468                         tok; tok = strtok_r(NULL, ", ", &tmp)) {
1469                 if (sort_dimension__add(tok) < 0) {
1470                         error("Unknown --sort key: `%s'", tok);
1471                         usage_with_options(annotate_usage, options);
1472                 }
1473         }
1474 
1475         free(str);
1476 }
1477 
1478 int cmd_annotate(int argc, const char **argv, const char *prefix __used)
1479 {
1480         symbol__init();
1481 
1482         page_size = getpagesize();
1483 
1484         argc = parse_options(argc, argv, options, annotate_usage, 0);
1485 
1486         setup_sorting();
1487 
1488         if (argc) {
1489                 /*
1490                  * Special case: if there's an argument left then assume tha
1491                  * it's a symbol filter:
1492                  */
1493                 if (argc > 1)
1494                         usage_with_options(annotate_usage, options);
1495 
1496                 sym_hist_filter = argv[0];
1497         }
1498 
1499         if (!sym_hist_filter)
1500                 usage_with_options(annotate_usage, options);
1501 
1502         setup_pager();
1503 
1504         return __cmd_annotate();
1505 }
1506 
  This page was automatically generated by the LXR engine.