Merge branches 'stable/ia64', 'stable/blkfront-cleanup' and 'stable/cleanup' of git...
[pandora-kernel.git] / tools / perf / util / event.c
1 #include <linux/types.h>
2 #include "event.h"
3 #include "debug.h"
4 #include "session.h"
5 #include "sort.h"
6 #include "string.h"
7 #include "strlist.h"
8 #include "thread.h"
9
10 static const char *event__name[] = {
11         [0]                      = "TOTAL",
12         [PERF_RECORD_MMAP]       = "MMAP",
13         [PERF_RECORD_LOST]       = "LOST",
14         [PERF_RECORD_COMM]       = "COMM",
15         [PERF_RECORD_EXIT]       = "EXIT",
16         [PERF_RECORD_THROTTLE]   = "THROTTLE",
17         [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE",
18         [PERF_RECORD_FORK]       = "FORK",
19         [PERF_RECORD_READ]       = "READ",
20         [PERF_RECORD_SAMPLE]     = "SAMPLE",
21         [PERF_RECORD_HEADER_ATTR]        = "ATTR",
22         [PERF_RECORD_HEADER_EVENT_TYPE]  = "EVENT_TYPE",
23         [PERF_RECORD_HEADER_TRACING_DATA]        = "TRACING_DATA",
24         [PERF_RECORD_HEADER_BUILD_ID]    = "BUILD_ID",
25         [PERF_RECORD_FINISHED_ROUND]     = "FINISHED_ROUND",
26 };
27
28 const char *event__get_event_name(unsigned int id)
29 {
30         if (id >= ARRAY_SIZE(event__name))
31                 return "INVALID";
32         if (!event__name[id])
33                 return "UNKNOWN";
34         return event__name[id];
35 }
36
37 static struct sample_data synth_sample = {
38         .pid       = -1,
39         .tid       = -1,
40         .time      = -1,
41         .stream_id = -1,
42         .cpu       = -1,
43         .period    = 1,
44 };
45
46 static pid_t event__synthesize_comm(event_t *event, pid_t pid, int full,
47                                     event__handler_t process,
48                                     struct perf_session *session)
49 {
50         char filename[PATH_MAX];
51         char bf[BUFSIZ];
52         FILE *fp;
53         size_t size = 0;
54         DIR *tasks;
55         struct dirent dirent, *next;
56         pid_t tgid = 0;
57
58         snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
59
60         fp = fopen(filename, "r");
61         if (fp == NULL) {
62 out_race:
63                 /*
64                  * We raced with a task exiting - just return:
65                  */
66                 pr_debug("couldn't open %s\n", filename);
67                 return 0;
68         }
69
70         memset(&event->comm, 0, sizeof(event->comm));
71
72         while (!event->comm.comm[0] || !event->comm.pid) {
73                 if (fgets(bf, sizeof(bf), fp) == NULL) {
74                         pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
75                         goto out;
76                 }
77
78                 if (memcmp(bf, "Name:", 5) == 0) {
79                         char *name = bf + 5;
80                         while (*name && isspace(*name))
81                                 ++name;
82                         size = strlen(name) - 1;
83                         memcpy(event->comm.comm, name, size++);
84                 } else if (memcmp(bf, "Tgid:", 5) == 0) {
85                         char *tgids = bf + 5;
86                         while (*tgids && isspace(*tgids))
87                                 ++tgids;
88                         tgid = event->comm.pid = atoi(tgids);
89                 }
90         }
91
92         event->comm.header.type = PERF_RECORD_COMM;
93         size = ALIGN(size, sizeof(u64));
94         memset(event->comm.comm + size, 0, session->id_hdr_size);
95         event->comm.header.size = (sizeof(event->comm) -
96                                 (sizeof(event->comm.comm) - size) +
97                                 session->id_hdr_size);
98         if (!full) {
99                 event->comm.tid = pid;
100
101                 process(event, &synth_sample, session);
102                 goto out;
103         }
104
105         snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
106
107         tasks = opendir(filename);
108         if (tasks == NULL)
109                 goto out_race;
110
111         while (!readdir_r(tasks, &dirent, &next) && next) {
112                 char *end;
113                 pid = strtol(dirent.d_name, &end, 10);
114                 if (*end)
115                         continue;
116
117                 event->comm.tid = pid;
118
119                 process(event, &synth_sample, session);
120         }
121
122         closedir(tasks);
123 out:
124         fclose(fp);
125
126         return tgid;
127 }
128
129 static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid,
130                                          event__handler_t process,
131                                          struct perf_session *session)
132 {
133         char filename[PATH_MAX];
134         FILE *fp;
135
136         snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
137
138         fp = fopen(filename, "r");
139         if (fp == NULL) {
140                 /*
141                  * We raced with a task exiting - just return:
142                  */
143                 pr_debug("couldn't open %s\n", filename);
144                 return -1;
145         }
146
147         event->header.type = PERF_RECORD_MMAP;
148         /*
149          * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
150          */
151         event->header.misc = PERF_RECORD_MISC_USER;
152
153         while (1) {
154                 char bf[BUFSIZ], *pbf = bf;
155                 int n;
156                 size_t size;
157                 if (fgets(bf, sizeof(bf), fp) == NULL)
158                         break;
159
160                 /* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
161                 n = hex2u64(pbf, &event->mmap.start);
162                 if (n < 0)
163                         continue;
164                 pbf += n + 1;
165                 n = hex2u64(pbf, &event->mmap.len);
166                 if (n < 0)
167                         continue;
168                 pbf += n + 3;
169                 if (*pbf == 'x') { /* vm_exec */
170                         char *execname = strchr(bf, '/');
171
172                         /* Catch VDSO */
173                         if (execname == NULL)
174                                 execname = strstr(bf, "[vdso]");
175
176                         if (execname == NULL)
177                                 continue;
178
179                         pbf += 3;
180                         n = hex2u64(pbf, &event->mmap.pgoff);
181
182                         size = strlen(execname);
183                         execname[size - 1] = '\0'; /* Remove \n */
184                         memcpy(event->mmap.filename, execname, size);
185                         size = ALIGN(size, sizeof(u64));
186                         event->mmap.len -= event->mmap.start;
187                         event->mmap.header.size = (sizeof(event->mmap) -
188                                                 (sizeof(event->mmap.filename) - size));
189                         memset(event->mmap.filename + size, 0, session->id_hdr_size);
190                         event->mmap.header.size += session->id_hdr_size;
191                         event->mmap.pid = tgid;
192                         event->mmap.tid = pid;
193
194                         process(event, &synth_sample, session);
195                 }
196         }
197
198         fclose(fp);
199         return 0;
200 }
201
202 int event__synthesize_modules(event__handler_t process,
203                               struct perf_session *session,
204                               struct machine *machine)
205 {
206         struct rb_node *nd;
207         struct map_groups *kmaps = &machine->kmaps;
208         event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
209
210         if (event == NULL) {
211                 pr_debug("Not enough memory synthesizing mmap event "
212                          "for kernel modules\n");
213                 return -1;
214         }
215
216         event->header.type = PERF_RECORD_MMAP;
217
218         /*
219          * kernel uses 0 for user space maps, see kernel/perf_event.c
220          * __perf_event_mmap
221          */
222         if (machine__is_host(machine))
223                 event->header.misc = PERF_RECORD_MISC_KERNEL;
224         else
225                 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
226
227         for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]);
228              nd; nd = rb_next(nd)) {
229                 size_t size;
230                 struct map *pos = rb_entry(nd, struct map, rb_node);
231
232                 if (pos->dso->kernel)
233                         continue;
234
235                 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
236                 event->mmap.header.type = PERF_RECORD_MMAP;
237                 event->mmap.header.size = (sizeof(event->mmap) -
238                                         (sizeof(event->mmap.filename) - size));
239                 memset(event->mmap.filename + size, 0, session->id_hdr_size);
240                 event->mmap.header.size += session->id_hdr_size;
241                 event->mmap.start = pos->start;
242                 event->mmap.len   = pos->end - pos->start;
243                 event->mmap.pid   = machine->pid;
244
245                 memcpy(event->mmap.filename, pos->dso->long_name,
246                        pos->dso->long_name_len + 1);
247                 process(event, &synth_sample, session);
248         }
249
250         free(event);
251         return 0;
252 }
253
254 static int __event__synthesize_thread(event_t *comm_event, event_t *mmap_event,
255                                       pid_t pid, event__handler_t process,
256                                       struct perf_session *session)
257 {
258         pid_t tgid = event__synthesize_comm(comm_event, pid, 1, process,
259                                             session);
260         if (tgid == -1)
261                 return -1;
262         return event__synthesize_mmap_events(mmap_event, pid, tgid,
263                                              process, session);
264 }
265
266 int event__synthesize_thread_map(struct thread_map *threads,
267                                  event__handler_t process,
268                                  struct perf_session *session)
269 {
270         event_t *comm_event, *mmap_event;
271         int err = -1, thread;
272
273         comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
274         if (comm_event == NULL)
275                 goto out;
276
277         mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
278         if (mmap_event == NULL)
279                 goto out_free_comm;
280
281         err = 0;
282         for (thread = 0; thread < threads->nr; ++thread) {
283                 if (__event__synthesize_thread(comm_event, mmap_event,
284                                                threads->map[thread],
285                                                process, session)) {
286                         err = -1;
287                         break;
288                 }
289         }
290         free(mmap_event);
291 out_free_comm:
292         free(comm_event);
293 out:
294         return err;
295 }
296
297 int event__synthesize_threads(event__handler_t process,
298                               struct perf_session *session)
299 {
300         DIR *proc;
301         struct dirent dirent, *next;
302         event_t *comm_event, *mmap_event;
303         int err = -1;
304
305         comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
306         if (comm_event == NULL)
307                 goto out;
308
309         mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
310         if (mmap_event == NULL)
311                 goto out_free_comm;
312
313         proc = opendir("/proc");
314         if (proc == NULL)
315                 goto out_free_mmap;
316
317         while (!readdir_r(proc, &dirent, &next) && next) {
318                 char *end;
319                 pid_t pid = strtol(dirent.d_name, &end, 10);
320
321                 if (*end) /* only interested in proper numerical dirents */
322                         continue;
323
324                 __event__synthesize_thread(comm_event, mmap_event, pid,
325                                            process, session);
326         }
327
328         closedir(proc);
329         err = 0;
330 out_free_mmap:
331         free(mmap_event);
332 out_free_comm:
333         free(comm_event);
334 out:
335         return err;
336 }
337
338 struct process_symbol_args {
339         const char *name;
340         u64        start;
341 };
342
343 static int find_symbol_cb(void *arg, const char *name, char type,
344                           u64 start, u64 end __used)
345 {
346         struct process_symbol_args *args = arg;
347
348         /*
349          * Must be a function or at least an alias, as in PARISC64, where "_text" is
350          * an 'A' to the same address as "_stext".
351          */
352         if (!(symbol_type__is_a(type, MAP__FUNCTION) ||
353               type == 'A') || strcmp(name, args->name))
354                 return 0;
355
356         args->start = start;
357         return 1;
358 }
359
360 int event__synthesize_kernel_mmap(event__handler_t process,
361                                   struct perf_session *session,
362                                   struct machine *machine,
363                                   const char *symbol_name)
364 {
365         size_t size;
366         const char *filename, *mmap_name;
367         char path[PATH_MAX];
368         char name_buff[PATH_MAX];
369         struct map *map;
370         int err;
371         /*
372          * We should get this from /sys/kernel/sections/.text, but till that is
373          * available use this, and after it is use this as a fallback for older
374          * kernels.
375          */
376         struct process_symbol_args args = { .name = symbol_name, };
377         event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
378
379         if (event == NULL) {
380                 pr_debug("Not enough memory synthesizing mmap event "
381                          "for kernel modules\n");
382                 return -1;
383         }
384
385         mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff));
386         if (machine__is_host(machine)) {
387                 /*
388                  * kernel uses PERF_RECORD_MISC_USER for user space maps,
389                  * see kernel/perf_event.c __perf_event_mmap
390                  */
391                 event->header.misc = PERF_RECORD_MISC_KERNEL;
392                 filename = "/proc/kallsyms";
393         } else {
394                 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
395                 if (machine__is_default_guest(machine))
396                         filename = (char *) symbol_conf.default_guest_kallsyms;
397                 else {
398                         sprintf(path, "%s/proc/kallsyms", machine->root_dir);
399                         filename = path;
400                 }
401         }
402
403         if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0)
404                 return -ENOENT;
405
406         map = machine->vmlinux_maps[MAP__FUNCTION];
407         size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
408                         "%s%s", mmap_name, symbol_name) + 1;
409         size = ALIGN(size, sizeof(u64));
410         event->mmap.header.type = PERF_RECORD_MMAP;
411         event->mmap.header.size = (sizeof(event->mmap) -
412                         (sizeof(event->mmap.filename) - size) + session->id_hdr_size);
413         event->mmap.pgoff = args.start;
414         event->mmap.start = map->start;
415         event->mmap.len   = map->end - event->mmap.start;
416         event->mmap.pid   = machine->pid;
417
418         err = process(event, &synth_sample, session);
419         free(event);
420
421         return err;
422 }
423
424 static void thread__comm_adjust(struct thread *self, struct hists *hists)
425 {
426         char *comm = self->comm;
427
428         if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
429             (!symbol_conf.comm_list ||
430              strlist__has_entry(symbol_conf.comm_list, comm))) {
431                 u16 slen = strlen(comm);
432
433                 if (hists__new_col_len(hists, HISTC_COMM, slen))
434                         hists__set_col_len(hists, HISTC_THREAD, slen + 6);
435         }
436 }
437
438 static int thread__set_comm_adjust(struct thread *self, const char *comm,
439                                    struct hists *hists)
440 {
441         int ret = thread__set_comm(self, comm);
442
443         if (ret)
444                 return ret;
445
446         thread__comm_adjust(self, hists);
447
448         return 0;
449 }
450
451 int event__process_comm(event_t *self, struct sample_data *sample __used,
452                         struct perf_session *session)
453 {
454         struct thread *thread = perf_session__findnew(session, self->comm.tid);
455
456         dump_printf(": %s:%d\n", self->comm.comm, self->comm.tid);
457
458         if (thread == NULL || thread__set_comm_adjust(thread, self->comm.comm,
459                                                       &session->hists)) {
460                 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
461                 return -1;
462         }
463
464         return 0;
465 }
466
467 int event__process_lost(event_t *self, struct sample_data *sample __used,
468                         struct perf_session *session)
469 {
470         dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
471                     self->lost.id, self->lost.lost);
472         session->hists.stats.total_lost += self->lost.lost;
473         return 0;
474 }
475
476 static void event_set_kernel_mmap_len(struct map **maps, event_t *self)
477 {
478         maps[MAP__FUNCTION]->start = self->mmap.start;
479         maps[MAP__FUNCTION]->end   = self->mmap.start + self->mmap.len;
480         /*
481          * Be a bit paranoid here, some perf.data file came with
482          * a zero sized synthesized MMAP event for the kernel.
483          */
484         if (maps[MAP__FUNCTION]->end == 0)
485                 maps[MAP__FUNCTION]->end = ~0ULL;
486 }
487
488 static int event__process_kernel_mmap(event_t *self,
489                         struct perf_session *session)
490 {
491         struct map *map;
492         char kmmap_prefix[PATH_MAX];
493         struct machine *machine;
494         enum dso_kernel_type kernel_type;
495         bool is_kernel_mmap;
496
497         machine = perf_session__findnew_machine(session, self->mmap.pid);
498         if (!machine) {
499                 pr_err("Can't find id %d's machine\n", self->mmap.pid);
500                 goto out_problem;
501         }
502
503         machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
504         if (machine__is_host(machine))
505                 kernel_type = DSO_TYPE_KERNEL;
506         else
507                 kernel_type = DSO_TYPE_GUEST_KERNEL;
508
509         is_kernel_mmap = memcmp(self->mmap.filename,
510                                 kmmap_prefix,
511                                 strlen(kmmap_prefix)) == 0;
512         if (self->mmap.filename[0] == '/' ||
513             (!is_kernel_mmap && self->mmap.filename[0] == '[')) {
514
515                 char short_module_name[1024];
516                 char *name, *dot;
517
518                 if (self->mmap.filename[0] == '/') {
519                         name = strrchr(self->mmap.filename, '/');
520                         if (name == NULL)
521                                 goto out_problem;
522
523                         ++name; /* skip / */
524                         dot = strrchr(name, '.');
525                         if (dot == NULL)
526                                 goto out_problem;
527                         snprintf(short_module_name, sizeof(short_module_name),
528                                         "[%.*s]", (int)(dot - name), name);
529                         strxfrchar(short_module_name, '-', '_');
530                 } else
531                         strcpy(short_module_name, self->mmap.filename);
532
533                 map = machine__new_module(machine, self->mmap.start,
534                                           self->mmap.filename);
535                 if (map == NULL)
536                         goto out_problem;
537
538                 name = strdup(short_module_name);
539                 if (name == NULL)
540                         goto out_problem;
541
542                 map->dso->short_name = name;
543                 map->dso->sname_alloc = 1;
544                 map->end = map->start + self->mmap.len;
545         } else if (is_kernel_mmap) {
546                 const char *symbol_name = (self->mmap.filename +
547                                 strlen(kmmap_prefix));
548                 /*
549                  * Should be there already, from the build-id table in
550                  * the header.
551                  */
552                 struct dso *kernel = __dsos__findnew(&machine->kernel_dsos,
553                                                      kmmap_prefix);
554                 if (kernel == NULL)
555                         goto out_problem;
556
557                 kernel->kernel = kernel_type;
558                 if (__machine__create_kernel_maps(machine, kernel) < 0)
559                         goto out_problem;
560
561                 event_set_kernel_mmap_len(machine->vmlinux_maps, self);
562                 perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
563                                                          symbol_name,
564                                                          self->mmap.pgoff);
565                 if (machine__is_default_guest(machine)) {
566                         /*
567                          * preload dso of guest kernel and modules
568                          */
569                         dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION],
570                                   NULL);
571                 }
572         }
573         return 0;
574 out_problem:
575         return -1;
576 }
577
578 int event__process_mmap(event_t *self, struct sample_data *sample __used,
579                         struct perf_session *session)
580 {
581         struct machine *machine;
582         struct thread *thread;
583         struct map *map;
584         u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
585         int ret = 0;
586
587         dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n",
588                         self->mmap.pid, self->mmap.tid, self->mmap.start,
589                         self->mmap.len, self->mmap.pgoff, self->mmap.filename);
590
591         if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
592             cpumode == PERF_RECORD_MISC_KERNEL) {
593                 ret = event__process_kernel_mmap(self, session);
594                 if (ret < 0)
595                         goto out_problem;
596                 return 0;
597         }
598
599         machine = perf_session__find_host_machine(session);
600         if (machine == NULL)
601                 goto out_problem;
602         thread = perf_session__findnew(session, self->mmap.pid);
603         if (thread == NULL)
604                 goto out_problem;
605         map = map__new(&machine->user_dsos, self->mmap.start,
606                         self->mmap.len, self->mmap.pgoff,
607                         self->mmap.pid, self->mmap.filename,
608                         MAP__FUNCTION);
609         if (map == NULL)
610                 goto out_problem;
611
612         thread__insert_map(thread, map);
613         return 0;
614
615 out_problem:
616         dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
617         return 0;
618 }
619
620 int event__process_task(event_t *self, struct sample_data *sample __used,
621                         struct perf_session *session)
622 {
623         struct thread *thread = perf_session__findnew(session, self->fork.tid);
624         struct thread *parent = perf_session__findnew(session, self->fork.ptid);
625
626         dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid,
627                     self->fork.ppid, self->fork.ptid);
628
629         if (self->header.type == PERF_RECORD_EXIT) {
630                 perf_session__remove_thread(session, thread);
631                 return 0;
632         }
633
634         if (thread == NULL || parent == NULL ||
635             thread__fork(thread, parent) < 0) {
636                 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
637                 return -1;
638         }
639
640         return 0;
641 }
642
643 int event__process(event_t *event, struct sample_data *sample,
644                    struct perf_session *session)
645 {
646         switch (event->header.type) {
647         case PERF_RECORD_COMM:
648                 event__process_comm(event, sample, session);
649                 break;
650         case PERF_RECORD_MMAP:
651                 event__process_mmap(event, sample, session);
652                 break;
653         case PERF_RECORD_FORK:
654         case PERF_RECORD_EXIT:
655                 event__process_task(event, sample, session);
656                 break;
657         default:
658                 break;
659         }
660
661         return 0;
662 }
663
664 void thread__find_addr_map(struct thread *self,
665                            struct perf_session *session, u8 cpumode,
666                            enum map_type type, pid_t pid, u64 addr,
667                            struct addr_location *al)
668 {
669         struct map_groups *mg = &self->mg;
670         struct machine *machine = NULL;
671
672         al->thread = self;
673         al->addr = addr;
674         al->cpumode = cpumode;
675         al->filtered = false;
676
677         if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
678                 al->level = 'k';
679                 machine = perf_session__find_host_machine(session);
680                 if (machine == NULL) {
681                         al->map = NULL;
682                         return;
683                 }
684                 mg = &machine->kmaps;
685         } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
686                 al->level = '.';
687                 machine = perf_session__find_host_machine(session);
688         } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
689                 al->level = 'g';
690                 machine = perf_session__find_machine(session, pid);
691                 if (machine == NULL) {
692                         al->map = NULL;
693                         return;
694                 }
695                 mg = &machine->kmaps;
696         } else {
697                 /*
698                  * 'u' means guest os user space.
699                  * TODO: We don't support guest user space. Might support late.
700                  */
701                 if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest)
702                         al->level = 'u';
703                 else
704                         al->level = 'H';
705                 al->map = NULL;
706
707                 if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
708                         cpumode == PERF_RECORD_MISC_GUEST_KERNEL) &&
709                         !perf_guest)
710                         al->filtered = true;
711                 if ((cpumode == PERF_RECORD_MISC_USER ||
712                         cpumode == PERF_RECORD_MISC_KERNEL) &&
713                         !perf_host)
714                         al->filtered = true;
715
716                 return;
717         }
718 try_again:
719         al->map = map_groups__find(mg, type, al->addr);
720         if (al->map == NULL) {
721                 /*
722                  * If this is outside of all known maps, and is a negative
723                  * address, try to look it up in the kernel dso, as it might be
724                  * a vsyscall or vdso (which executes in user-mode).
725                  *
726                  * XXX This is nasty, we should have a symbol list in the
727                  * "[vdso]" dso, but for now lets use the old trick of looking
728                  * in the whole kernel symbol list.
729                  */
730                 if ((long long)al->addr < 0 &&
731                     cpumode == PERF_RECORD_MISC_KERNEL &&
732                     machine && mg != &machine->kmaps) {
733                         mg = &machine->kmaps;
734                         goto try_again;
735                 }
736         } else
737                 al->addr = al->map->map_ip(al->map, al->addr);
738 }
739
740 void thread__find_addr_location(struct thread *self,
741                                 struct perf_session *session, u8 cpumode,
742                                 enum map_type type, pid_t pid, u64 addr,
743                                 struct addr_location *al,
744                                 symbol_filter_t filter)
745 {
746         thread__find_addr_map(self, session, cpumode, type, pid, addr, al);
747         if (al->map != NULL)
748                 al->sym = map__find_symbol(al->map, al->addr, filter);
749         else
750                 al->sym = NULL;
751 }
752
753 static void dso__calc_col_width(struct dso *self, struct hists *hists)
754 {
755         if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
756             (!symbol_conf.dso_list ||
757              strlist__has_entry(symbol_conf.dso_list, self->name))) {
758                 u16 slen = dso__name_len(self);
759                 hists__new_col_len(hists, HISTC_DSO, slen);
760         }
761
762         self->slen_calculated = 1;
763 }
764
765 int event__preprocess_sample(const event_t *self, struct perf_session *session,
766                              struct addr_location *al, struct sample_data *data,
767                              symbol_filter_t filter)
768 {
769         u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
770         struct thread *thread = perf_session__findnew(session, self->ip.pid);
771
772         if (thread == NULL)
773                 return -1;
774
775         if (symbol_conf.comm_list &&
776             !strlist__has_entry(symbol_conf.comm_list, thread->comm))
777                 goto out_filtered;
778
779         dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
780         /*
781          * Have we already created the kernel maps for the host machine?
782          *
783          * This should have happened earlier, when we processed the kernel MMAP
784          * events, but for older perf.data files there was no such thing, so do
785          * it now.
786          */
787         if (cpumode == PERF_RECORD_MISC_KERNEL &&
788             session->host_machine.vmlinux_maps[MAP__FUNCTION] == NULL)
789                 machine__create_kernel_maps(&session->host_machine);
790
791         thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
792                               self->ip.pid, self->ip.ip, al);
793         dump_printf(" ...... dso: %s\n",
794                     al->map ? al->map->dso->long_name :
795                         al->level == 'H' ? "[hypervisor]" : "<not found>");
796         al->sym = NULL;
797         al->cpu = data->cpu;
798
799         if (al->map) {
800                 if (symbol_conf.dso_list &&
801                     (!al->map || !al->map->dso ||
802                      !(strlist__has_entry(symbol_conf.dso_list,
803                                           al->map->dso->short_name) ||
804                        (al->map->dso->short_name != al->map->dso->long_name &&
805                         strlist__has_entry(symbol_conf.dso_list,
806                                            al->map->dso->long_name)))))
807                         goto out_filtered;
808                 /*
809                  * We have to do this here as we may have a dso with no symbol
810                  * hit that has a name longer than the ones with symbols
811                  * sampled.
812                  */
813                 if (!sort_dso.elide && !al->map->dso->slen_calculated)
814                         dso__calc_col_width(al->map->dso, &session->hists);
815
816                 al->sym = map__find_symbol(al->map, al->addr, filter);
817         } else {
818                 const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
819
820                 if (hists__col_len(&session->hists, HISTC_DSO) < unresolved_col_width &&
821                     !symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
822                     !symbol_conf.dso_list)
823                         hists__set_col_len(&session->hists, HISTC_DSO,
824                                            unresolved_col_width);
825         }
826
827         if (symbol_conf.sym_list && al->sym &&
828             !strlist__has_entry(symbol_conf.sym_list, al->sym->name))
829                 goto out_filtered;
830
831         return 0;
832
833 out_filtered:
834         al->filtered = true;
835         return 0;
836 }
837
838 static int event__parse_id_sample(const event_t *event,
839                                   struct perf_session *session,
840                                   struct sample_data *sample)
841 {
842         const u64 *array;
843         u64 type;
844
845         sample->cpu = sample->pid = sample->tid = -1;
846         sample->stream_id = sample->id = sample->time = -1ULL;
847
848         if (!session->sample_id_all)
849                 return 0;
850
851         array = event->sample.array;
852         array += ((event->header.size -
853                    sizeof(event->header)) / sizeof(u64)) - 1;
854         type = session->sample_type;
855
856         if (type & PERF_SAMPLE_CPU) {
857                 u32 *p = (u32 *)array;
858                 sample->cpu = *p;
859                 array--;
860         }
861
862         if (type & PERF_SAMPLE_STREAM_ID) {
863                 sample->stream_id = *array;
864                 array--;
865         }
866
867         if (type & PERF_SAMPLE_ID) {
868                 sample->id = *array;
869                 array--;
870         }
871
872         if (type & PERF_SAMPLE_TIME) {
873                 sample->time = *array;
874                 array--;
875         }
876
877         if (type & PERF_SAMPLE_TID) {
878                 u32 *p = (u32 *)array;
879                 sample->pid = p[0];
880                 sample->tid = p[1];
881         }
882
883         return 0;
884 }
885
886 int event__parse_sample(const event_t *event, struct perf_session *session,
887                         struct sample_data *data)
888 {
889         const u64 *array;
890         u64 type;
891
892         if (event->header.type != PERF_RECORD_SAMPLE)
893                 return event__parse_id_sample(event, session, data);
894
895         array = event->sample.array;
896         type = session->sample_type;
897
898         if (type & PERF_SAMPLE_IP) {
899                 data->ip = event->ip.ip;
900                 array++;
901         }
902
903         if (type & PERF_SAMPLE_TID) {
904                 u32 *p = (u32 *)array;
905                 data->pid = p[0];
906                 data->tid = p[1];
907                 array++;
908         }
909
910         if (type & PERF_SAMPLE_TIME) {
911                 data->time = *array;
912                 array++;
913         }
914
915         if (type & PERF_SAMPLE_ADDR) {
916                 data->addr = *array;
917                 array++;
918         }
919
920         data->id = -1ULL;
921         if (type & PERF_SAMPLE_ID) {
922                 data->id = *array;
923                 array++;
924         }
925
926         if (type & PERF_SAMPLE_STREAM_ID) {
927                 data->stream_id = *array;
928                 array++;
929         }
930
931         if (type & PERF_SAMPLE_CPU) {
932                 u32 *p = (u32 *)array;
933                 data->cpu = *p;
934                 array++;
935         } else
936                 data->cpu = -1;
937
938         if (type & PERF_SAMPLE_PERIOD) {
939                 data->period = *array;
940                 array++;
941         }
942
943         if (type & PERF_SAMPLE_READ) {
944                 pr_debug("PERF_SAMPLE_READ is unsuported for now\n");
945                 return -1;
946         }
947
948         if (type & PERF_SAMPLE_CALLCHAIN) {
949                 data->callchain = (struct ip_callchain *)array;
950                 array += 1 + data->callchain->nr;
951         }
952
953         if (type & PERF_SAMPLE_RAW) {
954                 u32 *p = (u32 *)array;
955                 data->raw_size = *p;
956                 p++;
957                 data->raw_data = p;
958         }
959
960         return 0;
961 }